motion-markdown-it 11.0.0 → 12.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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('![test](http://example.com)')).to eq "<p><img src=\"LINK\" alt=\"test\"></p>\n"
|
304
|
+
# expect(md.render('![test](http://example.com)')).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
|