Skip to content

Commit 983460c

Browse files
committed
🧪 test(parser): fence handling for zendesk tags and ref defs
1 parent 81a6cd6 commit 983460c

2 files changed

Lines changed: 61 additions & 5 deletions

File tree

‎sdiff/parser.py‎

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
_HEADING_LINE_RE = re.compile(r'^(\s*)(#{1,6})(?!#)(?=\S)')
1414
_REF_LINK_OR_IMAGE_RE = re.compile(r'!?\[[^\]]+\]\s*\[[^\]]*\]')
1515
_REF_DEF_LINE_RE = re.compile(r'^\s{0,3}\[[^\]]+\]:\s+\S+')
16-
_FENCE_RE = re.compile(r'^\s*(```|~~~)')
16+
_FENCE_RE = re.compile(r'^\s*(`{3,}|~{3,})')
1717
_INLINE_MARKERS = {
1818
'strong': '**',
1919
'emphasis': '*',
@@ -293,8 +293,11 @@ def _find_next_tag(self, text: str):
293293
matches.append((match.start(), name, match))
294294
if not matches:
295295
return None, None
296-
_, name, match = min(matches, key=lambda item: item[0])
297-
return name, match
296+
matches.sort(key=lambda item: item[0])
297+
for _, name, match in matches:
298+
if not _is_inside_fenced_block(text, match.start()):
299+
return name, match
300+
return None, None
298301

299302
def _parse_markdown(self, text: str):
300303
normalized = _remove_spaces_from_empty_lines(text)
@@ -360,15 +363,20 @@ def _extract_reference_definitions(text: str):
360363
output = []
361364
definitions = {}
362365
fence = None
366+
fence_len = 0
363367
counter = 0
364368
for line in lines:
365369
fence_match = _FENCE_RE.match(line)
366370
if fence_match:
367371
marker = fence_match.group(1)
372+
marker_len = len(marker)
373+
marker_char = marker[0]
368374
if fence is None:
369-
fence = marker
370-
elif fence == marker:
375+
fence = marker_char
376+
fence_len = marker_len
377+
elif marker_char == fence and marker_len >= fence_len:
371378
fence = None
379+
fence_len = 0
372380
output.append(line)
373381
continue
374382

@@ -384,6 +392,28 @@ def _extract_reference_definitions(text: str):
384392
return '\n'.join(output), definitions
385393

386394

395+
def _is_inside_fenced_block(text: str, offset: int) -> bool:
396+
fence = None
397+
fence_len = 0
398+
running = 0
399+
for line in text.splitlines(True):
400+
line_len = len(line)
401+
if running + line_len > offset:
402+
return fence is not None
403+
fence_match = _FENCE_RE.match(line)
404+
if fence_match:
405+
marker = fence_match.group(1)
406+
marker_len = len(marker)
407+
if fence is None:
408+
fence = marker[0]
409+
fence_len = marker_len
410+
elif marker[0] == fence and marker_len >= fence_len:
411+
fence = None
412+
fence_len = 0
413+
running += line_len
414+
return False
415+
416+
387417
def _remove_spaces_from_empty_lines(text):
388418
return '\n'.join([re.sub(r'^( {1,}|\t{1,})$', '\n', line) for line in text.splitlines()])
389419

‎tests/test_parser.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ def test_reference_definition_inside_fence_is_text(self):
110110
tree = self._parse(data)
111111
self.assertEqual('pt', tree.print_all())
112112

113+
def test_reference_definition_inside_long_fence_is_text(self):
114+
data = """````
115+
[id]: https://example.com
116+
[link][id]
117+
````"""
118+
tree = self._parse(data)
119+
self.assertEqual('pt', tree.print_all())
120+
113121
def test_softbreak_preserves_space(self):
114122
actual = self._parse('hello\nworld')
115123
self.assertEqual('hello world', actual.nodes[0].nodes[0].text)
@@ -177,6 +185,24 @@ def test_inline_callout_is_structural(self):
177185
</callout> outro"""
178186
self._run_and_assert(fixture, 'ptC1tptpt')
179187

188+
def test_zendesk_tags_inside_fenced_code_are_text(self):
189+
fixture = """```
190+
<callout>
191+
# title
192+
content
193+
</callout>
194+
<steps>
195+
1. one
196+
</steps>
197+
<tabs>
198+
# tab
199+
content
200+
</tabs>
201+
```"""
202+
tree = self._parse(fixture)
203+
self.assertEqual('pt', tree.print_all())
204+
self.assertFalse(any(node.name in {'callout', 'steps', 'tabs'} for node in tree.nodes))
205+
180206
def test_steps(self):
181207
steps_fixture = """
182208
<steps>

0 commit comments

Comments
 (0)