Skip to content

Commit 1b19f1f

Browse files
authored
Merge branch 'master' into fix-50--no-validate
2 parents e5809be + f568716 commit 1b19f1f

File tree

5 files changed

+60
-17
lines changed

5 files changed

+60
-17
lines changed

src/mdformat/_cli.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
from pathlib import Path
99
import shutil
1010
import sys
11-
import textwrap
1211

1312
import mdformat
1413
from mdformat._conf import DEFAULT_OPTS, InvalidConfError, read_toml_opts
15-
from mdformat._util import detect_newline_type, is_md_equal
14+
from mdformat._util import cached_textwrapper, detect_newline_type, is_md_equal
1615
import mdformat.plugins
1716
import mdformat.renderer
1817

@@ -418,9 +417,7 @@ def wrap_paragraphs(paragraphs: Iterable[str]) -> str:
418417
wrap_width = terminal_width
419418
else:
420419
wrap_width = 80
421-
wrapper = textwrap.TextWrapper(
422-
break_long_words=False, break_on_hyphens=False, width=wrap_width
423-
)
420+
wrapper = cached_textwrapper(wrap_width)
424421
return "\n\n".join(wrapper.fill(p) for p in paragraphs) + "\n"
425422

426423

src/mdformat/_util.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
from collections.abc import Iterable, Mapping
44
from contextlib import nullcontext
5+
import functools
56
import re
7+
import textwrap
68
from types import MappingProxyType
79
from typing import Any, Literal
810

@@ -45,6 +47,15 @@ def build_mdit(
4547
return mdit
4648

4749

50+
# Chars that markdown-it-py escapes when rendering code_inline:
51+
# https://github.com/executablebooks/markdown-it-py/blob/c5161b550f3c6c0a98d77e8389872405e8f9f9ee/markdown_it/common/utils.py#L138
52+
# Note that "&" is not included as it is used in the escape sequences of
53+
# these characters.
54+
_invalid_html_code_chars = '<>"'
55+
# a regex str that matches all except above chars
56+
_valid_html_code_char_re = rf"[^{re.escape(_invalid_html_code_chars)}]"
57+
58+
4859
def is_md_equal(
4960
md1: str,
5061
md2: str,
@@ -69,10 +80,11 @@ def is_md_equal(
6980
if codeformatters:
7081
langs_re = "|".join(re.escape(lang) for lang in codeformatters)
7182
html = re.sub(
72-
rf'<code class="language-(?:{langs_re})">.*</code>',
83+
rf'<code class="language-(?:{langs_re})">'
84+
rf"{_valid_html_code_char_re}*"
85+
r"</code>",
7386
"",
7487
html,
75-
flags=re.DOTALL,
7688
)
7789

7890
# Reduce all whitespace to a single space
@@ -114,3 +126,14 @@ def detect_newline_type(md: str, eol_setting: str) -> Literal["\n", "\r\n"]:
114126
if eol_setting == "crlf":
115127
return "\r\n"
116128
return "\n"
129+
130+
131+
@functools.lru_cache
132+
def cached_textwrapper(width: int) -> textwrap.TextWrapper:
133+
return textwrap.TextWrapper(
134+
break_long_words=False,
135+
break_on_hyphens=False,
136+
width=width,
137+
expand_tabs=False,
138+
replace_whitespace=False,
139+
)

src/mdformat/plugins.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import argparse
44
from collections.abc import Callable, Mapping
5-
from typing import Any, Protocol
5+
from typing import TYPE_CHECKING, Any, Protocol
66

77
from markdown_it import MarkdownIt
88

99
from mdformat._compat import importlib_metadata
10-
from mdformat.renderer.typing import Postprocess, Render
10+
11+
if TYPE_CHECKING:
12+
from mdformat.renderer.typing import Postprocess, Render
1113

1214

1315
def _load_entrypoints(

src/mdformat/renderer/_context.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
from contextlib import contextmanager
66
import logging
77
import re
8-
import textwrap
98
from types import MappingProxyType
109
from typing import TYPE_CHECKING, Any, Literal, NamedTuple
1110

1211
from markdown_it.rules_block.html_block import HTML_SEQUENCES
1312

1413
from mdformat import codepoints
1514
from mdformat._conf import DEFAULT_OPTS
15+
from mdformat._util import cached_textwrapper
1616
from mdformat.renderer._util import (
1717
RE_CHAR_REFERENCE,
1818
decimalify_leading,
@@ -344,13 +344,7 @@ def _wrap(text: str, *, width: int | Literal["no"]) -> str:
344344
if width == "no":
345345
return _recover_preserve_chars(text, replacements)
346346

347-
wrapper = textwrap.TextWrapper(
348-
break_long_words=False,
349-
break_on_hyphens=False,
350-
width=width,
351-
expand_tabs=False,
352-
replace_whitespace=False,
353-
)
347+
wrapper = cached_textwrapper(width)
354348
wrapped = wrapper.fill(text)
355349
wrapped = _recover_preserve_chars(wrapped, replacements)
356350
return wrapped

tests/test_util.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,30 @@ def test_is_md_equal():
2121
paragr"""
2222
assert not is_md_equal(md1, md2)
2323
assert is_md_equal(md1, md2, codeformatters=("js", "go"))
24+
25+
26+
def test_is_md_equal__not():
27+
md1 = """
28+
```js
29+
console.log()
30+
```
31+
32+
paragr
33+
34+
```js
35+
console.log()
36+
```
37+
"""
38+
md2 = """
39+
```js
40+
bonsole.l()g
41+
```
42+
43+
A different paragraph
44+
45+
```js
46+
console.log()
47+
```
48+
"""
49+
assert not is_md_equal(md1, md2)
50+
assert not is_md_equal(md1, md2, codeformatters=("js",))

0 commit comments

Comments
 (0)