motion-markdown-it 10.0.0 → 12.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7f2ac0d111cfc878b1017c5e3c32d1e9a6b9468176051937bac57f0378e5ac8
4
- data.tar.gz: 13b8f19a17c53fca0f8ae6c8e373f219bb90b9e6152e7d3a9a0b1ad54c3f7c63
3
+ metadata.gz: 74ae9a8bfdbc637f5e2127d34919298661b7d4f32b55830053a0c30012cd1ddf
4
+ data.tar.gz: 5787ec92937c5e8ef19fead547c0fae14b0de4507c0098cb5e8a79720dab611e
5
5
  SHA512:
6
- metadata.gz: d632e566f5280d655dac450d8e5c9532dc17829ec8c40aee01c1b35df2909f55e467940e2598bf557aa8c4ee85285a0d6bb1801a28ed1ddd3c1a1767a306c9eb
7
- data.tar.gz: f669a717a5d9f56c2f9d9d7669bd329610b0120a2dceeca3334eb72411184b371448d71a03ad04e4ff9d4f7c7d499750f98b091bd1415ba709011193b0fd385b
6
+ metadata.gz: 72214978791be3e608c627bfa80db56a1ca30df9650a1df85bef0c2a99fb68b822a1464261595779f16385a9e69cf9898fbd15966ba5e00ad969d4a0568c028a
7
+ data.tar.gz: 5e2ede784f3386d45b930789abb2c0a05ee8bc2dffb707d736c437e48fe722b9084dc75f2032bea6a8d47b723d0daac43428fb059e1ac1f7c6fa92dfad4a83e7
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.0.0_
10
+ _Currently synced with markdown-it 12.0.6_
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
- - [markdown-it](#markdown-it)
58
- - [Install](#install)
59
- - [Usage examples](#usage-examples)
60
- - [Simple](#simple)
61
- - [Init with presets and options](#init-with-presets-and-options)
62
- - [Plugins](#plugins)
63
- - [Upgrading](#upgrading)
64
- - [References / Thanks](#references--thanks)
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,
@@ -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.tlds('.py', false); // disables .py as top level domain
224
+ md.linkify.set({ fuzzyEmail: false }); // disables converting email to link
225
225
  ```
226
226
 
227
227
 
@@ -274,6 +274,10 @@ md = require('markdown-it')({
274
274
  });
275
275
  ```
276
276
 
277
+ You can find all rules in sources:
278
+ [parser_core.js](lib/parser_core.js), [parser_block](lib/parser_block.js),
279
+ [parser_inline](lib/parser_inline.js).
280
+
277
281
 
278
282
  ## Benchmark
279
283
 
@@ -45,7 +45,6 @@ module MarkdownIt
45
45
  'main',
46
46
  'menu',
47
47
  'menuitem',
48
- 'meta',
49
48
  'nav',
50
49
  'noframes',
51
50
  'ol',
@@ -68,4 +67,4 @@ module MarkdownIt
68
67
  'ul'
69
68
  ].freeze
70
69
 
71
- end
70
+ end
@@ -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
- return MDUrl::Decode.decode(MDUrl::Format.format(parsed))
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
 
@@ -352,7 +353,7 @@ module MarkdownIt
352
353
  # MarkdownIt.configure(presets)
353
354
  #
354
355
  # Batch load of all options and compenent settings. This is internal method,
355
- # and you probably will not need it. But if you with - see available presets
356
+ # and you probably will not need it. But if you will - see available presets
356
357
  # and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
357
358
  #
358
359
  # We strongly recommend to use presets instead of direct config loads. That
@@ -474,7 +475,7 @@ module MarkdownIt
474
475
  # - src (String): source string
475
476
  # - env (Object): environment sandbox
476
477
  #
477
- # Parse input string and returns list of block tokens (special token type
478
+ # Parse input string and return list of block tokens (special token type
478
479
  # "inline" will contain list of inline tokens). You should not call this
479
480
  # method directly, until you write custom renderer (for example, to produce
480
481
  # AST).
@@ -542,4 +543,4 @@ module MarkdownIt
542
543
  end
543
544
 
544
545
  end
545
- end
546
+ end
@@ -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
- langName = info.split(/\s+/)[0]
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 .clone() for token and simplify this part, but
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
 
@@ -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
 
@@ -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
- # skip spaces after ">" and re-calculate offset
26
- initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[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
- wasOutdented = true if (state.sCount[nextLine] < state.blkIndent)
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 && !wasOutdented # >
130
+ if charCodeAt(state.src, pos) == 0x3E && !isOutdented # >
132
131
  pos += 1
133
132
  # This line is inside the blockquote.
134
133
 
135
- # skip spaces after ">" and re-calculate offset
136
- initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[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
@@ -1,4 +1,4 @@
1
- # GFM table, non-standard
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.blkIndent
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
- escapes = 0
21
+ isEscaped = false
22
22
  lastPos = 0
23
- backTicked = false
24
- lastBackTick = 0
23
+ current = ''
25
24
 
26
25
  ch = charCodeAt(str, pos)
27
26
 
28
27
  while (pos < max)
29
- if ch == 0x60 # `
30
- if (backTicked)
31
- # make \` close code sequence, but not open it;
32
- # the reason is: `\` is correct code block
33
- backTicked = false
34
- lastBackTick = pos
35
- elsif escapes % 2 == 0
36
- backTicked = !backTicked
37
- lastBackTick = pos
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
- # If there was an un-closed backtick, go back to just after
52
- # the last backtick, but as if it was a normal character
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
- ch = charCodeAt(state.src, pos)
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 (ch != 0x7C && ch != 0x2D && ch != 0x3A) # | or - or :
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.gsub(/^\||\|$/, ''))
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 shouldn't be smaller than that (the rest of the rows can)
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 > aligns.length
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 !lineText.include?('|')
180
+ break if lineText.empty?
170
181
  break if state.sCount[nextLine] - state.blkIndent >= 4
171
- columns = self.escapedSplit(lineText.gsub(/^\||\|$/, ''))
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
- token = state.push('tbody_close', 'tbody', -1)
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
- tableLines[1] = tbodyLines[1] = nextLine
219
+ state.parentType = oldParentType
193
220
  state.line = nextLine
194
221
  return true
195
222
  end
@@ -67,10 +67,10 @@ module MarkdownIt
67
67
  gsub(/\.{2,}/, '…').gsub(/([?!])…/, "\\1..").
68
68
  gsub(/([?!]){4,}/, '\\1\\1\\1').gsub(/,{2,}/, ',').
69
69
  # em-dash
70
- gsub(/(^|[^-])---([^-]|$)/m, "\\1\u2014\\2").
70
+ gsub(/(^|[^-])---(?=[^-]|$)/m, "\\1\u2014").
71
71
  # en-dash
72
- gsub(/(^|\s)--(\s|$)/m, "\\1\u2013\\2").
73
- gsub(/(^|[^-\s])--([^-\s]|$)/m, "\\1\u2013\\2")
72
+ gsub(/(^|\s)--(?=\s|$)/m, "\\1\u2013").
73
+ gsub(/(^|[^-\s])--(?=[^-\s]|$)/m, "\\1\u2013")
74
74
  end
75
75
  end
76
76
 
@@ -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].type != 'text'
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].type != 'text'
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
@@ -113,8 +113,14 @@ module MarkdownIt
113
113
  end
114
114
 
115
115
  if (canOpen && canClose)
116
- # treat this as the middle of the word
117
- canOpen = false
116
+ # Replace quotes in the middle of punctuation sequence, but not
117
+ # in the middle of the words, i.e.:
118
+ #
119
+ # 1. foo " bar " baz - not replaced
120
+ # 2. foo-"-bar-"-baz - replaced
121
+ # 3. foo"bar"baz - not replaced
122
+ #
123
+ canOpen = isLastPunctChar
118
124
  canClose = isNextPunctChar
119
125
  end
120
126
 
@@ -5,8 +5,8 @@ module MarkdownIt
5
5
  class Autolink
6
6
  extend Common::Utils
7
7
 
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]*)>/
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
- tail = state.src[pos..-1]
17
+ start = state.pos
18
+ max = state.posMax
18
19
 
19
- return false if !tail.include?('>')
20
+ loop do
21
+ return false if ((pos += 1) >= max)
20
22
 
21
- if (AUTOLINK_RE =~ tail)
22
- linkMatch = tail.match(AUTOLINK_RE)
23
+ ch = charCodeAt(state.src, pos)
23
24
 
24
- url = linkMatch[0].slice(1...-1)
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 += linkMatch[0].length
49
+ state.pos += url.length + 2
43
50
  return true
44
51
  end
45
52
 
46
- if (EMAIL_RE =~ tail)
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 += emailMatch[0].length
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
- if (matchEnd - matchStart == marker.length)
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 += marker.length
67
+ state.pos += openerLength
49
68
  return true
50
69
  end
51
-
52
70
  end
53
71
  end
54
72
  end
@@ -27,20 +27,20 @@ module MarkdownIt
27
27
  end
28
28
 
29
29
  minOpenerIdx = openersBottom[closer[:marker]][closer[:length] % 3]
30
- newMinOpenerIdx = -1
31
30
 
32
31
  openerIdx = closerIdx - closer[:jump] - 1
33
-
32
+
33
+ # avoid crash if `closer.jump` is pointing outside of the array, see #742
34
+ openerIdx = -1 if (openerIdx < -1)
35
+
36
+ newMinOpenerIdx = openerIdx
37
+
34
38
  while openerIdx > minOpenerIdx
35
39
  opener = delimiters[openerIdx]
36
40
 
37
41
  (openerIdx -= opener[:jump] + 1) && next if (opener[:marker] != closer[:marker])
38
42
 
39
- newMinOpenerIdx = openerIdx if (newMinOpenerIdx == -1)
40
-
41
- if (opener[:open] &&
42
- opener[:end] < 0 &&
43
- opener[:level] == closer[:level])
43
+ if (opener[:open] && opener[:end] < 0)
44
44
 
45
45
  isOddMatch = false
46
46
 
@@ -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
@@ -5,8 +5,9 @@ module MarkdownIt
5
5
  class StateInline
6
6
  include MarkdownIt::Common::Utils
7
7
 
8
- attr_accessor :src, :env, :md, :tokens, :pos, :posMax, :level, :tokens_meta
9
- attr_accessor :pending, :pendingLevel, :cache, :delimiters
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,8 @@ module MarkdownIt
34
34
 
35
35
  state.delimiters.push({
36
36
  marker: marker,
37
- length: 0, # disable "rule of 3" length checks meant for emphasis
38
- jump: i,
37
+ length: 0, # disable "rule of 3" length checks meant for emphasis
38
+ jump: i / 2, # for `~~` 1 marker = 2 characters
39
39
  token: state.tokens.length - 1,
40
40
  end: -1,
41
41
  open: scanned[:can_open],
@@ -63,7 +63,10 @@ module MarkdownIt
63
63
 
64
64
  # * Token#info -> String
65
65
  # *
66
- # * fence infostring
66
+ # * Additional information:
67
+ # *
68
+ # * - Info string for "fence" tokens
69
+ # * - The value "auto" for autolink "link_open" and "link_close" tokens
67
70
  @info = ''
68
71
 
69
72
  # * Token#meta -> Object
@@ -1,3 +1,3 @@
1
1
  module MotionMarkdownIt
2
- VERSION = '10.0.0'
2
+ VERSION = '12.0.6'
3
3
  end
@@ -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>&amp;\n</code></pre>\n");
64
63
  expect(md.render("```\n&\n```")).to eq "<pre><code>&amp;\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 })
@@ -281,12 +293,12 @@ describe 'Url normalization' do
281
293
  return 'TEXT'
282
294
  end
283
295
 
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"
296
+ # expect(md.render('foo@example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
297
+ # expect(md.render('http://example.com')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
298
+ # expect(md.render('<foo@example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
299
+ # expect(md.render('<http://example.com>')).to eq "<p><a href=\"LINK\">TEXT</a></p>\n"
288
300
  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"
301
+ # expect(md.render('![test](http://example.com)')).to eq "<p><img src=\"LINK\" alt=\"test\"></p>\n"
290
302
  end
291
303
 
292
304
  end
@@ -403,4 +415,4 @@ describe 'Token attributes' do
403
415
 
404
416
  expect(t.attrGet('myattr')).to eq 'myvalue'
405
417
  end
406
- end
418
+ 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: 10.0.0
4
+ version: 12.0.6
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-16 00:00:00.000000000 Z
13
+ date: 2023-01-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mdurl-rb