diff --git a/lib/common/utils.js b/lib/common/utils.js index 5340d70..97372f6 100644 --- a/lib/common/utils.js +++ b/lib/common/utils.js @@ -3,6 +3,10 @@ 'use strict'; +function _class(obj) { return Object.prototype.toString.call(obj); } + +function isString(obj) { return _class(obj) === '[object String]'; } + // Merge objects // function assign(obj /*from1, from2, from3, ...*/) { @@ -86,6 +90,7 @@ function replaceEntities(str) { exports.assign = assign; +exports.isString = isString; exports.escapeHtml = escapeHtml; exports.unescapeMd = unescapeMd; exports.isValidEntityCode = isValidEntityCode; diff --git a/lib/configs/commonmark.js b/lib/configs/commonmark.js new file mode 100644 index 0000000..832464d --- /dev/null +++ b/lib/configs/commonmark.js @@ -0,0 +1,68 @@ +// Commonmark default options + +'use strict'; + + +module.exports = { + options: { + html: true, // Enable html tags in source + xhtmlOut: true, // Use '/' to close single tags (
) + breaks: false, // Convert '\n' in paragraphs into
+ langPrefix: 'language-', // CSS language prefix for fenced blocks + linkify: false, // autoconvert url-like texts to links + typographer: false, // Enable smartypants and other sweet transforms + + // Highlighter function. Should return escaped html, + // or '' if input not changed + highlight: function (/*str, , lang*/) { return ''; }, + + maxNesting: 20 // Internal protection, recursion limit + }, + + components: { + + block: { + rules: [ + 'blockquote', + 'code', + 'fences', + 'heading', + 'hr', + 'htmlblock', + 'lheading', + 'list', + 'paragraph' + ] + }, + + inline: { + rules: [ + 'autolink', + 'backticks', + 'emphasis', + 'entity', + 'escape', + 'escape_html_char', + 'htmltag', + 'links', + 'newline', + 'text' + ] + }, + + typographer: { + options: { + singleQuotes: '‘’', // set empty to disable + doubleQuotes: '“”', // set '«»' for russian, '„“' for deutch, empty to disable + copyright: true, // (c) (C) → © + trademark: true, // (tm) (TM) → ™ + registered: true, // (r) (R) → ® + plusminus: true, // +- → ± + paragraph: true, // (p) (P) → § + ellipsis: true, // ... → … + dupes: true, // ???????? → ???, !!!!! → !!!, `,,` → `,` + dashes: true // -- → — + } + } + } +}; diff --git a/lib/configs/default.js b/lib/configs/default.js new file mode 100644 index 0000000..4d34a5d --- /dev/null +++ b/lib/configs/default.js @@ -0,0 +1,70 @@ +// Remarkable default options + +'use strict'; + + +module.exports = { + options: { + html: false, // Enable html tags in source + xhtmlOut: false, // Use '/' to close single tags (
) + breaks: false, // Convert '\n' in paragraphs into
+ langPrefix: 'language-', // CSS language prefix for fenced blocks + linkify: false, // autoconvert url-like texts to links + typographer: false, // Enable smartypants and other sweet transforms + + // Highlighter function. Should return escaped html, + // or '' if input not changed + highlight: function (/*str, , lang*/) { return ''; }, + + maxNesting: 20 // Internal protection, recursion limit + }, + + components: { + + block: { + rules: [ + 'blockquote', + 'code', + 'fences', + 'heading', + 'hr', + 'htmlblock', + 'lheading', + 'list', + 'paragraph', + 'table' + ] + }, + + inline: { + rules: [ + 'autolink', + 'backticks', + 'del', + 'emphasis', + 'entity', + 'escape', + 'escape_html_char', + 'htmltag', + 'links', + 'newline', + 'text' + ] + }, + + typographer: { + options: { + singleQuotes: '‘’', // set empty to disable + doubleQuotes: '“”', // set '«»' for russian, '„“' for deutch, empty to disable + copyright: true, // (c) (C) → © + trademark: true, // (tm) (TM) → ™ + registered: true, // (r) (R) → ® + plusminus: true, // +- → ± + paragraph: true, // (p) (P) → § + ellipsis: true, // ... → … + dupes: true, // ???????? → ???, !!!!! → !!!, `,,` → `,` + dashes: true // -- → — + } + } + } +}; diff --git a/lib/defaults/commonmark.js b/lib/defaults/commonmark.js deleted file mode 100644 index e6d7731..0000000 --- a/lib/defaults/commonmark.js +++ /dev/null @@ -1,19 +0,0 @@ -// Commonmark default options - -'use strict'; - - -module.exports = { - html: true, // Enable html tags in source - xhtmlOut: true, // Use '/' to close single tags (
) - breaks: false, // Convert '\n' in paragraphs into
- langPrefix: 'language-', // CSS language prefix for fenced blocks - linkify: false, // autoconvert url-like texts to links - typographer: false, // Enable smartypants and other sweet transforms - - // Highlighter function. Should return escaped html, - // or '' if input not changed - highlight: function (/*str, , lang*/) { return ''; }, - - maxNesting: 20 // Internal protection, recursion limit -}; diff --git a/lib/defaults/commonmark_rules.js b/lib/defaults/commonmark_rules.js deleted file mode 100644 index 58d9204..0000000 --- a/lib/defaults/commonmark_rules.js +++ /dev/null @@ -1,26 +0,0 @@ -// List of active rules for strict commonmark mode - -module.exports.block = [ - 'code', - 'blockquote', - 'fences', - 'heading', - 'hr', - 'htmlblock', - 'lheading', - 'list', - 'paragraph' -]; - -module.exports.inline = [ - 'autolink', - 'backticks', - 'emphasis', - 'entity', - 'escape', - 'escape_html_char', - 'htmltag', - 'links', - 'newline', - 'text' -]; diff --git a/lib/defaults/remarkable.js b/lib/defaults/remarkable.js deleted file mode 100644 index 1b33a01..0000000 --- a/lib/defaults/remarkable.js +++ /dev/null @@ -1,19 +0,0 @@ -// Remarkable default options - -'use strict'; - - -module.exports = { - html: false, // Enable html tags in source - xhtmlOut: false, // Use '/' to close single tags (
) - breaks: false, // Convert '\n' in paragraphs into
- langPrefix: 'language-', // CSS language prefix for fenced blocks - linkify: false, // autoconvert url-like texts to links - typographer: false, // Enable smartypants and other sweet transforms - - // Highlighter function. Should return escaped html, - // or '' if input not changed - highlight: function (/*str, , lang*/) { return ''; }, - - maxNesting: 20 // Internal protection, recursion limit -}; diff --git a/lib/defaults/typographer.js b/lib/defaults/typographer.js deleted file mode 100644 index 75790d1..0000000 --- a/lib/defaults/typographer.js +++ /dev/null @@ -1,17 +0,0 @@ -// Default typograph options - -'use strict'; - - -module.exports = { - singleQuotes: '‘’', // set empty to disable - doubleQuotes: '“”', // set '«»' for russian, '„“' for deutch, empty to disable - copyright: true, // (c) (C) → © - trademark: true, // (tm) (TM) → ™ - registered: true, // (r) (R) → ® - plusminus: true, // +- → ± - paragraph: true, // (p) (P) → § - ellipsis: true, // ... → … - dupes: true, // ???????? → ???, !!!!! → !!!, `,,` → `,` - dashes: true // -- → — -}; diff --git a/lib/index.js b/lib/index.js index 2d73e24..4339166 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,6 +4,7 @@ var assign = require('./common/utils').assign; +var isString = require('./common/utils').isString; var Renderer = require('./renderer'); var ParserBlock = require('./parser_block'); var ParserInline = require('./parser_inline'); @@ -11,15 +12,41 @@ var Typographer = require('./typographer'); var Linkifier = require('./linkifier'); -var defaults = require('./defaults/remarkable'); -var cmmDefaults = require('./defaults/commonmark'); -var cmmRules = require('./defaults/commonmark_rules'); +var config = { + 'default': require('./configs/default'), + commonmark: require('./configs/commonmark') +}; + +function configure(self, setupName) { + var cfg = config[setupName]; + + if (!cfg) { throw new Error('Wrong config name'); } + if (cfg.options) { self.set(cfg.options); } + + if (cfg.components) { + Object.keys(cfg.components).forEach(function (name) { + if (cfg.components[name].rules) { + self[name].ruler.enable(cfg.components[name].rules, true); + } + if (cfg.components[name].options) { + self[name].set(cfg.components[name].options); + } + }); + } +} // Main class // -function Remarkable(options) { - this.options = assign({}, defaults); +function Remarkable(setupName, options) { + if (!options) { + if (!isString(setupName)) { + options = setupName || {}; + setupName = 'default'; + } + } + + this.options = {}; this.state = null; this.inline = new ParserInline(); @@ -33,6 +60,8 @@ function Remarkable(options) { this.inline.typographer = this.typographer; this.inline.linkifier = this.linkifier; + configure(this, setupName.toLowerCase()); + if (options) { this.set(options); } } @@ -40,13 +69,7 @@ function Remarkable(options) { // Set options, if you did not passed those to constructor // Remarkable.prototype.set = function (options) { - if (String(options).toLowerCase() === 'commonmark') { - assign(this.options, cmmDefaults); - this.inline.ruler.enable(cmmRules.inline, true); - this.block.ruler.enable(cmmRules.block, true); - } else { - assign(this.options, options); - } + assign(this.options, options); }; diff --git a/lib/typographer.js b/lib/typographer.js index 42580aa..825279f 100644 --- a/lib/typographer.js +++ b/lib/typographer.js @@ -7,7 +7,6 @@ // - miltiplication 2 x 4 -> 2 × 4 -var defaults = require('./defaults/typographer'); var assign = require('./common/utils').assign; var Ruler = require('./ruler'); @@ -21,7 +20,7 @@ var rules = [ function Typographer() { this._rules = []; - this.options = assign({}, defaults); + this.options = {}; this.ruler = new Ruler(this.rulesUpdate.bind(this));