// Main perser class 'use strict'; var utils = require('./common/utils'); var helpers = require('./helpers'); var Renderer = require('./renderer'); var ParserCore = require('./parser_core'); var ParserBlock = require('./parser_block'); var ParserInline = require('./parser_inline'); var config = { 'default': require('./presets/default'), zero: require('./presets/zero'), full: require('./presets/full'), commonmark: require('./presets/commonmark') }; function StateCore(self, src, env) { this.src = src; this.env = env; this.options = self.options; this.tokens = []; this.inlineMode = false; this.inline = self.inline; this.block = self.block; this.renderer = self.renderer; this.typographer = self.typographer; } /** * class MarkdownIt * * Main parser/renderer class. * * ##### Usage * * ```javascript * // node.js, "classic" way: * var MarkdownIt = require('markdown-it'), * md = new MarkdownIt(); * var result = md.render('# markdown-it rulezz!'); * * // node.js, the same, but with sugar: * var md = require('markdown-it')(); * var result = md.render('# markdown-it rulezz!'); * * // browser without AMD, added to "window" on script load * // Note, there are no dash. * var md = window.markdownit(); * var result = md.render('# markdown-it rulezz!'); * ``` * * Single line rendering, without paragraph wrap: * * ```javascript * var md = require('markdown-it')(); * var result = md.renderInline('__markdown-it__ rulezz!'); * ``` **/ /** * new MarkdownIt([presetName, options]) * - presetName (String): optional, `commonmark` / `full` / `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. * * - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) - * configures parser to strict [CommonMark](http://commonmark.org/) mode. * - ["full"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/full.js) - * enables all available rules, but still without html, typographer & autolinker. * - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) - * similar to GFM, used when no preset name given. * - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) - * all rules disabled. Useful to quickly setup your config via `.enable()`. * For example, when you need only `bold` and `italic` markup and nothing else. * * ##### 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 * (`
`). 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](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) + * quotes beautification (smartquotes). * - __quotes__ - `“”‘’`, string. Double + single quotes replacement pairs, when * typographer enabled and smartquotes on. Set doubles to '«»' for Russian, * '„“' for German. * - __highlight__ - `null`. Highlighter function for fenced code blocks. * Highlighter `function (str, lang)` should return escaped HTML. It can also * return empty string 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')('full', { * html: true, * linkify: true, * typographer: true * }); * ``` * * ##### Syntax highlighting * * ```js * var hljs = require('highlight.js') // https://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 * } * }); * ``` **/ function MarkdownIt(presetName, options) { if (!(this instanceof MarkdownIt)) { return new MarkdownIt(presetName, options); } if (!options) { if (!utils.isString(presetName)) { options = presetName || {}; presetName = 'default'; } } /** * MarkdownIt#inline -> ParserInline * * Instance of inline parser. You may need it to add new rules when * writing plugins. For simple rules control use [[MarkdownIt.disable]] and * [[MarkdownIt.enable]]. **/ this.inline = new ParserInline(); /** * MarkdownIt#block -> ParserBlock * * Instance of block parser. You may need it to add new rules when * writing plugins. For simple rules control use [[MarkdownIt.disable]] and * [[MarkdownIt.enable]]. **/ this.block = new ParserBlock(); /** * MarkdownIt#core -> ParserCore * * 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]]. **/ this.core = new ParserCore(); /** * 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). **/ this.renderer = new Renderer(); // Expose utils & helpers for easy acces from plugins /** * MarkdownIt#utils -> utils * * Assorted utility functions, useful to write plugins. See details * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js). **/ this.utils = utils; /** * MarkdownIt#helpers -> helpers * * Link components parser functions, useful to write plugins. See details * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers). **/ this.helpers = helpers; this.options = {}; this.configure(config[presetName]); if (options) { this.set(options); } } /** 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. **/ MarkdownIt.prototype.set = function (options) { utils.assign(this.options, options); return this; }; /** 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](https://github.com/markdown-it/markdown-it/tree/master/lib/presets) **/ MarkdownIt.prototype.configure = function (presets) { var self = this; if (!presets) { throw new Error('Wrong `markdown-it` preset, check name/content'); } if (presets.options) { self.set(presets.options); } if (presets.components) { Object.keys(presets.components).forEach(function (name) { if (presets.components[name].rules) { self[name].ruler.enableOnly(presets.components[name].rules); } }); } return this; }; /** chainable * MarkdownIt.enable(list) * - list (String|Array): rule name or list of rule names to enable * * Enable list or rules. It will automatically find appropriate components, * containing rules with given names. * * ##### Example * * ```javascript * var md = require('markdown-it')() * .enable(['sub', 'sup']) * .disable('smartquotes'); * ``` **/ MarkdownIt.prototype.enable = function (list) { [ 'core', 'block', 'inline' ].forEach(function (chain) { this[chain].ruler.enable(list, true); }, this); return this; }; /** chainable * MarkdownIt.disable(list) * - list (String|Array): rule name or list of rule names to disable. * * The same as [[MarkdownIt.enable]], but turn specified rules off. **/ MarkdownIt.prototype.disable = function (list) { [ 'core', 'block', 'inline' ].forEach(function (chain) { this[chain].ruler.disable(list, true); }, this); return this; }; /** chainable * MarkdownIt.use(plugin, options) * * Load specified plugin with given options into current parser instance. * * ##### Example * * ```javascript * var md = require('markdown-it')() * .use(require('makkdown-it-emoji')); * ``` **/ MarkdownIt.prototype.use = function (plugin, options) { plugin(this, options); return this; }; /** internal * MarkdownIt.parse(src, env) -> Array * - src (String): source string * - env (Object): enviroment variables * * 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 modified with additional info. For example, with references data. * Also `env` can be used to pass external info to plugins. **/ MarkdownIt.prototype.parse = function (src, env) { var state = new StateCore(this, src, env); this.core.process(state); return state.tokens; }; /** * MarkdownIt.render(src [, env]) -> String * - src (String): source string * - env (Object): optional, enviroment variables * * Render markdown string into html. It does all magic for you :). * * `env` is `{}` by default. It's not used now directly, but you can pass * with it any additional data to plugins. **/ MarkdownIt.prototype.render = function (src, env) { env = env || {}; return this.renderer.render(this.parse(src, env), this.options, env); }; /** internal * MarkdownIt.parseInline(src, env) -> Array * - src (String): source string * - env (Object): enviroment variables * * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the * block tokens list with th single `inline` element, containing parsed inline * tokens in `children` property. **/ MarkdownIt.prototype.parseInline = function (src, env) { var state = new StateCore(this, src, env); state.inlineMode = true; this.core.process(state); return state.tokens; }; /** * MarkdownIt.renderInline(src [, env]) -> String * - src (String): source string * - env (Object): optional, enviroment variables * * Similar to [[MarkdownIt.render]] but for single paragraph content. Result * will NOT be wrapped into `

` tags. **/ MarkdownIt.prototype.renderInline = function (src, env) { env = env || {}; return this.renderer.render(this.parseInline(src, env), this.options, env); }; module.exports = MarkdownIt;