motion-markdown-it 0.4.0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|