Skip to content

Commit 29a8d5e

Browse files
authored
🔀 MERGE: Synchronize with markdown-it v12.0.4 (#140)
Apply all relevant modifications in markdown-it/markdown-it@11.0.1...12.0.4
2 parents 09edd66 + 5417b21 commit 29a8d5e

22 files changed

+1067
-139
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ repos:
2828
hooks:
2929
- id: check-manifest
3030

31+
- repo: https://github.com/psf/black
32+
rev: 20.8b1
33+
hooks:
34+
- id: black
35+
3136
- repo: https://gitlab.com/pycqa/flake8
3237
rev: 3.8.4
3338
hooks:
3439
- id: flake8
3540
additional_dependencies: [flake8-bugbear==21.3.1]
3641

37-
- repo: https://github.com/psf/black
38-
rev: 20.8b1
39-
hooks:
40-
- id: black
41-
4242
- repo: https://github.com/pre-commit/mirrors-mypy
4343
rev: v0.790
4444
hooks:

markdown_it/common/html_blocks.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
"main",
4646
"menu",
4747
"menuitem",
48-
"meta",
4948
"nav",
5049
"noframes",
5150
"ol",

markdown_it/common/html_re.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>"
1919
comment = "<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->"
20-
processing = "<[?].*?[?]>"
20+
processing = "<[?][\\s\\S]*?[?]>"
2121
declaration = "<![A-Z]+\\s+[^>]*>"
2222
cdata = "<!\\[CDATA\\[[\\s\\S]*?\\]\\]>"
2323

markdown_it/helpers/parse_link_destination.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ def parseLinkDestination(string: str, pos: int, maximum: int) -> _Result:
2626
code = charCodeAt(string, pos)
2727
if code == 0x0A: # /* \n */)
2828
return result
29+
if code == 0x3C: # / * < * /
30+
return result
2931
if code == 0x3E: # /* > */) {
3032
result.pos = pos + 1
3133
result.str = unescapeAll(string[start + 1 : pos])
@@ -55,11 +57,15 @@ def parseLinkDestination(string: str, pos: int, maximum: int) -> _Result:
5557
break
5658

5759
if code == 0x5C and pos + 1 < maximum:
60+
if charCodeAt(string, pos + 1) == 0x20:
61+
break
5862
pos += 2
5963
continue
6064

6165
if code == 0x28: # /* ( */)
6266
level += 1
67+
if level > 32:
68+
return result
6369

6470
if code == 0x29: # /* ) */)
6571
if level == 0:

markdown_it/helpers/parse_link_title.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ def parseLinkTitle(string: str, pos: int, maximum: int) -> _Result:
4646
result.str = title
4747
result.ok = True
4848
return result
49+
elif code == 0x28 and marker == 0x29: # /* ( */ /* ) */
50+
return result
4951
elif code == 0x0A:
5052
lines += 1
5153
elif code == 0x5C and pos + 1 < maximum: # /* \ */

markdown_it/port.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
- package: markdown-it/markdown-it
2-
commit: 331ae117e09115366db12b517ca526b1b7fee1e8
3-
date: Sep 14, 2020
2+
version: 12.0.4
3+
commit: 7b8969ce5cb2edc54f2c1aa39a85a3a08076337d
4+
date: Dec 20, 2020
45
notes:
56
- Rename variables that use python built-in names, e.g.
67
- `max` -> `maximum`
@@ -39,3 +40,4 @@
3940
rather than `MarkdownIt.renderer.rules[name] = function`
4041
and renderers should declare a class property `__output__ = "html"`.
4142
This allows for extensability to more than just HTML renderers
43+
- inline tokens in tables are assigned a map (this is helpful for propagation to children)

markdown_it/renderer.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,22 +219,27 @@ def fence(self, tokens: Sequence[Token], idx: int, options, env) -> str:
219219
token = tokens[idx]
220220
info = unescapeAll(token.info).strip() if token.info else ""
221221
langName = ""
222+
langAttrs = ""
222223

223224
if info:
224225
langName = info.split()[0]
226+
arr = info.split(maxsplit=1)
227+
langName = arr[0]
228+
if len(arr) == 2:
229+
langAttrs = arr[1]
225230

226231
if options.highlight:
227-
highlighted = options.highlight(token.content, langName) or escapeHtml(
228-
token.content
229-
)
232+
highlighted = options.highlight(
233+
token.content, langName, langAttrs
234+
) or escapeHtml(token.content)
230235
else:
231236
highlighted = escapeHtml(token.content)
232237

233238
if highlighted.startswith("<pre"):
234239
return highlighted + "\n"
235240

236241
# If language exists, inject class gently, without modifying original token.
237-
# May be, one day we will add .clone() for token and simplify this part, but
242+
# May be, one day we will add .deepClone() for token and simplify this part, but
238243
# now we prefer to keep things local.
239244
if info:
240245
i = token.attrIndex("class")
@@ -243,6 +248,7 @@ def fence(self, tokens: Sequence[Token], idx: int, options, env) -> str:
243248
if i < 0:
244249
tmpAttrs.append(["class", options.langPrefix + langName])
245250
else:
251+
tmpAttrs[i] = tmpAttrs[i][:]
246252
tmpAttrs[i][1] += " " + options.langPrefix + langName
247253

248254
# Fake token just to render attributes

markdown_it/rules_block/table.py

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# GFM table, non-standard
1+
# GFM table, https://github.github.com/gfm/#tables-extension-
22
import re
33

44
from .state_block import StateBlock
@@ -10,7 +10,7 @@
1010

1111

1212
def getLine(state: StateBlock, line: int):
13-
pos = state.bMarks[line] + state.blkIndent
13+
pos = state.bMarks[line] + state.tShift[line]
1414
maximum = state.eMarks[line]
1515

1616
# return state.src.substr(pos, max - pos)
@@ -21,48 +21,35 @@ def escapedSplit(string):
2121
result = []
2222
pos = 0
2323
max = len(string)
24-
escapes = 0
24+
isEscaped = False
2525
lastPos = 0
26-
backTicked = False
27-
lastBackTick = 0
26+
current = ""
2827
ch = charCodeAt(string, pos)
2928

3029
while pos < max:
31-
if ch == 0x60: # /* ` */
32-
if backTicked:
33-
# make \` close code sequence, but not open it;
34-
# the reason is: `\` is correct code block
35-
backTicked = False
36-
lastBackTick = pos
37-
elif escapes % 2 == 0:
38-
backTicked = True
39-
lastBackTick = pos
40-
# /* | */
41-
elif ch == 0x7C and (escapes % 2 == 0) and not backTicked:
42-
result.append(string[lastPos:pos])
43-
lastPos = pos + 1
44-
45-
if ch == 0x5C: # /* \ */
46-
escapes += 1
47-
else:
48-
escapes = 0
30+
if ch == 0x7C: # /* | */
31+
if not isEscaped:
32+
# pipe separating cells, '|'
33+
result.append(current + string[lastPos:pos])
34+
current = ""
35+
lastPos = pos + 1
36+
else:
37+
# escaped pipe, '\|'
38+
current += string[lastPos : pos - 1]
39+
lastPos = pos
4940

41+
isEscaped = ch == 0x5C # /* \ */
5042
pos += 1
5143

52-
# If there was an un-closed backtick, go back to just after
53-
# the last backtick, but as if it was a normal character
54-
if pos == max and backTicked:
55-
backTicked = False
56-
pos = lastBackTick + 1
57-
5844
ch = charCodeAt(string, pos)
5945

60-
result.append(string[lastPos:])
46+
result.append(current + string[lastPos:])
6147

6248
return result
6349

6450

6551
def table(state: StateBlock, startLine: int, endLine: int, silent: bool):
52+
tbodyLines = None
6653

6754
# should have at least two lines
6855
if startLine + 2 > endLine:
@@ -129,17 +116,28 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool):
129116
return False
130117
if state.sCount[startLine] - state.blkIndent >= 4:
131118
return False
132-
columns = escapedSplit(enclosingPipesRe.sub("", lineText))
119+
columns = escapedSplit(lineText)
120+
if columns and columns[0] == "":
121+
columns.pop(0)
122+
if columns and columns[-1] == "":
123+
columns.pop()
133124

134125
# header row will define an amount of columns in the entire table,
135-
# and align row shouldn't be smaller than that (the rest of the rows can)
126+
# and align row should be exactly the same (the rest of the rows can differ)
136127
columnCount = len(columns)
137-
if columnCount > len(aligns):
128+
if columnCount == 0 or columnCount != len(aligns):
138129
return False
139130

140131
if silent:
141132
return True
142133

134+
oldParentType = state.parentType
135+
state.parentType = "table"
136+
137+
# use 'blockquote' lists for termination because it's
138+
# the most similar to tables
139+
terminatorRules = state.md.block.ruler.getRules("blockquote")
140+
143141
token = state.push("table_open", "table", 1)
144142
token.map = tableLines = [startLine, 0]
145143

@@ -151,43 +149,60 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool):
151149

152150
for i in range(len(columns)):
153151
token = state.push("th_open", "th", 1)
154-
token.map = [startLine, startLine + 1]
155152
if aligns[i]:
156153
token.attrs = [["style", "text-align:" + aligns[i]]]
157154

158155
token = state.push("inline", "", 0)
159-
token.content = columns[i].strip()
156+
# note in markdown-it this map was removed in v12.0.0 however, we keep it,
157+
# since it is helpful to propagate to children tokens
160158
token.map = [startLine, startLine + 1]
159+
token.content = columns[i].strip()
161160
token.children = []
162161

163162
token = state.push("th_close", "th", -1)
164163

165164
token = state.push("tr_close", "tr", -1)
166165
token = state.push("thead_close", "thead", -1)
167166

168-
token = state.push("tbody_open", "tbody", 1)
169-
token.map = tbodyLines = [startLine + 2, 0]
170-
171167
nextLine = startLine + 2
172168
while nextLine < endLine:
173169
if state.sCount[nextLine] < state.blkIndent:
174170
break
175171

172+
terminate = False
173+
for i in range(len(terminatorRules)):
174+
if terminatorRules[i](state, nextLine, endLine, True):
175+
terminate = True
176+
break
177+
178+
if terminate:
179+
break
176180
lineText = getLine(state, nextLine).strip()
177-
if "|" not in lineText:
181+
if not lineText:
178182
break
179183
if state.sCount[nextLine] - state.blkIndent >= 4:
180184
break
181-
columns = escapedSplit(enclosingPipesRe.sub("", lineText))
185+
columns = escapedSplit(lineText)
186+
if columns and columns[0] == "":
187+
columns.pop(0)
188+
if columns and columns[-1] == "":
189+
columns.pop()
190+
191+
if nextLine == startLine + 2:
192+
token = state.push("tbody_open", "tbody", 1)
193+
token.map = tbodyLines = [startLine + 2, 0]
182194

183195
token = state.push("tr_open", "tr", 1)
196+
token.map = [nextLine, nextLine + 1]
197+
184198
for i in range(columnCount):
185199
token = state.push("td_open", "td", 1)
186-
token.map = [nextLine, nextLine + 1]
187200
if aligns[i]:
188201
token.attrs = [["style", "text-align:" + aligns[i]]]
189202

190203
token = state.push("inline", "", 0)
204+
# note in markdown-it this map was removed in v12.0.0 however, we keep it,
205+
# since it is helpful to propagate to children tokens
191206
token.map = [nextLine, nextLine + 1]
192207
try:
193208
token.content = columns[i].strip() if columns[i] else ""
@@ -201,9 +216,13 @@ def table(state: StateBlock, startLine: int, endLine: int, silent: bool):
201216

202217
nextLine += 1
203218

204-
token = state.push("tbody_close", "tbody", -1)
219+
if tbodyLines:
220+
token = state.push("tbody_close", "tbody", -1)
221+
tbodyLines[1] = nextLine
222+
205223
token = state.push("table_close", "table", -1)
206224

207-
tableLines[1] = tbodyLines[1] = nextLine
225+
tableLines[1] = nextLine
226+
state.parentType = oldParentType
208227
state.line = nextLine
209228
return True

0 commit comments

Comments
 (0)