diff --git a/docs/users/changelog.md b/docs/users/changelog.md index 49794ba..afc7b28 100644 --- a/docs/users/changelog.md +++ b/docs/users/changelog.md @@ -8,6 +8,9 @@ Note that there is currently no guarantee for a stable Markdown formatting style - Deprecated - Plugin interface: `mdformat.plugins.ParserExtensionInterface.add_cli_options`. The replacing interface is `mdformat.plugins.ParserExtensionInterface.add_cli_argument_group`. +- Fixed + - Incorrect line wrap on lines right after a hard break. + Thank you, [MDW](https://github.com/mdeweerd), for the issue. - Added - Plugin interface: `mdformat.plugins.ParserExtensionInterface.add_cli_argument_group`. With this plugins can now read CLI arguments merged with values from `.mdformat.toml`. diff --git a/src/mdformat/renderer/_context.py b/src/mdformat/renderer/_context.py index b9a4da7..89140b1 100644 --- a/src/mdformat/renderer/_context.py +++ b/src/mdformat/renderer/_context.py @@ -387,7 +387,14 @@ def paragraph(node: RenderTreeNode, context: RenderContext) -> str: # noqa: C90 if isinstance(wrap_mode, int): wrap_mode -= context.env["indent_width"] wrap_mode = max(1, wrap_mode) - text = _wrap(text, width=wrap_mode) + # Newlines should be mostly WRAP_POINTs by now, but there are + # exceptional newlines that need to be preserved: + # - hard breaks: newline defines the hard break + # - html inline: newline vs space can be the difference between + # html block and html inline + # Split the text and word wrap each section separately. + sections = text.split("\n") + text = "\n".join(_wrap(s, width=wrap_mode) for s in sections) # A paragraph can start or end in whitespace e.g. if the whitespace was # in decimal representation form. We need to re-decimalify it, one reason being diff --git a/tests/data/wrap_width_50.md b/tests/data/wrap_width_50.md index ec0d7c9..a75a155 100644 --- a/tests/data/wrap_width_50.md +++ b/tests/data/wrap_width_50.md @@ -134,3 +134,49 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa   No-wrap-points-until- Unicode whitespace shouldnt act as wrap point, the normal space should . + + +Hard break (issue #326) +. +Loremiiinoeffefe\ +ipsum dolor sit amet, consectetur adip elitismisun. + +Here's 50 chars including hardbreak backslashhhhh\ +ipsum dolor sit amet, consectetur adip elitismisun. + +Here's 50 chars before hardbreak backslash ggggggg\ +ipsum dolor sit amet, consectetur adip elitismisun. +. +Loremiiinoeffefe\ +ipsum dolor sit amet, consectetur adip +elitismisun. + +Here's 50 chars including hardbreak backslashhhhh\ +ipsum dolor sit amet, consectetur adip +elitismisun. + +Here's 50 chars before hardbreak backslash +ggggggg\ +ipsum dolor sit amet, consectetur adip +elitismisun. +. + + +Newline in HTML inline +. +There is no hard break here, only HTML inlineee ipsum dolor sit amet, consectetur adip elitismisun. + +sssssssssssssssssssssssssssssssssssss backslash ipsum dolor sit amet, consectetur adip elitismisun. +. +There is no hard break here, only HTML inlineee + ipsum dolor sit amet, consectetur adip +elitismisun. + +sssssssssssssssssssssssssssssssssssss backslash + ipsum dolor sit amet, consectetur adip +elitismisun. +. diff --git a/tests/test_cli.py b/tests/test_cli.py index 6c4870c..77c8824 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -241,7 +241,6 @@ def test_consecutive_wrap_width_lines(tmp_path): assert file_path.read_text() == text -@pytest.mark.xfail(reason="https://github.com/executablebooks/mdformat/issues/326") def test_wrap__hard_break(tmp_path): file_path = tmp_path / "test_markdown.md" file_path.write_text(