Class: MarkdownIt::Parser

Inherits:
Object
  • Object
show all
Includes:
Common::Utils
Defined in:
lib/motion-markdown-it/index.rb

Constant Summary

Constants included from Common::Utils

Common::Utils::DIGITAL_ENTITY_TEST_RE, Common::Utils::ENTITY_RE, Common::Utils::HTML_ESCAPE_REPLACE_RE, Common::Utils::HTML_ESCAPE_TEST_RE, Common::Utils::HTML_REPLACEMENTS, Common::Utils::REGEXP_ESCAPE_RE, Common::Utils::UNESCAPE_ALL_RE, Common::Utils::UNESCAPE_MD_RE, Common::Utils::UNICODE_PUNCT_RE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Common::Utils

#arrayReplaceAt, #assign, #escapeHtml, #escapeRE, #fromCodePoint, #isMdAsciiPunct, #isPunctChar, #isValidEntityCode, #isWhiteSpace, #normalizeReference, #replaceEntityPattern, #unescapeAll, #unescapeMd

Constructor Details

#initialize(presetName = :default, options = {}) ⇒ Parser

new MarkdownIt([presetName, options])

  • presetName (String): optional, ‘commonmark` / `zero`

  • options (Object)

Creates parser instanse with given config. Can be called without ‘new`.

##### presetName

MarkdownIt provides named presets as a convenience to quickly enable/disable active syntax rules and options for common use cases.

##### options:

  • __html__ - ‘false`. Set `true` to enable HTML tags in source. Be careful! That’s not safe! You may need external sanitizer to protect output from XSS. It’s better to extend features via plugins, instead of enabling HTML.

  • __xhtmlOut__ - ‘false`. Set `true` to add ’/‘ when closing single tags (`<br />`). This is needed only for full CommonMark compatibility. In real world you will need HTML output.

  • __breaks__ - ‘false`. Set `true` to convert `n` in paragraphs into `
    `.

  • __langPrefix__ - ‘language-`. CSS language class prefix for fenced blocks. Can be useful for external highlighters.

  • __linkify__ - ‘false`. Set `true` to autoconvert URL-like text to links.

  • __typographer__ - ‘false`. Set `true` to enable [some language-neutral replacement](github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) + quotes beautification (smartquotes).

  • __quotes__ - ‘“”‘’`, String or Array. Double + single quotes replacement pairs, when typographer enabled and smartquotes on. For example, you can use `’«»„“‘` for Russian, `’„“‚‘‘` for German, and `[’«xA0’, ‘xA0»’, ‘‹xA0’, ‘xA0›’]‘ for French (including nbsp).

  • __highlight__ - ‘nil`. Highlighter function for fenced code blocks. Highlighter `function (str, lang)` should return escaped HTML. It can also return nil if the source was not changed and should be escaped externaly.

##### Example

“‘javascript // commonmark mode var md = require(’markdown-it’)(‘commonmark’);

// default mode var md = require(‘markdown-it’)();

// enable everything var md = require(‘markdown-it’)(

html: true,
linkify: true,
typographer: true

); “‘

##### Syntax highlighting

“‘js var hljs = require(’highlight.js’) // highlightjs.org/

var md = require(‘markdown-it’)({

highlight: function (str, lang) {
  if (lang && hljs.getLanguage(lang)) {
    try {
      return hljs.highlight(lang, str).value;
    } catch (__) {}
  }

  try {
    return hljs.highlightAuto(str).value;
  } catch (__) {}

  return ''; // use external default escaping
}

}); “‘




202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/motion-markdown-it/index.rb', line 202

def initialize(presetName = :default, options = {})
  if options.empty?
    if presetName.is_a? Hash
      options     = presetName
      presetName  = :default
    end
  end

  # MarkdownIt#inline -> ParserInline
  #
  # Instance of [[ParserInline]]. You may need it to add new rules when
  # writing plugins. For simple rules control use [[MarkdownIt.disable]] and
  # [[MarkdownIt.enable]].
  @inline = ParserInline.new

  # MarkdownIt#block -> ParserBlock
  #
  # Instance of [[ParserBlock]]. You may need it to add new rules when
  # writing plugins. For simple rules control use [[MarkdownIt.disable]] and
  # [[MarkdownIt.enable]].
  @block = ParserBlock.new

  # MarkdownIt#core -> Core
  #
  # Instance of [[Core]] chain executor. You may need it to add new rules when
  # writing plugins. For simple rules control use [[MarkdownIt.disable]] and
  # [[MarkdownIt.enable]].
  @core = ParserCore.new

  # MarkdownIt#renderer -> Renderer
  #
  # Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
  # rules for new token types, generated by plugins.
  #
  # ##### Example
  #
  # ```javascript
  # var md = require('markdown-it')();
  #
  # function myToken(tokens, idx, options, env, self) {
  #   //...
  #   return result;
  # };
  #
  # md.renderer.rules['my_token'] = myToken
  # ```
  #
  # See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
  @renderer = Renderer.new

  # MarkdownIt#linkify -> LinkifyIt
  #
  # [linkify-it](https://github.com/markdown-it/linkify-it) instance.
  # Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)
  # rule.
  @linkify = ::Linkify.new

  # MarkdownIt#validateLink(url) -> Boolean
  #
  # Link validation function. CommonMark allows too much in links. By default
  # we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas
  # except some embedded image types.
  #
  # You can change this behaviour:
  #
  # ```javascript
  # var md = require('markdown-it')();
  # // enable everything
  # md.validateLink = function () { return true; }
  # ```
  @validateLink = VALIDATE_LINK

  # MarkdownIt#normalizeLink(url) -> String
  #
  # Function used to encode link url to a machine-readable format,
  # which includes url-encoding, punycode, etc.
  @normalizeLink = NORMALIZE_LINK

  # MarkdownIt#normalizeLinkText(url) -> String
  #
  # Function used to decode link url to a human-readable format`
  @normalizeLinkText = NORMALIZE_LINK_TEXT

  #  Expose utils & helpers for easy acces from plugins

  @options = {}
  configure(presetName)
  set(options) if options
end

Instance Attribute Details

#blockObject

Returns the value of attribute block.



111
112
113
# File 'lib/motion-markdown-it/index.rb', line 111

def block
  @block
end

#coreObject

Returns the value of attribute core.



112
113
114
# File 'lib/motion-markdown-it/index.rb', line 112

def core
  @core
end

#inlineObject

Returns the value of attribute inline.



110
111
112
# File 'lib/motion-markdown-it/index.rb', line 110

def inline
  @inline
end

#linkifyObject

Returns the value of attribute linkify.



118
119
120
# File 'lib/motion-markdown-it/index.rb', line 118

def linkify
  @linkify
end

Returns the value of attribute normalizeLink.



116
117
118
# File 'lib/motion-markdown-it/index.rb', line 116

def normalizeLink
  @normalizeLink
end

#normalizeLinkTextObject

Returns the value of attribute normalizeLinkText.



117
118
119
# File 'lib/motion-markdown-it/index.rb', line 117

def normalizeLinkText
  @normalizeLinkText
end

#optionsObject

Returns the value of attribute options.



114
115
116
# File 'lib/motion-markdown-it/index.rb', line 114

def options
  @options
end

#rendererObject

Returns the value of attribute renderer.



113
114
115
# File 'lib/motion-markdown-it/index.rb', line 113

def renderer
  @renderer
end

Returns the value of attribute validateLink.



115
116
117
# File 'lib/motion-markdown-it/index.rb', line 115

def validateLink
  @validateLink
end

Instance Method Details

#configure(presets) ⇒ Object

chainable, internal MarkdownIt.configure(presets)

Batch load of all options and compenent settings. This is internal method, and you probably will not need it. But if you with - see available presets and data structure [here](github.com/markdown-it/markdown-it/tree/master/lib/presets)

We strongly recommend to use presets instead of direct config loads. That will give better compatibility with next versions.


Raises:

  • (ArgumentError)


328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/motion-markdown-it/index.rb', line 328

def configure(presets)
  raise(ArgumentError, 'Wrong `markdown-it` preset, can\'t be empty') unless presets

  unless presets.is_a? Hash
    presetName  = presets.to_sym
    presets     = CONFIG[presetName]
    raise(ArgumentError, "Wrong `markdown-it` preset #{presetName}, check name") unless presets
  end
  self.set(presets[:options]) if presets[:options]

  if presets[:components]
    presets[:components].each_key do |name|
      if presets[:components][name][:rules]
        self.send(name).ruler.enableOnly(presets[:components][name][:rules])
      end
    end
  end
  return self
end

#disable(list, ignoreInvalid = false) ⇒ Object

chainable MarkdownIt.disable(list, ignoreInvalid)

  • list (String|Array): rule name or list of rule names to disable.

  • ignoreInvalid (Boolean): set ‘true` to ignore errors when rule not found.

The same as [[MarkdownIt.enable]], but turn specified rules off.




392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/motion-markdown-it/index.rb', line 392

def disable(list, ignoreInvalid = false)
  result = []

  list = [ list ] if !list.is_a? Array

  result << @core.ruler.disable(list, true)
  result << @block.ruler.disable(list, true)
  result << @inline.ruler.disable(list, true)
  result.flatten!

  missed = list.select {|name| !result.include?(name) }
  if !(missed.empty? || ignoreInvalid)
    raise StandardError, "MarkdownIt. Failed to disable unknown rule(s): #{missed}"
  end

  return self
end

#enable(list, ignoreInvalid = false) ⇒ Object

chainable MarkdownIt.enable(list, ignoreInvalid)

  • list (String|Array): rule name or list of rule names to enable

  • ignoreInvalid (Boolean): set ‘true` to ignore errors when rule not found.

Enable list or rules. It will automatically find appropriate components, containing rules with given names. If rule not found, and ‘ignoreInvalid` not set - throws exception.

##### Example

“‘javascript var md = require(’markdown-it’)()

.enable(['sub', 'sup'])
.disable('smartquotes');

“‘




366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/motion-markdown-it/index.rb', line 366

def enable(list, ignoreInvalid = false)
  result = []

  list = [ list ] if !list.is_a? Array

  result << @core.ruler.enable(list, true)
  result << @block.ruler.enable(list, true)
  result << @inline.ruler.enable(list, true)
  result.flatten!
  
  missed = list.select {|name| !result.include?(name) }
  if !(missed.empty? || ignoreInvalid)
    raise StandardError, "MarkdownIt. Failed to enable unknown rule(s): #{missed}"
  end

  return self
end

#parse(src, env) ⇒ Object

internal MarkdownIt.parse(src, env) -> Array

  • src (String): source string

  • env (Object): environment sandbox

Parse input string and returns list of block tokens (special token type “inline” will contain list of inline tokens). You should not call this method directly, until you write custom renderer (for example, to produce AST).

‘env` is used to pass data between “distributed” rules and return additional metadata like reference info, needed for for renderer. It also can be used to inject data in specific cases. Usually, you will be ok to pass `{}`, and then pass updated object to renderer.




447
448
449
450
451
# File 'lib/motion-markdown-it/index.rb', line 447

def parse(src, env)
  state = RulesCore::StateCore.new(src, self, env)
  @core.process(state)
  return state.tokens
end

#parseInline(src, env) ⇒ Object

internal MarkdownIt.parseInline(src, env) -> Array

  • src (String): source string

  • env (Object): environment sandbox

The same as [[MarkdownIt.parse]] but skip all block rules. It returns the block tokens list with the single ‘inline` element, containing parsed inline tokens in `children` property. Also updates `env` object.




483
484
485
486
487
488
# File 'lib/motion-markdown-it/index.rb', line 483

def parseInline(src, env)
  state             = RulesCore::StateCore.new(src, self, env)
  state.inlineMode  = true
  @core.process(state)
  return state.tokens
end

#render(src, env = {}) ⇒ Object

MarkdownIt.render(src [, env]) -> String

  • src (String): source string

  • env (Object): environment sandbox

Render markdown string into html. It does all magic for you :).

‘env` can be used to inject additional metadata (`{}` by default). But you will not need it with high probability. See also comment in [[MarkdownIt.parse]].




463
464
465
466
467
# File 'lib/motion-markdown-it/index.rb', line 463

def render(src, env = {})
  # self.parse(src, { references: {} }).each {|token| pp token.to_json}

  return @renderer.render(parse(src, env), @options, env)
end

#renderInline(src, env = {}) ⇒ Object

MarkdownIt.renderInline(src [, env]) -> String

  • src (String): source string

  • env (Object): environment sandbox

Similar to [[MarkdownIt.render]] but for single paragraph content. Result will NOT be wrapped into ‘<p>` tags.




498
499
500
# File 'lib/motion-markdown-it/index.rb', line 498

def renderInline(src, env = {})
  return @renderer.render(parseInline(src, env), @options, env)
end

#set(options) ⇒ Object

chainable MarkdownIt.set(options)

Set parser options (in the same format as in constructor). Probably, you will never need it, but you can change options after constructor call.

##### Example

“‘javascript var md = require(’markdown-it’)()

.set({ html: true, breaks: true })
.set({ typographer, true });

“‘

Note: To achieve the best possible performance, don’t modify a ‘markdown-it` instance options on the fly. If you need multiple configurations it’s best to create multiple instances and initialize each with separate config.




312
313
314
315
# File 'lib/motion-markdown-it/index.rb', line 312

def set(options)
  assign(@options, options)
  return self
end

#to_html(src, env = {}) ⇒ Object




470
471
472
# File 'lib/motion-markdown-it/index.rb', line 470

def to_html(src, env = {})
  render(src, env)
end

#use(plugin, *args) ⇒ Object

chainable MarkdownIt.use(plugin, params)

Initialize and Load specified plugin with given params into current parser instance. It’s just a sugar to call ‘plugin.init_plugin(md, params)`

##### Example

“‘ruby md = MarkdownIt::Parser.new md.use(MDPlugin::Iterator, ’foo_replace’, ‘text’,

lambda {|tokens, idx|
  tokens[idx].content = tokens[idx].content.gsub(/foo/, 'bar')

}) “‘



426
427
428
429
# File 'lib/motion-markdown-it/index.rb', line 426

def use(plugin, *args)
  plugin.init_plugin(self, *args)
  return self
end