motion-markdown-it 8.4.1.1 → 9.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +43 -2
  3. data/lib/motion-markdown-it/common/entities.rb +3 -0
  4. data/lib/motion-markdown-it/common/simpleidn.rb +8 -9
  5. data/lib/motion-markdown-it/common/utils.rb +48 -8
  6. data/lib/motion-markdown-it/helpers/parse_link_destination.rb +5 -5
  7. data/lib/motion-markdown-it/helpers/parse_link_label.rb +1 -1
  8. data/lib/motion-markdown-it/helpers/parse_link_title.rb +3 -3
  9. data/lib/motion-markdown-it/parser_core.rb +3 -3
  10. data/lib/motion-markdown-it/ruler.rb +3 -3
  11. data/lib/motion-markdown-it/rules_block/blockquote.rb +8 -8
  12. data/lib/motion-markdown-it/rules_block/fence.rb +5 -3
  13. data/lib/motion-markdown-it/rules_block/heading.rb +4 -4
  14. data/lib/motion-markdown-it/rules_block/hr.rb +2 -2
  15. data/lib/motion-markdown-it/rules_block/html_block.rb +2 -1
  16. data/lib/motion-markdown-it/rules_block/lheading.rb +2 -1
  17. data/lib/motion-markdown-it/rules_block/list.rb +36 -12
  18. data/lib/motion-markdown-it/rules_block/reference.rb +13 -13
  19. data/lib/motion-markdown-it/rules_block/state_block.rb +13 -11
  20. data/lib/motion-markdown-it/rules_block/table.rb +8 -8
  21. data/lib/motion-markdown-it/rules_core/linkify.rb +1 -1
  22. data/lib/motion-markdown-it/rules_core/normalize.rb +2 -2
  23. data/lib/motion-markdown-it/rules_core/replacements.rb +1 -1
  24. data/lib/motion-markdown-it/rules_core/smartquotes.rb +5 -5
  25. data/lib/motion-markdown-it/rules_inline/autolink.rb +3 -2
  26. data/lib/motion-markdown-it/rules_inline/backticks.rb +8 -5
  27. data/lib/motion-markdown-it/rules_inline/balance_pairs.rb +13 -3
  28. data/lib/motion-markdown-it/rules_inline/emphasis.rb +1 -1
  29. data/lib/motion-markdown-it/rules_inline/entity.rb +6 -6
  30. data/lib/motion-markdown-it/rules_inline/escape.rb +3 -3
  31. data/lib/motion-markdown-it/rules_inline/html_inline.rb +5 -5
  32. data/lib/motion-markdown-it/rules_inline/image.rb +8 -8
  33. data/lib/motion-markdown-it/rules_inline/link.rb +7 -7
  34. data/lib/motion-markdown-it/rules_inline/newline.rb +4 -4
  35. data/lib/motion-markdown-it/rules_inline/state_inline.rb +7 -7
  36. data/lib/motion-markdown-it/rules_inline/strikethrough.rb +1 -1
  37. data/lib/motion-markdown-it/rules_inline/text.rb +2 -1
  38. data/lib/motion-markdown-it/rules_inline/text_collapse.rb +10 -2
  39. data/lib/motion-markdown-it/version.rb +1 -3
  40. data/lib/motion-markdown-it.rb +0 -1
  41. data/spec/spec_helper.rb +2 -1
  42. metadata +11 -13
  43. data/lib/motion-markdown-it/common/string.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ce02411a4d64cb6e09347db122e59cb409d77316
4
- data.tar.gz: 130993721fe5e59734b17af32a77aa7980d60fcf
2
+ SHA256:
3
+ metadata.gz: 2731c7d392eb70c89a0b583ff854d85ea277e299f86a6a3f02502427b4effdda
4
+ data.tar.gz: 25c49dfc9916421e4ea44878dd499c4e535e26d106f2663a594911002dd6cb21
5
5
  SHA512:
6
- metadata.gz: 90fce20e2e664e6ea14def698f0a846c1e7235687164c48a7c0388d495fd431f11c83387534e6e965658e4211b7c55e4650f0a3681f5517f4a36a7c76e6c10a8
7
- data.tar.gz: 77560ecca3754fb7ab767ee6837a69f3b15c0f89c7d966c29c87a937cfa702e5f4728e2127ead479a5dab18673ef264eba3e0b1dfe117aa98044950f5d7da34e
6
+ metadata.gz: f8a8d408d9a62779180b1176404c6f0e2f0616e0fd45e95e068eadec6780b1eb68268cda6a4339cd188e442e276f757d5cc54faa6f94eeb18ed5ac8992cbe410
7
+ data.tar.gz: f6b204daacb84fb2bd888d1246aab6882810d1c85bf5444bc92a2bc1dc837f750ec42f2df6a806550ae7822f516e2ebfddecbd386ae512f57ebf6105afb53edd
data/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # motion-markdown-it
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/motion-markdown-it.svg)](http://badge.fury.io/rb/motion-markdown-it)
4
- [![Build Status](https://travis-ci.org/digitalmoksha/motion-markdown-it.svg?branch=master)](https://travis-ci.org/digitalmoksha/motion-markdown-it)
4
+ [![Build Status](https://github.com/digitalmoksha/motion-markdown-it/actions/workflows/ci.yml/badge.svg)](https://github.com/digitalmoksha/motion-markdown-it/actions/workflows/ci.yml)
5
5
 
6
6
  Ruby/RubyMotion version of Markdown-it (CommonMark compliant and extendable)
7
7
 
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. Currently synced with markdown-it 8.4.1
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
+
10
+ _Currently synced with markdown-it 9.0.1_
9
11
 
10
12
  ---
11
13
 
@@ -55,6 +57,7 @@ redcarpet 3.4.0 0.0065
55
57
  - [Install](#install)
56
58
  - [Usage examples](#usage-examples)
57
59
  - [Plugins](#plugins)
60
+ - [Upgrading](#upgrading)
58
61
  - [References / Thanks](#references--thanks)
59
62
  - [License](#license)
60
63
 
@@ -297,6 +300,44 @@ other implementations.
297
300
 
298
301
  -->
299
302
 
303
+ ## Upgrading
304
+
305
+ Upgrading to `8.4.1.2` could cause some small breakage if you are using any custom plugins. The [motion-markdown-it-plugins](https://github.com/digitalmoksha/motion-markdown-it-plugins) plugins have already been upgraded.
306
+
307
+ #### charCodeAt
308
+
309
+ Make sure you have
310
+
311
+ ```ruby
312
+ include MarkdownIt::Common::Utils
313
+ ```
314
+
315
+ at the top of your plugin file. Then change any references to `charCodeAt`. For example,
316
+
317
+ ```ruby
318
+ state.src.charCodeAt(pos)
319
+ ```
320
+
321
+ would become
322
+
323
+ ```ruby
324
+ charCodeAt(state.src, pos)
325
+ ```
326
+
327
+ #### slice_to_end
328
+
329
+ `slice_to_end` has been removed. Change references like this
330
+
331
+ ```ruby
332
+ state.src.slice_to_end(pos)
333
+ ```
334
+
335
+ to
336
+
337
+ ```ruby
338
+ state.src[pos..-1]
339
+ ```
340
+
300
341
  ## References / Thanks
301
342
 
302
343
  Thanks to the authors of the original implementation in Javascript, [markdown-it](https://github.com/markdown-it/markdown-it):
@@ -3,6 +3,8 @@ module MarkdownIt
3
3
 
4
4
  # TODO this list needs to be brought up to same level as the WC3 document
5
5
  # http://www.w3.org/TR/xml-entity-names/byalpha.html
6
+ # Consider pulling in https://github.com/fb55/entities/blob/master/maps/entities.json,
7
+ # is kept up to date
6
8
  #------------------------------------------------------------------------------
7
9
  class HTMLEntities
8
10
 
@@ -626,6 +628,7 @@ module MarkdownIt
626
628
  'nearr' => 0x2197, # ↗ NORTH EAST ARROW
627
629
  'nequiv' => 0x2262, # ≢ NOT IDENTICAL TO
628
630
  'nexist' => 0x2204, # ∄ THERE DOES NOT EXIST
631
+ 'ngE' => '≧̸', # ≧̸ from https://github.com/fb55/entities/blob/master/maps/entities.json
629
632
  'nge' => 0x2271, # ≱ dup NEITHER GREATER-THAN NOR EQUAL TO
630
633
  'nges' => 0x2271, # ≱ dup skip NEITHER GREATER-THAN NOR EQUAL TO
631
634
  'Ngr' => 0x039d, # Ν dup skip GREEK CAPITAL LETTER NU
@@ -1,11 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  # Borrowed from https://github.com/mmriis/simpleidn
3
3
  #------------------------------------------------------------------------------
4
- class Integer
5
- def to_utf8_character
6
- [self].pack("U*")
7
- end
8
- end
9
4
 
10
5
  module SimpleIDN
11
6
 
@@ -21,7 +16,11 @@ module SimpleIDN
21
16
  SKEW = 38
22
17
  MAXINT = 0x7FFFFFFF
23
18
 
24
- module_function
19
+ module_function
20
+
21
+ def to_utf8_character(int)
22
+ [int].pack("U*")
23
+ end
25
24
 
26
25
  # decode_digit(cp) returns the numeric value of a basic code
27
26
  # point (for use in representing integers) in the range 0 to
@@ -75,7 +74,7 @@ module SimpleIDN
75
74
  # Handle the basic code points: Let basic be the number of input code
76
75
  # points before the last delimiter, or 0 if there is none, then
77
76
  # copy the first basic code points to the output.
78
- basic = input.rindex(DELIMITER.to_utf8_character) || 0
77
+ basic = input.rindex(to_utf8_character(DELIMITER)) || 0
79
78
 
80
79
  input.unpack("U*")[0, basic].each do |char|
81
80
  raise(RangeError, "Illegal input >= 0x80") if char >= 0x80
@@ -126,7 +125,7 @@ module SimpleIDN
126
125
  i %= out
127
126
 
128
127
  # Insert n at position i of the output:
129
- output.insert(i, n.to_utf8_character)
128
+ output.insert(i, to_utf8_character(n))
130
129
  i += 1
131
130
  end
132
131
 
@@ -202,7 +201,7 @@ module SimpleIDN
202
201
  delta += 1
203
202
  n += 1
204
203
  end
205
- return output.collect {|c| c.to_utf8_character}.join
204
+ return output.collect {|c| to_utf8_character(c)}.join
206
205
  end
207
206
 
208
207
  end
@@ -48,7 +48,10 @@ module MarkdownIt
48
48
 
49
49
  #------------------------------------------------------------------------------
50
50
  def fromCodePoint(c)
51
- c.chr(Encoding::UTF_8)
51
+ # Some html entities are mapped directly as characters rather than code points.
52
+ # So if we're passed an Integer, convert to character, otherwise just return
53
+ # the character. For example `≧̸`
54
+ c.is_a?(Integer) ? c.chr(Encoding::UTF_8) : c
52
55
  end
53
56
 
54
57
  #------------------------------------------------------------------------------
@@ -56,6 +59,10 @@ module MarkdownIt
56
59
  c.chr
57
60
  end
58
61
 
62
+ #------------------------------------------------------------------------------
63
+ def charCodeAt(str, ch)
64
+ str[ch].ord unless str[ch].nil?
65
+ end
59
66
 
60
67
  UNESCAPE_MD_RE = /\\([\!\"\#\$\%\&\'\(\)\*\+\,\-.\/:;<=>?@\[\\\]^_`{|}~])/
61
68
 
@@ -70,8 +77,8 @@ module MarkdownIt
70
77
 
71
78
  return fromCodePoint(MarkdownIt::HTMLEntities::MAPPINGS[name]) if MarkdownIt::HTMLEntities::MAPPINGS[name]
72
79
 
73
- if (name.charCodeAt(0) == 0x23 && DIGITAL_ENTITY_TEST_RE =~ name) # '#'
74
- code = name[1].downcase == 'x' ? name.slice_to_end(2).to_i(16) : name.slice_to_end(1).to_i
80
+ if (charCodeAt(name, 0) == 0x23 && DIGITAL_ENTITY_TEST_RE =~ name) # '#'
81
+ code = name[1].downcase == 'x' ? name[2..-1].to_i(16) : name[1..-1].to_i
75
82
  if (isValidEntityCode(code))
76
83
  return fromCodePoint(code)
77
84
  end
@@ -212,11 +219,44 @@ module MarkdownIt
212
219
  # Hepler to unify [reference labels].
213
220
  #------------------------------------------------------------------------------
214
221
  def normalizeReference(str)
215
- # use .toUpperCase() instead of .toLowerCase()
216
- # here to avoid a conflict with Object.prototype
217
- # members (most notably, `__proto__`)
218
- return str.strip.gsub(/\s+/, ' ').upcase
222
+ # Trim and collapse whitespace
223
+ #
224
+ str = str.strip.gsub(/\s+/, ' ')
225
+
226
+ # .toLowerCase().toUpperCase() should get rid of all differences
227
+ # between letter variants.
228
+ #
229
+ # Simple .toLowerCase() doesn't normalize 125 code points correctly,
230
+ # and .toUpperCase doesn't normalize 6 of them (list of exceptions:
231
+ # İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently
232
+ # uppercased versions).
233
+ #
234
+ # Here's an example showing how it happens. Lets take greek letter omega:
235
+ # uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)
236
+ #
237
+ # Unicode entries:
238
+ # 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;
239
+ # 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398
240
+ # 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398
241
+ # 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;
242
+ #
243
+ # Case-insensitive comparison should treat all of them as equivalent.
244
+ #
245
+ # But .toLowerCase() doesn't change ϑ (it's already lowercase),
246
+ # and .toUpperCase() doesn't change ϴ (already uppercase).
247
+ #
248
+ # Applying first lower then upper case normalizes any character:
249
+ # '\u0398\u03f4\u03b8\u03d1'.toLowerCase().toUpperCase() === '\u0398\u0398\u0398\u0398'
250
+ #
251
+ # Note: this is equivalent to unicode case folding; unicode normalization
252
+ # is a different step that is not required here.
253
+ #
254
+ # Final result should be uppercased, because it's later stored in an object
255
+ # (this avoid a conflict with Object.prototype members,
256
+ # most notably, `__proto__`)
257
+ #
258
+ return str.downcase.upcase
219
259
  end
220
260
  end
221
261
  end
222
- end
262
+ end
@@ -11,11 +11,11 @@ module MarkdownIt
11
11
  start = pos
12
12
  result = {ok: false, pos: 0, lines: 0, str: ''}
13
13
 
14
- if (str.charCodeAt(pos) == 0x3C ) # <
14
+ if (charCodeAt(str, pos) == 0x3C ) # <
15
15
  pos += 1
16
16
  while (pos < max)
17
- code = str.charCodeAt(pos)
18
- return result if (code == 0x0A || isSpace(code)) # \n
17
+ code = charCodeAt(str, pos)
18
+ return result if (code == 0x0A) # \n
19
19
  if (code == 0x3E) # >
20
20
  result[:pos] = pos + 1
21
21
  result[:str] = unescapeAll(str.slice((start + 1)...pos))
@@ -38,7 +38,7 @@ module MarkdownIt
38
38
 
39
39
  level = 0
40
40
  while (pos < max)
41
- code = str.charCodeAt(pos)
41
+ code = charCodeAt(str, pos)
42
42
 
43
43
  break if (code == 0x20)
44
44
 
@@ -73,4 +73,4 @@ module MarkdownIt
73
73
  end
74
74
  end
75
75
  end
76
- end
76
+ end
@@ -15,7 +15,7 @@ module MarkdownIt
15
15
  level = 1
16
16
 
17
17
  while (state.pos < max)
18
- marker = state.src.charCodeAt(state.pos)
18
+ marker = charCodeAt(state.src, state.pos)
19
19
  if (marker == 0x5D) # ]
20
20
  level -= 1
21
21
  if (level == 0)
@@ -12,7 +12,7 @@ module MarkdownIt
12
12
 
13
13
  return result if (pos >= max)
14
14
 
15
- marker = str.charCodeAt(pos)
15
+ marker = charCodeAt(str, pos)
16
16
 
17
17
  return result if (marker != 0x22 && marker != 0x27 && marker != 0x28) # " ' (
18
18
 
@@ -22,7 +22,7 @@ module MarkdownIt
22
22
  marker = 0x29 if (marker == 0x28)
23
23
 
24
24
  while (pos < max)
25
- code = str.charCodeAt(pos)
25
+ code = charCodeAt(str, pos)
26
26
  if (code == marker)
27
27
  result[:pos] = pos + 1
28
28
  result[:lines] = lines
@@ -33,7 +33,7 @@ module MarkdownIt
33
33
  lines += 1
34
34
  elsif (code == 0x5C && pos + 1 < max) # \
35
35
  pos += 1
36
- if (str.charCodeAt(pos) == 0x0A)
36
+ if (charCodeAt(str, pos) == 0x0A)
37
37
  lines += 1
38
38
  end
39
39
  end
@@ -8,9 +8,9 @@ module MarkdownIt
8
8
  class ParserCore
9
9
 
10
10
  attr_accessor :ruler
11
-
11
+
12
12
  RULES = [
13
- [ 'normalize', lambda { |state| RulesCore::Normalize.inline(state) } ],
13
+ [ 'normalize', lambda { |state| RulesCore::Normalize.normalize(state) } ],
14
14
  [ 'block', lambda { |state| RulesCore::Block.block(state) } ],
15
15
  [ 'inline', lambda { |state| RulesCore::Inline.inline(state) } ],
16
16
  [ 'linkify', lambda { |state| RulesCore::Linkify.linkify(state) } ],
@@ -43,4 +43,4 @@ module MarkdownIt
43
43
  end
44
44
  end
45
45
  end
46
- end
46
+ end
@@ -16,7 +16,7 @@
16
16
  #------------------------------------------------------------------------------
17
17
 
18
18
  module MarkdownIt
19
- class Ruler
19
+ class Ruler
20
20
 
21
21
  def initialize
22
22
  # // List of added rules. Each element is:
@@ -94,7 +94,7 @@ module MarkdownIt
94
94
  # *
95
95
  # * ##### Example
96
96
  # *
97
- # * Replace existing typorgapher replacement rule with new one:
97
+ # * Replace existing typographer replacement rule with new one:
98
98
  # *
99
99
  # * ```javascript
100
100
  # * var md = require('markdown-it')();
@@ -108,7 +108,7 @@ module MarkdownIt
108
108
  index = __find__(name)
109
109
 
110
110
  raise(StandardError, "Parser rule not found: #{name}") if index == -1
111
-
111
+
112
112
  @__rules__[index][:fn] = fn
113
113
  @__rules__[index][:alt] = opt[:alt] || ['']
114
114
  @__cache__ = nil
@@ -15,7 +15,7 @@ module MarkdownIt
15
15
  return false if (state.sCount[startLine] - state.blkIndent >= 4)
16
16
 
17
17
  # check the block quote marker
18
- return false if state.src.charCodeAt(pos) != 0x3E # >
18
+ return false if charCodeAt(state.src, pos) != 0x3E # >
19
19
  pos += 1
20
20
 
21
21
  # we know that it's going to be a valid blockquote,
@@ -26,7 +26,7 @@ module MarkdownIt
26
26
  initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine])
27
27
 
28
28
  # skip one optional space after '>'
29
- if state.src.charCodeAt(pos) == 0x20 # space
29
+ if charCodeAt(state.src, pos) == 0x20 # space
30
30
  # ' > test '
31
31
  # ^ -- position start of line here:
32
32
  pos += 1
@@ -34,7 +34,7 @@ module MarkdownIt
34
34
  offset +=1
35
35
  adjustTab = false
36
36
  spaceAfterMarker = true
37
- elsif state.src.charCodeAt(pos) == 0x09 # tab
37
+ elsif charCodeAt(state.src, pos) == 0x09 # tab
38
38
  spaceAfterMarker = true
39
39
 
40
40
  if ((state.bsCount[startLine] + offset) % 4 == 3)
@@ -58,7 +58,7 @@ module MarkdownIt
58
58
  state.bMarks[startLine] = pos
59
59
 
60
60
  while pos < max
61
- ch = state.src.charCodeAt(pos)
61
+ ch = charCodeAt(state.src, pos)
62
62
 
63
63
  if isSpace(ch)
64
64
  if ch == 0x09
@@ -128,7 +128,7 @@ module MarkdownIt
128
128
  break
129
129
  end
130
130
 
131
- if state.src.charCodeAt(pos) == 0x3E && !wasOutdented # >
131
+ if charCodeAt(state.src, pos) == 0x3E && !wasOutdented # >
132
132
  pos += 1
133
133
  # This line is inside the blockquote.
134
134
 
@@ -136,7 +136,7 @@ module MarkdownIt
136
136
  initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[nextLine])
137
137
 
138
138
  # skip one optional space after '>'
139
- if state.src.charCodeAt(pos) == 0x20 # space
139
+ if charCodeAt(state.src, pos) == 0x20 # space
140
140
  # ' > test '
141
141
  # ^ -- position start of line here:
142
142
  pos += 1
@@ -144,7 +144,7 @@ module MarkdownIt
144
144
  offset += 1
145
145
  adjustTab = false
146
146
  spaceAfterMarker = true
147
- elsif state.src.charCodeAt(pos) == 0x09 # tab
147
+ elsif charCodeAt(state.src, pos) == 0x09 # tab
148
148
  spaceAfterMarker = true
149
149
 
150
150
  if ((state.bsCount[nextLine] + offset) % 4 == 3)
@@ -168,7 +168,7 @@ module MarkdownIt
168
168
  state.bMarks[nextLine] = pos
169
169
 
170
170
  while pos < max
171
- ch = state.src.charCodeAt(pos)
171
+ ch = charCodeAt(state.src, pos)
172
172
 
173
173
  if isSpace(ch)
174
174
  if ch == 0x09
@@ -16,7 +16,7 @@ module MarkdownIt
16
16
 
17
17
  return false if pos + 3 > max
18
18
 
19
- marker = state.src.charCodeAt(pos)
19
+ marker = charCodeAt(state.src, pos)
20
20
 
21
21
  if marker != 0x7E && marker != 0x60 # != ~ && != `
22
22
  return false
@@ -32,7 +32,9 @@ module MarkdownIt
32
32
  markup = state.src.slice(mem...pos)
33
33
  params = state.src.slice(pos...max)
34
34
 
35
- return false if params.include?(fromCharCode(marker))
35
+ if (marker == 0x60) # `
36
+ return false if params.include?(fromCharCode(marker))
37
+ end
36
38
 
37
39
  # Since start is found, we can report success here in validation mode
38
40
  return true if silent
@@ -58,7 +60,7 @@ module MarkdownIt
58
60
  break
59
61
  end
60
62
 
61
- next if state.src.charCodeAt(pos) != marker
63
+ next if charCodeAt(state.src, pos) != marker
62
64
 
63
65
  if state.sCount[nextLine] - state.blkIndent >= 4
64
66
  # closing fence should be indented less than 4 spaces
@@ -13,18 +13,18 @@ module MarkdownIt
13
13
  # if it's indented more than 3 spaces, it should be a code block
14
14
  return false if state.sCount[startLine] - state.blkIndent >= 4
15
15
 
16
- ch = state.src.charCodeAt(pos)
16
+ ch = charCodeAt(state.src, pos)
17
17
 
18
18
  return false if (ch != 0x23 || pos >= max)
19
19
 
20
20
  # count heading level
21
21
  level = 1
22
22
  pos += 1
23
- ch = state.src.charCodeAt(pos)
23
+ ch = charCodeAt(state.src, pos)
24
24
  while (ch == 0x23 && pos < max && level <= 6) # '#'
25
25
  level += 1
26
26
  pos += 1
27
- ch = state.src.charCodeAt(pos)
27
+ ch = charCodeAt(state.src, pos)
28
28
  end
29
29
 
30
30
  return false if (level > 6 || (pos < max && !isSpace(ch)))
@@ -35,7 +35,7 @@ module MarkdownIt
35
35
 
36
36
  max = state.skipSpacesBack(max, pos)
37
37
  tmp = state.skipCharsBack(max, 0x23, pos) # '#'
38
- if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1)))
38
+ if (tmp > pos && isSpace(charCodeAt(state.src, tmp - 1)))
39
39
  max = tmp
40
40
  end
41
41
 
@@ -13,7 +13,7 @@ module MarkdownIt
13
13
  # if it's indented more than 3 spaces, it should be a code block
14
14
  return false if (state.sCount[startLine] - state.blkIndent >= 4)
15
15
 
16
- marker = state.src.charCodeAt(pos)
16
+ marker = charCodeAt(state.src, pos)
17
17
  pos += 1
18
18
 
19
19
  # Check hr marker
@@ -27,7 +27,7 @@ module MarkdownIt
27
27
 
28
28
  cnt = 1
29
29
  while (pos < max)
30
- ch = state.src.charCodeAt(pos)
30
+ ch = charCodeAt(state.src, pos)
31
31
  pos += 1
32
32
  return false if ch != marker && !isSpace(ch)
33
33
  cnt += 1 if ch == marker
@@ -3,6 +3,7 @@
3
3
  module MarkdownIt
4
4
  module RulesBlock
5
5
  class HtmlBlock
6
+ extend Common::Utils
6
7
 
7
8
  HTML_OPEN_CLOSE_TAG_RE = MarkdownIt::Common::HtmlRe::HTML_OPEN_CLOSE_TAG_RE
8
9
 
@@ -28,7 +29,7 @@ module MarkdownIt
28
29
  return false if state.sCount[startLine] - state.blkIndent >= 4
29
30
 
30
31
  return false if !state.md.options[:html]
31
- return false if state.src.charCodeAt(pos) != 0x3C # <
32
+ return false if charCodeAt(state.src, pos) != 0x3C # <
32
33
 
33
34
  lineText = state.src.slice(pos...max)
34
35
 
@@ -3,6 +3,7 @@
3
3
  module MarkdownIt
4
4
  module RulesBlock
5
5
  class Lheading
6
+ extend Common::Utils
6
7
 
7
8
  #------------------------------------------------------------------------------
8
9
  def self.lheading(state, startLine, endLine, silent = true)
@@ -29,7 +30,7 @@ module MarkdownIt
29
30
  max = state.eMarks[nextLine]
30
31
 
31
32
  if pos < max
32
- marker = state.src.charCodeAt(pos)
33
+ marker = charCodeAt(state.src, pos)
33
34
 
34
35
  if marker == 0x2D || marker == 0x3D # - or =
35
36
  pos = state.skipChars(pos, marker)
@@ -12,7 +12,7 @@ module MarkdownIt
12
12
  pos = state.bMarks[startLine] + state.tShift[startLine]
13
13
  max = state.eMarks[startLine]
14
14
 
15
- marker = state.src.charCodeAt(pos)
15
+ marker = charCodeAt(state.src, pos)
16
16
  pos += 1
17
17
  # Check bullet
18
18
  if (marker != 0x2A && # *
@@ -22,7 +22,7 @@ module MarkdownIt
22
22
  end
23
23
 
24
24
  if pos < max
25
- ch = state.src.charCodeAt(pos)
25
+ ch = charCodeAt(state.src, pos)
26
26
 
27
27
  if !isSpace(ch)
28
28
  # " -test " - is not a list item
@@ -44,7 +44,7 @@ module MarkdownIt
44
44
  # List marker should have at least 2 chars (digit + dot)
45
45
  return -1 if (pos + 1 >= max)
46
46
 
47
- ch = state.src.charCodeAt(pos)
47
+ ch = charCodeAt(state.src, pos)
48
48
  pos += 1
49
49
 
50
50
  return -1 if ch.nil?
@@ -54,7 +54,7 @@ module MarkdownIt
54
54
  # EOL -> fail
55
55
  return -1 if (pos >= max)
56
56
 
57
- ch = state.src.charCodeAt(pos)
57
+ ch = charCodeAt(state.src, pos)
58
58
  pos += 1
59
59
 
60
60
  if (ch >= 0x30 && ch <= 0x39) # >= 0 && <= 9
@@ -75,7 +75,7 @@ module MarkdownIt
75
75
  end
76
76
 
77
77
  if pos < max
78
- ch = state.src.charCodeAt(pos)
78
+ ch = charCodeAt(state.src, pos)
79
79
 
80
80
  if !isSpace(ch)
81
81
  # " 1.test " - is not a list item
@@ -109,6 +109,18 @@ module MarkdownIt
109
109
  # if it's indented more than 3 spaces, it should be a code block
110
110
  return false if (state.sCount[startLine] - state.blkIndent >= 4)
111
111
 
112
+ # Special case:
113
+ # - item 1
114
+ # - item 2
115
+ # - item 3
116
+ # - item 4
117
+ # - this one is a paragraph continuation
118
+ if (state.listIndent >= 0 &&
119
+ state.sCount[startLine] - state.listIndent >= 4 &&
120
+ state.sCount[startLine] < state.blkIndent)
121
+ return false
122
+ end
123
+
112
124
  # limit conditions when list can interrupt
113
125
  # a paragraph (validation mode only)
114
126
  if silent && state.parentType == 'paragraph'
@@ -144,7 +156,7 @@ module MarkdownIt
144
156
  end
145
157
 
146
158
  # We should terminate list on style change. Remember first one to compare.
147
- markerCharCode = state.src.charCodeAt(posAfterMarker - 1)
159
+ markerCharCode = charCodeAt(state.src, posAfterMarker - 1)
148
160
 
149
161
  # For validation mode we can terminate immediately
150
162
  return true if (silent)
@@ -185,7 +197,7 @@ module MarkdownIt
185
197
  initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine])
186
198
 
187
199
  while pos < max
188
- ch = state.src.charCodeAt(pos)
200
+ ch = charCodeAt(state.src, pos)
189
201
 
190
202
  if ch == 0x09
191
203
  offset += 4 - (offset + state.bsCount[nextLine]) % 4
@@ -220,11 +232,19 @@ module MarkdownIt
220
232
  token.markup = markerCharCode.chr
221
233
  token.map = itemLines = [ startLine, 0 ]
222
234
 
223
- oldIndent = state.blkIndent
235
+ # change current state, then restore it after parser subcall
224
236
  oldTight = state.tight
225
237
  oldTShift = state.tShift[startLine]
226
- oldLIndent = state.sCount[startLine]
238
+ oldSCount = state.sCount[startLine]
239
+
240
+ # - example list
241
+ # ^ listIndent position will be here
242
+ # ^ blkIndent position will be here
243
+ #
244
+ oldListIndent = state.listIndent
245
+ state.listIndent = state.blkIndent
227
246
  state.blkIndent = indent
247
+
228
248
  state.tight = true
229
249
  state.tShift[startLine] = contentStart - state.bMarks[startLine]
230
250
  state.sCount[startLine] = offset
@@ -250,9 +270,10 @@ module MarkdownIt
250
270
  # but we should filter last element, because it means list finish
251
271
  prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1)
252
272
 
253
- state.blkIndent = oldIndent
273
+ state.blkIndent = state.listIndent
274
+ state.listIndent = oldListIndent
254
275
  state.tShift[startLine] = oldTShift
255
- state.sCount[startLine] = oldLIndent
276
+ state.sCount[startLine] = oldSCount
256
277
  state.tight = oldTight
257
278
 
258
279
  token = state.push('list_item_close', 'li', -1)
@@ -269,6 +290,9 @@ module MarkdownIt
269
290
  #
270
291
  break if (state.sCount[nextLine] < state.blkIndent)
271
292
 
293
+ # if it's indented more than 3 spaces, it should be a code block
294
+ break if (state.sCount[startLine] - state.blkIndent >= 4)
295
+
272
296
  # fail if terminating block found
273
297
  terminate = false
274
298
  (0...terminatorRules.length).each do |i|
@@ -288,7 +312,7 @@ module MarkdownIt
288
312
  break if (posAfterMarker < 0)
289
313
  end
290
314
 
291
- break if (markerCharCode != state.src.charCodeAt(posAfterMarker - 1))
315
+ break if (markerCharCode != charCodeAt(state.src, posAfterMarker - 1))
292
316
  end
293
317
 
294
318
  # Finalize list