'use strict'; /** * Local dependencies */ var assign = require('./common/utils').assign; var Renderer = require('./renderer'); var ParserCore = require('./parser_core'); var ParserBlock = require('./parser_block'); var ParserInline = require('./parser_inline'); var Ruler = require('./ruler'); /** * Preset configs */ var config = { 'default': require('./configs/default'), 'full': require('./configs/full'), 'commonmark': require('./configs/commonmark') }; /** * The `StateCore` class manages state. * * @param {Object} `instance` Remarkable instance * @param {String} `str` Markdown string * @param {Object} `env` */ function StateCore(instance, str, env) { this.src = str; this.env = env; this.options = instance.options; this.tokens = []; this.inlineMode = false; this.inline = instance.inline; this.block = instance.block; this.renderer = instance.renderer; this.typographer = instance.typographer; } /** * The main `Remarkable` class. Create an instance of * `Remarkable` with a `preset` and/or `options`. * * @param {String} `preset` If no preset is given, `default` is used. * @param {Object} `options` */ function Remarkable(preset, options) { if (typeof preset !== 'string') { options = preset; preset = 'default'; } this.inline = new ParserInline(); this.block = new ParserBlock(); this.core = new ParserCore(); this.renderer = new Renderer(); this.ruler = new Ruler(); this.options = {}; this.configure(config[preset]); this.set(options || {}); } /** * Set options as an alternative to passing them * to the constructor. * * ```js * md.set({typographer: true}); * ``` * @param {Object} `options` * @api public */ Remarkable.prototype.set = function (options) { assign(this.options, options); }; /** * Batch loader for components rules states, and options * * @param {Object} `presets` */ Remarkable.prototype.configure = function (presets) { var self = this; if (!presets) { throw new Error('Wrong `remarkable` 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.enable(presets.components[name].rules, true); } }); } }; /** * Use a plugin. * * ```js * var md = new Remarkable(); * * md.use(plugin1) * .use(plugin2, opts) * .use(plugin3); * ``` * * @param {Function} `plugin` * @param {Object} `options` * @return {Object} `Remarkable` for chaining */ Remarkable.prototype.use = function (plugin, options) { plugin(this, options); return this; }; /** * Parse the input `string` and return a tokens array. * Modifies `env` with definitions data. * * @param {String} `string` * @param {Object} `env` * @return {Array} Array of tokens */ Remarkable.prototype.parse = function (str, env) { var state = new StateCore(this, str, env); this.core.process(state); return state.tokens; }; /** * The main `.render()` method that does all the magic :) * * @param {String} `string` * @param {Object} `env` * @return {String} Rendered HTML. */ Remarkable.prototype.render = function (str, env) { env = env || {}; return this.renderer.render(this.parse(str, env), this.options, env); }; /** * Parse the given content `string` as a single string. * * @param {String} `string` * @param {Object} `env` * @return {Array} Array of tokens */ Remarkable.prototype.parseInline = function (str, env) { var state = new StateCore(this, str, env); state.inlineMode = true; this.core.process(state); return state.tokens; }; /** * Render a single content `string`, without wrapping it * to paragraphs * * @param {String} `str` * @param {Object} `env` * @return {String} */ Remarkable.prototype.renderInline = function (str, env) { env = env || {}; return this.renderer.render(this.parseInline(str, env), this.options, env); }; /** * Expose `Remarkable` */ module.exports = Remarkable; /** * Expose `utils`, Useful helper functions for custom * rendering. */ module.exports.utils = require('./common/utils');