Skip to content

Commit

Permalink
https://github.com/jackdewinter/pymarkdown/issues/964
Browse files Browse the repository at this point in the history
  • Loading branch information
jackdewinter committed Jan 28, 2024
1 parent 67ee195 commit 5962228
Show file tree
Hide file tree
Showing 18 changed files with 405 additions and 96 deletions.
8 changes: 4 additions & 4 deletions publish/coverage.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
"projectName": "pymarkdown",
"reportSource": "pytest",
"branchLevel": {
"totalMeasured": 4785,
"totalCovered": 4785
"totalMeasured": 4795,
"totalCovered": 4795
},
"lineLevel": {
"totalMeasured": 19327,
"totalCovered": 19327
"totalMeasured": 19342,
"totalCovered": 19342
}
}

6 changes: 4 additions & 2 deletions publish/pylint_suppression.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,9 @@
"too-many-arguments": 6
},
"pymarkdown/plugins/rule_md_028.py": {},
"pymarkdown/plugins/rule_md_029.py": {},
"pymarkdown/plugins/rule_md_029.py": {
"too-many-arguments": 1
},
"pymarkdown/plugins/rule_md_030.py": {
"too-many-instance-attributes": 1
},
Expand Down Expand Up @@ -493,7 +495,7 @@
"too-many-instance-attributes": 24,
"too-many-public-methods": 4,
"too-few-public-methods": 39,
"too-many-arguments": 226,
"too-many-arguments": 227,
"too-many-locals": 38,
"chained-comparison": 1,
"too-many-boolean-expressions": 2,
Expand Down
6 changes: 3 additions & 3 deletions publish/test-results.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@
},
{
"name": "test.gfm.test_markdown_list_blocks",
"totalTests": 135,
"totalTests": 137,
"failedTests": 0,
"errorTests": 0,
"skippedTests": 4,
Expand Down Expand Up @@ -1140,7 +1140,7 @@
},
{
"name": "test.rules.test_md005",
"totalTests": 88,
"totalTests": 94,
"failedTests": 0,
"errorTests": 0,
"skippedTests": 2,
Expand All @@ -1156,7 +1156,7 @@
},
{
"name": "test.rules.test_md007",
"totalTests": 62,
"totalTests": 68,
"failedTests": 0,
"errorTests": 0,
"skippedTests": 0,
Expand Down
29 changes: 26 additions & 3 deletions pymarkdown/plugins/rule_md_007.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def get_details(self) -> PluginDetailsV2:
plugin_url="https://github.com/jackdewinter/pymarkdown/blob/main/docs/rules/rule_md007.md",
plugin_configuration="indent,start_indented",
plugin_supports_fix=True,
plugin_fix_level=3,
)

@classmethod
Expand Down Expand Up @@ -169,21 +170,43 @@ def __check_apply_fix(
whitespace_length = len(list_token.extracted_whitespace)
assert whitespace_length >= column_delta
adjusted_whitespace = list_token.extracted_whitespace[:-column_delta]
follow_space_delta = (list_token.indent_level - list_token.column_number) - 1
self.register_fix_token_request(
context,
token,
"next_token",
"extracted_whitespace",
adjusted_whitespace,
)
if token.is_new_list_item:
self.register_fix_token_request(
context,
token,
"next_token",
"indent_level",
list_token.indent_level - column_delta - follow_space_delta,
)
if not token.is_new_list_item:
self.register_fix_token_request(
context,
token,
"next_token",
"indent_level",
list_token.indent_level - column_delta,
"column_number",
list_token.column_number - column_delta,
)
if list_token.leading_spaces:
new_spaces = []
total_delta = column_delta + follow_space_delta
for i in list_token.leading_spaces.split("\n"):
if len(i) >= list_token.indent_level:
i = i[:-total_delta]
new_spaces.append(i)
self.register_fix_token_request(
context,
list_token,
"next_token",
"leading_spaces",
"\n".join(new_spaces),
)

def __check(self, context: PluginScanContext, token: MarkdownToken) -> None:
# print(f"{token}".replace(ParserHelper.newline_character, "\\n"))
Expand Down
14 changes: 12 additions & 2 deletions pymarkdown/plugins/rule_md_019.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Optional, cast

from pymarkdown.general.parser_helper import ParserHelper
from pymarkdown.general.tab_helper import TabHelper
from pymarkdown.plugin_manager.plugin_details import PluginDetailsV2
from pymarkdown.plugin_manager.plugin_scan_context import PluginScanContext
from pymarkdown.plugin_manager.rule_plugin import RulePlugin
Expand All @@ -21,7 +22,7 @@ class RuleMd019(RulePlugin):

def __init__(self) -> None:
super().__init__()
self.__atx_heading_token: Optional[MarkdownToken] = None
self.__atx_heading_token: Optional[AtxHeadingMarkdownToken] = None

def get_details(self) -> PluginDetailsV2:
"""
Expand Down Expand Up @@ -65,13 +66,22 @@ def next_token(self, context: PluginScanContext, token: MarkdownToken) -> None:
if token.is_atx_heading:
atx_token = cast(AtxHeadingMarkdownToken, token)
if not atx_token.remove_trailing_count:
self.__atx_heading_token = token
self.__atx_heading_token = atx_token
elif token.is_paragraph_end:
self.__atx_heading_token = None
elif token.is_text:
text_token = cast(TextMarkdownToken, token)
resolved_extracted_whitespace = ParserHelper.remove_all_from_text(
text_token.extracted_whitespace
)
if self.__atx_heading_token and "\t" in resolved_extracted_whitespace:
start_index = (
self.__atx_heading_token.column_number
- 1
+ self.__atx_heading_token.hash_count
)
resolved_extracted_whitespace = TabHelper.detabify_string(
resolved_extracted_whitespace, start_index
)
if self.__atx_heading_token and len(resolved_extracted_whitespace) > 1:
self.__report(context, text_token)
98 changes: 58 additions & 40 deletions pymarkdown/plugins/rule_md_029.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ def __match_first_item(
self, context: PluginScanContext, token: MarkdownToken
) -> Tuple[Optional[str], Optional[int]]:
list_token = cast(ListStartMarkdownToken, token)
list_style: Optional[str] = self.__style
last_known_number: Optional[int] = int(list_token.list_start_content)
last_known_number: int = int(list_token.list_start_content)

list_style: str = self.__style
if list_style == RuleMd029.__one_or_ordered_style and last_known_number != 1:
list_style = RuleMd029.__ordered_style

Expand All @@ -109,27 +109,12 @@ def __match_first_item(
elif list_style == RuleMd029.__zero_style:
is_valid = last_known_number == 0
# print(f"list_style={list_style},last_known_number={last_known_number},is_valid={is_valid}")
if not is_valid:
assert list_style is not None
style, expected_number = self.__calculate_match_info(
list_style, True, last_known_number
)
extra_error_information = f"Expected: {expected_number}; Actual: {last_known_number}; Style: {style}"
if context.in_fix_mode:
self.register_fix_token_request(
context,
token,
"next_token",
"list_start_content",
str(expected_number),
)
last_known_number = expected_number
else:
self.report_next_token_error(
context, token, extra_error_information=extra_error_information
)
list_style, last_known_number = (None, None)
return list_style, last_known_number
if is_valid:
return list_style, last_known_number

return self.__report_invalid(
context, list_token, True, list_style, last_known_number, None
)

def __match_non_first_items(
self,
Expand All @@ -140,7 +125,8 @@ def __match_non_first_items(
) -> Tuple[Optional[str], Optional[int]]:
if list_style:
list_token = cast(ListStartMarkdownToken, token)
new_number: Optional[int] = int(list_token.list_start_content)
new_number: int = int(list_token.list_start_content)

# print(f"list_style={list_style},last_known_number={last_known_number},new_number={new_number}")
if list_style == RuleMd029.__one_or_ordered_style:
list_style = (
Expand All @@ -159,28 +145,60 @@ def __match_non_first_items(
assert last_known_number is not None
is_valid = new_number == last_known_number + 1
if not is_valid:
style, expected_number = self.__calculate_match_info(
list_style, False, last_known_number
)
extra_error_information = (
f"Expected: {expected_number}; Actual: {new_number}; Style: {style}"
return self.__report_invalid(
context,
list_token,
False,
list_style,
last_known_number,
new_number,
)
if context.in_fix_mode:
last_known_number = new_number
return list_style, last_known_number

# pylint: disable=too-many-arguments
def __report_invalid(
self,
context: PluginScanContext,
token: ListStartMarkdownToken,
initial_match: bool,
list_style: str,
last_known_number: Optional[int],
new_number: Optional[int],
) -> Tuple[Optional[str], Optional[int]]:
style, expected_number = self.__calculate_match_info(
list_style, initial_match, last_known_number
)
actual_number = last_known_number if new_number is None else new_number
extra_error_information = (
f"Expected: {expected_number}; Actual: {actual_number}; Style: {style}"
)
if context.in_fix_mode:
self.register_fix_token_request(
context,
token,
"next_token",
"list_start_content",
str(expected_number),
)
if not initial_match and new_number is not None:
expected_number_as_string = str(expected_number)
new_number_as_string = str(new_number)
if delta := len(expected_number_as_string) - len(new_number_as_string):
self.register_fix_token_request(
context,
token,
"next_token",
"list_start_content",
str(expected_number),
)
new_number = expected_number
else:
self.report_next_token_error(
context, token, extra_error_information=extra_error_information
"indent_level",
token.indent_level + delta,
)
list_style, new_number = (None, None)
last_known_number = new_number
return list_style, last_known_number
return list_style, expected_number
self.report_next_token_error(
context, token, extra_error_information=extra_error_information
)
return (None, None)

# pylint: enable=too-many-arguments

def next_token(self, context: PluginScanContext, token: MarkdownToken) -> None:
"""
Expand Down
98 changes: 98 additions & 0 deletions test/gfm/test_markdown_list_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4703,6 +4703,104 @@ def test_list_blocks_extra_6xc():
act_and_assert(source_markdown, expected_gfm, expected_tokens)


@pytest.mark.gfm
def test_list_blocks_extra_6xd():
"""
Test case 06: the sublist is properly idented, but the start is extra
indented to right justify the list
"""

# Arrange
source_markdown = """* First
* Second
* Third
"""
expected_tokens = [
"[ulist(1,1):*::2::]",
"[para(1,3):]",
"[text(1,3):First:]",
"[end-para:::True]",
"[ulist(2,3):*::4: ]",
"[para(2,5):]",
"[text(2,5):Second:]",
"[end-para:::True]",
"[end-ulist:::True]",
"[li(3,1):2::]",
"[para(3,3):]",
"[text(3,3):Third:]",
"[end-para:::True]",
"[BLANK(4,1):]",
"[end-ulist:::True]",
]
expected_gfm = """<ul>
<li>First
<ul>
<li>Second</li>
</ul>
</li>
<li>Third</li>
</ul>"""

# Act & Assert
act_and_assert(source_markdown, expected_gfm, expected_tokens)


@pytest.mark.gfm
def test_list_blocks_extra_6xe():
"""
Test case 06: the sublist is properly idented, but the start is extra
indented to right justify the list
"""

# Arrange
source_markdown = """ * First
first paragraph
* Second
second paragraph
* Third
"""
expected_tokens = [
"[ulist(1,2):*::4: : \n\n \n]",
"[para(1,5):\n]",
"[text(1,5):First\nfirst paragraph::\n]",
"[end-para:::True]",
"[BLANK(3,1):]",
"[ulist(4,5):*::7: :]",
"[para(4,8):]",
"[text(4,8):Second:]",
"[end-para:::True]",
"[BLANK(5,1):]",
"[end-ulist:::True]",
"[para(6,5):]",
"[text(6,5):second paragraph:]",
"[end-para:::True]",
"[li(7,2):4: :]",
"[para(7,5):]",
"[text(7,5):Third:]",
"[end-para:::True]",
"[BLANK(8,1):]",
"[end-ulist:::True]",
]
expected_gfm = """<ul>
<li>
<p>First
first paragraph</p>
<ul>
<li>Second</li>
</ul>
<p>second paragraph</p>
</li>
<li>
<p>Third</p>
</li>
</ul>"""

# Act & Assert
act_and_assert(source_markdown, expected_gfm, expected_tokens)


@pytest.mark.gfm
def test_list_blocks_extra_6ax():
"""
Expand Down
Loading

0 comments on commit 5962228

Please sign in to comment.