Repository: jackdewinter/pymarkdown

Issue:
Second line of maxed nested list has extra whitespace
Found during https://github.com/jackdewinter/pymarkdown/issues/250 :

second line should be:
```
        >       item
```
but is:
```
                >       item
```

Tests:
- test_nested_three_block_max_block_max_ordered_max_no_bq1
- test_nested_three_block_max_block_max_unordered_max_no_bq1

Discussion:

Patch:
diff --git a/changelog.md b/changelog.md
index 6bc024ca..714a09ca 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,7 +8,8 @@
 
 ### Changed
 
-- None
+- [Changed - Issue 248](https://github.com/jackdewinter/pymarkdown/issues/248)
+  - github actions: only run against `main` branch
 
 ### Fixed
 
@@ -17,6 +18,26 @@
 - [Fixed - Issue 218](https://github.com/jackdewinter/pymarkdown/issues/218)
   - parser: lot of small things needed fixing to set the variables properly for this issue's resolution
   - parser: after that, was not properly handling shutting down a block quote that downgraded
+- [Fixed - Issue 227](https://github.com/jackdewinter/pymarkdown/issues/227)
+  - scenario tests: adding 3-level nesting tests with max space, and max space plus one variations
+- [Fixed - Issue 228](https://github.com/jackdewinter/pymarkdown/issues/228)
+  - parser: previous adjustment no longer needed
+- [Fixed - Issue 229](https://github.com/jackdewinter/pymarkdown/issues/229)
+  - parser: generated HTML did not include indented code block
+- [Fixed - Issue 230](https://github.com/jackdewinter/pymarkdown/issues/230)
+  - parser: dropping leading `>`
+- [Fixed - Issue 231](https://github.com/jackdewinter/pymarkdown/issues/231)
+  - parser: fixed by issue-229
+- [Fixed - Issue 232](https://github.com/jackdewinter/pymarkdown/issues/232)
+  - parser: fixed by issue-233
+  - parser: fixed by issue-228
+- [Fixed - Issue 233](https://github.com/jackdewinter/pymarkdown/issues/233)
+  - parser: limiting container checking to limited set, expanded
+  - parser: extra indent was not accounted for in space calculations
+  - parser: double block quotes not being handled properly
+  - parser: indent being processed twice
+- [Fixed - Issue 252](https://github.com/jackdewinter/pymarkdown/issues/252)
+  - parser: in rare cases, was adding leading spaces to both list and paragraph within
 
 ## Version 0.9.4 - Date: 2022-01-04
 
diff --git a/publish/coverage.json b/publish/coverage.json
index 9056c0ef..d1a10eae 100644
--- a/publish/coverage.json
+++ b/publish/coverage.json
@@ -2,12 +2,12 @@
     "projectName": "pymarkdown",
     "reportSource": "pytest",
     "branchLevel": {
-        "totalMeasured": 3010,
-        "totalCovered": 3010
+        "totalMeasured": 3016,
+        "totalCovered": 3016
     },
     "lineLevel": {
-        "totalMeasured": 10521,
-        "totalCovered": 10521
+        "totalMeasured": 10534,
+        "totalCovered": 10534
     }
 }
 
diff --git a/pymarkdown/container_block_processor.py b/pymarkdown/container_block_processor.py
index f3dda39d..4a2d3341 100644
--- a/pymarkdown/container_block_processor.py
+++ b/pymarkdown/container_block_processor.py
@@ -138,7 +138,7 @@ class ContainerBlockProcessor:
             and len(extracted_whitespace) >= 4
             and is_not_in_root_list
         ):
-            # POGGER.debug("indent")
+            POGGER.debug("indent")
             (
                 can_continue,
                 line_to_parse,
@@ -153,10 +153,12 @@ class ContainerBlockProcessor:
                 last_list_start_index,
                 skip_containers_before_leaf_blocks,
                 indent_already_processed,
+                was_other_paragraph_continuation,
             ) = ContainerBlockProcessor.__handle_indented_block_start(
                 parser_state, position_marker
             )
         else:
+            was_other_paragraph_continuation = False
             (
                 can_continue,
                 container_level_tokens,
@@ -187,6 +189,10 @@ class ContainerBlockProcessor:
                 parser_properties,
             )
         # POGGER.debug("was_paragraph_continuation>>$", was_paragraph_continuation)
+        # POGGER.debug(
+        #     "was_other_paragraph_continuation>>$", was_other_paragraph_continuation
+        # )
+
         # POGGER.debug("line_to_parse>>$", line_to_parse)
         # POGGER.debug("start_index>>$", start_index)
 
@@ -215,11 +221,13 @@ class ContainerBlockProcessor:
                 was_paragraph_continuation,
                 skip_containers_before_leaf_blocks,
                 indent_already_processed,
+                container_depth,
             )
             # POGGER.debug(
             #     ">>was_paragraph_continuation>>:$:", was_paragraph_continuation
             # )
 
+        _ = was_other_paragraph_continuation
         return (
             container_level_tokens,
             line_to_parse,
@@ -279,11 +287,11 @@ class ContainerBlockProcessor:
             extracted_whitespace,
             is_para_continue,
         )
-        # POGGER.debug(
-        #     "skip_containers_before_leaf_blocks:$:", skip_containers_before_leaf_blocks
-        # )
-        # POGGER.debug("have_pre_processed_indent:$:", have_pre_processed_indent)
-        # POGGER.debug("indent_already_processed=$", indent_already_processed)
+        POGGER.debug(
+            "skip_containers_before_leaf_blocks:$:", skip_containers_before_leaf_blocks
+        )
+        POGGER.debug("have_pre_processed_indent:$:", have_pre_processed_indent)
+        POGGER.debug("indent_already_processed=$", indent_already_processed)
         if have_pre_processed_indent:
             (
                 can_continue,
@@ -815,6 +823,7 @@ class ContainerBlockProcessor:
             last_block_quote_index,
             last_list_start_index,
             indent_already_processed,
+            was_other_paragraph_continuation,
         ) = (
             True,
             position_marker.text_to_parse,
@@ -828,8 +837,10 @@ class ContainerBlockProcessor:
             -1,
             -1,
             False,
+            False,
         )
         POGGER.debug("was_paragraph_continuation>>$", was_paragraph_continuation)
+        POGGER.debug("parser_state.token_stack>>$", parser_state.token_stack)
         is_paragraph_continuation = (
             parser_state.token_stack and parser_state.token_stack[-1].is_paragraph
         )
@@ -839,6 +850,8 @@ class ContainerBlockProcessor:
         POGGER.debug("block_index>>$", block_index)
         if is_paragraph_continuation and block_index > list_index:
             was_paragraph_continuation = True
+        if is_paragraph_continuation and block_index < list_index:
+            was_other_paragraph_continuation = True
         POGGER.debug("was_paragraph_continuation>>$", was_paragraph_continuation)
         if (
             not is_paragraph_continuation
@@ -867,6 +880,7 @@ class ContainerBlockProcessor:
             last_list_start_index,
             False,
             indent_already_processed,
+            was_other_paragraph_continuation,
         )
 
     # pylint: enable=too-many-locals
@@ -1426,6 +1440,7 @@ class ContainerBlockProcessor:
         was_paragraph_continuation,
         skip_containers_before_leaf_blocks,
         indent_already_processed,
+        container_depth,
     ):
         # POGGER.debug("line_to_parse>>$", line_to_parse)
         # POGGER.debug("start_index>>$", start_index)
@@ -1465,6 +1480,7 @@ class ContainerBlockProcessor:
             was_paragraph_continuation,
             skip_containers_before_leaf_blocks,
             indent_already_processed,
+            container_depth,
         )
         parser_state.clear_after_leaf_processing()
 
@@ -2592,6 +2608,24 @@ class ContainerBlockProcessor:
         else:
             POGGER.debug("not adjust_for_inner_list_container")
 
+    @staticmethod
+    def __adjust_for_list_container_find(parser_state, xposition_marker):
+        found_list_token, document_index = (
+            None,
+            len(parser_state.token_document) - 1,
+        )
+        if (
+            document_index >= 0
+            and parser_state.token_document[document_index].line_number
+            == xposition_marker.line_number
+        ):
+            assert (
+                parser_state.token_document[document_index].is_list_start
+                or parser_state.token_document[document_index].is_new_list_item
+            )
+            found_list_token = parser_state.token_document[document_index]
+        return found_list_token
+
     # pylint: disable=too-many-arguments
     @staticmethod
     def __adjust_for_list_container(
@@ -2602,8 +2636,10 @@ class ContainerBlockProcessor:
         extracted_whitespace,
         xposition_marker,
         indent_already_processed,
+        container_depth,
     ):
         POGGER.debug("??? adjust_for_list_container")
+        removed_leading_space = None
         # pylint: disable=chained-comparison
         if (
             not indent_already_processed
@@ -2613,21 +2649,9 @@ class ContainerBlockProcessor:
         ):
             # pylint: enable=chained-comparison
             POGGER.debug("yes adjust_for_list_container")
-            found_list_token, document_index = (
-                None,
-                len(parser_state.token_document) - 1,
+            found_list_token = ContainerBlockProcessor.__adjust_for_list_container_find(
+                parser_state, xposition_marker
             )
-            while (
-                document_index >= 0
-                and parser_state.token_document[document_index].line_number
-                == xposition_marker.line_number
-            ):
-                assert (
-                    parser_state.token_document[document_index].is_list_start
-                    or parser_state.token_document[document_index].is_new_list_item
-                )
-                found_list_token = parser_state.token_document[document_index]
-                break
             # POGGER.debug("line_number>>:$:<", xposition_marker.line_number)
             # POGGER.debug("column_number>>:$:<", xposition_marker.index_number)
             # POGGER.debug("found_list_token>>:$:<", found_list_token)
@@ -2654,6 +2678,17 @@ class ContainerBlockProcessor:
                 parser_state.token_stack[
                     last_list_index
                 ].matching_markdown_token.add_leading_spaces(extracted_whitespace)
+
+                # POGGER.debug(
+                #     "xposition_marker($:$)>>$",
+                #     xposition_marker.index_number,
+                #     xposition_marker.index_indent,
+                #     xposition_marker.text_to_parse,
+                # )
+                # POGGER.debug("orig:$:", parser_state.original_line_to_parse)
+
+                if not container_depth and not xposition_marker.index_indent:
+                    removed_leading_space = extracted_whitespace
                 # POGGER.debug(
                 #     "plt-b>>last_block_token>>$",
                 #     parser_state.token_stack[last_list_index].matching_markdown_token,
@@ -2663,6 +2698,8 @@ class ContainerBlockProcessor:
                 # )
         else:
             POGGER.debug("not adjust_for_list_container")
+        # POGGER.debug("removed_leading_space:$:", removed_leading_space)
+        return removed_leading_space
 
     # pylint: enable=too-many-arguments
 
@@ -2880,8 +2917,8 @@ class ContainerBlockProcessor:
                 new_text_to_parse
             )
 
-            # POGGER.debug("new_text_to_parse>>:$:<", new_text_to_parse)
-            # POGGER.debug("new_index_indent>>:$:<", new_index_indent)
+            POGGER.debug("new_text_to_parse>>:$:<", new_text_to_parse)
+            POGGER.debug("new_index_indent>>:$:<", new_index_indent)
             text_removed_by_container = (
                 text_removed_by_container + prefix_text
                 if text_removed_by_container
@@ -2973,6 +3010,7 @@ class ContainerBlockProcessor:
         was_paragraph_continuation,
         skip_containers_before_leaf_blocks,
         indent_already_processed,
+        container_depth,
     ):
         assert not leaf_tokens
         POGGER.debug("parsing leaf>>")
@@ -2984,19 +3022,19 @@ class ContainerBlockProcessor:
             index_indent=xposition_marker.index_indent,
         )
 
-        POGGER.debug("ttp>>:$:<", xposition_marker.text_to_parse)
-        POGGER.debug("index_number>>:$:<", xposition_marker.index_number)
-        POGGER.debug("index_indent>>:$:<", xposition_marker.index_indent)
-        POGGER.debug("removed_chars_at_start>>:$:<", removed_chars_at_start)
+        # POGGER.debug("ttp>>:$:<", position_marker.text_to_parse)
+        # POGGER.debug("index_number>>:$:<", position_marker.index_number)
+        # POGGER.debug("index_indent>>:$:<", position_marker.index_indent)
+        # POGGER.debug("removed_chars_at_start>>:$:<", removed_chars_at_start)
 
         (
             new_index_number,
             extracted_whitespace,
-        ) = ParserHelper.extract_whitespace(xposition_marker.text_to_parse, 0)
-        POGGER.debug("new_index_number>>:$:<", new_index_number)
-        POGGER.debug("extracted_whitespace>>:$:<", extracted_whitespace)
-        POGGER.debug("text_removed_by_container>>:$:<", text_removed_by_container)
-        total_ws = new_index_number + xposition_marker.index_indent
+        ) = ParserHelper.extract_whitespace(position_marker.text_to_parse, 0)
+        # POGGER.debug("new_index_number>>:$:<", new_index_number)
+        # POGGER.debug("extracted_whitespace>>:$:<", extracted_whitespace)
+        # POGGER.debug("text_removed_by_container>>:$:<", text_removed_by_container)
+        total_ws = new_index_number + position_marker.index_indent
 
         last_block_index = parser_state.find_last_block_quote_on_stack()
         last_list_index = parser_state.find_last_list_block_on_stack()
@@ -3032,26 +3070,45 @@ class ContainerBlockProcessor:
             parser_state,
             last_block_index,
             last_list_index,
-            xposition_marker.line_number,
+            position_marker.line_number,
         )
 
-        ContainerBlockProcessor.__adjust_for_list_container(
+        removed_leading_space = ContainerBlockProcessor.__adjust_for_list_container(
             parser_state,
             last_block_index,
             last_list_index,
             text_removed_by_container,
             extracted_whitespace,
-            xposition_marker,
+            position_marker,
             indent_already_processed,
+            container_depth,
         )
+        # POGGER.debug("removed_leading_space:$:", removed_leading_space)
+        if removed_leading_space:
+            position_marker = PositionMarker(
+                position_marker.line_number,
+                len(removed_leading_space),
+                position_marker.text_to_parse,
+                index_indent=position_marker.index_indent,
+            )
 
-        if not close_tokens and not skip_containers_before_leaf_blocks:
+        # POGGER.debug(
+        #     "position_marker($:$)>>$",
+        #     position_marker.index_number,
+        #     position_marker.index_indent,
+        #     position_marker.text_to_parse,
+        # )
+        if (
+            not close_tokens
+            and not skip_containers_before_leaf_blocks
+            and not removed_leading_space
+        ):
             (
                 position_marker,
                 text_removed_by_container,
             ) = ContainerBlockProcessor.__adjust_containers_before_leaf_blocks(
                 parser_state,
-                xposition_marker,
+                position_marker,
                 was_paragraph_continuation,
                 last_block_index,
                 text_removed_by_container,
@@ -3088,7 +3145,7 @@ class ContainerBlockProcessor:
             parser_state,
             text_removed_by_container,
             orig_text_removed_by_container,
-            xposition_marker.line_number,
+            position_marker.line_number,
         )
 
         close_tokens.extend(leaf_tokens)


Test patch:
diff --git a/publish/test-results.json b/publish/test-results.json
index cd065c8b..89913953 100644
--- a/publish/test-results.json
+++ b/publish/test-results.json
@@ -471,7 +471,7 @@
             "totalTests": 174,
             "failedTests": 0,
             "errorTests": 0,
-            "skippedTests": 2,
+            "skippedTests": 0,
             "elapsedTimeInMilliseconds": 0
         },
         {
diff --git a/test/test_markdown_nested_three_block_block.py b/test/test_markdown_nested_three_block_block.py
index 1198ced0..2374083d 100644
--- a/test/test_markdown_nested_three_block_block.py
+++ b/test/test_markdown_nested_three_block_block.py
@@ -4517,7 +4517,6 @@ item</li>
 
 
 @pytest.mark.gfm
-@pytest.mark.skip
 def test_nested_three_block_max_block_max_unordered_max_no_bq1():
     """
     Verify that a nesting of block quote, block quote, unordered list, with
@@ -4532,7 +4531,7 @@ def test_nested_three_block_max_block_max_unordered_max_no_bq1():
         "[block-quote(1,4):   :   > ]",
         "[block-quote(1,9)::   >    > \n]",
         "[ulist(1,14):+::15:   :        ]",
-        "[para(1,16):\n        ]",
+        "[para(1,16):\n]",
         "[text(1,16):list\n\a>\a&gt;\a      item::\n]",
         "[end-para:::True]",
         "[end-ulist:::True]",
@@ -5010,7 +5009,6 @@ item</li>
 
 
 @pytest.mark.gfm
-@pytest.mark.skip
 def test_nested_three_block_max_block_max_ordered_max_no_bq1():
     """
     Verify that a nesting of block quote, block quote, ordered list, with
@@ -5025,7 +5023,7 @@ def test_nested_three_block_max_block_max_ordered_max_no_bq1():
         "[block-quote(1,4):   :   > ]",
         "[block-quote(1,9)::   >    > \n]",
         "[olist(1,14):.:1:16:   :        ]",
-        "[para(1,17):\n        ]",
+        "[para(1,17):\n]",
         "[text(1,17):list\n\a>\a&gt;\a       item::\n]",
         "[end-para:::True]",
         "[end-olist:::True]",
@@ -5042,7 +5040,7 @@ def test_nested_three_block_max_block_max_ordered_max_no_bq1():
 </blockquote>"""
 
     # Act & Assert
-    act_and_assert(source_markdown, expected_gfm, expected_tokens)
+    act_and_assert(source_markdown, expected_gfm, expected_tokens, show_debug=True)
 
 
 @pytest.mark.gfm