UNPKG

markdown-it-incremental-dom

Version:

markdown-it renderer plugin by using Incremental DOM.

122 lines (102 loc) 3.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; var _Parser = _interopRequireDefault(require("htmlparser2/lib/Parser")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _default(incrementalDom) { const autoClosingStack = []; const autoClosing = () => { const stack = autoClosingStack.shift(); if (!stack) return; stack.reverse().forEach(tag => incrementalDom.elementClose(tag)); }; const { attr, elementOpenEnd, elementVoid, text } = incrementalDom; const elementOpen = (tag, ...args) => { if (autoClosingStack.length > 0) autoClosingStack[0].push(tag); incrementalDom.elementOpen(tag, ...args); }; const elementOpenStart = tag => { if (autoClosingStack.length > 0) autoClosingStack[0].push(tag); incrementalDom.elementOpenStart(tag); }; const elementClose = tag => { if (autoClosingStack.length > 0) autoClosingStack[0].pop(); incrementalDom.elementClose(tag); }; const sanitizeName = name => name.replace(/[^-:\w]/g, ''); const iDOMParser = new _Parser.default({ onopentag: name => elementOpenEnd(sanitizeName(name)), onopentagname: name => elementOpenStart(sanitizeName(name)), onattribute: (name, value) => { const sanitizedName = sanitizeName(name); if (sanitizedName !== '') attr(sanitizedName, value); }, ontext: text, onclosetag: name => elementClose(sanitizeName(name)) }, { decodeEntities: true, lowerCaseAttributeNames: false, lowerCaseTags: false }); const wrapIncrementalDOM = html => typeof html === 'function' ? html() : iDOMParser.write(html); return { renderAttrsToArray(token) { if (!token.attrs) return []; return token.attrs.reduce((v, a) => v.concat(a), []); }, renderInline(tokens, options, env) { return () => { autoClosingStack.unshift([]); tokens.forEach((current, i) => { const { type } = current; if (this.rules[type] !== undefined) { wrapIncrementalDOM(this.rules[type](tokens, i, options, env, this)); } else { this.renderToken(tokens, i, options)(); } }); autoClosing(); }; }, renderToken(tokens, idx) { return () => { const token = tokens[idx]; if (token.hidden) return; if (token.nesting === -1) { elementClose(token.tag); } else { const func = token.nesting === 0 ? elementVoid : elementOpen; func.apply(this, [token.tag, '', []].concat(this.renderAttrsToArray(token))); } }; }, render(tokens, options, env) { return () => { autoClosingStack.unshift([]); tokens.forEach((current, i) => { const { type } = current; if (type === 'inline') { this.renderInline(current.children, options, env)(); } else if (this.rules[type] !== undefined) { wrapIncrementalDOM(this.rules[type](tokens, i, options, env, this)); } else { this.renderToken(tokens, i, options, env)(); } }); autoClosing(); iDOMParser.reset(); }; } }; }