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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +243 -0
  3. data/lib/motion-markdown-it.rb +71 -0
  4. data/lib/motion-markdown-it/common/entities.rb +1084 -0
  5. data/lib/motion-markdown-it/common/html_blocks.rb +60 -0
  6. data/lib/motion-markdown-it/common/html_re.rb +28 -0
  7. data/lib/motion-markdown-it/common/string.rb +14 -0
  8. data/lib/motion-markdown-it/common/url_schemas.rb +173 -0
  9. data/lib/motion-markdown-it/common/utils.rb +216 -0
  10. data/lib/motion-markdown-it/helpers/parse_link_destination.rb +75 -0
  11. data/lib/motion-markdown-it/helpers/parse_link_label.rb +51 -0
  12. data/lib/motion-markdown-it/helpers/parse_link_title.rb +48 -0
  13. data/lib/motion-markdown-it/index.rb +507 -0
  14. data/lib/motion-markdown-it/parser_block.rb +113 -0
  15. data/lib/motion-markdown-it/parser_core.rb +46 -0
  16. data/lib/motion-markdown-it/parser_inline.rb +121 -0
  17. data/lib/motion-markdown-it/presets/commonmark.rb +76 -0
  18. data/lib/motion-markdown-it/presets/default.rb +42 -0
  19. data/lib/motion-markdown-it/presets/zero.rb +59 -0
  20. data/lib/motion-markdown-it/renderer.rb +286 -0
  21. data/lib/motion-markdown-it/ruler.rb +327 -0
  22. data/lib/motion-markdown-it/rules_block/blockquote.rb +138 -0
  23. data/lib/motion-markdown-it/rules_block/code.rb +35 -0
  24. data/lib/motion-markdown-it/rules_block/fence.rb +94 -0
  25. data/lib/motion-markdown-it/rules_block/heading.rb +56 -0
  26. data/lib/motion-markdown-it/rules_block/hr.rb +45 -0
  27. data/lib/motion-markdown-it/rules_block/html_block.rb +73 -0
  28. data/lib/motion-markdown-it/rules_block/lheading.rb +54 -0
  29. data/lib/motion-markdown-it/rules_block/list.rb +242 -0
  30. data/lib/motion-markdown-it/rules_block/paragraph.rb +51 -0
  31. data/lib/motion-markdown-it/rules_block/reference.rb +161 -0
  32. data/lib/motion-markdown-it/rules_block/state_block.rb +184 -0
  33. data/lib/motion-markdown-it/rules_block/table.rb +161 -0
  34. data/lib/motion-markdown-it/rules_core/block.rb +20 -0
  35. data/lib/motion-markdown-it/rules_core/inline.rb +20 -0
  36. data/lib/motion-markdown-it/rules_core/linkify.rb +138 -0
  37. data/lib/motion-markdown-it/rules_core/normalize.rb +44 -0
  38. data/lib/motion-markdown-it/rules_core/replacements.rb +90 -0
  39. data/lib/motion-markdown-it/rules_core/smartquotes.rb +158 -0
  40. data/lib/motion-markdown-it/rules_core/state_core.rb +20 -0
  41. data/lib/motion-markdown-it/rules_inline/autolink.rb +74 -0
  42. data/lib/motion-markdown-it/rules_inline/backticks.rb +51 -0
  43. data/lib/motion-markdown-it/rules_inline/emphasis.rb +172 -0
  44. data/lib/motion-markdown-it/rules_inline/entity.rb +51 -0
  45. data/lib/motion-markdown-it/rules_inline/escape.rb +55 -0
  46. data/lib/motion-markdown-it/rules_inline/html_inline.rb +49 -0
  47. data/lib/motion-markdown-it/rules_inline/image.rb +158 -0
  48. data/lib/motion-markdown-it/rules_inline/link.rb +153 -0
  49. data/lib/motion-markdown-it/rules_inline/newline.rb +47 -0
  50. data/lib/motion-markdown-it/rules_inline/state_inline.rb +57 -0
  51. data/lib/motion-markdown-it/rules_inline/strikethrough.rb +130 -0
  52. data/lib/motion-markdown-it/rules_inline/text.rb +94 -0
  53. data/lib/motion-markdown-it/token.rb +134 -0
  54. data/lib/motion-markdown-it/version.rb +5 -0
  55. data/spec/motion-markdown-it/bench_mark_spec.rb +44 -0
  56. data/spec/motion-markdown-it/commonmark_spec.rb +16 -0
  57. data/spec/motion-markdown-it/markdown_it_spec.rb +18 -0
  58. data/spec/motion-markdown-it/misc_spec.rb +277 -0
  59. data/spec/motion-markdown-it/ruler_spec.rb +153 -0
  60. data/spec/motion-markdown-it/testgen_helper.rb +68 -0
  61. data/spec/motion-markdown-it/token_spec.rb +17 -0
  62. data/spec/motion-markdown-it/utils_spec.rb +82 -0
  63. data/spec/spec_helper.rb +6 -0
  64. 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