motion-markdown-it 11.0.0 → 12.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -13
- data/lib/motion-markdown-it/common/html_blocks.rb +1 -2
- data/lib/motion-markdown-it/common/html_re.rb +2 -2
- data/lib/motion-markdown-it/helpers/parse_link_destination.rb +3 -0
- data/lib/motion-markdown-it/helpers/parse_link_title.rb +3 -1
- data/lib/motion-markdown-it/index.rb +4 -3
- data/lib/motion-markdown-it/parser_block.rb +2 -2
- data/lib/motion-markdown-it/renderer.rb +12 -6
- data/lib/motion-markdown-it/rules_block/blockquote.rb +6 -7
- data/lib/motion-markdown-it/rules_block/code.rb +1 -1
- data/lib/motion-markdown-it/rules_block/html_block.rb +1 -1
- data/lib/motion-markdown-it/rules_block/list.rb +6 -2
- data/lib/motion-markdown-it/rules_block/table.rb +74 -47
- data/lib/motion-markdown-it/rules_core/smartquotes.rb +2 -2
- data/lib/motion-markdown-it/rules_inline/autolink.rb +17 -13
- data/lib/motion-markdown-it/rules_inline/backticks.rb +21 -3
- data/lib/motion-markdown-it/rules_inline/balance_pairs.rb +39 -17
- data/lib/motion-markdown-it/rules_inline/emphasis.rb +4 -11
- data/lib/motion-markdown-it/rules_inline/link.rb +2 -3
- data/lib/motion-markdown-it/rules_inline/newline.rb +7 -1
- data/lib/motion-markdown-it/rules_inline/state_inline.rb +7 -2
- data/lib/motion-markdown-it/rules_inline/strikethrough.rb +1 -2
- data/lib/motion-markdown-it/token.rb +5 -1
- data/lib/motion-markdown-it/version.rb +1 -1
- data/spec/motion-markdown-it/misc_spec.rb +60 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c31536746654ba78827fdf56f400de64e4b70bb1e459c7bbd610febaaf1074b3
|
4
|
+
data.tar.gz: 80e94ade9943fe02ce4c3b153ff002ddbaca3239d632f3cce74e4724182b7527
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f2566c0fcae8a7ee85f0c7be95440429c643dbc3e7d1d7b94b67bb5deeedbabb4553c81ba566db87087b5c058516420b0a9c45e29b85467baaa5875a7476fab
|
7
|
+
data.tar.gz: 89fe0c6e543efb1eb11f0186e346fbe31f2e714745ee8272ca75e953e1a6fb7796e19754d97fcc67d5b0d3e01fc8731a8a46a03ea8eaacb598e3e690a7720c27
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ Ruby/RubyMotion version of Markdown-it (CommonMark compliant and extendable)
|
|
7
7
|
|
8
8
|
This gem is a port of the [markdown-it Javascript package](https://github.com/markdown-it/markdown-it) by Vitaly Puzrin and Alex Kocharin.
|
9
9
|
|
10
|
-
_Currently synced with markdown-it
|
10
|
+
_Currently synced with markdown-it 12.3.2_
|
11
11
|
|
12
12
|
---
|
13
13
|
|
@@ -54,15 +54,14 @@ redcarpet 3.4.0 0.0065
|
|
54
54
|
|
55
55
|
## Table of content
|
56
56
|
|
57
|
-
- [
|
58
|
-
|
59
|
-
- [
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
- [License](#license)
|
57
|
+
- [Install](#install)
|
58
|
+
- [Usage examples](#usage-examples)
|
59
|
+
- [Simple](#simple)
|
60
|
+
- [Init with presets and options](#init-with-presets-and-options)
|
61
|
+
- [Plugins](#plugins)
|
62
|
+
- [Upgrading](#upgrading)
|
63
|
+
- [References / Thanks](#references--thanks)
|
64
|
+
- [License](#license)
|
66
65
|
|
67
66
|
<!--
|
68
67
|
- [API](#api)
|
@@ -134,6 +133,7 @@ parser = MarkdownIt::Parser.new({
|
|
134
133
|
linkify: false, # Autoconvert URL-like text to links
|
135
134
|
|
136
135
|
# Enable some language-neutral replacement + quotes beautification
|
136
|
+
# For the full list of replacements, see https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js
|
137
137
|
typographer: false,
|
138
138
|
|
139
139
|
# Double + single quotes replacement pairs, when typographer enabled,
|
@@ -185,7 +185,7 @@ var md = require('markdown-it')({
|
|
185
185
|
highlight: function (str, lang) {
|
186
186
|
if (lang && hljs.getLanguage(lang)) {
|
187
187
|
try {
|
188
|
-
return hljs.highlight(
|
188
|
+
return hljs.highlight(str, { language: lang }).value;
|
189
189
|
} catch (__) {}
|
190
190
|
}
|
191
191
|
|
@@ -205,7 +205,7 @@ var md = require('markdown-it')({
|
|
205
205
|
if (lang && hljs.getLanguage(lang)) {
|
206
206
|
try {
|
207
207
|
return '<pre class="hljs"><code>' +
|
208
|
-
hljs.highlight(
|
208
|
+
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
209
209
|
'</code></pre>';
|
210
210
|
} catch (__) {}
|
211
211
|
}
|
@@ -221,7 +221,7 @@ var md = require('markdown-it')({
|
|
221
221
|
configure linkify-it, access the linkify instance through `md.linkify`:
|
222
222
|
|
223
223
|
```js
|
224
|
-
md.linkify.
|
224
|
+
md.linkify.set({ fuzzyEmail: false }); // disables converting email to link
|
225
225
|
```
|
226
226
|
|
227
227
|
|
@@ -17,7 +17,7 @@ module MarkdownIt
|
|
17
17
|
|
18
18
|
CLOSE_TAG = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>'
|
19
19
|
COMMENT = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->'
|
20
|
-
PROCESSING = '<[?]
|
20
|
+
PROCESSING = '<[?][\\s\\S]*?[?]>'
|
21
21
|
DECLARATION = '<![A-Z]+\\s+[^>]*>'
|
22
22
|
CDATA = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>'
|
23
23
|
|
@@ -27,4 +27,4 @@ module MarkdownIt
|
|
27
27
|
HTML_OPEN_CLOSE_TAG_RE = Regexp.new('^(?:' + OPEN_TAG + '|' + CLOSE_TAG + ')')
|
28
28
|
end
|
29
29
|
end
|
30
|
-
end
|
30
|
+
end
|
@@ -16,6 +16,7 @@ module MarkdownIt
|
|
16
16
|
while (pos < max)
|
17
17
|
code = charCodeAt(str, pos)
|
18
18
|
return result if (code == 0x0A) # \n
|
19
|
+
return result if (code == 0x3C) # <
|
19
20
|
if (code == 0x3E) # >
|
20
21
|
result[:pos] = pos + 1
|
21
22
|
result[:str] = unescapeAll(str.slice((start + 1)...pos))
|
@@ -46,12 +47,14 @@ module MarkdownIt
|
|
46
47
|
break if (code < 0x20 || code == 0x7F)
|
47
48
|
|
48
49
|
if (code == 0x5C && pos + 1 < max) # \
|
50
|
+
break if (charCodeAt(str, pos + 1) == 0x20)
|
49
51
|
pos += 2
|
50
52
|
next
|
51
53
|
end
|
52
54
|
|
53
55
|
if (code == 0x28) # (
|
54
56
|
level += 1
|
57
|
+
return result if (level > 32)
|
55
58
|
end
|
56
59
|
|
57
60
|
if (code == 0x29) # )
|
@@ -29,6 +29,8 @@ module MarkdownIt
|
|
29
29
|
result[:str] = unescapeAll(str.slice((start + 1)...pos))
|
30
30
|
result[:ok] = true
|
31
31
|
return result
|
32
|
+
elsif (code == 0x28 && marker == 0x29) # ( and )
|
33
|
+
return result
|
32
34
|
elsif (code == 0x0A)
|
33
35
|
lines += 1
|
34
36
|
elsif (code == 0x5C && pos + 1 < max) # \
|
@@ -45,4 +47,4 @@ module MarkdownIt
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
end
|
48
|
-
end
|
50
|
+
end
|
@@ -69,7 +69,8 @@ NORMALIZE_LINK_TEXT = lambda do |url|
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
|
72
|
+
# add '%' to exclude list because of https://github.com/markdown-it/markdown-it/issues/720
|
73
|
+
return MDUrl::Decode.decode(MDUrl::Format.format(parsed), MDUrl::Decode::DEFTAULT_CHARS + '%')
|
73
74
|
end
|
74
75
|
|
75
76
|
|
@@ -189,7 +190,7 @@ module MarkdownIt
|
|
189
190
|
# highlight: function (str, lang) {
|
190
191
|
# if (lang && hljs.getLanguage(lang)) {
|
191
192
|
# try {
|
192
|
-
# return hljs.highlight(
|
193
|
+
# return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value;
|
193
194
|
# } catch (__) {}
|
194
195
|
# }
|
195
196
|
#
|
@@ -209,7 +210,7 @@ module MarkdownIt
|
|
209
210
|
# if (lang && hljs.getLanguage(lang)) {
|
210
211
|
# try {
|
211
212
|
# return '<pre class="hljs"><code>' +
|
212
|
-
# hljs.highlight(
|
213
|
+
# hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
213
214
|
# '</code></pre>';
|
214
215
|
# } catch (__) {}
|
215
216
|
# }
|
@@ -18,9 +18,9 @@ module MarkdownIt
|
|
18
18
|
[ 'hr', lambda { |state, startLine, endLine, silent| RulesBlock::Hr.hr(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
|
19
19
|
[ 'list', lambda { |state, startLine, endLine, silent| RulesBlock::List.list(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
|
20
20
|
[ 'reference', lambda { |state, startLine, endLine, silent| RulesBlock::Reference.reference(state, startLine, endLine, silent) } ],
|
21
|
+
[ 'html_block', lambda { |state, startLine, endLine, silent| RulesBlock::HtmlBlock.html_block(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
|
21
22
|
[ 'heading', lambda { |state, startLine, endLine, silent| RulesBlock::Heading.heading(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
|
22
23
|
[ 'lheading', lambda { |state, startLine, endLine, silent| RulesBlock::Lheading.lheading(state, startLine, endLine, silent) } ],
|
23
|
-
[ 'html_block', lambda { |state, startLine, endLine, silent| RulesBlock::HtmlBlock.html_block(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
|
24
24
|
[ 'paragraph', lambda { |state, startLine, endLine, silent| RulesBlock::Paragraph.paragraph(state, startLine) } ]
|
25
25
|
]
|
26
26
|
|
@@ -107,4 +107,4 @@ module MarkdownIt
|
|
107
107
|
end
|
108
108
|
|
109
109
|
end
|
110
|
-
end
|
110
|
+
end
|
@@ -35,13 +35,16 @@ module MarkdownIt
|
|
35
35
|
token = tokens[idx]
|
36
36
|
info = token.info ? unescapeAll(token.info).strip : ''
|
37
37
|
langName = ''
|
38
|
+
langAttrs = ''
|
38
39
|
|
39
40
|
if !info.empty?
|
40
|
-
|
41
|
+
arr = info.split(/\s+/)
|
42
|
+
langName = arr[0]
|
43
|
+
langAttrs = arr[1..-1].join(' ')
|
41
44
|
end
|
42
45
|
|
43
46
|
if options[:highlight]
|
44
|
-
highlighted = options[:highlight].call(token.content, langName) || escapeHtml(token.content)
|
47
|
+
highlighted = options[:highlight].call(token.content, langName, langAttrs) || escapeHtml(token.content)
|
45
48
|
else
|
46
49
|
highlighted = escapeHtml(token.content)
|
47
50
|
end
|
@@ -51,7 +54,7 @@ module MarkdownIt
|
|
51
54
|
end
|
52
55
|
|
53
56
|
# If language exists, inject class gently, without modifying original token.
|
54
|
-
# May be, one day we will add .
|
57
|
+
# May be, one day we will add .deepClone() for token and simplify this part, but
|
55
58
|
# now we prefer to keep things local.
|
56
59
|
if !info.empty?
|
57
60
|
i = token.attrIndex('class')
|
@@ -60,6 +63,7 @@ module MarkdownIt
|
|
60
63
|
if i < 0
|
61
64
|
tmpAttrs.push([ 'class', options[:langPrefix] + langName ])
|
62
65
|
else
|
66
|
+
tmpAttrs[i] = tmpAttrs[i].slice(0..-1)
|
63
67
|
tmpAttrs[i][1] += ' ' + options[:langPrefix] + langName
|
64
68
|
end
|
65
69
|
|
@@ -241,7 +245,7 @@ module MarkdownIt
|
|
241
245
|
|
242
246
|
|
243
247
|
# Renderer.renderInline(tokens, options, env) -> String
|
244
|
-
# - tokens (Array): list on block tokens to
|
248
|
+
# - tokens (Array): list on block tokens to render
|
245
249
|
# - options (Object): params of parser instance
|
246
250
|
# - env (Object): additional data from parsed input (references, for example)
|
247
251
|
#
|
@@ -267,7 +271,7 @@ module MarkdownIt
|
|
267
271
|
|
268
272
|
# internal
|
269
273
|
# Renderer.renderInlineAsText(tokens, options, env) -> String
|
270
|
-
# - tokens (Array): list on block tokens to
|
274
|
+
# - tokens (Array): list on block tokens to render
|
271
275
|
# - options (Object): params of parser instance
|
272
276
|
# - env (Object): additional data from parsed input (references, for example)
|
273
277
|
#
|
@@ -283,6 +287,8 @@ module MarkdownIt
|
|
283
287
|
result += tokens[i].content
|
284
288
|
elsif tokens[i].type == 'image'
|
285
289
|
result += renderInlineAsText(tokens[i].children, options, env)
|
290
|
+
elsif tokens[i].type == 'softbreak'
|
291
|
+
result += "\n"
|
286
292
|
end
|
287
293
|
end
|
288
294
|
|
@@ -291,7 +297,7 @@ module MarkdownIt
|
|
291
297
|
|
292
298
|
|
293
299
|
# Renderer.render(tokens, options, env) -> String
|
294
|
-
# - tokens (Array): list on block tokens to
|
300
|
+
# - tokens (Array): list on block tokens to render
|
295
301
|
# - options (Object): params of parser instance
|
296
302
|
# - env (Object): additional data from parsed input (references, for example)
|
297
303
|
#
|
@@ -22,8 +22,8 @@ module MarkdownIt
|
|
22
22
|
# so no point trying to find the end of it in silent mode
|
23
23
|
return true if silent
|
24
24
|
|
25
|
-
#
|
26
|
-
initial = offset = state.sCount[startLine] +
|
25
|
+
# set offset past spaces and ">"
|
26
|
+
initial = offset = state.sCount[startLine] + 1
|
27
27
|
|
28
28
|
# skip one optional space after '>'
|
29
29
|
if charCodeAt(state.src, pos) == 0x20 # space
|
@@ -88,7 +88,6 @@ module MarkdownIt
|
|
88
88
|
|
89
89
|
oldParentType = state.parentType
|
90
90
|
state.parentType = 'blockquote'
|
91
|
-
wasOutdented = false
|
92
91
|
|
93
92
|
# Search the end of the block
|
94
93
|
#
|
@@ -118,7 +117,7 @@ module MarkdownIt
|
|
118
117
|
# > current blockquote
|
119
118
|
# 2. checking this line
|
120
119
|
# ```
|
121
|
-
|
120
|
+
isOutdented = state.sCount[nextLine] < state.blkIndent
|
122
121
|
|
123
122
|
pos = state.bMarks[nextLine] + state.tShift[nextLine]
|
124
123
|
max = state.eMarks[nextLine]
|
@@ -128,12 +127,12 @@ module MarkdownIt
|
|
128
127
|
break
|
129
128
|
end
|
130
129
|
|
131
|
-
if charCodeAt(state.src, pos) == 0x3E && !
|
130
|
+
if charCodeAt(state.src, pos) == 0x3E && !isOutdented # >
|
132
131
|
pos += 1
|
133
132
|
# This line is inside the blockquote.
|
134
133
|
|
135
|
-
#
|
136
|
-
initial = offset = state.sCount[nextLine] +
|
134
|
+
# set offset past spaces and ">"
|
135
|
+
initial = offset = state.sCount[nextLine] + 1
|
137
136
|
|
138
137
|
# skip one optional space after '>'
|
139
138
|
if charCodeAt(state.src, pos) == 0x20 # space
|
@@ -26,7 +26,7 @@ module MarkdownIt
|
|
26
26
|
state.line = last
|
27
27
|
|
28
28
|
token = state.push('code_block', 'code', 0)
|
29
|
-
token.content = state.getLines(startLine, last, 4 + state.blkIndent,
|
29
|
+
token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + "\n"
|
30
30
|
token.map = [ startLine, state.line ]
|
31
31
|
return true
|
32
32
|
end
|
@@ -11,7 +11,7 @@ module MarkdownIt
|
|
11
11
|
# last argument defines whether it can terminate a paragraph or not
|
12
12
|
#
|
13
13
|
HTML_SEQUENCES = [
|
14
|
-
[ /^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true ],
|
14
|
+
[ /^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true ],
|
15
15
|
[ /^<!--/, /-->/, true ],
|
16
16
|
[ /^<\?/, /\?>/, true ],
|
17
17
|
[ /^<![A-Z]/, />/, true ],
|
@@ -129,7 +129,7 @@ module MarkdownIt
|
|
129
129
|
# This code can fail if plugins use blkIndent as well as lists,
|
130
130
|
# but I hope the spec gets fixed long before that happens.
|
131
131
|
#
|
132
|
-
if state.
|
132
|
+
if state.sCount[startLine] >= state.blkIndent
|
133
133
|
isTerminatingParagraph = true
|
134
134
|
end
|
135
135
|
end
|
@@ -138,7 +138,7 @@ module MarkdownIt
|
|
138
138
|
if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0)
|
139
139
|
isOrdered = true
|
140
140
|
start = state.bMarks[startLine] + state.tShift[startLine]
|
141
|
-
markerValue = state.src[start, posAfterMarker -
|
141
|
+
markerValue = state.src[start, posAfterMarker - 1].to_i
|
142
142
|
|
143
143
|
# If we're starting a new ordered list right after
|
144
144
|
# a paragraph, it should start with 1.
|
@@ -231,6 +231,9 @@ module MarkdownIt
|
|
231
231
|
token = state.push('list_item_open', 'li', 1)
|
232
232
|
token.markup = markerCharCode.chr
|
233
233
|
token.map = itemLines = [ startLine, 0 ]
|
234
|
+
if (isOrdered)
|
235
|
+
token.info = state.src.slice(start...posAfterMarker - 1)
|
236
|
+
end
|
234
237
|
|
235
238
|
# change current state, then restore it after parser subcall
|
236
239
|
oldTight = state.tight
|
@@ -307,6 +310,7 @@ module MarkdownIt
|
|
307
310
|
if (isOrdered)
|
308
311
|
posAfterMarker = skipOrderedListMarker(state, nextLine)
|
309
312
|
break if (posAfterMarker < 0)
|
313
|
+
start = state.bMarks[nextLine] + state.tShift[nextLine]
|
310
314
|
else
|
311
315
|
posAfterMarker = skipBulletListMarker(state, nextLine)
|
312
316
|
break if (posAfterMarker < 0)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# GFM table,
|
1
|
+
# GFM table, https://github.github.com/gfm/#tables-extension-
|
2
2
|
#------------------------------------------------------------------------------
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesBlock
|
@@ -7,7 +7,7 @@ module MarkdownIt
|
|
7
7
|
|
8
8
|
#------------------------------------------------------------------------------
|
9
9
|
def self.getLine(state, line)
|
10
|
-
pos = state.bMarks[line] + state.
|
10
|
+
pos = state.bMarks[line] + state.tShift[line]
|
11
11
|
max = state.eMarks[line]
|
12
12
|
|
13
13
|
return state.src[pos, max - pos]
|
@@ -18,51 +18,37 @@ module MarkdownIt
|
|
18
18
|
result = []
|
19
19
|
pos = 0
|
20
20
|
max = str.length
|
21
|
-
|
21
|
+
isEscaped = false
|
22
22
|
lastPos = 0
|
23
|
-
|
24
|
-
lastBackTick = 0
|
23
|
+
current = ''
|
25
24
|
|
26
25
|
ch = charCodeAt(str, pos)
|
27
26
|
|
28
27
|
while (pos < max)
|
29
|
-
if ch ==
|
30
|
-
if (
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
if ch == 0x7c # |
|
29
|
+
if (!isEscaped)
|
30
|
+
# pipe separating cells, '|'
|
31
|
+
result.push(current + str[lastPos...pos])
|
32
|
+
current = ''
|
33
|
+
lastPos = pos + 1
|
34
|
+
else
|
35
|
+
# escaped pipe, '\|'
|
36
|
+
current += str[lastPos...(pos - 1)]
|
37
|
+
lastPos = pos
|
38
38
|
end
|
39
|
-
elsif (ch == 0x7c && (escapes % 2 == 0) && !backTicked) # '|'
|
40
|
-
result.push(str[lastPos...pos])
|
41
|
-
lastPos = pos + 1
|
42
|
-
end
|
43
|
-
|
44
|
-
if ch == 0x5c # '\'
|
45
|
-
escapes += 1
|
46
|
-
else
|
47
|
-
escapes = 0
|
48
39
|
end
|
49
40
|
|
41
|
+
isEscaped = (ch == 0x5c) # '\'
|
50
42
|
pos += 1
|
51
|
-
|
52
|
-
|
53
|
-
if (pos == max && backTicked)
|
54
|
-
backTicked = false
|
55
|
-
pos = lastBackTick + 1
|
56
|
-
end
|
57
|
-
ch = charCodeAt(str, pos)
|
43
|
+
|
44
|
+
ch = charCodeAt(str, pos)
|
58
45
|
end
|
59
46
|
|
60
|
-
result.push(str[lastPos..-1])
|
47
|
+
result.push(current + str[lastPos..-1])
|
61
48
|
|
62
49
|
return result
|
63
50
|
end
|
64
51
|
|
65
|
-
|
66
52
|
#------------------------------------------------------------------------------
|
67
53
|
def self.table(state, startLine, endLine, silent)
|
68
54
|
# should have at least two lines
|
@@ -82,9 +68,19 @@ module MarkdownIt
|
|
82
68
|
pos = state.bMarks[nextLine] + state.tShift[nextLine]
|
83
69
|
return false if (pos >= state.eMarks[nextLine])
|
84
70
|
|
85
|
-
|
71
|
+
firstCh = charCodeAt(state.src, pos)
|
72
|
+
pos += 1
|
73
|
+
return false if (firstCh != 0x7C && firstCh != 0x2D && firstCh != 0x3A) # | or - or :
|
74
|
+
|
75
|
+
return false if (pos >= state.eMarks[nextLine])
|
76
|
+
|
77
|
+
secondCh = charCodeAt(state.src, pos)
|
86
78
|
pos += 1
|
87
|
-
return false if (
|
79
|
+
return false if (secondCh != 0x7C && secondCh != 0x2D && secondCh != 0x3A && !isSpace(secondCh)) # | or - or :
|
80
|
+
|
81
|
+
# if first character is '-', then second character must not be a space
|
82
|
+
# (due to parsing ambiguity with list)
|
83
|
+
return false if (firstCh === 0x2D && isSpace(secondCh)) # -
|
88
84
|
|
89
85
|
while pos < state.eMarks[nextLine]
|
90
86
|
ch = charCodeAt(state.src, pos)
|
@@ -122,15 +118,25 @@ module MarkdownIt
|
|
122
118
|
lineText = getLine(state, startLine).strip
|
123
119
|
return false if !lineText.include?('|')
|
124
120
|
return false if state.sCount[startLine] - state.blkIndent >= 4
|
125
|
-
columns = self.escapedSplit(lineText
|
121
|
+
columns = self.escapedSplit(lineText)
|
122
|
+
|
123
|
+
columns.shift if (columns.length && columns[0] == '')
|
124
|
+
columns.pop if (columns.length && columns[columns.length - 1] == '')
|
126
125
|
|
127
126
|
# header row will define an amount of columns in the entire table,
|
128
|
-
# and align row
|
127
|
+
# and align row should be exactly the same (the rest of the rows can differ)
|
129
128
|
columnCount = columns.length
|
130
|
-
return false if columnCount
|
129
|
+
return false if columnCount == 0 || columnCount != aligns.length
|
131
130
|
|
132
131
|
return true if silent
|
133
132
|
|
133
|
+
oldParentType = state.parentType
|
134
|
+
state.parentType = 'table'
|
135
|
+
|
136
|
+
# use 'blockquote' lists for termination because it's
|
137
|
+
# the most similar to tables
|
138
|
+
terminatorRules = state.md.block.ruler.getRules('blockquote')
|
139
|
+
|
134
140
|
token = state.push('table_open', 'table', 1)
|
135
141
|
token.map = tableLines = [ startLine, 0 ]
|
136
142
|
|
@@ -142,14 +148,12 @@ module MarkdownIt
|
|
142
148
|
|
143
149
|
(0...columns.length).each do |i|
|
144
150
|
token = state.push('th_open', 'th', 1)
|
145
|
-
token.map = [ startLine, startLine + 1 ]
|
146
151
|
unless aligns[i].empty?
|
147
152
|
token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ]
|
148
153
|
end
|
149
154
|
|
150
155
|
token = state.push('inline', '', 0)
|
151
156
|
token.content = columns[i].strip
|
152
|
-
token.map = [ startLine, startLine + 1 ]
|
153
157
|
token.children = []
|
154
158
|
|
155
159
|
token = state.push('th_close', 'th', -1)
|
@@ -158,21 +162,38 @@ module MarkdownIt
|
|
158
162
|
token = state.push('tr_close', 'tr', -1)
|
159
163
|
token = state.push('thead_close', 'thead', -1)
|
160
164
|
|
161
|
-
token = state.push('tbody_open', 'tbody', 1)
|
162
|
-
token.map = tbodyLines = [ startLine + 2, 0 ]
|
163
|
-
|
164
165
|
nextLine = startLine + 2
|
165
166
|
while nextLine < endLine
|
166
167
|
break if (state.sCount[nextLine] < state.blkIndent)
|
167
168
|
|
169
|
+
terminate = false
|
170
|
+
(0...terminatorRules.length).each do |i|
|
171
|
+
if (terminatorRules[i].call(state, nextLine, endLine, true))
|
172
|
+
terminate = true
|
173
|
+
break
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
break if (terminate)
|
178
|
+
|
168
179
|
lineText = getLine(state, nextLine).strip
|
169
|
-
break if
|
180
|
+
break if lineText.empty?
|
170
181
|
break if state.sCount[nextLine] - state.blkIndent >= 4
|
171
|
-
columns = self.escapedSplit(lineText
|
182
|
+
columns = self.escapedSplit(lineText)
|
183
|
+
columns.shift if (columns.length && columns[0] == '')
|
184
|
+
columns.pop if (columns.length && columns[columns.length - 1] == '')
|
185
|
+
|
186
|
+
if (nextLine == startLine + 2)
|
187
|
+
token = state.push('tbody_open', 'tbody', 1)
|
188
|
+
token.map = tbodyLines = [ startLine + 2, 0 ]
|
189
|
+
end
|
190
|
+
|
191
|
+
token = state.push('tr_open', 'tr', 1)
|
192
|
+
token.map = [ nextLine, nextLine + 1 ]
|
172
193
|
|
173
|
-
token = state.push('tr_open', 'tr', 1)
|
174
194
|
(0...columnCount).each do |i|
|
175
195
|
token = state.push('td_open', 'td', 1)
|
196
|
+
token.map = [ nextLine, nextLine + 1 ]
|
176
197
|
unless aligns[i].empty?
|
177
198
|
token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ]
|
178
199
|
end
|
@@ -186,10 +207,16 @@ module MarkdownIt
|
|
186
207
|
token = state.push('tr_close', 'tr', -1)
|
187
208
|
nextLine += 1
|
188
209
|
end
|
189
|
-
|
210
|
+
|
211
|
+
if (tbodyLines)
|
212
|
+
token = state.push('tbody_close', 'tbody', -1)
|
213
|
+
tbodyLines[1] = nextLine
|
214
|
+
end
|
215
|
+
|
190
216
|
token = state.push('table_close', 'table', -1)
|
217
|
+
tableLines[1] = nextLine
|
191
218
|
|
192
|
-
|
219
|
+
state.parentType = oldParentType
|
193
220
|
state.line = nextLine
|
194
221
|
return true
|
195
222
|
end
|
@@ -59,7 +59,7 @@ module MarkdownIt
|
|
59
59
|
else
|
60
60
|
(i - 1).downto(0) do |j|
|
61
61
|
break if tokens[j].type == 'softbreak' || tokens[j].type == 'hardbreak' # lastChar defaults to 0x20
|
62
|
-
next if tokens[j].
|
62
|
+
next if tokens[j].content.empty? # should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
63
63
|
|
64
64
|
lastChar = charCodeAt(tokens[j].content, tokens[j].content.length - 1)
|
65
65
|
break
|
@@ -76,7 +76,7 @@ module MarkdownIt
|
|
76
76
|
else
|
77
77
|
(i + 1).upto(tokens.length - 1) do |j|
|
78
78
|
break if tokens[j].type == 'softbreak' || tokens[j].type == 'hardbreak' # nextChar defaults to 0x20
|
79
|
-
next if tokens[j].
|
79
|
+
next if tokens[j].content.empty? # should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
80
80
|
|
81
81
|
nextChar = charCodeAt(tokens[j].content, 0)
|
82
82
|
break
|
@@ -5,8 +5,8 @@ module MarkdownIt
|
|
5
5
|
class Autolink
|
6
6
|
extend Common::Utils
|
7
7
|
|
8
|
-
EMAIL_RE =
|
9
|
-
AUTOLINK_RE =
|
8
|
+
EMAIL_RE = /^([a-zA-Z0-9.!#$\%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/
|
9
|
+
AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$/
|
10
10
|
|
11
11
|
#------------------------------------------------------------------------------
|
12
12
|
def self.autolink(state, silent)
|
@@ -14,14 +14,21 @@ module MarkdownIt
|
|
14
14
|
|
15
15
|
return false if (charCodeAt(state.src, pos) != 0x3C) # <
|
16
16
|
|
17
|
-
|
17
|
+
start = state.pos
|
18
|
+
max = state.posMax
|
18
19
|
|
19
|
-
|
20
|
+
loop do
|
21
|
+
return false if ((pos += 1) >= max)
|
20
22
|
|
21
|
-
|
22
|
-
linkMatch = tail.match(AUTOLINK_RE)
|
23
|
+
ch = charCodeAt(state.src, pos)
|
23
24
|
|
24
|
-
|
25
|
+
return false if (ch == 0x3C) # <
|
26
|
+
break if (ch == 0x3E) # >
|
27
|
+
end
|
28
|
+
|
29
|
+
url = state.src.slice((start + 1)...pos)
|
30
|
+
|
31
|
+
if (AUTOLINK_RE =~ url)
|
25
32
|
fullUrl = state.md.normalizeLink.call(url)
|
26
33
|
return false if (!state.md.validateLink.call(fullUrl))
|
27
34
|
|
@@ -39,14 +46,11 @@ module MarkdownIt
|
|
39
46
|
token.info = 'auto'
|
40
47
|
end
|
41
48
|
|
42
|
-
state.pos +=
|
49
|
+
state.pos += url.length + 2
|
43
50
|
return true
|
44
51
|
end
|
45
52
|
|
46
|
-
if (EMAIL_RE =~
|
47
|
-
emailMatch = tail.match(EMAIL_RE)
|
48
|
-
|
49
|
-
url = emailMatch[0].slice(1...-1)
|
53
|
+
if (EMAIL_RE =~ url)
|
50
54
|
fullUrl = state.md.normalizeLink.call('mailto:' + url)
|
51
55
|
return false if (!state.md.validateLink.call(fullUrl))
|
52
56
|
|
@@ -64,7 +68,7 @@ module MarkdownIt
|
|
64
68
|
token.info = 'auto'
|
65
69
|
end
|
66
70
|
|
67
|
-
state.pos +=
|
71
|
+
state.pos += url.length + 2
|
68
72
|
return true
|
69
73
|
end
|
70
74
|
|
@@ -16,22 +16,35 @@ module MarkdownIt
|
|
16
16
|
pos += 1
|
17
17
|
max = state.posMax
|
18
18
|
|
19
|
+
# scan marker length
|
19
20
|
while (pos < max && charCodeAt(state.src, pos) == 0x60) # `
|
20
21
|
pos += 1
|
21
22
|
end
|
22
23
|
|
23
24
|
marker = state.src.slice(start...pos)
|
25
|
+
openerLength = marker.length
|
26
|
+
|
27
|
+
if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start)
|
28
|
+
state.pending += marker if (!silent)
|
29
|
+
state.pos += openerLength
|
30
|
+
return true
|
31
|
+
end
|
24
32
|
|
25
33
|
matchStart = matchEnd = pos
|
26
34
|
|
35
|
+
# Nothing found in the cache, scan until the end of the line (or until marker is found)
|
27
36
|
while ((matchStart = state.src.index('`', matchEnd)) != nil)
|
28
37
|
matchEnd = matchStart + 1
|
29
38
|
|
39
|
+
# scan marker length
|
30
40
|
while (matchEnd < max && charCodeAt(state.src, matchEnd) == 0x60) # `
|
31
41
|
matchEnd += 1
|
32
42
|
end
|
33
43
|
|
34
|
-
|
44
|
+
closerLength = matchEnd - matchStart
|
45
|
+
|
46
|
+
if (closerLength == openerLength)
|
47
|
+
# Found matching closer length.
|
35
48
|
if (!silent)
|
36
49
|
token = state.push('code_inline', 'code', 0)
|
37
50
|
token.markup = marker
|
@@ -42,13 +55,18 @@ module MarkdownIt
|
|
42
55
|
state.pos = matchEnd
|
43
56
|
return true
|
44
57
|
end
|
58
|
+
|
59
|
+
# Some different length found, put it in cache as upper limit of where closer can be found
|
60
|
+
state.backticks[closerLength] = matchStart
|
45
61
|
end
|
46
62
|
|
63
|
+
# Scanned through the end, didn't find anything
|
64
|
+
state.backticksScanned = true
|
65
|
+
|
47
66
|
state.pending += marker if (!silent)
|
48
|
-
state.pos +=
|
67
|
+
state.pos += openerLength
|
49
68
|
return true
|
50
69
|
end
|
51
|
-
|
52
70
|
end
|
53
71
|
end
|
54
72
|
end
|
@@ -9,9 +9,28 @@ module MarkdownIt
|
|
9
9
|
openersBottom = {}
|
10
10
|
max = delimiters.length
|
11
11
|
|
12
|
+
return if (!max)
|
13
|
+
|
14
|
+
# headerIdx is the first delimiter of the current (where closer is) delimiter run
|
15
|
+
headerIdx = 0
|
16
|
+
lastTokenIdx = -2 # needs any value lower than -1
|
17
|
+
jumps = []
|
18
|
+
|
12
19
|
0.upto(max - 1) do |closerIdx|
|
13
20
|
closer = delimiters[closerIdx]
|
14
21
|
|
22
|
+
jumps.push(0)
|
23
|
+
|
24
|
+
# markers belong to same delimiter run if:
|
25
|
+
# - they have adjacent tokens
|
26
|
+
# - AND markers are the same
|
27
|
+
#
|
28
|
+
if (delimiters[headerIdx][:marker] != closer[:marker] || lastTokenIdx != closer[:token] - 1)
|
29
|
+
headerIdx = closerIdx
|
30
|
+
end
|
31
|
+
|
32
|
+
lastTokenIdx = closer[:token]
|
33
|
+
|
15
34
|
# Length is only used for emphasis-specific "rule of 3",
|
16
35
|
# if it's not defined (in strikethrough or 3rd party plugins),
|
17
36
|
# we can default it to 0 to disable those checks.
|
@@ -21,26 +40,25 @@ module MarkdownIt
|
|
21
40
|
next if (!closer[:close])
|
22
41
|
|
23
42
|
# Previously calculated lower bounds (previous fails)
|
24
|
-
# for each marker
|
43
|
+
# for each marker, each delimiter length modulo 3,
|
44
|
+
# and for whether this closer can be an opener;
|
45
|
+
# https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460
|
25
46
|
unless openersBottom[closer[:marker]]
|
26
|
-
openersBottom[closer[:marker]] = [ -1, -1, -1 ]
|
47
|
+
openersBottom[closer[:marker]] = [ -1, -1, -1, -1, -1, -1 ]
|
27
48
|
end
|
28
49
|
|
29
|
-
minOpenerIdx = openersBottom[closer[:marker]][closer[:length] % 3]
|
30
|
-
newMinOpenerIdx = -1
|
31
|
-
|
32
|
-
openerIdx = closerIdx - closer[:jump] - 1
|
50
|
+
minOpenerIdx = openersBottom[closer[:marker]][(closer[:open] ? 3 : 0) + (closer[:length] % 3)]
|
33
51
|
|
52
|
+
openerIdx = headerIdx - jumps[headerIdx] - 1
|
53
|
+
|
54
|
+
newMinOpenerIdx = openerIdx
|
55
|
+
|
34
56
|
while openerIdx > minOpenerIdx
|
35
57
|
opener = delimiters[openerIdx]
|
36
58
|
|
37
|
-
(openerIdx -=
|
38
|
-
|
39
|
-
newMinOpenerIdx = openerIdx if (newMinOpenerIdx == -1)
|
59
|
+
(openerIdx -= jumps[openerIdx] + 1) && next if (opener[:marker] != closer[:marker])
|
40
60
|
|
41
|
-
if (opener[:open] &&
|
42
|
-
opener[:end] < 0 &&
|
43
|
-
opener[:level] == closer[:level])
|
61
|
+
if (opener[:open] && opener[:end] < 0)
|
44
62
|
|
45
63
|
isOddMatch = false
|
46
64
|
|
@@ -65,19 +83,23 @@ module MarkdownIt
|
|
65
83
|
# sure algorithm has linear complexity (see *_*_*_*_*_... case).
|
66
84
|
#
|
67
85
|
lastJump = openerIdx > 0 && !delimiters[openerIdx - 1][:open] ?
|
68
|
-
|
86
|
+
jumps[openerIdx - 1] + 1 : 0
|
69
87
|
|
70
|
-
|
88
|
+
jumps[closerIdx] = closerIdx - openerIdx + lastJump
|
89
|
+
jumps[openerIdx] = lastJump
|
90
|
+
|
71
91
|
closer[:open] = false
|
72
92
|
opener[:end] = closerIdx
|
73
|
-
opener[:jump] = lastJump
|
74
93
|
opener[:close] = false
|
75
94
|
newMinOpenerIdx = -1
|
95
|
+
# treat next token as start of run,
|
96
|
+
# it optimizes skips in **<...>**a**<...>** pathological case
|
97
|
+
lastTokenIdx = -2
|
76
98
|
break
|
77
99
|
end
|
78
100
|
end
|
79
101
|
|
80
|
-
openerIdx -=
|
102
|
+
openerIdx -= jumps[openerIdx] + 1
|
81
103
|
end
|
82
104
|
|
83
105
|
if (newMinOpenerIdx != -1)
|
@@ -88,7 +110,7 @@ module MarkdownIt
|
|
88
110
|
# See details here:
|
89
111
|
# https://github.com/commonmark/cmark/issues/178#issuecomment-270417442
|
90
112
|
#
|
91
|
-
openersBottom[closer[:marker]][(closer[:length] || 0) % 3] = newMinOpenerIdx
|
113
|
+
openersBottom[closer[:marker]][(closer[:open] ? 3 : 0) + ((closer[:length] || 0) % 3)] = newMinOpenerIdx
|
92
114
|
end
|
93
115
|
end
|
94
116
|
end
|
@@ -30,15 +30,6 @@ module MarkdownIt
|
|
30
30
|
#
|
31
31
|
length: scanned[:length],
|
32
32
|
|
33
|
-
# An amount of characters before this one that's equivalent to
|
34
|
-
# current one. In plain English: if this delimiter does not open
|
35
|
-
# an emphasis, neither do previous `jump` characters.
|
36
|
-
#
|
37
|
-
# Used to skip sequences like "*****" in one step, for 1st asterisk
|
38
|
-
# value will be 0, for 2nd it's 1 and so on.
|
39
|
-
#
|
40
|
-
jump: i,
|
41
|
-
|
42
33
|
# A position of the token this delimiter corresponds to.
|
43
34
|
#
|
44
35
|
token: state.tokens.length - 1,
|
@@ -82,9 +73,11 @@ module MarkdownIt
|
|
82
73
|
#
|
83
74
|
isStrong = i > 0 &&
|
84
75
|
delimiters[i - 1][:end] == startDelim[:end] + 1 &&
|
76
|
+
# check that first two markers match and adjacent
|
77
|
+
delimiters[i - 1][:marker] == startDelim[:marker] &&
|
85
78
|
delimiters[i - 1][:token] == startDelim[:token] - 1 &&
|
86
|
-
|
87
|
-
delimiters[
|
79
|
+
# check that last two markers are adjacent (we can safely assume they match)
|
80
|
+
delimiters[startDelim[:end] + 1][:token] == endDelim[:token] + 1
|
88
81
|
|
89
82
|
ch = fromCodePoint(startDelim[:marker])
|
90
83
|
|
@@ -8,6 +8,7 @@ module MarkdownIt
|
|
8
8
|
#------------------------------------------------------------------------------
|
9
9
|
def self.link(state, silent)
|
10
10
|
href = ''
|
11
|
+
title = ''
|
11
12
|
oldPos = state.pos
|
12
13
|
max = state.posMax
|
13
14
|
start = state.pos
|
@@ -76,8 +77,6 @@ module MarkdownIt
|
|
76
77
|
break if (!isSpace(code) && code != 0x0A)
|
77
78
|
pos += 1
|
78
79
|
end
|
79
|
-
else
|
80
|
-
title = ''
|
81
80
|
end
|
82
81
|
|
83
82
|
if (pos >= max || charCodeAt(state.src, pos) != 0x29) # )
|
@@ -145,4 +144,4 @@ module MarkdownIt
|
|
145
144
|
|
146
145
|
end
|
147
146
|
end
|
148
|
-
end
|
147
|
+
end
|
@@ -20,7 +20,13 @@ module MarkdownIt
|
|
20
20
|
if !silent
|
21
21
|
if pmax >= 0 && charCodeAt(state.pending, pmax) == 0x20
|
22
22
|
if pmax >= 1 && charCodeAt(state.pending, pmax - 1) == 0x20
|
23
|
-
|
23
|
+
# Find whitespaces tail of pending chars.
|
24
|
+
ws = pmax - 1
|
25
|
+
while (ws >= 1 && charCodeAt(state.pending, ws - 1) == 0x20)
|
26
|
+
ws -= 1
|
27
|
+
end
|
28
|
+
|
29
|
+
state.pending = state.pending.slice(0...ws)
|
24
30
|
state.push('hardbreak', 'br', 0)
|
25
31
|
else
|
26
32
|
state.pending = state.pending.slice(0...-1)
|
@@ -5,8 +5,9 @@ module MarkdownIt
|
|
5
5
|
class StateInline
|
6
6
|
include MarkdownIt::Common::Utils
|
7
7
|
|
8
|
-
attr_accessor
|
9
|
-
attr_accessor
|
8
|
+
attr_accessor :src, :env, :md, :tokens, :pos, :posMax, :level, :tokens_meta
|
9
|
+
attr_accessor :pending, :pendingLevel, :cache, :delimiters
|
10
|
+
attr_accessor :backticks, :backticksScanned
|
10
11
|
|
11
12
|
#------------------------------------------------------------------------------
|
12
13
|
def initialize(src, md, env, outTokens)
|
@@ -31,6 +32,10 @@ module MarkdownIt
|
|
31
32
|
|
32
33
|
# Stack of delimiter lists for upper level tags
|
33
34
|
@_prev_delimiters = [];
|
35
|
+
|
36
|
+
# backtick length => last seen position
|
37
|
+
@backticks = {}
|
38
|
+
@backticksScanned = false
|
34
39
|
end
|
35
40
|
|
36
41
|
|
@@ -34,8 +34,7 @@ module MarkdownIt
|
|
34
34
|
|
35
35
|
state.delimiters.push({
|
36
36
|
marker: marker,
|
37
|
-
length: 0,
|
38
|
-
jump: i,
|
37
|
+
length: 0, # disable "rule of 3" length checks meant for emphasis
|
39
38
|
token: state.tokens.length - 1,
|
40
39
|
end: -1,
|
41
40
|
open: scanned[:can_open],
|
@@ -63,7 +63,11 @@ module MarkdownIt
|
|
63
63
|
|
64
64
|
# * Token#info -> String
|
65
65
|
# *
|
66
|
-
# *
|
66
|
+
# * Additional information:
|
67
|
+
# *
|
68
|
+
# * - Info string for "fence" tokens
|
69
|
+
# * - The value "auto" for autolink "link_open" and "link_close" tokens
|
70
|
+
# * - The string value of the item marker for ordered-list "list_item_open" tokens
|
67
71
|
@info = ''
|
68
72
|
|
69
73
|
# * Token#meta -> Object
|
@@ -48,7 +48,7 @@ describe 'API' do
|
|
48
48
|
#------------------------------------------------------------------------------
|
49
49
|
it 'highlight' do
|
50
50
|
md = MarkdownIt::Parser.new({
|
51
|
-
highlight: lambda do |str, obj|
|
51
|
+
highlight: lambda do |str, obj, attrs|
|
52
52
|
return '<pre><code>==' + str + '==</code></pre>'
|
53
53
|
end
|
54
54
|
})
|
@@ -58,12 +58,24 @@ describe 'API' do
|
|
58
58
|
|
59
59
|
#------------------------------------------------------------------------------
|
60
60
|
it 'highlight escape by default' do
|
61
|
-
md = MarkdownIt::Parser.new({highlight: lambda {|value, obj| return nil }})
|
61
|
+
md = MarkdownIt::Parser.new({highlight: lambda {|value, obj, attrs| return nil }})
|
62
62
|
|
63
|
-
# assert.strictEqual(md.render("```\n&\n```"), "<pre><code>&\n</code></pre>\n");
|
64
63
|
expect(md.render("```\n&\n```")).to eq "<pre><code>&\n</code></pre>\n"
|
65
64
|
end
|
66
65
|
|
66
|
+
#------------------------------------------------------------------------------
|
67
|
+
it 'highlight arguments' do
|
68
|
+
md = MarkdownIt::Parser.new({
|
69
|
+
highlight: lambda do |str, lang, attrs|
|
70
|
+
expect(lang).to eq 'a'
|
71
|
+
expect(attrs).to eq 'b c d'
|
72
|
+
return '<pre><code>==' + str + '==</code></pre>'
|
73
|
+
end
|
74
|
+
})
|
75
|
+
|
76
|
+
expect(md.render("``` a b c d \nhl\n```")).to eq"<pre><code>==hl\n==</code></pre>\n"
|
77
|
+
end
|
78
|
+
|
67
79
|
#------------------------------------------------------------------------------
|
68
80
|
it 'force hardbreaks' do
|
69
81
|
md = MarkdownIt::Parser.new({ breaks: false })
|
@@ -183,6 +195,9 @@ describe 'Misc' do
|
|
183
195
|
|
184
196
|
expect(md.render('123')).to eq "<p>123</p>\n"
|
185
197
|
expect(md.render("123\n")).to eq "<p>123</p>\n"
|
198
|
+
|
199
|
+
expect(md.render(' codeblock')).to eq "<pre><code>codeblock\n</code></pre>\n"
|
200
|
+
expect(md.render(" codeblock\n")).to eq "<pre><code>codeblock\n</code></pre>\n"
|
186
201
|
end
|
187
202
|
|
188
203
|
#------------------------------------------------------------------------------
|
@@ -281,12 +296,12 @@ describe 'Url normalization' do
|
|
281
296
|
return 'TEXT'
|
282
297
|
end
|
283
298
|
|
284
|
-
expect(md.render('foo@example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
285
|
-
expect(md.render('http://example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
286
|
-
expect(md.render('<foo@example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
287
|
-
expect(md.render('<http://example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
299
|
+
# expect(md.render('foo@example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
300
|
+
# expect(md.render('http://example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
301
|
+
# expect(md.render('<foo@example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
302
|
+
# expect(md.render('<http://example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
|
288
303
|
expect(md.render('[test](http://example.com)')).to eq "<p><a href=\"LINK\">test</a></p>\n"
|
289
|
-
expect(md.render('')).to eq "<p><img src=\"LINK\" alt=\"test\"></p>\n"
|
304
|
+
# expect(md.render('')).to eq "<p><img src=\"LINK\" alt=\"test\"></p>\n"
|
290
305
|
end
|
291
306
|
|
292
307
|
end
|
@@ -359,6 +374,42 @@ describe 'smartquotes' do
|
|
359
374
|
end
|
360
375
|
end
|
361
376
|
|
377
|
+
describe 'Ordered list info' do
|
378
|
+
md = MarkdownIt::Parser.new
|
379
|
+
|
380
|
+
def type_filter(tokens, type)
|
381
|
+
return tokens.select { |t| t.type === type }
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'Should mark ordered list item tokens with info' do
|
385
|
+
tokens = md.parse("1. Foo\n2. Bar\n20. Fuzz", {})
|
386
|
+
expect(type_filter(tokens, 'ordered_list_open').length).to eq 1
|
387
|
+
|
388
|
+
tokens = type_filter(tokens, 'list_item_open')
|
389
|
+
expect(tokens.length).to eq 3
|
390
|
+
expect(tokens[0].info).to eq '1'
|
391
|
+
expect(tokens[0].markup).to eq '.'
|
392
|
+
expect(tokens[1].info).to eq '2'
|
393
|
+
expect(tokens[1].markup).to eq '.'
|
394
|
+
expect(tokens[2].info).to eq '20'
|
395
|
+
expect(tokens[2].markup).to eq '.'
|
396
|
+
|
397
|
+
tokens = md.parse(" 1. Foo\n2. Bar\n 20. Fuzz\n 199. Flp", {})
|
398
|
+
expect(type_filter(tokens, 'ordered_list_open').length).to eq 1
|
399
|
+
|
400
|
+
tokens = type_filter(tokens, 'list_item_open')
|
401
|
+
expect(tokens.length).to eq 4
|
402
|
+
expect(tokens[0].info).to eq '1'
|
403
|
+
expect(tokens[0].markup).to eq '.'
|
404
|
+
expect(tokens[1].info).to eq '2'
|
405
|
+
expect(tokens[1].markup).to eq '.'
|
406
|
+
expect(tokens[2].info).to eq '20'
|
407
|
+
expect(tokens[2].markup).to eq '.'
|
408
|
+
expect(tokens[3].info).to eq '199'
|
409
|
+
expect(tokens[3].markup).to eq '.'
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
362
413
|
#------------------------------------------------------------------------------
|
363
414
|
describe 'Token attributes' do
|
364
415
|
|
@@ -403,4 +454,4 @@ describe 'Token attributes' do
|
|
403
454
|
|
404
455
|
expect(t.attrGet('myattr')).to eq 'myvalue'
|
405
456
|
end
|
406
|
-
end
|
457
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-markdown-it
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 12.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Walker
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-01-
|
13
|
+
date: 2023-01-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: mdurl-rb
|