motion-markdown-it 0.4.0.3.0 → 4.1.0.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 +14 -13
- data/lib/motion-markdown-it/common/simpleidn.rb +268 -0
- data/lib/motion-markdown-it/common/utils.rb +4 -13
- data/lib/motion-markdown-it/index.rb +55 -63
- data/lib/motion-markdown-it/renderer.rb +2 -0
- data/lib/motion-markdown-it/rules_core/linkify.rb +93 -95
- data/lib/motion-markdown-it/rules_core/replacements.rb +1 -1
- data/lib/motion-markdown-it/rules_core/smartquotes.rb +2 -2
- data/lib/motion-markdown-it/rules_inline/strikethrough.rb +2 -2
- data/lib/motion-markdown-it/version.rb +1 -1
- data/lib/motion-markdown-it.rb +2 -0
- data/spec/motion-markdown-it/bench_mark_spec.rb +5 -5
- data/spec/motion-markdown-it/misc_spec.rb +241 -221
- data/spec/motion-markdown-it/utils_spec.rb +0 -12
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff09df2d99031e399da64902f3d11648574bd646
|
4
|
+
data.tar.gz: f6f52c3479c1805ec267503ff12f567d7539df61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c145910ac522f1e62985bce82e1509fb79f6ab803d52d35886ac1c370d3e84d3bc495c4c9592b501bd25775146a505471422ff17875ac78f97ebb7f25c5518fd
|
7
|
+
data.tar.gz: 2d20509844c9f7d40b2702a0cb366dca3a65e8a0b2ed693b3c3c3e79b953004a460c6843a4e5d88ce415669c674d3cb3d4191302af5bd9965ae2077960700749
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# motion-markdown-it
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/motion-markdown-it)
|
4
4
|
|
5
|
-
|
5
|
+
Ruby/RubyMotion version of Markdown-it (CommonMark compliant and extendable)
|
6
|
+
|
7
|
+
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 4.0.3
|
6
8
|
|
7
9
|
__[Javascript Live demo](https://markdown-it.github.io)__
|
8
10
|
|
@@ -11,14 +13,14 @@ __[Javascript Live demo](https://markdown-it.github.io)__
|
|
11
13
|
- High speed
|
12
14
|
- Community-written plugins
|
13
15
|
|
14
|
-
## Beta
|
15
|
-
|
16
|
-
The gem is still a work in progress. There are several areas to get working better, including plugins and performance. It will track as closely as possible to fixes and enhancements in the main _markdown-it_ implementation. Currently synced with markdown-it 4.0.3
|
17
|
-
|
18
16
|
## Benefit
|
19
17
|
|
20
18
|
The benefit of this project, for me at least, is to have a standardized CommonMark compliant, fast, and extendable, Markdown parser which can be used from Javascript, Ruby, and/or RubyMotion, as the development situation warrants.
|
21
19
|
|
20
|
+
## Performance
|
21
|
+
|
22
|
+
Performance is still an issue. While it performs reasonably well with small to medium files, it degrades for large files. Work in progres...
|
23
|
+
|
22
24
|
## Table of content
|
23
25
|
|
24
26
|
- [Install](#install)
|
@@ -61,20 +63,19 @@ and run `bundle install`
|
|
61
63
|
|
62
64
|
```ruby
|
63
65
|
parser = MarkdownIt::Parser.new(:commonmark, { html: false })
|
64
|
-
parser.render('# markdown-it
|
66
|
+
parser.render('# markdown-it in **Ruby**')
|
65
67
|
```
|
66
68
|
|
67
69
|
Single line rendering, without paragraph wrap:
|
68
70
|
|
69
71
|
```ruby
|
70
|
-
result = MarkdownIt::Parser.new.renderInline('__markdown-it__
|
72
|
+
result = MarkdownIt::Parser.new.renderInline('__markdown-it__ in Ruby')
|
71
73
|
```
|
72
74
|
|
73
75
|
### Init with presets and options
|
74
76
|
|
75
|
-
(*)
|
76
|
-
`:commonmark`, `:zero` or `:default` (if skipped).
|
77
|
-
[markdown-it Javascript API docs](https://markdown-it.github.io/markdown-it/#MarkdownIt.new) for more details.
|
77
|
+
(*) presets define combinations of active rules and options. Can be
|
78
|
+
`:commonmark`, `:zero` or `:default` (if skipped).
|
78
79
|
|
79
80
|
```ruby
|
80
81
|
#--- commonmark mode
|
@@ -104,8 +105,8 @@ parser = MarkdownIt::Parser.new({
|
|
104
105
|
quotes: '“”‘’',
|
105
106
|
|
106
107
|
# Highlighter function. Should return escaped HTML,
|
107
|
-
# or
|
108
|
-
highlight: lambda {|str, lang| return
|
108
|
+
# or nil if the source string is not changed and should be escaped externaly.
|
109
|
+
highlight: lambda {|str, lang| return nil}
|
109
110
|
})
|
110
111
|
```
|
111
112
|
|
@@ -0,0 +1,268 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Borrowed from https://github.com/mmriis/simpleidn
|
3
|
+
#------------------------------------------------------------------------------
|
4
|
+
class Integer
|
5
|
+
def to_utf8_character
|
6
|
+
[self].pack("U*")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module SimpleIDN
|
11
|
+
|
12
|
+
module Punycode
|
13
|
+
|
14
|
+
INITIAL_N = 0x80
|
15
|
+
INITIAL_BIAS = 72
|
16
|
+
DELIMITER = 0x2D
|
17
|
+
BASE = 36
|
18
|
+
DAMP = 700
|
19
|
+
TMIN = 1
|
20
|
+
TMAX = 26
|
21
|
+
SKEW = 38
|
22
|
+
MAXINT = 0x7FFFFFFF
|
23
|
+
|
24
|
+
module_function
|
25
|
+
|
26
|
+
# decode_digit(cp) returns the numeric value of a basic code
|
27
|
+
# point (for use in representing integers) in the range 0 to
|
28
|
+
# base-1, or base if cp is does not represent a value.
|
29
|
+
def decode_digit(cp)
|
30
|
+
cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : BASE
|
31
|
+
end
|
32
|
+
|
33
|
+
# encode_digit(d,flag) returns the basic code point whose value
|
34
|
+
# (when used for representing integers) is d, which needs to be in
|
35
|
+
# the range 0 to base-1. The lowercase form is used unless flag is
|
36
|
+
# nonzero, in which case the uppercase form is used. The behavior
|
37
|
+
# is undefined if flag is nonzero and digit d has no uppercase form.
|
38
|
+
def encode_digit(d)
|
39
|
+
d + 22 + 75 * (d < 26 ? 1 : 0)
|
40
|
+
# 0..25 map to ASCII a..z or A..Z
|
41
|
+
# 26..35 map to ASCII 0..9
|
42
|
+
end
|
43
|
+
|
44
|
+
# Bias adaptation function
|
45
|
+
def adapt(delta, numpoints, firsttime)
|
46
|
+
delta = firsttime ? (delta / DAMP) : (delta >> 1)
|
47
|
+
delta += (delta / numpoints)
|
48
|
+
|
49
|
+
k = 0
|
50
|
+
while delta > (((BASE - TMIN) * TMAX) / 2) do
|
51
|
+
delta /= BASE - TMIN
|
52
|
+
k += BASE
|
53
|
+
end
|
54
|
+
return k + (BASE - TMIN + 1) * delta / (delta + SKEW)
|
55
|
+
end
|
56
|
+
|
57
|
+
# encode_basic(bcp,flag) forces a basic code point to lowercase if flag is zero,
|
58
|
+
# uppercase if flag is nonzero, and returns the resulting code point.
|
59
|
+
# The code point is unchanged if it is caseless.
|
60
|
+
# The behavior is undefined if bcp is not a basic code point.
|
61
|
+
def encode_basic(bcp, flag)
|
62
|
+
bcp -= (bcp - 97 < 26 ? 1 : 0) << 5
|
63
|
+
return bcp + ((!flag && (bcp - 65 < 26 ? 1 : 0)) << 5)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Main decode
|
67
|
+
def decode(input)
|
68
|
+
output = []
|
69
|
+
|
70
|
+
# Initialize the state:
|
71
|
+
n = INITIAL_N
|
72
|
+
i = 0
|
73
|
+
bias = INITIAL_BIAS
|
74
|
+
|
75
|
+
# Handle the basic code points: Let basic be the number of input code
|
76
|
+
# points before the last delimiter, or 0 if there is none, then
|
77
|
+
# copy the first basic code points to the output.
|
78
|
+
basic = input.rindex(DELIMITER.to_utf8_character) || 0
|
79
|
+
|
80
|
+
input.unpack("U*")[0, basic].each do |char|
|
81
|
+
raise(RangeError, "Illegal input >= 0x80") if char >= 0x80
|
82
|
+
output << char.chr # to_utf8_character not needed her because ord < 0x80 (128) which is within US-ASCII.
|
83
|
+
end
|
84
|
+
|
85
|
+
# Main decoding loop: Start just after the last delimiter if any
|
86
|
+
# basic code points were copied; start at the beginning otherwise.
|
87
|
+
|
88
|
+
ic = basic > 0 ? basic + 1 : 0
|
89
|
+
while ic < input.length do
|
90
|
+
# ic is the index of the next character to be consumed,
|
91
|
+
|
92
|
+
# Decode a generalized variable-length integer into delta,
|
93
|
+
# which gets added to i. The overflow checking is easier
|
94
|
+
# if we increase i as we go, then subtract off its starting
|
95
|
+
# value at the end to obtain delta.
|
96
|
+
oldi = i
|
97
|
+
w = 1
|
98
|
+
k = BASE
|
99
|
+
while true do
|
100
|
+
raise(RangeError, "punycode_bad_input(1)") if ic >= input.length
|
101
|
+
|
102
|
+
digit = decode_digit(input[ic].ord)
|
103
|
+
ic += 1
|
104
|
+
|
105
|
+
raise(RangeError, "punycode_bad_input(2)") if digit >= BASE
|
106
|
+
|
107
|
+
raise(RangeError, "punycode_overflow(1)") if digit > (MAXINT - i) / w
|
108
|
+
|
109
|
+
i += digit * w
|
110
|
+
t = k <= bias ? TMIN : k >= bias + TMAX ? TMAX : k - bias
|
111
|
+
break if digit < t
|
112
|
+
raise(RangeError, "punycode_overflow(2)") if w > MAXINT / (BASE - t)
|
113
|
+
|
114
|
+
w *= BASE - t
|
115
|
+
k += BASE
|
116
|
+
end
|
117
|
+
|
118
|
+
out = output.length + 1
|
119
|
+
bias = adapt(i - oldi, out, oldi == 0)
|
120
|
+
|
121
|
+
# i was supposed to wrap around from out to 0,
|
122
|
+
# incrementing n each time, so we'll fix that now:
|
123
|
+
raise(RangeError, "punycode_overflow(3)") if (i / out) > MAXINT - n
|
124
|
+
|
125
|
+
n += (i / out)
|
126
|
+
i %= out
|
127
|
+
|
128
|
+
# Insert n at position i of the output:
|
129
|
+
output.insert(i, n.to_utf8_character)
|
130
|
+
i += 1
|
131
|
+
end
|
132
|
+
|
133
|
+
return output.join
|
134
|
+
end
|
135
|
+
|
136
|
+
# Main encode function
|
137
|
+
def encode(input)
|
138
|
+
|
139
|
+
input = input.downcase.unpack("U*")
|
140
|
+
output = []
|
141
|
+
|
142
|
+
# Initialize the state:
|
143
|
+
n = INITIAL_N
|
144
|
+
delta = 0
|
145
|
+
bias = INITIAL_BIAS
|
146
|
+
|
147
|
+
# Handle the basic code points:
|
148
|
+
output = input.select do |char|
|
149
|
+
char if char < 0x80
|
150
|
+
end
|
151
|
+
|
152
|
+
h = b = output.length
|
153
|
+
|
154
|
+
# h is the number of code points that have been handled, b is the
|
155
|
+
# number of basic code points
|
156
|
+
|
157
|
+
output << DELIMITER if b > 0
|
158
|
+
|
159
|
+
# Main encoding loop:
|
160
|
+
while h < input.length do
|
161
|
+
# All non-basic code points < n have been
|
162
|
+
# handled already. Find the next larger one:
|
163
|
+
|
164
|
+
m = MAXINT
|
165
|
+
|
166
|
+
input.each do |char|
|
167
|
+
m = char if char >= n && char < m
|
168
|
+
end
|
169
|
+
|
170
|
+
# Increase delta enough to advance the decoder's
|
171
|
+
# <n,i> state to <m,0>, but guard against overflow:
|
172
|
+
|
173
|
+
raise(RangeError, "punycode_overflow (1)") if m - n > ((MAXINT - delta) / (h + 1)).floor
|
174
|
+
|
175
|
+
delta += (m - n) * (h + 1)
|
176
|
+
n = m
|
177
|
+
|
178
|
+
input.each_with_index do |char, j|
|
179
|
+
if char < n
|
180
|
+
delta += 1
|
181
|
+
raise(StandardError,"punycode_overflow(2)") if delta > MAXINT
|
182
|
+
end
|
183
|
+
|
184
|
+
if (char == n)
|
185
|
+
# Represent delta as a generalized variable-length integer:
|
186
|
+
q = delta
|
187
|
+
k = BASE
|
188
|
+
while true do
|
189
|
+
t = k <= bias ? TMIN : k >= bias + TMAX ? TMAX : k - bias
|
190
|
+
break if q < t
|
191
|
+
output << encode_digit(t + (q - t) % (BASE - t))
|
192
|
+
q = ( (q - t) / (BASE - t) ).floor
|
193
|
+
k += BASE
|
194
|
+
end
|
195
|
+
output << encode_digit(q)
|
196
|
+
bias = adapt(delta, h + 1, h == b)
|
197
|
+
delta = 0
|
198
|
+
h += 1
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
delta += 1
|
203
|
+
n += 1
|
204
|
+
end
|
205
|
+
return output.collect {|c| c.to_utf8_character}.join
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
module_function
|
211
|
+
|
212
|
+
# Converts a UTF-8 unicode string to a punycode ACE string.
|
213
|
+
# == Example
|
214
|
+
# SimpleIDN.to_ascii("møllerriis.com")
|
215
|
+
# => "xn--mllerriis-l8a.com"
|
216
|
+
def to_ascii(domain)
|
217
|
+
domain_array = domain.split(".") rescue []
|
218
|
+
return domain if domain_array.length == 0
|
219
|
+
out = []
|
220
|
+
i = 0
|
221
|
+
while i < domain_array.length
|
222
|
+
s = domain_array[i]
|
223
|
+
out << (s =~ /[^A-Z0-9\-*_]/i ? "xn--" + Punycode.encode(s) : s)
|
224
|
+
i += 1
|
225
|
+
end
|
226
|
+
return out.join(".")
|
227
|
+
end
|
228
|
+
|
229
|
+
# Converts a punycode ACE string to a UTF-8 unicode string.
|
230
|
+
# == Example
|
231
|
+
# SimpleIDN.to_unicode("xn--mllerriis-l8a.com")
|
232
|
+
# => "møllerriis.com"
|
233
|
+
def to_unicode(domain)
|
234
|
+
domain_array = domain.split(".") rescue []
|
235
|
+
return domain if domain_array.length == 0
|
236
|
+
out = []
|
237
|
+
i = 0
|
238
|
+
while i < domain_array.length
|
239
|
+
s = domain_array[i]
|
240
|
+
out << (s =~ /^xn\-\-/i ? Punycode.decode(s.gsub('xn--','')) : s)
|
241
|
+
i += 1
|
242
|
+
end
|
243
|
+
return out.join(".")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
#------------------------------------------------------------------------------
|
248
|
+
# The MIT License
|
249
|
+
#
|
250
|
+
# Copyright (c) 2011-2013 Morten Møller Riis
|
251
|
+
#
|
252
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
253
|
+
# of this software and associated documentation files (the "Software"), to deal
|
254
|
+
# in the Software without restriction, including without limitation the rights
|
255
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
256
|
+
# copies of the Software, and to permit persons to whom the Software is
|
257
|
+
# furnished to do so, subject to the following conditions:
|
258
|
+
#
|
259
|
+
# The above copyright notice and this permission notice shall be included in
|
260
|
+
# all copies or substantial portions of the Software.
|
261
|
+
#
|
262
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
263
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
264
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
265
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
266
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
267
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
268
|
+
# THE SOFTWARE.
|
@@ -20,7 +20,9 @@ module MarkdownIt
|
|
20
20
|
# Useful for some operations with tokens
|
21
21
|
#------------------------------------------------------------------------------
|
22
22
|
def arrayReplaceAt(src, pos, newElements)
|
23
|
-
|
23
|
+
src[pos] = newElements
|
24
|
+
src.flatten!(1)
|
25
|
+
return src
|
24
26
|
end
|
25
27
|
|
26
28
|
#------------------------------------------------------------------------------
|
@@ -73,13 +75,6 @@ module MarkdownIt
|
|
73
75
|
return match
|
74
76
|
end
|
75
77
|
|
76
|
-
# not used
|
77
|
-
#------------------------------------------------------------------------------
|
78
|
-
# def replaceEntities(str)
|
79
|
-
# return str if str.index('&').nil?
|
80
|
-
# return str.gsub(ENTITY_RE, replaceEntityPattern)
|
81
|
-
# end
|
82
|
-
|
83
78
|
#------------------------------------------------------------------------------
|
84
79
|
def unescapeMd(str)
|
85
80
|
return str if !str.include?('\\')
|
@@ -143,11 +138,7 @@ module MarkdownIt
|
|
143
138
|
return false
|
144
139
|
end
|
145
140
|
|
146
|
-
|
147
|
-
# https://github.com/markdown-it/uc.micro
|
148
|
-
# UNICODE_PUNCT_RE = /[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDE38-\uDE3D]|\uD805[\uDCC6\uDDC1-\uDDC9\uDE41-\uDE43]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F/
|
149
|
-
# was unable to get abouve to work TODO
|
150
|
-
UNICODE_PUNCT_RE = /[!-#%-\*,-\/:;\?@\[-\]_\{\}]/
|
141
|
+
UNICODE_PUNCT_RE = UCMicro::Categories::P::REGEX
|
151
142
|
|
152
143
|
# Currently without astral characters support.
|
153
144
|
#------------------------------------------------------------------------------
|
@@ -7,18 +7,21 @@ CONFIG = {
|
|
7
7
|
commonmark: MarkdownIt::Presets::Commonmark.options
|
8
8
|
}
|
9
9
|
|
10
|
+
#------------------------------------------------------------------------------
|
11
|
+
# This validator does not pretend to functionality of full weight sanitizers.
|
12
|
+
# It's a tradeoff between default security, simplicity and usability.
|
13
|
+
# If you need different setup - override validator method as you wish. Or
|
14
|
+
# replace it with dummy function and use external sanitizer.
|
10
15
|
|
11
|
-
|
16
|
+
BAD_PROTO_RE = /^(vbscript|javascript|file|data):/
|
17
|
+
GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/
|
12
18
|
|
13
19
|
VALIDATE_LINK = lambda do |url|
|
14
20
|
# url should be normalized at this point, and existing entities are decoded
|
15
21
|
#
|
16
22
|
str = url.strip.downcase
|
17
23
|
|
18
|
-
|
19
|
-
return false
|
20
|
-
end
|
21
|
-
return true
|
24
|
+
return !!(BAD_PROTO_RE =~ str) ? (!!(GOOD_DATA_RE =~ str) ? true : false) : true
|
22
25
|
end
|
23
26
|
|
24
27
|
RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ]
|
@@ -26,40 +29,44 @@ RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ]
|
|
26
29
|
# mdurl comes from https://github.com/markdown-it/mdurl
|
27
30
|
NORMALIZE_LINK = lambda do |url|
|
28
31
|
parsed = MDUrl::Url.urlParse(url, true)
|
32
|
+
if parsed.hostname
|
33
|
+
# Encode hostnames in urls like:
|
34
|
+
# `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
35
|
+
#
|
36
|
+
# We don't encode unknown schemas, because it's likely that we encode
|
37
|
+
# something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
38
|
+
if !parsed.protocol || RECODE_HOSTNAME_FOR.include?(parsed.protocol)
|
39
|
+
begin
|
40
|
+
trailing_dot = parsed.hostname[-1] == '.'
|
41
|
+
parsed.hostname = SimpleIDN.to_ascii(parsed.hostname)
|
42
|
+
parsed.hostname << '.' if trailing_dot
|
43
|
+
rescue
|
44
|
+
# then use what we already have
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
29
48
|
|
30
|
-
|
31
|
-
# # Encode hostnames in urls like:
|
32
|
-
# # `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
33
|
-
# #
|
34
|
-
# # We don't encode unknown schemas, because it's likely that we encode
|
35
|
-
# # something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
36
|
-
# if !parsed[:protocol] || RECODE_HOSTNAME_FOR.include?(parsed[:protocol])
|
37
|
-
# # TODO is punycode really needed?
|
38
|
-
# # try {
|
39
|
-
# # parsed.hostname = punycode.toASCII(parsed.hostname);
|
40
|
-
# # } catch(er) {}
|
41
|
-
# end
|
42
|
-
# end
|
43
|
-
|
44
|
-
return MDUrl::Encode.encode(MDUrl::Format.format(parsed));
|
49
|
+
return MDUrl::Encode.encode(MDUrl::Format.format(parsed))
|
45
50
|
end
|
46
51
|
|
47
52
|
NORMALIZE_LINK_TEXT = lambda do |url|
|
48
53
|
parsed = MDUrl::Url.urlParse(url, true)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
54
|
+
if parsed.hostname
|
55
|
+
# Encode hostnames in urls like:
|
56
|
+
# `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
57
|
+
#
|
58
|
+
# We don't encode unknown schemas, because it's likely that we encode
|
59
|
+
# something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
60
|
+
if !parsed.protocol || RECODE_HOSTNAME_FOR.include?(parsed.protocol)
|
61
|
+
begin
|
62
|
+
trailing_dot = parsed.hostname[-1] == '.'
|
63
|
+
parsed.hostname = SimpleIDN.to_unicode(parsed.hostname)
|
64
|
+
parsed.hostname << '.' if trailing_dot
|
65
|
+
rescue
|
66
|
+
# then use what we already have
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
63
70
|
|
64
71
|
return MDUrl::Decode.decode(MDUrl::Format.format(parsed))
|
65
72
|
end
|
@@ -147,9 +154,9 @@ module MarkdownIt
|
|
147
154
|
# - __quotes__ - `“”‘’`, string. Double + single quotes replacement pairs, when
|
148
155
|
# typographer enabled and smartquotes on. Set doubles to '«»' for Russian,
|
149
156
|
# '„“' for German.
|
150
|
-
# - __highlight__ - `
|
157
|
+
# - __highlight__ - `nil`. Highlighter function for fenced code blocks.
|
151
158
|
# Highlighter `function (str, lang)` should return escaped HTML. It can also
|
152
|
-
# return
|
159
|
+
# return nil if the source was not changed and should be escaped externaly.
|
153
160
|
#
|
154
161
|
# ##### Example
|
155
162
|
#
|
@@ -273,20 +280,6 @@ module MarkdownIt
|
|
273
280
|
|
274
281
|
# Expose utils & helpers for easy acces from plugins
|
275
282
|
|
276
|
-
# TODO I don't know if these (utils and helpers) are really needed
|
277
|
-
# MarkdownIt#utils -> utils
|
278
|
-
#
|
279
|
-
# Assorted utility functions, useful to write plugins. See details
|
280
|
-
# [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).
|
281
|
-
# this.utils = utils;
|
282
|
-
|
283
|
-
# MarkdownIt#helpers -> helpers
|
284
|
-
#
|
285
|
-
# Link components parser functions, useful to write plugins. See details
|
286
|
-
# [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).
|
287
|
-
# this.helpers = helpers;
|
288
|
-
|
289
|
-
|
290
283
|
@options = {}
|
291
284
|
configure(presetName)
|
292
285
|
set(options) if options
|
@@ -366,7 +359,7 @@ module MarkdownIt
|
|
366
359
|
# .disable('smartquotes');
|
367
360
|
# ```
|
368
361
|
#------------------------------------------------------------------------------
|
369
|
-
def enable(list, ignoreInvalid)
|
362
|
+
def enable(list, ignoreInvalid = false)
|
370
363
|
result = []
|
371
364
|
|
372
365
|
list = [ list ] if !list.is_a? Array
|
@@ -374,10 +367,10 @@ module MarkdownIt
|
|
374
367
|
result << @core.ruler.enable(list, true)
|
375
368
|
result << @block.ruler.enable(list, true)
|
376
369
|
result << @inline.ruler.enable(list, true)
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
if missed.
|
370
|
+
result.flatten!
|
371
|
+
|
372
|
+
missed = list.select {|name| !result.include?(name) }
|
373
|
+
if !(missed.empty? || ignoreInvalid)
|
381
374
|
raise StandardError, "MarkdownIt. Failed to enable unknown rule(s): #{missed}"
|
382
375
|
end
|
383
376
|
|
@@ -391,7 +384,8 @@ module MarkdownIt
|
|
391
384
|
# - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
392
385
|
#
|
393
386
|
# The same as [[MarkdownIt.enable]], but turn specified rules off.
|
394
|
-
|
387
|
+
#------------------------------------------------------------------------------
|
388
|
+
def disable(list, ignoreInvalid = false)
|
395
389
|
result = []
|
396
390
|
|
397
391
|
list = [ list ] if !list.is_a? Array
|
@@ -399,10 +393,10 @@ module MarkdownIt
|
|
399
393
|
result << @core.ruler.disable(list, true)
|
400
394
|
result << @block.ruler.disable(list, true)
|
401
395
|
result << @inline.ruler.disable(list, true)
|
396
|
+
result.flatten!
|
402
397
|
|
403
|
-
missed = list.select {|name| result.include?(name) }
|
404
|
-
|
405
|
-
if missed.length && !ignoreInvalid
|
398
|
+
missed = list.select {|name| !result.include?(name) }
|
399
|
+
if !(missed.empty? || ignoreInvalid)
|
406
400
|
raise StandardError, "MarkdownIt. Failed to disable unknown rule(s): #{missed}"
|
407
401
|
end
|
408
402
|
|
@@ -426,10 +420,8 @@ module MarkdownIt
|
|
426
420
|
# });
|
427
421
|
# ```
|
428
422
|
def use(plugin, *args)
|
429
|
-
|
430
|
-
|
431
|
-
# plugin.call(plugin, args)
|
432
|
-
# return self
|
423
|
+
plugin.call(plugin, *args)
|
424
|
+
return self
|
433
425
|
end
|
434
426
|
|
435
427
|
|