motion-markdown-it 0.4.0.3.0
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 +7 -0
- data/README.md +243 -0
- data/lib/motion-markdown-it.rb +71 -0
- data/lib/motion-markdown-it/common/entities.rb +1084 -0
- data/lib/motion-markdown-it/common/html_blocks.rb +60 -0
- data/lib/motion-markdown-it/common/html_re.rb +28 -0
- data/lib/motion-markdown-it/common/string.rb +14 -0
- data/lib/motion-markdown-it/common/url_schemas.rb +173 -0
- data/lib/motion-markdown-it/common/utils.rb +216 -0
- data/lib/motion-markdown-it/helpers/parse_link_destination.rb +75 -0
- data/lib/motion-markdown-it/helpers/parse_link_label.rb +51 -0
- data/lib/motion-markdown-it/helpers/parse_link_title.rb +48 -0
- data/lib/motion-markdown-it/index.rb +507 -0
- data/lib/motion-markdown-it/parser_block.rb +113 -0
- data/lib/motion-markdown-it/parser_core.rb +46 -0
- data/lib/motion-markdown-it/parser_inline.rb +121 -0
- data/lib/motion-markdown-it/presets/commonmark.rb +76 -0
- data/lib/motion-markdown-it/presets/default.rb +42 -0
- data/lib/motion-markdown-it/presets/zero.rb +59 -0
- data/lib/motion-markdown-it/renderer.rb +286 -0
- data/lib/motion-markdown-it/ruler.rb +327 -0
- data/lib/motion-markdown-it/rules_block/blockquote.rb +138 -0
- data/lib/motion-markdown-it/rules_block/code.rb +35 -0
- data/lib/motion-markdown-it/rules_block/fence.rb +94 -0
- data/lib/motion-markdown-it/rules_block/heading.rb +56 -0
- data/lib/motion-markdown-it/rules_block/hr.rb +45 -0
- data/lib/motion-markdown-it/rules_block/html_block.rb +73 -0
- data/lib/motion-markdown-it/rules_block/lheading.rb +54 -0
- data/lib/motion-markdown-it/rules_block/list.rb +242 -0
- data/lib/motion-markdown-it/rules_block/paragraph.rb +51 -0
- data/lib/motion-markdown-it/rules_block/reference.rb +161 -0
- data/lib/motion-markdown-it/rules_block/state_block.rb +184 -0
- data/lib/motion-markdown-it/rules_block/table.rb +161 -0
- data/lib/motion-markdown-it/rules_core/block.rb +20 -0
- data/lib/motion-markdown-it/rules_core/inline.rb +20 -0
- data/lib/motion-markdown-it/rules_core/linkify.rb +138 -0
- data/lib/motion-markdown-it/rules_core/normalize.rb +44 -0
- data/lib/motion-markdown-it/rules_core/replacements.rb +90 -0
- data/lib/motion-markdown-it/rules_core/smartquotes.rb +158 -0
- data/lib/motion-markdown-it/rules_core/state_core.rb +20 -0
- data/lib/motion-markdown-it/rules_inline/autolink.rb +74 -0
- data/lib/motion-markdown-it/rules_inline/backticks.rb +51 -0
- data/lib/motion-markdown-it/rules_inline/emphasis.rb +172 -0
- data/lib/motion-markdown-it/rules_inline/entity.rb +51 -0
- data/lib/motion-markdown-it/rules_inline/escape.rb +55 -0
- data/lib/motion-markdown-it/rules_inline/html_inline.rb +49 -0
- data/lib/motion-markdown-it/rules_inline/image.rb +158 -0
- data/lib/motion-markdown-it/rules_inline/link.rb +153 -0
- data/lib/motion-markdown-it/rules_inline/newline.rb +47 -0
- data/lib/motion-markdown-it/rules_inline/state_inline.rb +57 -0
- data/lib/motion-markdown-it/rules_inline/strikethrough.rb +130 -0
- data/lib/motion-markdown-it/rules_inline/text.rb +94 -0
- data/lib/motion-markdown-it/token.rb +134 -0
- data/lib/motion-markdown-it/version.rb +5 -0
- data/spec/motion-markdown-it/bench_mark_spec.rb +44 -0
- data/spec/motion-markdown-it/commonmark_spec.rb +16 -0
- data/spec/motion-markdown-it/markdown_it_spec.rb +18 -0
- data/spec/motion-markdown-it/misc_spec.rb +277 -0
- data/spec/motion-markdown-it/ruler_spec.rb +153 -0
- data/spec/motion-markdown-it/testgen_helper.rb +68 -0
- data/spec/motion-markdown-it/token_spec.rb +17 -0
- data/spec/motion-markdown-it/utils_spec.rb +82 -0
- data/spec/spec_helper.rb +6 -0
- metadata +158 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# Parse link destination
|
2
|
+
#------------------------------------------------------------------------------
|
3
|
+
module MarkdownIt
|
4
|
+
module Helpers
|
5
|
+
module ParseLinkDestination
|
6
|
+
|
7
|
+
#------------------------------------------------------------------------------
|
8
|
+
def parseLinkDestination(str, pos, max)
|
9
|
+
lines = 0
|
10
|
+
start = pos
|
11
|
+
result = {ok: false, pos: 0, lines: 0, str: ''}
|
12
|
+
|
13
|
+
if (str.charCodeAt(pos) == 0x3C ) # <
|
14
|
+
pos += 1
|
15
|
+
while (pos < max)
|
16
|
+
code = str.charCodeAt(pos)
|
17
|
+
return result if (code == 0x0A ) # \n
|
18
|
+
if (code == 0x3E) # >
|
19
|
+
result[:pos] = pos + 1
|
20
|
+
result[:str] = unescapeAll(str.slice((start + 1)...pos))
|
21
|
+
result[:ok] = true
|
22
|
+
return result
|
23
|
+
end
|
24
|
+
if (code == 0x5C && pos + 1 < max) # \
|
25
|
+
pos += 2
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
pos += 1
|
30
|
+
end
|
31
|
+
|
32
|
+
# no closing '>'
|
33
|
+
return result
|
34
|
+
end
|
35
|
+
|
36
|
+
# this should be ... } else { ... branch
|
37
|
+
|
38
|
+
level = 0
|
39
|
+
while (pos < max)
|
40
|
+
code = str.charCodeAt(pos)
|
41
|
+
|
42
|
+
break if (code == 0x20)
|
43
|
+
|
44
|
+
# ascii control characters
|
45
|
+
break if (code < 0x20 || code == 0x7F)
|
46
|
+
|
47
|
+
if (code == 0x5C && pos + 1 < max) # \
|
48
|
+
pos += 2
|
49
|
+
next
|
50
|
+
end
|
51
|
+
|
52
|
+
if (code == 0x28) # (
|
53
|
+
level += 1
|
54
|
+
break if (level > 1)
|
55
|
+
end
|
56
|
+
|
57
|
+
if (code == 0x29) # )
|
58
|
+
level -= 1
|
59
|
+
break if (level < 0)
|
60
|
+
end
|
61
|
+
|
62
|
+
pos += 1
|
63
|
+
end
|
64
|
+
|
65
|
+
return result if (start == pos)
|
66
|
+
|
67
|
+
result[:str] = unescapeAll(str.slice(start...pos))
|
68
|
+
result[:lines] = lines
|
69
|
+
result[:pos] = pos
|
70
|
+
result[:ok] = true
|
71
|
+
return result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Parse link label
|
2
|
+
#
|
3
|
+
# this function assumes that first character ("[") already matches;
|
4
|
+
# returns the end of the label
|
5
|
+
#
|
6
|
+
#------------------------------------------------------------------------------
|
7
|
+
module MarkdownIt
|
8
|
+
module Helpers
|
9
|
+
module ParseLinkLabel
|
10
|
+
def parseLinkLabel(state, start, disableNested = false)
|
11
|
+
labelEnd = -1
|
12
|
+
max = state.posMax
|
13
|
+
oldPos = state.pos
|
14
|
+
state.pos = start + 1
|
15
|
+
level = 1
|
16
|
+
|
17
|
+
while (state.pos < max)
|
18
|
+
marker = state.src.charCodeAt(state.pos)
|
19
|
+
if (marker == 0x5D) # ]
|
20
|
+
level -= 1
|
21
|
+
if (level == 0)
|
22
|
+
found = true
|
23
|
+
break
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
prevPos = state.pos
|
28
|
+
state.md.inline.skipToken(state)
|
29
|
+
if (marker == 0x5B) # [
|
30
|
+
if (prevPos == state.pos - 1)
|
31
|
+
# increase level if we find text `[`, which is not a part of any token
|
32
|
+
level += 1
|
33
|
+
elsif (disableNested)
|
34
|
+
state.pos = oldPos
|
35
|
+
return -1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if (found)
|
41
|
+
labelEnd = state.pos
|
42
|
+
end
|
43
|
+
|
44
|
+
# restore old state
|
45
|
+
state.pos = oldPos
|
46
|
+
|
47
|
+
return labelEnd
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Parse link title
|
2
|
+
#------------------------------------------------------------------------------
|
3
|
+
module MarkdownIt
|
4
|
+
module Helpers
|
5
|
+
module ParseLinkTitle
|
6
|
+
|
7
|
+
#------------------------------------------------------------------------------
|
8
|
+
def parseLinkTitle(str, pos, max)
|
9
|
+
lines = 0
|
10
|
+
start = pos
|
11
|
+
result = {ok: false, pos: 0, lines: 0, str: ''}
|
12
|
+
|
13
|
+
return result if (pos >= max)
|
14
|
+
|
15
|
+
marker = str.charCodeAt(pos)
|
16
|
+
|
17
|
+
return result if (marker != 0x22 && marker != 0x27 && marker != 0x28) # " ' (
|
18
|
+
|
19
|
+
pos += 1
|
20
|
+
|
21
|
+
# if opening marker is "(", switch it to closing marker ")"
|
22
|
+
marker = 0x29 if (marker == 0x28)
|
23
|
+
|
24
|
+
while (pos < max)
|
25
|
+
code = str.charCodeAt(pos)
|
26
|
+
if (code == marker)
|
27
|
+
result[:pos] = pos + 1
|
28
|
+
result[:lines] = lines
|
29
|
+
result[:str] = unescapeAll(str.slice((start + 1)...pos))
|
30
|
+
result[:ok] = true
|
31
|
+
return result
|
32
|
+
elsif (code == 0x0A)
|
33
|
+
lines += 1
|
34
|
+
elsif (code == 0x5C && pos + 1 < max) # \
|
35
|
+
pos += 1
|
36
|
+
if (str.charCodeAt(pos) == 0x0A)
|
37
|
+
lines += 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
pos += 1
|
42
|
+
end
|
43
|
+
|
44
|
+
return result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,507 @@
|
|
1
|
+
# Main parser class
|
2
|
+
#------------------------------------------------------------------------------
|
3
|
+
|
4
|
+
CONFIG = {
|
5
|
+
default: MarkdownIt::Presets::Default.options,
|
6
|
+
zero: MarkdownIt::Presets::Zero.options,
|
7
|
+
commonmark: MarkdownIt::Presets::Commonmark.options
|
8
|
+
}
|
9
|
+
|
10
|
+
|
11
|
+
BAD_PROTOCOLS = [ 'vbscript', 'javascript', 'file' ]
|
12
|
+
|
13
|
+
VALIDATE_LINK = lambda do |url|
|
14
|
+
# url should be normalized at this point, and existing entities are decoded
|
15
|
+
#
|
16
|
+
str = url.strip.downcase
|
17
|
+
|
18
|
+
if str.include?(':') && BAD_PROTOCOLS.include?(str.split(':')[0])
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
|
24
|
+
RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ]
|
25
|
+
|
26
|
+
# mdurl comes from https://github.com/markdown-it/mdurl
|
27
|
+
NORMALIZE_LINK = lambda do |url|
|
28
|
+
parsed = MDUrl::Url.urlParse(url, true)
|
29
|
+
|
30
|
+
# if parsed[:hostname]
|
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));
|
45
|
+
end
|
46
|
+
|
47
|
+
NORMALIZE_LINK_TEXT = lambda do |url|
|
48
|
+
parsed = MDUrl::Url.urlParse(url, true)
|
49
|
+
|
50
|
+
# if parsed[:hostname]
|
51
|
+
# # Encode hostnames in urls like:
|
52
|
+
# # `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
53
|
+
# #
|
54
|
+
# # We don't encode unknown schemas, because it's likely that we encode
|
55
|
+
# # something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
56
|
+
# if !parsed[:protocol] || RECODE_HOSTNAME_FOR.include?(parsed[:protocol])
|
57
|
+
# # TODO is punycode really needed?
|
58
|
+
# # try {
|
59
|
+
# # parsed.hostname = punycode.toUnicode(parsed.hostname);
|
60
|
+
# # } catch(er) {}
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
|
64
|
+
return MDUrl::Decode.decode(MDUrl::Format.format(parsed))
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
#------------------------------------------------------------------------------
|
69
|
+
# class MarkdownIt
|
70
|
+
#
|
71
|
+
# Main parser/renderer class.
|
72
|
+
#
|
73
|
+
# ##### Usage
|
74
|
+
#
|
75
|
+
# ```javascript
|
76
|
+
# // node.js, "classic" way:
|
77
|
+
# var MarkdownIt = require('markdown-it'),
|
78
|
+
# md = new MarkdownIt();
|
79
|
+
# var result = md.render('# markdown-it rulezz!');
|
80
|
+
#
|
81
|
+
# // node.js, the same, but with sugar:
|
82
|
+
# var md = require('markdown-it')();
|
83
|
+
# var result = md.render('# markdown-it rulezz!');
|
84
|
+
#
|
85
|
+
# // browser without AMD, added to "window" on script load
|
86
|
+
# // Note, there are no dash.
|
87
|
+
# var md = window.markdownit();
|
88
|
+
# var result = md.render('# markdown-it rulezz!');
|
89
|
+
# ```
|
90
|
+
#
|
91
|
+
# Single line rendering, without paragraph wrap:
|
92
|
+
#
|
93
|
+
# ```javascript
|
94
|
+
# var md = require('markdown-it')();
|
95
|
+
# var result = md.renderInline('__markdown-it__ rulezz!');
|
96
|
+
# ```
|
97
|
+
#------------------------------------------------------------------------------
|
98
|
+
module MarkdownIt
|
99
|
+
class Parser
|
100
|
+
include MarkdownIt::Common::Utils
|
101
|
+
|
102
|
+
attr_accessor :inline
|
103
|
+
attr_accessor :block
|
104
|
+
attr_accessor :core
|
105
|
+
attr_accessor :renderer
|
106
|
+
attr_accessor :options
|
107
|
+
attr_accessor :validateLink
|
108
|
+
attr_accessor :normalizeLink
|
109
|
+
attr_accessor :normalizeLinkText
|
110
|
+
attr_accessor :linkify
|
111
|
+
|
112
|
+
# new MarkdownIt([presetName, options])
|
113
|
+
# - presetName (String): optional, `commonmark` / `zero`
|
114
|
+
# - options (Object)
|
115
|
+
#
|
116
|
+
# Creates parser instanse with given config. Can be called without `new`.
|
117
|
+
#
|
118
|
+
# ##### presetName
|
119
|
+
#
|
120
|
+
# MarkdownIt provides named presets as a convenience to quickly
|
121
|
+
# enable/disable active syntax rules and options for common use cases.
|
122
|
+
#
|
123
|
+
# - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -
|
124
|
+
# configures parser to strict [CommonMark](http://commonmark.org/) mode.
|
125
|
+
# - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -
|
126
|
+
# similar to GFM, used when no preset name given. Enables all available rules,
|
127
|
+
# but still without html, typographer & autolinker.
|
128
|
+
# - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -
|
129
|
+
# all rules disabled. Useful to quickly setup your config via `.enable()`.
|
130
|
+
# For example, when you need only `bold` and `italic` markup and nothing else.
|
131
|
+
#
|
132
|
+
# ##### options:
|
133
|
+
#
|
134
|
+
# - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!
|
135
|
+
# That's not safe! You may need external sanitizer to protect output from XSS.
|
136
|
+
# It's better to extend features via plugins, instead of enabling HTML.
|
137
|
+
# - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags
|
138
|
+
# (`<br />`). This is needed only for full CommonMark compatibility. In real
|
139
|
+
# world you will need HTML output.
|
140
|
+
# - __breaks__ - `false`. Set `true` to convert `\n` in paragraphs into `<br>`.
|
141
|
+
# - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.
|
142
|
+
# Can be useful for external highlighters.
|
143
|
+
# - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.
|
144
|
+
# - __typographer__ - `false`. Set `true` to enable [some language-neutral
|
145
|
+
# replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +
|
146
|
+
# quotes beautification (smartquotes).
|
147
|
+
# - __quotes__ - `“”‘’`, string. Double + single quotes replacement pairs, when
|
148
|
+
# typographer enabled and smartquotes on. Set doubles to '«»' for Russian,
|
149
|
+
# '„“' for German.
|
150
|
+
# - __highlight__ - `null`. Highlighter function for fenced code blocks.
|
151
|
+
# Highlighter `function (str, lang)` should return escaped HTML. It can also
|
152
|
+
# return empty string if the source was not changed and should be escaped externaly.
|
153
|
+
#
|
154
|
+
# ##### Example
|
155
|
+
#
|
156
|
+
# ```javascript
|
157
|
+
# // commonmark mode
|
158
|
+
# var md = require('markdown-it')('commonmark');
|
159
|
+
#
|
160
|
+
# // default mode
|
161
|
+
# var md = require('markdown-it')();
|
162
|
+
#
|
163
|
+
# // enable everything
|
164
|
+
# var md = require('markdown-it')({
|
165
|
+
# html: true,
|
166
|
+
# linkify: true,
|
167
|
+
# typographer: true
|
168
|
+
# });
|
169
|
+
# ```
|
170
|
+
#
|
171
|
+
# ##### Syntax highlighting
|
172
|
+
#
|
173
|
+
# ```js
|
174
|
+
# var hljs = require('highlight.js') // https://highlightjs.org/
|
175
|
+
#
|
176
|
+
# var md = require('markdown-it')({
|
177
|
+
# highlight: function (str, lang) {
|
178
|
+
# if (lang && hljs.getLanguage(lang)) {
|
179
|
+
# try {
|
180
|
+
# return hljs.highlight(lang, str).value;
|
181
|
+
# } catch (__) {}
|
182
|
+
# }
|
183
|
+
#
|
184
|
+
# try {
|
185
|
+
# return hljs.highlightAuto(str).value;
|
186
|
+
# } catch (__) {}
|
187
|
+
#
|
188
|
+
# return ''; // use external default escaping
|
189
|
+
# }
|
190
|
+
# });
|
191
|
+
# ```
|
192
|
+
#-----------------------------------------------------------------------------
|
193
|
+
def initialize(presetName = :default, options = {})
|
194
|
+
if options.empty?
|
195
|
+
if presetName.is_a? Hash
|
196
|
+
options = presetName
|
197
|
+
presetName = :default
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# MarkdownIt#inline -> ParserInline
|
202
|
+
#
|
203
|
+
# Instance of [[ParserInline]]. You may need it to add new rules when
|
204
|
+
# writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
205
|
+
# [[MarkdownIt.enable]].
|
206
|
+
@inline = ParserInline.new
|
207
|
+
|
208
|
+
# MarkdownIt#block -> ParserBlock
|
209
|
+
#
|
210
|
+
# Instance of [[ParserBlock]]. You may need it to add new rules when
|
211
|
+
# writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
212
|
+
# [[MarkdownIt.enable]].
|
213
|
+
@block = ParserBlock.new
|
214
|
+
|
215
|
+
# MarkdownIt#core -> Core
|
216
|
+
#
|
217
|
+
# Instance of [[Core]] chain executor. You may need it to add new rules when
|
218
|
+
# writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
219
|
+
# [[MarkdownIt.enable]].
|
220
|
+
@core = ParserCore.new
|
221
|
+
|
222
|
+
# MarkdownIt#renderer -> Renderer
|
223
|
+
#
|
224
|
+
# Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
|
225
|
+
# rules for new token types, generated by plugins.
|
226
|
+
#
|
227
|
+
# ##### Example
|
228
|
+
#
|
229
|
+
# ```javascript
|
230
|
+
# var md = require('markdown-it')();
|
231
|
+
#
|
232
|
+
# function myToken(tokens, idx, options, env, self) {
|
233
|
+
# //...
|
234
|
+
# return result;
|
235
|
+
# };
|
236
|
+
#
|
237
|
+
# md.renderer.rules['my_token'] = myToken
|
238
|
+
# ```
|
239
|
+
#
|
240
|
+
# See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
|
241
|
+
@renderer = Renderer.new
|
242
|
+
|
243
|
+
# MarkdownIt#linkify -> LinkifyIt
|
244
|
+
#
|
245
|
+
# [linkify-it](https://github.com/markdown-it/linkify-it) instance.
|
246
|
+
# Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)
|
247
|
+
# rule.
|
248
|
+
@linkify = ::Linkify.new
|
249
|
+
|
250
|
+
# MarkdownIt#validateLink(url) -> Boolean
|
251
|
+
#
|
252
|
+
# Link validation function. CommonMark allows too much in links. By default
|
253
|
+
# we disable `javascript:` and `vbscript:` schemas. You can change this
|
254
|
+
# behaviour.
|
255
|
+
#
|
256
|
+
# ```javascript
|
257
|
+
# var md = require('markdown-it')();
|
258
|
+
# // enable everything
|
259
|
+
# md.validateLink = function () { return true; }
|
260
|
+
# ```
|
261
|
+
@validateLink = VALIDATE_LINK
|
262
|
+
|
263
|
+
# MarkdownIt#normalizeLink(url) -> String
|
264
|
+
#
|
265
|
+
# Function used to encode link url to a machine-readable format,
|
266
|
+
# which includes url-encoding, punycode, etc.
|
267
|
+
@normalizeLink = NORMALIZE_LINK
|
268
|
+
|
269
|
+
# MarkdownIt#normalizeLinkText(url) -> String
|
270
|
+
#
|
271
|
+
# Function used to decode link url to a human-readable format`
|
272
|
+
@normalizeLinkText = NORMALIZE_LINK_TEXT
|
273
|
+
|
274
|
+
# Expose utils & helpers for easy acces from plugins
|
275
|
+
|
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
|
+
@options = {}
|
291
|
+
configure(presetName)
|
292
|
+
set(options) if options
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
# chainable
|
297
|
+
# MarkdownIt.set(options)
|
298
|
+
#
|
299
|
+
# Set parser options (in the same format as in constructor). Probably, you
|
300
|
+
# will never need it, but you can change options after constructor call.
|
301
|
+
#
|
302
|
+
# ##### Example
|
303
|
+
#
|
304
|
+
# ```javascript
|
305
|
+
# var md = require('markdown-it')()
|
306
|
+
# .set({ html: true, breaks: true })
|
307
|
+
# .set({ typographer, true });
|
308
|
+
# ```
|
309
|
+
#
|
310
|
+
# __Note:__ To achieve the best possible performance, don't modify a
|
311
|
+
# `markdown-it` instance options on the fly. If you need multiple configurations
|
312
|
+
# it's best to create multiple instances and initialize each with separate
|
313
|
+
# config.
|
314
|
+
#------------------------------------------------------------------------------
|
315
|
+
def set(options)
|
316
|
+
assign(@options, options)
|
317
|
+
return self
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
# chainable, internal
|
322
|
+
# MarkdownIt.configure(presets)
|
323
|
+
#
|
324
|
+
# Batch load of all options and compenent settings. This is internal method,
|
325
|
+
# and you probably will not need it. But if you with - see available presets
|
326
|
+
# and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
|
327
|
+
#
|
328
|
+
# We strongly recommend to use presets instead of direct config loads. That
|
329
|
+
# will give better compatibility with next versions.
|
330
|
+
#------------------------------------------------------------------------------
|
331
|
+
def configure(presets)
|
332
|
+
raise(ArgumentError, 'Wrong `markdown-it` preset, can\'t be empty') unless presets
|
333
|
+
|
334
|
+
unless presets.is_a? Hash
|
335
|
+
presetName = presets.to_sym
|
336
|
+
presets = CONFIG[presetName]
|
337
|
+
raise(ArgumentError, "Wrong `markdown-it` preset #{presetName}, check name") unless presets
|
338
|
+
end
|
339
|
+
self.set(presets[:options]) if presets[:options]
|
340
|
+
|
341
|
+
if presets[:components]
|
342
|
+
presets[:components].each_key do |name|
|
343
|
+
if presets[:components][name][:rules]
|
344
|
+
self.send(name).ruler.enableOnly(presets[:components][name][:rules])
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
return self
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
# chainable
|
353
|
+
# MarkdownIt.enable(list, ignoreInvalid)
|
354
|
+
# - list (String|Array): rule name or list of rule names to enable
|
355
|
+
# - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
356
|
+
#
|
357
|
+
# Enable list or rules. It will automatically find appropriate components,
|
358
|
+
# containing rules with given names. If rule not found, and `ignoreInvalid`
|
359
|
+
# not set - throws exception.
|
360
|
+
#
|
361
|
+
# ##### Example
|
362
|
+
#
|
363
|
+
# ```javascript
|
364
|
+
# var md = require('markdown-it')()
|
365
|
+
# .enable(['sub', 'sup'])
|
366
|
+
# .disable('smartquotes');
|
367
|
+
# ```
|
368
|
+
#------------------------------------------------------------------------------
|
369
|
+
def enable(list, ignoreInvalid)
|
370
|
+
result = []
|
371
|
+
|
372
|
+
list = [ list ] if !list.is_a? Array
|
373
|
+
|
374
|
+
result << @core.ruler.enable(list, true)
|
375
|
+
result << @block.ruler.enable(list, true)
|
376
|
+
result << @inline.ruler.enable(list, true)
|
377
|
+
|
378
|
+
missed = list.select {|name| result.include?(name) }
|
379
|
+
|
380
|
+
if missed.length && !ignoreInvalid
|
381
|
+
raise StandardError, "MarkdownIt. Failed to enable unknown rule(s): #{missed}"
|
382
|
+
end
|
383
|
+
|
384
|
+
return self
|
385
|
+
end
|
386
|
+
|
387
|
+
|
388
|
+
# chainable
|
389
|
+
# MarkdownIt.disable(list, ignoreInvalid)
|
390
|
+
# - list (String|Array): rule name or list of rule names to disable.
|
391
|
+
# - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
392
|
+
#
|
393
|
+
# The same as [[MarkdownIt.enable]], but turn specified rules off.
|
394
|
+
def disable(list, ignoreInvalid)
|
395
|
+
result = []
|
396
|
+
|
397
|
+
list = [ list ] if !list.is_a? Array
|
398
|
+
|
399
|
+
result << @core.ruler.disable(list, true)
|
400
|
+
result << @block.ruler.disable(list, true)
|
401
|
+
result << @inline.ruler.disable(list, true)
|
402
|
+
|
403
|
+
missed = list.select {|name| result.include?(name) }
|
404
|
+
|
405
|
+
if missed.length && !ignoreInvalid
|
406
|
+
raise StandardError, "MarkdownIt. Failed to disable unknown rule(s): #{missed}"
|
407
|
+
end
|
408
|
+
|
409
|
+
return self
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
# chainable
|
414
|
+
# MarkdownIt.use(plugin, params)
|
415
|
+
#
|
416
|
+
# Load specified plugin with given params into current parser instance.
|
417
|
+
# It's just a sugar to call `plugin(md, params)` with curring.
|
418
|
+
#
|
419
|
+
# ##### Example
|
420
|
+
#
|
421
|
+
# ```javascript
|
422
|
+
# var iterator = require('markdown-it-for-inline');
|
423
|
+
# var md = require('markdown-it')()
|
424
|
+
# .use(iterator, 'foo_replace', 'text', function (tokens, idx) {
|
425
|
+
# tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');
|
426
|
+
# });
|
427
|
+
# ```
|
428
|
+
def use(plugin, *args)
|
429
|
+
puts "Implement: Parser.use"
|
430
|
+
# var args = [ this ].concat(Array.prototype.slice.call(arguments, 1));
|
431
|
+
# plugin.call(plugin, args)
|
432
|
+
# return self
|
433
|
+
end
|
434
|
+
|
435
|
+
|
436
|
+
# internal
|
437
|
+
# MarkdownIt.parse(src, env) -> Array
|
438
|
+
# - src (String): source string
|
439
|
+
# - env (Object): environment sandbox
|
440
|
+
#
|
441
|
+
# Parse input string and returns list of block tokens (special token type
|
442
|
+
# "inline" will contain list of inline tokens). You should not call this
|
443
|
+
# method directly, until you write custom renderer (for example, to produce
|
444
|
+
# AST).
|
445
|
+
#
|
446
|
+
# `env` is used to pass data between "distributed" rules and return additional
|
447
|
+
# metadata like reference info, needed for for renderer. It also can be used to
|
448
|
+
# inject data in specific cases. Usually, you will be ok to pass `{}`,
|
449
|
+
# and then pass updated object to renderer.
|
450
|
+
#------------------------------------------------------------------------------
|
451
|
+
def parse(src, env)
|
452
|
+
state = RulesCore::StateCore.new(src, self, env)
|
453
|
+
@core.process(state)
|
454
|
+
return state.tokens
|
455
|
+
end
|
456
|
+
|
457
|
+
# MarkdownIt.render(src [, env]) -> String
|
458
|
+
# - src (String): source string
|
459
|
+
# - env (Object): environment sandbox
|
460
|
+
#
|
461
|
+
# Render markdown string into html. It does all magic for you :).
|
462
|
+
#
|
463
|
+
# `env` can be used to inject additional metadata (`{}` by default).
|
464
|
+
# But you will not need it with high probability. See also comment
|
465
|
+
# in [[MarkdownIt.parse]].
|
466
|
+
#------------------------------------------------------------------------------
|
467
|
+
def render(src, env = {})
|
468
|
+
# self.parse(src, { references: {} }).each {|token| pp token.to_json}
|
469
|
+
|
470
|
+
return @renderer.render(parse(src, env), @options, env)
|
471
|
+
end
|
472
|
+
|
473
|
+
#------------------------------------------------------------------------------
|
474
|
+
def to_html(src, env = {})
|
475
|
+
render(src, env)
|
476
|
+
end
|
477
|
+
|
478
|
+
# internal
|
479
|
+
# MarkdownIt.parseInline(src, env) -> Array
|
480
|
+
# - src (String): source string
|
481
|
+
# - env (Object): environment sandbox
|
482
|
+
#
|
483
|
+
# The same as [[MarkdownIt.parse]] but skip all block rules. It returns the
|
484
|
+
# block tokens list with the single `inline` element, containing parsed inline
|
485
|
+
# tokens in `children` property. Also updates `env` object.
|
486
|
+
#------------------------------------------------------------------------------
|
487
|
+
def parseInline(src, env)
|
488
|
+
state = RulesCore::StateCore.new(src, self, env)
|
489
|
+
state.inlineMode = true
|
490
|
+
@core.process(state)
|
491
|
+
return state.tokens
|
492
|
+
end
|
493
|
+
|
494
|
+
|
495
|
+
# MarkdownIt.renderInline(src [, env]) -> String
|
496
|
+
# - src (String): source string
|
497
|
+
# - env (Object): environment sandbox
|
498
|
+
#
|
499
|
+
# Similar to [[MarkdownIt.render]] but for single paragraph content. Result
|
500
|
+
# will NOT be wrapped into `<p>` tags.
|
501
|
+
#------------------------------------------------------------------------------
|
502
|
+
def renderInline(src, env = {})
|
503
|
+
return @renderer.render(parseInline(src, env), @options, env)
|
504
|
+
end
|
505
|
+
|
506
|
+
end
|
507
|
+
end
|