Improved support of code fences for cmark 0.30.

This commit is contained in:
Franco Masotti 2022-01-24 23:58:48 +01:00
parent e264f1d8da
commit d516c0d6c3
Signed by: frnmst
GPG Key ID: 24116ED85666780A
2 changed files with 85 additions and 4 deletions

View File

@ -1243,8 +1243,22 @@ def is_opening_code_fence(line: str, parser: str = 'github'):
i += 1
info_string = line[info_string_start:len(line)]
# [0.29]
# The line with the opening code fence may optionally contain
# some text following the code fence; this is trimmed of leading
# and trailing whitespace and called the info string.
# [0.30]
# The line with the opening code fence may optionally contain
# some text following the code fence; this is trimmed of leading
# and trailing spaces or tabs and called the info string.
# This does not change the end result of this function.
if parser in ['github', 'commonmarker']:
spaces = ' '
else:
spaces = ' \u0009'
info_string = info_string.strip(spaces)
# Backticks or tildes in info string are explicitly forbidden
# Backticks or tildes in info strings are explicitly forbidden
# in a backtick-opened code fence, for Commonmark 0.29.
# This also solves example 107 [Commonmark 0.28]. See:
# https://github.github.com/gfm/#example-107
@ -1298,7 +1312,7 @@ def is_closing_code_fence(line: str,
return False
# Additional security.
fence = fence.rstrip('\n').rstrip(' ')
fence = fence.rstrip(' \n')
# Check that all fence characters are equal.
if fence != len(fence) * fence[0]:
return False
@ -1320,7 +1334,19 @@ def is_closing_code_fence(line: str,
if not line.startswith(fence):
return False
line = line.rstrip('\n').rstrip(' ')
# [0.29]
# The closing code fence may be indented up to three spaces, and may be
# followed only by spaces, which are ignored.
# [0.30]
# The closing code fence may be preceded by up to three spaces of
# indentation, and may be followed only by spaces or tabs,
# which are ignored.
if parser in ['github', 'commonmarker']:
spaces = ' '
else:
spaces = ' \u0009'
line = line.rstrip(spaces + '\n')
# Solves:
# example 93 -> 94 [Commonmark 0.28]
# example 94 -> 95 [Commonmark 0.29]

View File

@ -1969,18 +1969,47 @@ class TestApi(unittest.TestCase):
# example 112 [Commonmark 0.29].
# example 142 [Commonmark 0.30].
# Info string.
self.assertEqual(
api.is_opening_code_fence(BACKTICK3 + CMARK_INFO_STRING_FOO),
BACKTICK3)
self.assertEqual(
api.is_opening_code_fence(BACKTICK4 + CMARK_INFO_STRING_FOO),
BACKTICK4)
self.assertEqual(
api.is_opening_code_fence(BACKTICK10 + CMARK_INFO_STRING_FOO),
BACKTICK10)
self.assertEqual(
api.is_opening_code_fence(BACKTICK3 + S3 + CMARK_INFO_STRING_FOO),
BACKTICK3)
self.assertEqual(
api.is_opening_code_fence(BACKTICK3 + S3 + CMARK_INFO_STRING_FOO, 'cmark'),
BACKTICK3)
self.assertEqual(
api.is_opening_code_fence(BACKTICK3 + T3 + CMARK_INFO_STRING_FOO),
BACKTICK3)
self.assertEqual(
api.is_opening_code_fence(BACKTICK3 + T3 + CMARK_INFO_STRING_FOO, 'cmark'),
BACKTICK3)
self.assertEqual(
api.is_opening_code_fence(TILDE3 + CMARK_INFO_STRING_FOO), TILDE3)
self.assertEqual(
api.is_opening_code_fence(TILDE4 + CMARK_INFO_STRING_FOO), TILDE4)
self.assertEqual(
api.is_opening_code_fence(TILDE10 + CMARK_INFO_STRING_FOO),
TILDE10)
self.assertEqual(
api.is_opening_code_fence(TILDE3 + S3 + CMARK_INFO_STRING_FOO),
TILDE3)
self.assertEqual(
api.is_opening_code_fence(TILDE3 + S3 + CMARK_INFO_STRING_FOO, 'cmark'),
TILDE3)
self.assertEqual(
api.is_opening_code_fence(TILDE3 + T3 + CMARK_INFO_STRING_FOO),
TILDE3)
self.assertEqual(
api.is_opening_code_fence(TILDE3 + T3 + CMARK_INFO_STRING_FOO, 'cmark'),
TILDE3)
# Example 112 [Commonmark 0.28].
# Example 113 [Commonmark 0.29].
@ -2060,6 +2089,7 @@ class TestApi(unittest.TestCase):
# Example 96 [Commonmark 0.28].
# Example 97 [Commonmark 0.29].
# Example 127 [Commonmark 0.30].
# End of document.
self.assertTrue(
api.is_closing_code_fence(LINE_LINE_FEED + BACKTICK3 + LINE_LINE_FEED + 'aaa',
BACKTICK5, True))
@ -2071,7 +2101,10 @@ class TestApi(unittest.TestCase):
# Example 97 [Commonmark 0.28].
# Example 98 [Commonmark 0.29].
# Example 128 [Commonmark 0.30].
# not relevant because we don't have to find headings inside blockquotes.
# Not relevant because we don't have to find headings inside blockquotes.
# Example 129 -> 134 [Commonmark 0.30].
# See test_is_opening_code_fence.
# Example 104 [Commonmark 0.28].
# Example 105 [Commonmark 0.29].
@ -2107,6 +2140,9 @@ class TestApi(unittest.TestCase):
self.assertFalse(
api.is_closing_code_fence(BACKTICK3 + S1 + BACKTICK2, BACKTICK6))
# Example 140 -> 146 [Commonmark 0.30].
# See test_is_opening_code_fence.
# Example 115 [Commonmark 0.28].
# Example 117 [Commonmark 0.29].
# Example 147 [Commonmark 0.30].
@ -2116,6 +2152,25 @@ class TestApi(unittest.TestCase):
self.assertFalse(
api.is_closing_code_fence(TILDE3 + S1 + 'aaa', TILDE3))
# Extra examples for tabs [Commonmark 0.30].
self.assertTrue(
api.is_closing_code_fence(BACKTICK3 + T1, BACKTICK3, 'cmark'))
self.assertFalse(
api.is_closing_code_fence(BACKTICK3 + T1, BACKTICK3))
self.assertTrue(
api.is_closing_code_fence(BACKTICK3 + T4 + S4, BACKTICK3, 'cmark'))
self.assertFalse(
api.is_closing_code_fence(BACKTICK3 + T4 + S4, BACKTICK3))
self.assertTrue(
api.is_closing_code_fence(TILDE3 + T1, TILDE3, 'cmark'))
self.assertFalse(
api.is_closing_code_fence(TILDE3 + T4 + S4, TILDE3))
self.assertTrue(
api.is_closing_code_fence(TILDE3 + T1, TILDE3, 'cmark'))
self.assertFalse(
api.is_closing_code_fence(TILDE3 + T4 + S4, TILDE3))
@unittest.skip("empty test")
def test_init_indentation_status_list(self):
r"""Test building of the indentation data structure.