motion-markdown-it 4.4.0 → 8.4.1
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 +69 -16
- data/lib/motion-markdown-it.rb +7 -5
- data/lib/motion-markdown-it/common/html_blocks.rb +6 -2
- data/lib/motion-markdown-it/common/utils.rb +19 -4
- data/lib/motion-markdown-it/helpers/helper_wrapper.rb +9 -0
- data/lib/motion-markdown-it/helpers/parse_link_destination.rb +8 -7
- data/lib/motion-markdown-it/index.rb +60 -18
- data/lib/motion-markdown-it/parser_block.rb +7 -10
- data/lib/motion-markdown-it/parser_inline.rb +50 -14
- data/lib/motion-markdown-it/presets/commonmark.rb +7 -1
- data/lib/motion-markdown-it/presets/default.rb +4 -3
- data/lib/motion-markdown-it/presets/zero.rb +6 -1
- data/lib/motion-markdown-it/renderer.rb +46 -14
- data/lib/motion-markdown-it/rules_block/blockquote.rb +167 -31
- data/lib/motion-markdown-it/rules_block/code.rb +4 -3
- data/lib/motion-markdown-it/rules_block/fence.rb +9 -4
- data/lib/motion-markdown-it/rules_block/heading.rb +8 -3
- data/lib/motion-markdown-it/rules_block/hr.rb +10 -5
- data/lib/motion-markdown-it/rules_block/html_block.rb +6 -3
- data/lib/motion-markdown-it/rules_block/lheading.rb +64 -26
- data/lib/motion-markdown-it/rules_block/list.rb +91 -22
- data/lib/motion-markdown-it/rules_block/paragraph.rb +14 -9
- data/lib/motion-markdown-it/rules_block/reference.rb +24 -14
- data/lib/motion-markdown-it/rules_block/state_block.rb +79 -24
- data/lib/motion-markdown-it/rules_block/table.rb +52 -26
- data/lib/motion-markdown-it/rules_core/normalize.rb +1 -23
- data/lib/motion-markdown-it/rules_core/replacements.rb +22 -2
- data/lib/motion-markdown-it/rules_core/smartquotes.rb +41 -12
- data/lib/motion-markdown-it/rules_inline/autolink.rb +5 -4
- data/lib/motion-markdown-it/rules_inline/balance_pairs.rb +48 -0
- data/lib/motion-markdown-it/rules_inline/emphasis.rb +104 -149
- data/lib/motion-markdown-it/rules_inline/entity.rb +2 -2
- data/lib/motion-markdown-it/rules_inline/escape.rb +5 -3
- data/lib/motion-markdown-it/rules_inline/image.rb +12 -23
- data/lib/motion-markdown-it/rules_inline/link.rb +20 -25
- data/lib/motion-markdown-it/rules_inline/newline.rb +2 -1
- data/lib/motion-markdown-it/rules_inline/state_inline.rb +60 -1
- data/lib/motion-markdown-it/rules_inline/strikethrough.rb +81 -97
- data/lib/motion-markdown-it/rules_inline/text_collapse.rb +40 -0
- data/lib/motion-markdown-it/token.rb +46 -1
- data/lib/motion-markdown-it/version.rb +1 -1
- data/spec/motion-markdown-it/markdown_it_spec.rb +2 -2
- data/spec/motion-markdown-it/misc_spec.rb +90 -14
- data/spec/motion-markdown-it/testgen_helper.rb +1 -1
- data/spec/spec_helper.rb +2 -3
- metadata +13 -13
- data/lib/motion-markdown-it/common/url_schemas.rb +0 -173
- data/spec/motion-markdown-it/bench_mark_spec.rb +0 -44
@@ -4,7 +4,7 @@ module MarkdownIt
|
|
4
4
|
module RulesInline
|
5
5
|
class Entity
|
6
6
|
extend Common::Utils
|
7
|
-
|
7
|
+
|
8
8
|
DIGITAL_RE = /^&#((?:x[a-f0-9]{1,8}|[0-9]{1,8}));/i
|
9
9
|
NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i
|
10
10
|
|
@@ -33,7 +33,7 @@ module MarkdownIt
|
|
33
33
|
match = state.src.slice_to_end(pos).match(NAMED_RE)
|
34
34
|
if match
|
35
35
|
if HTMLEntities::MAPPINGS[match[1]]
|
36
|
-
state.pending += HTMLEntities::MAPPINGS[match[1]]
|
36
|
+
state.pending += fromCodePoint(HTMLEntities::MAPPINGS[match[1]]) if !silent
|
37
37
|
state.pos += match[0].length
|
38
38
|
return true
|
39
39
|
end
|
@@ -1,8 +1,9 @@
|
|
1
|
-
#
|
1
|
+
# Process escaped chars and hardbreaks
|
2
2
|
#------------------------------------------------------------------------------
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesInline
|
5
5
|
class Escape
|
6
|
+
extend Common::Utils
|
6
7
|
|
7
8
|
ESCAPED = []
|
8
9
|
|
@@ -36,7 +37,9 @@ module MarkdownIt
|
|
36
37
|
|
37
38
|
pos += 1
|
38
39
|
# skip leading whitespaces from next line
|
39
|
-
while
|
40
|
+
while pos < max
|
41
|
+
ch = state.src.charCodeAt(pos)
|
42
|
+
break if !isSpace(ch)
|
40
43
|
pos += 1
|
41
44
|
end
|
42
45
|
|
@@ -49,7 +52,6 @@ module MarkdownIt
|
|
49
52
|
state.pos += 1
|
50
53
|
return true
|
51
54
|
end
|
52
|
-
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -3,9 +3,6 @@
|
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesInline
|
5
5
|
class Image
|
6
|
-
extend Helpers::ParseLinkDestination
|
7
|
-
extend Helpers::ParseLinkLabel
|
8
|
-
extend Helpers::ParseLinkTitle
|
9
6
|
extend Common::Utils
|
10
7
|
|
11
8
|
#------------------------------------------------------------------------------
|
@@ -18,7 +15,7 @@ module MarkdownIt
|
|
18
15
|
return false if (state.src.charCodeAt(state.pos + 1) != 0x5B) # [
|
19
16
|
|
20
17
|
labelStart = state.pos + 2
|
21
|
-
labelEnd = parseLinkLabel(state, state.pos + 1, false)
|
18
|
+
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false)
|
22
19
|
|
23
20
|
# parser failed to find ']', so it's not a valid link
|
24
21
|
return false if (labelEnd < 0)
|
@@ -34,7 +31,7 @@ module MarkdownIt
|
|
34
31
|
pos += 1
|
35
32
|
while pos < max
|
36
33
|
code = state.src.charCodeAt(pos)
|
37
|
-
break if (code
|
34
|
+
break if (!isSpace(code) && code != 0x0A)
|
38
35
|
pos += 1
|
39
36
|
end
|
40
37
|
return false if (pos >= max)
|
@@ -42,7 +39,7 @@ module MarkdownIt
|
|
42
39
|
# [link]( <href> "title" )
|
43
40
|
# ^^^^^^ parsing link destination
|
44
41
|
start = pos
|
45
|
-
res = parseLinkDestination(state.src, pos, state.posMax)
|
42
|
+
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax)
|
46
43
|
if (res[:ok])
|
47
44
|
href = state.md.normalizeLink.call(res[:str])
|
48
45
|
if (state.md.validateLink.call(href))
|
@@ -57,13 +54,13 @@ module MarkdownIt
|
|
57
54
|
start = pos
|
58
55
|
while pos < max
|
59
56
|
code = state.src.charCodeAt(pos)
|
60
|
-
break if (code
|
57
|
+
break if (!isSpace(code) && code != 0x0A)
|
61
58
|
pos += 1
|
62
59
|
end
|
63
60
|
|
64
61
|
# [link]( <href> "title" )
|
65
62
|
# ^^^^^^^ parsing link title
|
66
|
-
res = parseLinkTitle(state.src, pos, state.posMax)
|
63
|
+
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax)
|
67
64
|
if (pos < max && start != pos && res[:ok])
|
68
65
|
title = res[:str]
|
69
66
|
pos = res[:pos]
|
@@ -72,7 +69,7 @@ module MarkdownIt
|
|
72
69
|
# ^^ skipping these spaces
|
73
70
|
while pos < max
|
74
71
|
code = state.src.charCodeAt(pos);
|
75
|
-
break if (code
|
72
|
+
break if (!isSpace(code) && code != 0x0A)
|
76
73
|
pos += 1
|
77
74
|
end
|
78
75
|
else
|
@@ -90,17 +87,9 @@ module MarkdownIt
|
|
90
87
|
#
|
91
88
|
return false if state.env[:references].nil?
|
92
89
|
|
93
|
-
# [foo] [bar]
|
94
|
-
# ^^ optional whitespace (can include newlines)
|
95
|
-
while pos < max
|
96
|
-
code = state.src.charCodeAt(pos)
|
97
|
-
break if (code != 0x20 && code != 0x0A)
|
98
|
-
pos += 1
|
99
|
-
end
|
100
|
-
|
101
90
|
if (pos < max && state.src.charCodeAt(pos) == 0x5B) # [
|
102
91
|
start = pos + 1
|
103
|
-
pos = parseLinkLabel(state, pos)
|
92
|
+
pos = state.md.helpers.parseLinkLabel(state, pos)
|
104
93
|
if (pos >= 0)
|
105
94
|
label = state.src.slice(start...pos)
|
106
95
|
pos += 1
|
@@ -129,20 +118,20 @@ module MarkdownIt
|
|
129
118
|
# so all that's left to do is to call tokenizer.
|
130
119
|
#
|
131
120
|
if (!silent)
|
132
|
-
state.
|
133
|
-
state.posMax = labelEnd
|
121
|
+
content = state.src.slice(labelStart...labelEnd)
|
134
122
|
|
135
|
-
|
136
|
-
|
123
|
+
state.md.inline.parse(
|
124
|
+
content,
|
137
125
|
state.md,
|
138
126
|
state.env,
|
139
127
|
tokens = []
|
140
128
|
)
|
141
|
-
newState.md.inline.tokenize(newState)
|
142
129
|
|
143
130
|
token = state.push('image', 'img', 0)
|
144
131
|
token.attrs = attrs = [ [ 'src', href ], [ 'alt', '' ] ]
|
145
132
|
token.children = tokens
|
133
|
+
token.content = content;
|
134
|
+
|
146
135
|
unless (title.nil? || title.empty?)
|
147
136
|
attrs.push([ 'title', title ])
|
148
137
|
end
|
@@ -3,22 +3,20 @@
|
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesInline
|
5
5
|
class Link
|
6
|
-
extend Helpers::ParseLinkDestination
|
7
|
-
extend Helpers::ParseLinkLabel
|
8
|
-
extend Helpers::ParseLinkTitle
|
9
6
|
extend Common::Utils
|
10
7
|
|
11
8
|
#------------------------------------------------------------------------------
|
12
9
|
def self.link(state, silent)
|
13
|
-
href
|
14
|
-
oldPos
|
15
|
-
max
|
16
|
-
start
|
10
|
+
href = ''
|
11
|
+
oldPos = state.pos
|
12
|
+
max = state.posMax
|
13
|
+
start = state.pos
|
14
|
+
parseReference = true
|
17
15
|
|
18
16
|
return false if (state.src.charCodeAt(state.pos) != 0x5B) # [
|
19
17
|
|
20
18
|
labelStart = state.pos + 1
|
21
|
-
labelEnd = parseLinkLabel(state, state.pos, true)
|
19
|
+
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true)
|
22
20
|
|
23
21
|
# parser failed to find ']', so it's not a valid link
|
24
22
|
return false if (labelEnd < 0)
|
@@ -29,12 +27,15 @@ module MarkdownIt
|
|
29
27
|
# Inline link
|
30
28
|
#
|
31
29
|
|
30
|
+
# might have found a valid shortcut link, disable reference parsing
|
31
|
+
parseReference = false
|
32
|
+
|
32
33
|
# [link]( <href> "title" )
|
33
34
|
# ^^ skipping these spaces
|
34
35
|
pos += 1
|
35
36
|
while pos < max
|
36
37
|
code = state.src.charCodeAt(pos)
|
37
|
-
break if (code
|
38
|
+
break if (!isSpace(code) && code != 0x0A)
|
38
39
|
pos += 1
|
39
40
|
end
|
40
41
|
return false if (pos >= max)
|
@@ -42,7 +43,7 @@ module MarkdownIt
|
|
42
43
|
# [link]( <href> "title" )
|
43
44
|
# ^^^^^^ parsing link destination
|
44
45
|
start = pos
|
45
|
-
res = parseLinkDestination(state.src, pos, state.posMax)
|
46
|
+
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax)
|
46
47
|
if (res[:ok])
|
47
48
|
href = state.md.normalizeLink.call(res[:str])
|
48
49
|
if (state.md.validateLink.call(href))
|
@@ -57,13 +58,13 @@ module MarkdownIt
|
|
57
58
|
start = pos
|
58
59
|
while pos < max
|
59
60
|
code = state.src.charCodeAt(pos)
|
60
|
-
break if (code
|
61
|
+
break if (!isSpace(code) && code != 0x0A)
|
61
62
|
pos += 1
|
62
63
|
end
|
63
64
|
|
64
65
|
# [link]( <href> "title" )
|
65
66
|
# ^^^^^^^ parsing link title
|
66
|
-
res = parseLinkTitle(state.src, pos, state.posMax)
|
67
|
+
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax)
|
67
68
|
if (pos < max && start != pos && res[:ok])
|
68
69
|
title = res[:str]
|
69
70
|
pos = res[:pos]
|
@@ -72,7 +73,7 @@ module MarkdownIt
|
|
72
73
|
# ^^ skipping these spaces
|
73
74
|
while pos < max
|
74
75
|
code = state.src.charCodeAt(pos)
|
75
|
-
break if (code
|
76
|
+
break if (!isSpace(code) && code != 0x0A)
|
76
77
|
pos += 1
|
77
78
|
end
|
78
79
|
else
|
@@ -80,27 +81,21 @@ module MarkdownIt
|
|
80
81
|
end
|
81
82
|
|
82
83
|
if (pos >= max || state.src.charCodeAt(pos) != 0x29) # )
|
83
|
-
|
84
|
-
|
84
|
+
# parsing a valid shortcut link failed, fallback to reference
|
85
|
+
parseReference = true
|
85
86
|
end
|
86
87
|
pos += 1
|
87
|
-
|
88
|
+
end
|
89
|
+
|
90
|
+
if parseReference
|
88
91
|
#
|
89
92
|
# Link reference
|
90
93
|
#
|
91
94
|
return false if state.env[:references].nil?
|
92
95
|
|
93
|
-
# [foo] [bar]
|
94
|
-
# ^^ optional whitespace (can include newlines)
|
95
|
-
while pos < max
|
96
|
-
code = state.src.charCodeAt(pos);
|
97
|
-
break if (code != 0x20 && code != 0x0A)
|
98
|
-
pos += 1
|
99
|
-
end
|
100
|
-
|
101
96
|
if (pos < max && state.src.charCodeAt(pos) == 0x5B) # [
|
102
97
|
start = pos + 1
|
103
|
-
pos = parseLinkLabel(state, pos)
|
98
|
+
pos = state.md.helpers.parseLinkLabel(state, pos)
|
104
99
|
if (pos >= 0)
|
105
100
|
label = state.src.slice(start...pos)
|
106
101
|
pos += 1
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesInline
|
5
5
|
class Newline
|
6
|
+
extend Common::Utils
|
6
7
|
|
7
8
|
#------------------------------------------------------------------------------
|
8
9
|
def self.newline(state, silent)
|
@@ -34,7 +35,7 @@ module MarkdownIt
|
|
34
35
|
pos += 1
|
35
36
|
|
36
37
|
# skip heading spaces for next line
|
37
|
-
while pos < max && state.src.charCodeAt(pos)
|
38
|
+
while pos < max && isSpace(state.src.charCodeAt(pos))
|
38
39
|
pos += 1
|
39
40
|
end
|
40
41
|
|
@@ -3,9 +3,10 @@
|
|
3
3
|
module MarkdownIt
|
4
4
|
module RulesInline
|
5
5
|
class StateInline
|
6
|
+
include MarkdownIt::Common::Utils
|
6
7
|
|
7
8
|
attr_accessor :src, :env, :md, :tokens, :pos, :posMax, :level
|
8
|
-
attr_accessor :pending, :pendingLevel, :cache
|
9
|
+
attr_accessor :pending, :pendingLevel, :cache, :delimiters
|
9
10
|
|
10
11
|
#------------------------------------------------------------------------------
|
11
12
|
def initialize(src, md, env, outTokens)
|
@@ -22,6 +23,7 @@ module MarkdownIt
|
|
22
23
|
|
23
24
|
@cache = {} # Stores { start: end } pairs. Useful for backtrack
|
24
25
|
# optimization of pairs parse (emphasis, strikes).
|
26
|
+
@delimiters = []
|
25
27
|
end
|
26
28
|
|
27
29
|
|
@@ -52,6 +54,63 @@ module MarkdownIt
|
|
52
54
|
return token
|
53
55
|
end
|
54
56
|
|
57
|
+
# Scan a sequence of emphasis-like markers, and determine whether
|
58
|
+
# it can start an emphasis sequence or end an emphasis sequence.
|
59
|
+
#
|
60
|
+
# - start - position to scan from (it should point at a valid marker);
|
61
|
+
# - canSplitWord - determine if these markers can be found inside a word
|
62
|
+
#------------------------------------------------------------------------------
|
63
|
+
def scanDelims(start, canSplitWord)
|
64
|
+
pos = start
|
65
|
+
left_flanking = true
|
66
|
+
right_flanking = true
|
67
|
+
max = @posMax
|
68
|
+
marker = @src.charCodeAt(start)
|
69
|
+
|
70
|
+
# treat beginning of the line as a whitespace
|
71
|
+
lastChar = start > 0 ? @src.charCodeAt(start - 1) : 0x20
|
72
|
+
|
73
|
+
while (pos < max && @src.charCodeAt(pos) == marker)
|
74
|
+
pos += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
count = pos - start
|
78
|
+
|
79
|
+
# treat end of the line as a whitespace
|
80
|
+
nextChar = pos < max ? @src.charCodeAt(pos) : 0x20
|
81
|
+
|
82
|
+
isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(fromCodePoint(lastChar))
|
83
|
+
isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(fromCodePoint(nextChar))
|
84
|
+
|
85
|
+
isLastWhiteSpace = isWhiteSpace(lastChar)
|
86
|
+
isNextWhiteSpace = isWhiteSpace(nextChar)
|
87
|
+
|
88
|
+
if (isNextWhiteSpace)
|
89
|
+
left_flanking = false
|
90
|
+
elsif (isNextPunctChar)
|
91
|
+
if (!(isLastWhiteSpace || isLastPunctChar))
|
92
|
+
left_flanking = false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
if isLastWhiteSpace
|
97
|
+
right_flanking = false
|
98
|
+
elsif isLastPunctChar
|
99
|
+
if !(isNextWhiteSpace || isNextPunctChar)
|
100
|
+
right_flanking = false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if !canSplitWord
|
105
|
+
can_open = left_flanking && (!right_flanking || isLastPunctChar)
|
106
|
+
can_close = right_flanking && (!left_flanking || isNextPunctChar)
|
107
|
+
else
|
108
|
+
can_open = left_flanking
|
109
|
+
can_close = right_flanking
|
110
|
+
end
|
111
|
+
|
112
|
+
return { can_open: can_open, can_close: can_close, length: count }
|
113
|
+
end
|
55
114
|
end
|
56
115
|
end
|
57
116
|
end
|
@@ -4,127 +4,111 @@ module MarkdownIt
|
|
4
4
|
module RulesInline
|
5
5
|
class Strikethrough
|
6
6
|
extend Common::Utils
|
7
|
-
|
8
|
-
# parse sequence of markers,
|
9
|
-
# "start" should point at a valid marker
|
10
|
-
def self.scanDelims(state, start)
|
11
|
-
pos = start
|
12
|
-
can_open = true
|
13
|
-
can_close = true
|
14
|
-
max = state.posMax
|
15
|
-
marker = state.src.charCodeAt(start)
|
16
|
-
|
17
|
-
# treat beginning of the line as a whitespace
|
18
|
-
lastChar = start > 0 ? state.src.charCodeAt(start - 1) : 0x20
|
19
|
-
|
20
|
-
while (pos < max && state.src.charCodeAt(pos) == marker)
|
21
|
-
pos += 1
|
22
|
-
end
|
23
7
|
|
24
|
-
|
25
|
-
|
26
|
-
|
8
|
+
# Insert each marker as a separate text token, and add it to delimiter list
|
9
|
+
#------------------------------------------------------------------------------
|
10
|
+
def self.tokenize(state, silent)
|
11
|
+
start = state.pos
|
12
|
+
marker = state.src.charCodeAt(start)
|
27
13
|
|
28
|
-
|
14
|
+
return false if silent
|
29
15
|
|
30
|
-
|
31
|
-
nextChar = pos < max ? state.src.charCodeAt(pos) : 0x20
|
16
|
+
return false if marker != 0x7E # ~
|
32
17
|
|
33
|
-
|
34
|
-
|
18
|
+
scanned = state.scanDelims(state.pos, true)
|
19
|
+
len = scanned[:length]
|
20
|
+
ch = fromCodePoint(marker)
|
35
21
|
|
36
|
-
|
37
|
-
isNextWhiteSpace = isWhiteSpace(nextChar)
|
22
|
+
return false if len < 2
|
38
23
|
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
can_open = false
|
44
|
-
end
|
24
|
+
if len % 2 > 0
|
25
|
+
token = state.push('text', '', 0)
|
26
|
+
token.content = ch
|
27
|
+
len -= 1
|
45
28
|
end
|
46
29
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
30
|
+
i = 0
|
31
|
+
while i < len
|
32
|
+
token = state.push('text', '', 0)
|
33
|
+
token.content = ch + ch
|
34
|
+
|
35
|
+
state.delimiters.push({
|
36
|
+
marker: marker,
|
37
|
+
length: scanned[:length],
|
38
|
+
jump: i,
|
39
|
+
token: state.tokens.length - 1,
|
40
|
+
level: state.level,
|
41
|
+
end: -1,
|
42
|
+
open: scanned[:can_open],
|
43
|
+
close: scanned[:can_close]
|
44
|
+
})
|
45
|
+
i += 2
|
53
46
|
end
|
54
47
|
|
55
|
-
|
48
|
+
state.pos += scanned[:length]
|
49
|
+
|
50
|
+
return true
|
56
51
|
end
|
57
52
|
|
53
|
+
# Walk through delimiter list and replace text tokens with tags
|
58
54
|
#------------------------------------------------------------------------------
|
59
|
-
def self.
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
def self.postProcess(state)
|
56
|
+
loneMarkers = []
|
57
|
+
delimiters = state.delimiters
|
58
|
+
max = state.delimiters.length
|
63
59
|
|
64
|
-
|
65
|
-
|
60
|
+
0.upto(max - 1) do |i|
|
61
|
+
startDelim = delimiters[i]
|
66
62
|
|
67
|
-
|
68
|
-
startCount = res[:delims]
|
69
|
-
if (!res[:can_open])
|
70
|
-
state.pos += startCount
|
71
|
-
# Earlier we checked !silent, but this implementation does not need it
|
72
|
-
state.pending += state.src.slice(start...state.pos)
|
73
|
-
return true
|
74
|
-
end
|
63
|
+
next if startDelim[:marker] != 0x7E # ~
|
75
64
|
|
76
|
-
|
77
|
-
return false if (stack <= 0)
|
78
|
-
state.pos = start + startCount
|
79
|
-
|
80
|
-
while (state.pos < max)
|
81
|
-
if (state.src.charCodeAt(state.pos) == marker)
|
82
|
-
res = scanDelims(state, state.pos)
|
83
|
-
count = res[:delims]
|
84
|
-
tagCount = (count / 2).floor
|
85
|
-
if (res[:can_close])
|
86
|
-
if (tagCount >= stack)
|
87
|
-
state.pos += count - 2
|
88
|
-
found = true
|
89
|
-
break
|
90
|
-
end
|
91
|
-
stack -= tagCount
|
92
|
-
state.pos += count
|
93
|
-
next
|
94
|
-
end
|
95
|
-
|
96
|
-
stack += tagCount if (res[:can_open])
|
97
|
-
state.pos += count
|
98
|
-
next
|
99
|
-
end
|
65
|
+
next if startDelim[:end] == -1
|
100
66
|
|
101
|
-
|
102
|
-
end
|
67
|
+
endDelim = delimiters[startDelim[:end]]
|
103
68
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
69
|
+
token = state.tokens[startDelim[:token]]
|
70
|
+
token.type = 's_open'
|
71
|
+
token.tag = 's'
|
72
|
+
token.nesting = 1
|
73
|
+
token.markup = '~~'
|
74
|
+
token.content = ''
|
109
75
|
|
110
|
-
|
111
|
-
|
112
|
-
|
76
|
+
token = state.tokens[endDelim[:token]]
|
77
|
+
token.type = 's_close'
|
78
|
+
token.tag = 's'
|
79
|
+
token.nesting = -1
|
80
|
+
token.markup = '~~'
|
81
|
+
token.content = ''
|
113
82
|
|
114
|
-
|
115
|
-
|
116
|
-
|
83
|
+
if (state.tokens[endDelim[:token] - 1].type == 'text' &&
|
84
|
+
state.tokens[endDelim[:token] - 1].content == '~')
|
85
|
+
loneMarkers.push(endDelim[:token] - 1)
|
86
|
+
end
|
87
|
+
end
|
117
88
|
|
118
|
-
|
89
|
+
# If a marker sequence has an odd number of characters, it's splitted
|
90
|
+
# like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the
|
91
|
+
# start of the sequence.
|
92
|
+
#
|
93
|
+
# So, we have to move all those markers after subsequent s_close tags.
|
94
|
+
#
|
95
|
+
while loneMarkers.length > 0
|
96
|
+
i = loneMarkers.pop
|
97
|
+
j = i + 1
|
98
|
+
|
99
|
+
while j < state.tokens.length && state.tokens[j].type == 's_close'
|
100
|
+
j += 1
|
101
|
+
end
|
119
102
|
|
120
|
-
|
121
|
-
token.markup = '~~'
|
103
|
+
j -= 1
|
122
104
|
|
123
|
-
|
124
|
-
|
125
|
-
|
105
|
+
if i != j
|
106
|
+
token = state.tokens[j]
|
107
|
+
state.tokens[j] = state.tokens[i]
|
108
|
+
state.tokens[i] = token
|
109
|
+
end
|
110
|
+
end
|
126
111
|
end
|
127
|
-
|
128
112
|
end
|
129
113
|
end
|
130
114
|
end
|