UNPKG

markmap-lib

Version:

Visualize your Markdown as mindmaps with Markmap

183 lines (154 loc) 4.57 kB
"use strict"; exports.__esModule = true; exports.buildTree = buildTree; exports.transform = transform; var _remarkable = require("remarkable"); var _util = require("./util"); const md = new _remarkable.Remarkable(); md.block.ruler.enable(['deflist']); function extractInline(token) { const html = []; let style = {}; for (const child of token.children) { if (child.type === 'text') { html.push((0, _util.wrapStyle)((0, _util.escapeHtml)(child.content), style)); } else if (child.type === 'code') { html.push((0, _util.wrapHtml)('code', (0, _util.wrapStyle)((0, _util.escapeHtml)(child.content), style))); } else if (child.type === 'softbreak') { html.push('<br/>'); } else if (child.type.endsWith('_open')) { const type = child.type.slice(0, -5); if (type === 'link') { html.push((0, _util.htmlOpen)('a', { href: child.href, title: child.title, target: '_blank', rel: 'noopener noreferrer' })); } else { style = Object.assign(Object.assign({}, style), {}, { [type]: true }); } } else if (child.type.endsWith('_close')) { const type = child.type.slice(0, -6); if (type === 'link') { html.push((0, _util.htmlClose)('a')); } else { style = Object.assign(Object.assign({}, style), {}, { [type]: false }); } } } return html.join(''); } function cleanNode(node, depth = 0) { if (node.t === 'heading') { // drop all paragraphs node.c = node.c.filter(item => item.t !== 'paragraph'); } else if (node.t === 'list_item') { var _node$p; // keep first paragraph as content of list_item, drop others node.c = node.c.filter(item => { if (['paragraph', 'fence'].includes(item.t)) { if (!node.v) node.v = item.v; return false; } return true; }); if (((_node$p = node.p) == null ? void 0 : _node$p.index) != null) { node.v = `${node.p.index}. ${node.v}`; } } else if (node.t === 'ordered_list') { var _node$p$start, _node$p2; let index = (_node$p$start = (_node$p2 = node.p) == null ? void 0 : _node$p2.start) != null ? _node$p$start : 1; node.c.forEach(item => { if (item.t === 'list_item') { item.p = Object.assign(Object.assign({}, item.p), {}, { index: index }); index += 1; } }); } if (node.c.length === 0) { delete node.c; } else { if (node.c.length === 1 && !node.c[0].v) { node.c = node.c[0].c; } node.c.forEach(child => cleanNode(child, depth + 1)); } node.d = depth; delete node.p; } function buildTree(tokens) { // TODO deal with <dl><dt> const root = { t: 'root', d: 0, v: '', c: [] }; const stack = [root]; let depth = 0; for (const token of tokens) { let current = stack[stack.length - 1]; if (token.type.endsWith('_open')) { const type = token.type.slice(0, -5); const payload = {}; if (type === 'heading') { depth = token.hLevel; while (((_current = current) == null ? void 0 : _current.d) >= depth) { var _current; stack.pop(); current = stack[stack.length - 1]; } } else { var _current2; depth = Math.max(depth, ((_current2 = current) == null ? void 0 : _current2.d) || 0) + 1; if (type === 'ordered_list') { payload.start = token.order; } } const item = { t: type, d: depth, p: payload, v: '', c: [] }; current.c.push(item); stack.push(item); } else if (!current) { continue; } else if (token.type === `${current.t}_close`) { if (current.t === 'heading') { depth = current.d; } else { stack.pop(); depth = 0; } } else if (token.type === 'inline') { current.v = `${current.v || ''}${extractInline(token)}`; } else if (token.type === 'fence') { current.c.push({ t: token.type, d: depth + 1, v: `<pre><code class="language-${token.params}">${(0, _util.escapeHtml)(token.content)}</code></pre>`, c: [] }); } else {// ignore other nodes } } return root; } function transform(content) { var _root$c; const tokens = md.parse(content || '', {}); let root = buildTree(tokens); cleanNode(root); if (((_root$c = root.c) == null ? void 0 : _root$c.length) === 1) root = root.c[0]; return root; }