markmap-lib
Advanced tools
Comparing version 0.5.1 to 0.6.0
@@ -12,2 +12,3 @@ #!/usr/bin/env node | ||
.option('-o, --output <output>', 'specify filename of the output HTML') | ||
.option('--enable-mathjax', 'enable MathJax support') | ||
.option('--no-open', 'do not open the output file after generation') | ||
@@ -19,2 +20,3 @@ .action((input, cmd) => { | ||
output: cmd.output, | ||
mathJax: cmd.enableMathjax, | ||
}); | ||
@@ -21,0 +23,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
'use strict'; | ||
@@ -11,2 +11,3 @@ | ||
var remarkable = require('remarkable'); | ||
var util = require('./util'); | ||
var template = require('./template'); | ||
@@ -17,41 +18,13 @@ | ||
function shallowEqual(a, b) { | ||
a = a || {}; | ||
b = b || {}; | ||
return Object.keys(a).length === Object.keys(b).length && Object.keys(a).every(k => a[k] === b[k]); | ||
} | ||
function extractInline(token) { | ||
const root = { | ||
t: 'inline', | ||
c: [] | ||
}; | ||
const stack = [root]; | ||
const html = []; | ||
let style = {}; | ||
for (const child of token.children) { | ||
const current = stack[stack.length - 1]; | ||
if (child.type === 'text') { | ||
current.c.push({ | ||
t: 'text', | ||
v: child.content, | ||
p: { | ||
style | ||
} | ||
}); | ||
html.push(util.wrapStyle(util.escapeHtml(child.content), style)); | ||
} else if (child.type === 'code') { | ||
current.c.push({ | ||
t: 'text', | ||
v: child.content, | ||
p: { | ||
style: { ...style, | ||
code: true | ||
} | ||
} | ||
}); | ||
html.push(util.wrapHtml('code', util.wrapStyle(util.escapeHtml(child.content), style))); | ||
} else if (child.type === 'softbreak') { | ||
current.c.push({ | ||
t: 'softbreak' | ||
}); | ||
html.push('<br/>'); | ||
} else if (child.type.endsWith('_open')) { | ||
@@ -61,12 +34,8 @@ const type = child.type.slice(0, -5); | ||
if (type === 'link') { | ||
const item = { | ||
t: 'link', | ||
c: [], | ||
p: { | ||
href: child.href, | ||
title: child.title | ||
} | ||
}; | ||
current.c.push(item); | ||
stack.push(item); | ||
html.push(util.htmlOpen('a', { | ||
href: child.href, | ||
title: child.title, | ||
target: '_blank', | ||
rel: 'noopener noreferrer' | ||
})); | ||
} else { | ||
@@ -81,3 +50,3 @@ style = { ...style, | ||
if (type === 'link') { | ||
stack.pop(); | ||
html.push(util.htmlClose('a')); | ||
} else { | ||
@@ -91,3 +60,3 @@ style = { ...style, | ||
return root.c; | ||
return html.join(''); | ||
} | ||
@@ -105,3 +74,3 @@ | ||
if (item.t === 'paragraph') { | ||
if (!node.v.length) node.v.push(...item.v); | ||
if (!node.v) node.v = item.v; | ||
return false; | ||
@@ -114,6 +83,3 @@ } | ||
if (((_node$p = node.p) == null ? void 0 : _node$p.index) != null) { | ||
node.v.unshift({ | ||
t: 'text', | ||
v: `${node.p.index}. ` | ||
}); | ||
node.v = `${node.p.index}. ${node.v}`; | ||
} | ||
@@ -137,3 +103,3 @@ } else if (node.t === 'ordered_list') { | ||
} else { | ||
if (node.c.length === 1 && !node.c[0].v.length) { | ||
if (node.c.length === 1 && !node.c[0].v) { | ||
node.c = node.c[0].c; | ||
@@ -145,18 +111,2 @@ } | ||
let last; | ||
const content = []; | ||
for (const item of node.v) { | ||
var _last, _last$p, _item$p; | ||
if (((_last = last) == null ? void 0 : _last.t) === 'text' && item.t === 'text' && shallowEqual((_last$p = last.p) == null ? void 0 : _last$p.style, (_item$p = item.p) == null ? void 0 : _item$p.style)) { | ||
last.v += item.v; | ||
} else { | ||
content.push(item); | ||
} | ||
last = item; | ||
} | ||
node.v = content; | ||
node.d = depth; | ||
@@ -171,3 +121,3 @@ delete node.p; | ||
d: 0, | ||
v: [], | ||
v: '', | ||
c: [] | ||
@@ -207,4 +157,4 @@ }; | ||
d: depth, | ||
v: [], | ||
p: payload, | ||
v: '', | ||
c: [] | ||
@@ -224,3 +174,3 @@ }; | ||
} else if (token.type === 'inline') { | ||
current.v.push(...extractInline(token)); | ||
current.v = `${current.v || ''}${extractInline(token)}`; | ||
} | ||
@@ -244,3 +194,4 @@ } | ||
input, | ||
open: openFile = true | ||
open: openFile = true, | ||
mathJax = false | ||
} = options; | ||
@@ -261,3 +212,5 @@ let { | ||
const root = transform(content || ''); | ||
const html = template.fillTemplate(root); | ||
const html = template.fillTemplate(root, { | ||
mathJax | ||
}); | ||
fs.promises.writeFile(output, html, 'utf8'); | ||
@@ -264,0 +217,0 @@ if (openFile) open(output); |
@@ -1,2 +0,2 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
'use strict'; | ||
@@ -6,5 +6,42 @@ | ||
const template = "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n<title>Markmap</title>\n<style>\n* {\n margin: 0;\n padding: 0;\n}\n#mindmap {\n display: block;\n width: 100vw;\n height: 100vh;\n}\n</style>\n<script src=\"https://cdn.jsdelivr.net/npm/d3@5\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/markmap-lib@0.5.1/dist/view.min.js\"></script>\n</head>\n<body>\n<svg id=\"mindmap\"></svg>\n<script>markmap.markmap('svg#mindmap', {/* data */}).fit()</script>\n</body>\n</html>\n"; | ||
function fillTemplate(data) { | ||
const html = template.replace('{/* data */}', JSON.stringify(data)); | ||
var util = require('./util'); | ||
const template = "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n<title>Markmap</title>\n<style>\n* {\n margin: 0;\n padding: 0;\n}\n#mindmap {\n display: block;\n width: 100vw;\n height: 100vh;\n}\n</style>\n<!--JS-->\n</head>\n<body>\n<svg id=\"mindmap\"></svg>\n<script>markmap.markmap('svg#mindmap',{/*extra*/}).fit()</script>\n</body>\n</html>\n"; | ||
const js = [{ | ||
src: 'https://cdn.jsdelivr.net/npm/d3@5' | ||
}, { | ||
src: 'https://cdn.jsdelivr.net/npm/markmap-lib@0.6.0/dist/view.min.js' | ||
}]; | ||
function buildCode(fn) { | ||
return `(${fn.toString()})()`; | ||
} | ||
function fillTemplate(data, opts) { | ||
const jsList = [...js]; | ||
const extra = [JSON.stringify(data)]; | ||
if (opts == null ? void 0 : opts.mathJax) { | ||
jsList.push(buildCode(() => { | ||
window.MathJax = { | ||
options: { | ||
skipHtmlTags: { | ||
'[-]': ['code', 'pre'] | ||
} | ||
} | ||
}; | ||
}), { | ||
src: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js' | ||
}); | ||
extra.push(buildCode(() => ({ | ||
processHtml: nodes => { | ||
var _MathJax$typeset, _MathJax; | ||
(_MathJax$typeset = (_MathJax = window.MathJax).typeset) == null ? void 0 : _MathJax$typeset.call(_MathJax, nodes); | ||
} | ||
}))); | ||
} | ||
const jsStr = jsList.map(data => util.wrapHtml('script', typeof data === 'string' ? data : '', typeof data === 'string' ? null : data)).join(''); | ||
const html = template.replace('<!--JS-->', jsStr).replace('{/*extra*/}', extra.join(',')); | ||
return html; | ||
@@ -11,0 +48,0 @@ } |
@@ -1,5 +0,6 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
'use strict'; | ||
var remarkable = require('remarkable'); | ||
var util = require('./util'); | ||
@@ -9,41 +10,13 @@ const md = new remarkable.Remarkable(); | ||
function shallowEqual(a, b) { | ||
a = a || {}; | ||
b = b || {}; | ||
return Object.keys(a).length === Object.keys(b).length && Object.keys(a).every(k => a[k] === b[k]); | ||
} | ||
function extractInline(token) { | ||
const root = { | ||
t: 'inline', | ||
c: [] | ||
}; | ||
const stack = [root]; | ||
const html = []; | ||
let style = {}; | ||
for (const child of token.children) { | ||
const current = stack[stack.length - 1]; | ||
if (child.type === 'text') { | ||
current.c.push({ | ||
t: 'text', | ||
v: child.content, | ||
p: { | ||
style | ||
} | ||
}); | ||
html.push(util.wrapStyle(util.escapeHtml(child.content), style)); | ||
} else if (child.type === 'code') { | ||
current.c.push({ | ||
t: 'text', | ||
v: child.content, | ||
p: { | ||
style: { ...style, | ||
code: true | ||
} | ||
} | ||
}); | ||
html.push(util.wrapHtml('code', util.wrapStyle(util.escapeHtml(child.content), style))); | ||
} else if (child.type === 'softbreak') { | ||
current.c.push({ | ||
t: 'softbreak' | ||
}); | ||
html.push('<br/>'); | ||
} else if (child.type.endsWith('_open')) { | ||
@@ -53,12 +26,8 @@ const type = child.type.slice(0, -5); | ||
if (type === 'link') { | ||
const item = { | ||
t: 'link', | ||
c: [], | ||
p: { | ||
href: child.href, | ||
title: child.title | ||
} | ||
}; | ||
current.c.push(item); | ||
stack.push(item); | ||
html.push(util.htmlOpen('a', { | ||
href: child.href, | ||
title: child.title, | ||
target: '_blank', | ||
rel: 'noopener noreferrer' | ||
})); | ||
} else { | ||
@@ -73,3 +42,3 @@ style = { ...style, | ||
if (type === 'link') { | ||
stack.pop(); | ||
html.push(util.htmlClose('a')); | ||
} else { | ||
@@ -83,3 +52,3 @@ style = { ...style, | ||
return root.c; | ||
return html.join(''); | ||
} | ||
@@ -97,3 +66,3 @@ | ||
if (item.t === 'paragraph') { | ||
if (!node.v.length) node.v.push(...item.v); | ||
if (!node.v) node.v = item.v; | ||
return false; | ||
@@ -106,6 +75,3 @@ } | ||
if (((_node$p = node.p) == null ? void 0 : _node$p.index) != null) { | ||
node.v.unshift({ | ||
t: 'text', | ||
v: `${node.p.index}. ` | ||
}); | ||
node.v = `${node.p.index}. ${node.v}`; | ||
} | ||
@@ -129,3 +95,3 @@ } else if (node.t === 'ordered_list') { | ||
} else { | ||
if (node.c.length === 1 && !node.c[0].v.length) { | ||
if (node.c.length === 1 && !node.c[0].v) { | ||
node.c = node.c[0].c; | ||
@@ -137,18 +103,2 @@ } | ||
let last; | ||
const content = []; | ||
for (const item of node.v) { | ||
var _last, _last$p, _item$p; | ||
if (((_last = last) == null ? void 0 : _last.t) === 'text' && item.t === 'text' && shallowEqual((_last$p = last.p) == null ? void 0 : _last$p.style, (_item$p = item.p) == null ? void 0 : _item$p.style)) { | ||
last.v += item.v; | ||
} else { | ||
content.push(item); | ||
} | ||
last = item; | ||
} | ||
node.v = content; | ||
node.d = depth; | ||
@@ -163,3 +113,3 @@ delete node.p; | ||
d: 0, | ||
v: [], | ||
v: '', | ||
c: [] | ||
@@ -199,4 +149,4 @@ }; | ||
d: depth, | ||
v: [], | ||
p: payload, | ||
v: '', | ||
c: [] | ||
@@ -216,3 +166,3 @@ }; | ||
} else if (token.type === 'inline') { | ||
current.v.push(...extractInline(token)); | ||
current.v = `${current.v || ''}${extractInline(token)}`; | ||
} | ||
@@ -219,0 +169,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
'use strict'; | ||
@@ -7,2 +7,10 @@ | ||
const uniqId = Math.random().toString(36).slice(2, 8); | ||
let globalIndex = 0; | ||
function getId() { | ||
globalIndex += 1; | ||
return `mm-${uniqId}-${globalIndex}`; | ||
} | ||
function walkTree(tree, callback, key = 'c') { | ||
@@ -20,37 +28,2 @@ const walk = (item, parent) => callback(item, () => { | ||
let canvas; | ||
function getTextRect(items, options) { | ||
// re-use canvas object for better performance | ||
if (!canvas) canvas = document.createElement('canvas'); | ||
const context = canvas.getContext('2d'); | ||
context.font = options.nodeFont; | ||
let maxWidth = 0; | ||
let width = 0; | ||
let height = options.lineHeight; | ||
let row = 0; | ||
const walk = item => { | ||
if (item.t === 'text') { | ||
height = (row + 1) * options.lineHeight; | ||
item.p = { ...item.p, | ||
x: width, | ||
y: height | ||
}; | ||
if (!width && row) item.p.newline = true; | ||
const metrics = context.measureText(item.v); | ||
width += metrics.width; | ||
if (maxWidth < width) maxWidth = width; | ||
} else if (item.t === 'softbreak') { | ||
width = 0; | ||
row += 1; | ||
} else if (item.t === 'link') { | ||
item.c.forEach(walk); | ||
} | ||
}; | ||
items.forEach(walk); | ||
return [maxWidth, height]; | ||
} | ||
function linkWidth(nodeData) { | ||
@@ -61,11 +34,2 @@ const data = nodeData.data; | ||
function getKey(v) { | ||
const result = ['<']; | ||
v.forEach(item => { | ||
if (item.t === 'text') result.push(item.v.replace(/[<|&]/g, m => `&${m}`));else if (item.c) result.push(getKey(item.c)); | ||
}); | ||
result.push('>'); | ||
return result.join(''); | ||
} | ||
function adjustSpacing(tree, spacing) { | ||
@@ -79,17 +43,38 @@ walkTree(tree, (d, next) => { | ||
function getChildNodes() { | ||
return this.childNodes; | ||
function arrayFrom(arrayLike) { | ||
const array = []; | ||
for (let i = 0; i < arrayLike.length; i += 1) { | ||
array.push(arrayLike[i]); | ||
} | ||
return array; | ||
} | ||
function markmap(svg, data, opts) { | ||
svg = svg.datum ? svg : d3.select(svg); | ||
const classList = (svg.attr('class') || '').split(' ').filter(Boolean); | ||
function childSelector(filter) { | ||
if (typeof filter === 'string') { | ||
const tagName = filter; | ||
if (classList.indexOf('markmap') < 0) { | ||
classList.push('markmap'); | ||
svg.attr('class', classList.join(' ')); | ||
filter = el => el.tagName === tagName; | ||
} | ||
const style = svg.append('style'); | ||
const g = svg.append('g'); | ||
const filterFn = filter; | ||
return function selector() { | ||
let nodes = arrayFrom(this.childNodes); | ||
if (filterFn) nodes = nodes.filter(node => filterFn(node)); | ||
return nodes; | ||
}; | ||
} | ||
function addClass(className, ...rest) { | ||
const classList = (className || '').split(' ').filter(Boolean); | ||
rest.forEach(item => { | ||
if (item && classList.indexOf(item) < 0) classList.push(item); | ||
}); | ||
return classList.join(' '); | ||
} | ||
function markmap(svg, data, opts) { | ||
svg = svg.datum ? svg : d3.select(svg); | ||
const styleNode = svg.append('style'); | ||
const zoom = d3.zoom().on('zoom', handleZoom); | ||
@@ -99,4 +84,4 @@ const svgNode = svg.node(); | ||
duration: 500, | ||
nodeFont: '300 16px sans-serif', | ||
lineHeight: 20, | ||
nodeFont: '300 16px/20px sans-serif', | ||
nodeMinHeight: 16, | ||
spacingVertical: 5, | ||
@@ -108,5 +93,9 @@ spacingHorizontal: 80, | ||
colorDepth: 0, | ||
paddingX: 8, | ||
...opts | ||
}; | ||
const state = {}; | ||
const state = { | ||
id: options.id || getId() | ||
}; | ||
const g = svg.append('g').attr('class', `${state.id}-g`); | ||
updateStyle(); | ||
@@ -126,12 +115,22 @@ | ||
function getStyleContent() { | ||
const { | ||
style | ||
} = options; | ||
const styleText = style ? style(state.id) : `\ | ||
.${state.id} a { color: #0097e6; } | ||
.${state.id} a:hover { color: #00a8ff; } | ||
.${state.id}-g > path { fill: none; } | ||
.${state.id}-fo > div { font: ${options.nodeFont}; white-space: nowrap; } | ||
.${state.id}-fo > div > code { padding: .2em .4em; font-size: calc(1em - 2px); color: #555; background-color: #f0f0f0; border-radius: 2px; } | ||
.${state.id}-fo > div > em { font-style: italic; } | ||
.${state.id}-fo > div > strong { font-weight: 500; } | ||
.${state.id}-g > g { cursor: pointer; } | ||
`; | ||
return styleText; | ||
} | ||
function updateStyle() { | ||
style.text(`\ | ||
.markmap a { fill: #0097e6; } | ||
.markmap a:hover { fill: #00a8ff; } | ||
.markmap path { fill: none; } | ||
.markmap text { font: ${options.nodeFont} } | ||
.markmap tspan.markmap-em { font-style: italic; } | ||
.markmap tspan.markmap-strong { font-weight: 500; } | ||
.markmap g > g { cursor: pointer; } | ||
`); | ||
svg.attr('class', addClass(svg.attr('class'), state.id)); | ||
styleNode.text(getStyleContent()); | ||
} | ||
@@ -146,3 +145,3 @@ | ||
function addKeys(node) { | ||
function initializeData(node) { | ||
let i = 0; | ||
@@ -153,2 +152,22 @@ let c = 0; | ||
} = options; | ||
const container = document.createElement('div'); | ||
const containerClass = `${state.id}-container`; | ||
container.className = addClass(container.className, `${state.id}-fo`, containerClass); | ||
const style = document.createElement('style'); | ||
style.textContent = ` | ||
${getStyleContent()} | ||
.${containerClass} { | ||
position: absolute; | ||
width: 0; | ||
height: 0; | ||
top: -100px; | ||
left: -100px; | ||
overflow: hidden; | ||
font: ${options.nodeFont}; | ||
} | ||
.${containerClass} > div { | ||
display: inline-block; | ||
} | ||
`; | ||
document.body.append(style, container); | ||
walkTree(node, (item, next, parent) => { | ||
@@ -160,2 +179,5 @@ var _parent$p; | ||
const el = document.createElement('div'); | ||
el.innerHTML = item.v; | ||
container.append(el); | ||
item.p = { | ||
@@ -166,6 +188,7 @@ // unique ID | ||
c, | ||
el, | ||
...item.p, | ||
// TODO keep keys for unchanged objects | ||
// unique key, should be based on content | ||
k: `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${i}:${getKey(item.v)}` | ||
k: `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${i}:${item.v}` | ||
}; | ||
@@ -175,2 +198,10 @@ next(); | ||
}); | ||
if (options.processHtml) options.processHtml(arrayFrom(container.childNodes)); | ||
walkTree(node, (item, next) => { | ||
const rect = item.p.el.getBoundingClientRect(); | ||
item.p.s = [Math.ceil(rect.width), Math.max(Math.ceil(rect.height), options.nodeMinHeight)]; | ||
next(); | ||
}); | ||
container.remove(); | ||
style.remove(); | ||
} | ||
@@ -183,3 +214,3 @@ | ||
function setData(data, opts) { | ||
addKeys(data); | ||
initializeData(data); | ||
state.data = data; | ||
@@ -220,44 +251,2 @@ if (opts) setOptions(opts); | ||
function handleLink(d) { | ||
d3.event.preventDefault(); | ||
window.open(d.p.href); | ||
} | ||
function renderTextNode(t, d) { | ||
if (d.t === 'link') { | ||
const a = t.append('a').attr('href', d.p.href).attr('title', d.p.title).on('click', handleLink); | ||
const text = a.selectAll(getChildNodes).data(d => d.c); | ||
text.enter().each(function (d) { | ||
const t = d3.select(this); | ||
renderTextNode(t, d); | ||
}); | ||
} | ||
if (d.t === 'text') { | ||
t.append('tspan').text(d.v).attr('class', d => { | ||
var _d$p; | ||
const style = ((_d$p = d.p) == null ? void 0 : _d$p.style) || {}; | ||
return [style.em && 'markmap-em', style.strong && 'markmap-strong'].filter(Boolean).join(' '); | ||
}).attr('x', d => { | ||
var _d$p2; | ||
return ((_d$p2 = d.p) == null ? void 0 : _d$p2.x) + 8; | ||
}).attr('y', d => { | ||
var _d$p3; | ||
return ((_d$p3 = d.p) == null ? void 0 : _d$p3.y) - 4; | ||
}); | ||
} | ||
} | ||
function renderText(text) { | ||
const textNode = text.selectAll(getChildNodes).data(d => d.data.v); | ||
textNode.enter().each(function (d) { | ||
const t = d3.select(this); | ||
renderTextNode(t, d); | ||
}); | ||
return text; | ||
} | ||
function renderData(originData) { | ||
@@ -271,9 +260,8 @@ var _origin$data$x, _origin$data$y; | ||
const layout = d3Flextree.flextree().children(d => { | ||
var _d$p4; | ||
var _d$p; | ||
return !((_d$p4 = d.p) == null ? void 0 : _d$p4.f) && d.c; | ||
return !((_d$p = d.p) == null ? void 0 : _d$p.f) && d.c; | ||
}).nodeSize(d => { | ||
d.outerSize = d.outerSize || getTextRect(d.data.v, options); | ||
const [width, height] = d.outerSize; | ||
return [height, width + (width ? 16 : 0) + spacingHorizontal]; | ||
const [width, height] = d.data.p.s; | ||
return [height, width + (width ? options.paddingX * 2 : 0) + spacingHorizontal]; | ||
}).spacing((a, b) => { | ||
@@ -301,14 +289,14 @@ return a.parent === b.parent ? options.spacingVertical : options.spacingVertical * 2; | ||
const node = g.selectAll('g').data(descendants, d => d.data.p.k); | ||
const node = g.selectAll(childSelector('g')).data(descendants, d => d.data.p.k); | ||
const nodeEnter = node.enter().append('g').attr('transform', d => `translate(${y0 + origin.ySizeInner - d.ySizeInner},${x0 + origin.xSize / 2 - d.xSize})`).on('click', handleClick); | ||
const nodeExit = node.exit().transition().duration(options.duration); | ||
nodeExit.select('rect').attr('width', 0).attr('x', d => d.ySizeInner); | ||
nodeExit.select('text').attr('fill-opacity', 0); | ||
nodeExit.select('foreignObject').style('opacity', 0); | ||
nodeExit.attr('transform', d => `translate(${origin.y + origin.ySizeInner - d.ySizeInner},${origin.x + origin.xSize / 2 - d.xSize})`).remove(); | ||
const nodeMerge = node.merge(nodeEnter); | ||
nodeMerge.transition().duration(options.duration).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`); | ||
nodeMerge.selectAll('rect').data(d => [d], d => d.data.p.k).join(enter => { | ||
nodeMerge.selectAll(childSelector('rect')).data(d => [d], d => d.data.p.k).join(enter => { | ||
return enter.append('rect').attr('x', d => d.ySizeInner).attr('y', d => d.xSize - linkWidth(d) / 2).attr('width', 0).attr('height', linkWidth); | ||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('x', -1).attr('width', d => d.ySizeInner + 2).attr('fill', d => options.color(d.data.p.c)); | ||
nodeMerge.selectAll('circle').data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => { | ||
nodeMerge.selectAll(childSelector('circle')).data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => { | ||
return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('r', 0); | ||
@@ -320,7 +308,13 @@ }, update => update, exit => exit.remove()).transition().duration(options.duration).attr('r', 6).attr('stroke', d => options.color(d.data.p.c)).attr('fill', d => { | ||
}); | ||
nodeMerge.selectAll('text').data(d => [d], d => d.data.p.k).join(enter => { | ||
return enter.append('text').attr('x', 8).attr('y', 0).attr('text-anchor', 'start').attr('fill-opacity', 0).call(renderText); | ||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('fill-opacity', 1); // Update the links | ||
nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.p.k).join(enter => { | ||
const fo = enter.append('foreignObject').attr('class', `${state.id}-fo`).attr('x', options.paddingX).attr('y', 0).style('opacity', 0).attr('height', d => d.xSize); | ||
fo.append('xhtml:div').select(function (d) { | ||
const node = d.data.p.el.cloneNode(true); | ||
this.replaceWith(node); | ||
return node; | ||
}).attr('xmlns', 'http://www.w3.org/1999/xhtml'); | ||
return fo; | ||
}, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - options.paddingX * 2)).transition().duration(options.duration).style('opacity', 1); // Update the links | ||
g.selectAll('path').data(links, d => d.target.data.p.k).join(enter => { | ||
g.selectAll(childSelector('path')).data(links, d => d.target.data.p.k).join(enter => { | ||
const source = [y0 + origin.ySizeInner, x0 + origin.xSize / 2]; | ||
@@ -327,0 +321,0 @@ return enter.insert('path', 'g').attr('d', linkShape({ |
244
dist/view.js
@@ -1,2 +0,2 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
(function (exports, d3) { | ||
@@ -560,2 +560,10 @@ 'use strict'; | ||
const uniqId = Math.random().toString(36).slice(2, 8); | ||
let globalIndex = 0; | ||
function getId() { | ||
globalIndex += 1; | ||
return `mm-${uniqId}-${globalIndex}`; | ||
} | ||
function walkTree(tree, callback, key = 'c') { | ||
@@ -573,37 +581,2 @@ const walk = (item, parent) => callback(item, () => { | ||
let canvas; | ||
function getTextRect(items, options) { | ||
// re-use canvas object for better performance | ||
if (!canvas) canvas = document.createElement('canvas'); | ||
const context = canvas.getContext('2d'); | ||
context.font = options.nodeFont; | ||
let maxWidth = 0; | ||
let width = 0; | ||
let height = options.lineHeight; | ||
let row = 0; | ||
const walk = item => { | ||
if (item.t === 'text') { | ||
height = (row + 1) * options.lineHeight; | ||
item.p = { ...item.p, | ||
x: width, | ||
y: height | ||
}; | ||
if (!width && row) item.p.newline = true; | ||
const metrics = context.measureText(item.v); | ||
width += metrics.width; | ||
if (maxWidth < width) maxWidth = width; | ||
} else if (item.t === 'softbreak') { | ||
width = 0; | ||
row += 1; | ||
} else if (item.t === 'link') { | ||
item.c.forEach(walk); | ||
} | ||
}; | ||
items.forEach(walk); | ||
return [maxWidth, height]; | ||
} | ||
function linkWidth(nodeData) { | ||
@@ -614,11 +587,2 @@ const data = nodeData.data; | ||
function getKey(v) { | ||
const result = ['<']; | ||
v.forEach(item => { | ||
if (item.t === 'text') result.push(item.v.replace(/[<|&]/g, m => `&${m}`));else if (item.c) result.push(getKey(item.c)); | ||
}); | ||
result.push('>'); | ||
return result.join(''); | ||
} | ||
function adjustSpacing(tree, spacing) { | ||
@@ -632,17 +596,38 @@ walkTree(tree, (d, next) => { | ||
function getChildNodes() { | ||
return this.childNodes; | ||
function arrayFrom(arrayLike) { | ||
const array = []; | ||
for (let i = 0; i < arrayLike.length; i += 1) { | ||
array.push(arrayLike[i]); | ||
} | ||
return array; | ||
} | ||
function markmap(svg, data, opts) { | ||
svg = svg.datum ? svg : d3.select(svg); | ||
const classList = (svg.attr('class') || '').split(' ').filter(Boolean); | ||
function childSelector(filter) { | ||
if (typeof filter === 'string') { | ||
const tagName = filter; | ||
if (classList.indexOf('markmap') < 0) { | ||
classList.push('markmap'); | ||
svg.attr('class', classList.join(' ')); | ||
filter = el => el.tagName === tagName; | ||
} | ||
const style = svg.append('style'); | ||
const g = svg.append('g'); | ||
const filterFn = filter; | ||
return function selector() { | ||
let nodes = arrayFrom(this.childNodes); | ||
if (filterFn) nodes = nodes.filter(node => filterFn(node)); | ||
return nodes; | ||
}; | ||
} | ||
function addClass(className, ...rest) { | ||
const classList = (className || '').split(' ').filter(Boolean); | ||
rest.forEach(item => { | ||
if (item && classList.indexOf(item) < 0) classList.push(item); | ||
}); | ||
return classList.join(' '); | ||
} | ||
function markmap(svg, data, opts) { | ||
svg = svg.datum ? svg : d3.select(svg); | ||
const styleNode = svg.append('style'); | ||
const zoom = d3.zoom().on('zoom', handleZoom); | ||
@@ -652,4 +637,4 @@ const svgNode = svg.node(); | ||
duration: 500, | ||
nodeFont: '300 16px sans-serif', | ||
lineHeight: 20, | ||
nodeFont: '300 16px/20px sans-serif', | ||
nodeMinHeight: 16, | ||
spacingVertical: 5, | ||
@@ -661,5 +646,9 @@ spacingHorizontal: 80, | ||
colorDepth: 0, | ||
paddingX: 8, | ||
...opts | ||
}; | ||
const state = {}; | ||
const state = { | ||
id: options.id || getId() | ||
}; | ||
const g = svg.append('g').attr('class', `${state.id}-g`); | ||
updateStyle(); | ||
@@ -679,12 +668,22 @@ | ||
function getStyleContent() { | ||
const { | ||
style | ||
} = options; | ||
const styleText = style ? style(state.id) : `\ | ||
.${state.id} a { color: #0097e6; } | ||
.${state.id} a:hover { color: #00a8ff; } | ||
.${state.id}-g > path { fill: none; } | ||
.${state.id}-fo > div { font: ${options.nodeFont}; white-space: nowrap; } | ||
.${state.id}-fo > div > code { padding: .2em .4em; font-size: calc(1em - 2px); color: #555; background-color: #f0f0f0; border-radius: 2px; } | ||
.${state.id}-fo > div > em { font-style: italic; } | ||
.${state.id}-fo > div > strong { font-weight: 500; } | ||
.${state.id}-g > g { cursor: pointer; } | ||
`; | ||
return styleText; | ||
} | ||
function updateStyle() { | ||
style.text(`\ | ||
.markmap a { fill: #0097e6; } | ||
.markmap a:hover { fill: #00a8ff; } | ||
.markmap path { fill: none; } | ||
.markmap text { font: ${options.nodeFont} } | ||
.markmap tspan.markmap-em { font-style: italic; } | ||
.markmap tspan.markmap-strong { font-weight: 500; } | ||
.markmap g > g { cursor: pointer; } | ||
`); | ||
svg.attr('class', addClass(svg.attr('class'), state.id)); | ||
styleNode.text(getStyleContent()); | ||
} | ||
@@ -699,3 +698,3 @@ | ||
function addKeys(node) { | ||
function initializeData(node) { | ||
let i = 0; | ||
@@ -706,2 +705,22 @@ let c = 0; | ||
} = options; | ||
const container = document.createElement('div'); | ||
const containerClass = `${state.id}-container`; | ||
container.className = addClass(container.className, `${state.id}-fo`, containerClass); | ||
const style = document.createElement('style'); | ||
style.textContent = ` | ||
${getStyleContent()} | ||
.${containerClass} { | ||
position: absolute; | ||
width: 0; | ||
height: 0; | ||
top: -100px; | ||
left: -100px; | ||
overflow: hidden; | ||
font: ${options.nodeFont}; | ||
} | ||
.${containerClass} > div { | ||
display: inline-block; | ||
} | ||
`; | ||
document.body.append(style, container); | ||
walkTree(node, (item, next, parent) => { | ||
@@ -713,2 +732,5 @@ var _parent$p; | ||
const el = document.createElement('div'); | ||
el.innerHTML = item.v; | ||
container.append(el); | ||
item.p = { | ||
@@ -719,6 +741,7 @@ // unique ID | ||
c, | ||
el, | ||
...item.p, | ||
// TODO keep keys for unchanged objects | ||
// unique key, should be based on content | ||
k: `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${i}:${getKey(item.v)}` | ||
k: `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${i}:${item.v}` | ||
}; | ||
@@ -728,2 +751,10 @@ next(); | ||
}); | ||
if (options.processHtml) options.processHtml(arrayFrom(container.childNodes)); | ||
walkTree(node, (item, next) => { | ||
const rect = item.p.el.getBoundingClientRect(); | ||
item.p.s = [Math.ceil(rect.width), Math.max(Math.ceil(rect.height), options.nodeMinHeight)]; | ||
next(); | ||
}); | ||
container.remove(); | ||
style.remove(); | ||
} | ||
@@ -736,3 +767,3 @@ | ||
function setData(data, opts) { | ||
addKeys(data); | ||
initializeData(data); | ||
state.data = data; | ||
@@ -773,44 +804,2 @@ if (opts) setOptions(opts); | ||
function handleLink(d) { | ||
d3.event.preventDefault(); | ||
window.open(d.p.href); | ||
} | ||
function renderTextNode(t, d) { | ||
if (d.t === 'link') { | ||
const a = t.append('a').attr('href', d.p.href).attr('title', d.p.title).on('click', handleLink); | ||
const text = a.selectAll(getChildNodes).data(d => d.c); | ||
text.enter().each(function (d) { | ||
const t = d3.select(this); | ||
renderTextNode(t, d); | ||
}); | ||
} | ||
if (d.t === 'text') { | ||
t.append('tspan').text(d.v).attr('class', d => { | ||
var _d$p; | ||
const style = ((_d$p = d.p) == null ? void 0 : _d$p.style) || {}; | ||
return [style.em && 'markmap-em', style.strong && 'markmap-strong'].filter(Boolean).join(' '); | ||
}).attr('x', d => { | ||
var _d$p2; | ||
return ((_d$p2 = d.p) == null ? void 0 : _d$p2.x) + 8; | ||
}).attr('y', d => { | ||
var _d$p3; | ||
return ((_d$p3 = d.p) == null ? void 0 : _d$p3.y) - 4; | ||
}); | ||
} | ||
} | ||
function renderText(text) { | ||
const textNode = text.selectAll(getChildNodes).data(d => d.data.v); | ||
textNode.enter().each(function (d) { | ||
const t = d3.select(this); | ||
renderTextNode(t, d); | ||
}); | ||
return text; | ||
} | ||
function renderData(originData) { | ||
@@ -824,9 +813,8 @@ var _origin$data$x, _origin$data$y; | ||
const layout = flextree().children(d => { | ||
var _d$p4; | ||
var _d$p; | ||
return !((_d$p4 = d.p) == null ? void 0 : _d$p4.f) && d.c; | ||
return !((_d$p = d.p) == null ? void 0 : _d$p.f) && d.c; | ||
}).nodeSize(d => { | ||
d.outerSize = d.outerSize || getTextRect(d.data.v, options); | ||
const [width, height] = d.outerSize; | ||
return [height, width + (width ? 16 : 0) + spacingHorizontal]; | ||
const [width, height] = d.data.p.s; | ||
return [height, width + (width ? options.paddingX * 2 : 0) + spacingHorizontal]; | ||
}).spacing((a, b) => { | ||
@@ -854,14 +842,14 @@ return a.parent === b.parent ? options.spacingVertical : options.spacingVertical * 2; | ||
const node = g.selectAll('g').data(descendants, d => d.data.p.k); | ||
const node = g.selectAll(childSelector('g')).data(descendants, d => d.data.p.k); | ||
const nodeEnter = node.enter().append('g').attr('transform', d => `translate(${y0 + origin.ySizeInner - d.ySizeInner},${x0 + origin.xSize / 2 - d.xSize})`).on('click', handleClick); | ||
const nodeExit = node.exit().transition().duration(options.duration); | ||
nodeExit.select('rect').attr('width', 0).attr('x', d => d.ySizeInner); | ||
nodeExit.select('text').attr('fill-opacity', 0); | ||
nodeExit.select('foreignObject').style('opacity', 0); | ||
nodeExit.attr('transform', d => `translate(${origin.y + origin.ySizeInner - d.ySizeInner},${origin.x + origin.xSize / 2 - d.xSize})`).remove(); | ||
const nodeMerge = node.merge(nodeEnter); | ||
nodeMerge.transition().duration(options.duration).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`); | ||
nodeMerge.selectAll('rect').data(d => [d], d => d.data.p.k).join(enter => { | ||
nodeMerge.selectAll(childSelector('rect')).data(d => [d], d => d.data.p.k).join(enter => { | ||
return enter.append('rect').attr('x', d => d.ySizeInner).attr('y', d => d.xSize - linkWidth(d) / 2).attr('width', 0).attr('height', linkWidth); | ||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('x', -1).attr('width', d => d.ySizeInner + 2).attr('fill', d => options.color(d.data.p.c)); | ||
nodeMerge.selectAll('circle').data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => { | ||
nodeMerge.selectAll(childSelector('circle')).data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => { | ||
return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('r', 0); | ||
@@ -873,7 +861,13 @@ }, update => update, exit => exit.remove()).transition().duration(options.duration).attr('r', 6).attr('stroke', d => options.color(d.data.p.c)).attr('fill', d => { | ||
}); | ||
nodeMerge.selectAll('text').data(d => [d], d => d.data.p.k).join(enter => { | ||
return enter.append('text').attr('x', 8).attr('y', 0).attr('text-anchor', 'start').attr('fill-opacity', 0).call(renderText); | ||
}, update => update, exit => exit.remove()).transition().duration(options.duration).attr('fill-opacity', 1); // Update the links | ||
nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.p.k).join(enter => { | ||
const fo = enter.append('foreignObject').attr('class', `${state.id}-fo`).attr('x', options.paddingX).attr('y', 0).style('opacity', 0).attr('height', d => d.xSize); | ||
fo.append('xhtml:div').select(function (d) { | ||
const node = d.data.p.el.cloneNode(true); | ||
this.replaceWith(node); | ||
return node; | ||
}).attr('xmlns', 'http://www.w3.org/1999/xhtml'); | ||
return fo; | ||
}, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - options.paddingX * 2)).transition().duration(options.duration).style('opacity', 1); // Update the links | ||
g.selectAll('path').data(links, d => d.target.data.p.k).join(enter => { | ||
g.selectAll(childSelector('path')).data(links, d => d.target.data.p.k).join(enter => { | ||
const source = [y0 + origin.ySizeInner, x0 + origin.xSize / 2]; | ||
@@ -880,0 +874,0 @@ return enter.insert('path', 'g').attr('d', linkShape({ |
@@ -1,2 +0,2 @@ | ||
/*! markmap-lib v0.5.1 | MIT License */ | ||
!function(t,e){"use strict";function n(t){var e=0,n=t.children,r=n&&n.length;if(r)for(;--r>=0;)e+=n[r].value;else e=1;t.value=e}function r(t,e){var n,r,a,s,c,h=new l(t),u=+t.value&&(h.value=t.value),d=[h];for(null==e&&(e=i);n=d.pop();)if(u&&(n.value=+n.data.value),(a=e(n.data))&&(c=a.length))for(n.children=new Array(c),s=c-1;s>=0;--s)d.push(r=n.children[s]=new l(a[s])),r.parent=n,r.depth=n.depth+1;return h.eachBefore(o)}function i(t){return t.children}function a(t){t.data=t.data.data}function o(t){var e=0;do{t.height=e}while((t=t.parent)&&t.height<++e)}function l(t){this.data=t,this.depth=this.height=0,this.parent=null}l.prototype=r.prototype={constructor:l,count:function(){return this.eachAfter(n)},each:function(t){var e,n,r,i,a=this,o=[a];do{for(e=o.reverse(),o=[];a=e.pop();)if(t(a),n=a.children)for(r=0,i=n.length;r<i;++r)o.push(n[r])}while(o.length);return this},eachAfter:function(t){for(var e,n,r,i=this,a=[i],o=[];i=a.pop();)if(o.push(i),e=i.children)for(n=0,r=e.length;n<r;++n)a.push(e[n]);for(;i=o.pop();)t(i);return this},eachBefore:function(t){for(var e,n,r=this,i=[r];r=i.pop();)if(t(r),e=r.children)for(n=e.length-1;n>=0;--n)i.push(e[n]);return this},sum:function(t){return this.eachAfter((function(e){for(var n=+t(e.data)||0,r=e.children,i=r&&r.length;--i>=0;)n+=r[i].value;e.value=n}))},sort:function(t){return this.eachBefore((function(e){e.children&&e.children.sort(t)}))},path:function(t){for(var e=this,n=function(t,e){if(t===e)return t;var n=t.ancestors(),r=e.ancestors(),i=null;t=n.pop(),e=r.pop();for(;t===e;)i=t,t=n.pop(),e=r.pop();return i}(e,t),r=[e];e!==n;)e=e.parent,r.push(e);for(var i=r.length;t!==n;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e},descendants:function(){var t=[];return this.each((function(e){t.push(e)})),t},leaves:function(){var t=[];return this.eachBefore((function(e){e.children||t.push(e)})),t},links:function(){var t=this,e=[];return t.each((function(n){n!==t&&e.push({source:n.parent,target:n})})),e},copy:function(){return r(this).eachBefore(a)}};const s=Object.freeze({children:t=>t.children,nodeSize:t=>t.data.size,spacing:0});function c(t){const e=Object.assign({},s,t);function n(t){const n=e[t];return"function"==typeof n?n:()=>n}function i(t){const e=o(function(){const t=a(),e=n("nodeSize"),r=n("spacing");return class extends t{constructor(t){super(t),Object.assign(this,{x:0,y:0,relX:0,prelim:0,shift:0,change:0,lExt:this,lExtRelX:0,lThr:null,rExt:this,rExtRelX:0,rThr:null})}get size(){return e(this.data)}spacing(t){return r(this.data,t.data)}get x(){return this.data.x}set x(t){this.data.x=t}get y(){return this.data.y}set y(t){this.data.y=t}update(){return h(this),u(this),this}}}(),t,t=>t.children);return e.update(),e.data}function a(){const t=n("nodeSize"),e=n("spacing");return class n extends r.prototype.constructor{constructor(t){super(t)}copy(){const t=o(this.constructor,this,t=>t.children);return t.each(t=>t.data=t.data.data),t}get size(){return t(this)}spacing(t){return e(this,t)}get nodes(){return this.descendants()}get xSize(){return this.size[0]}get ySize(){return this.size[1]}get top(){return this.y}get bottom(){return this.y+this.ySize}get left(){return this.x-this.xSize/2}get right(){return this.x+this.xSize/2}get root(){const t=this.ancestors();return t[t.length-1]}get numChildren(){return this.hasChildren?this.children.length:0}get hasChildren(){return!this.noChildren}get noChildren(){return null===this.children}get firstChild(){return this.hasChildren?this.children[0]:null}get lastChild(){return this.hasChildren?this.children[this.numChildren-1]:null}get extents(){return(this.children||[]).reduce((t,e)=>n.maxExtents(t,e.extents),this.nodeExtents)}get nodeExtents(){return{top:this.top,bottom:this.bottom,left:this.left,right:this.right}}static maxExtents(t,e){return{top:Math.min(t.top,e.top),bottom:Math.max(t.bottom,e.bottom),left:Math.min(t.left,e.left),right:Math.max(t.right,e.right)}}}}function o(t,e,n){const r=(e,i)=>{const a=new t(e);Object.assign(a,{parent:i,depth:null===i?0:i.depth+1,height:0,length:1});const o=n(e)||[];return a.children=0===o.length?null:o.map(t=>r(t,a)),a.children&&Object.assign(a,a.children.reduce((t,e)=>({height:Math.max(t.height,e.height+1),length:t.length+e.length}),a)),a};return r(e,null)}return Object.assign(i,{nodeSize(t){return arguments.length?(e.nodeSize=t,i):e.nodeSize},spacing(t){return arguments.length?(e.spacing=t,i):e.spacing},children(t){return arguments.length?(e.children=t,i):e.children},hierarchy(t,n){const r=void 0===n?e.children:n;return o(a(),t,r)},dump(t){const e=n("nodeSize"),r=t=>n=>{const i=t+" ",a=t+" ",{x:o,y:l}=n,s=e(n),c=n.children||[],h=0===c.length?" ":`,${i}children: [${a}${c.map(r(a)).join(a)}${i}],${t}`;return`{ size: [${s.join(", ")}],${i}x: ${o}, y: ${l}${h}},`};return r("\n")(t)}}),i}c.version="2.1.1";const h=(t,e=0)=>(t.y=e,(t.children||[]).reduce((e,n)=>{const[r,i]=e;h(n,t.y+t.ySize);const a=(0===r?n.lExt:n.rExt).bottom;return 0!==r&&p(t,r,i),[r+1,S(a,r,i)]},[0,null]),d(t),z(t),t),u=(t,e,n)=>{void 0===e&&(e=-t.relX-t.prelim,n=0);const r=e+t.relX;return t.relX=r+t.prelim-n,t.prelim=0,t.x=n+t.relX,(t.children||[]).forEach(e=>u(e,r,t.x)),t},d=t=>{(t.children||[]).reduce((t,e)=>{const[n,r]=t,i=n+e.shift,a=r+i+e.change;return e.relX+=a,[i,a]},[0,0])},p=(t,e,n)=>{const r=t.children[e-1],i=t.children[e];let a=r,o=r.relX,l=i,s=i.relX,c=!0;for(;a&&l;){a.bottom>n.lowY&&(n=n.next);const r=o+a.prelim-(s+l.prelim)+a.xSize/2+l.xSize/2+a.spacing(l);(r>0||r<0&&c)&&(s+=r,f(i,r),x(t,e,n.index,r)),c=!1;const h=a.bottom,u=l.bottom;h<=u&&(a=m(a),a&&(o+=a.relX)),h>=u&&(l=g(l),l&&(s+=l.relX))}!a&&l?y(t,e,l,s):a&&!l&&v(t,e,a,o)},f=(t,e)=>{t.relX+=e,t.lExtRelX+=e,t.rExtRelX+=e},x=(t,e,n,r)=>{const i=t.children[e],a=e-n;if(a>1){const e=r/a;t.children[n+1].shift+=e,i.shift-=e,i.change-=r-e}},g=t=>t.hasChildren?t.firstChild:t.lThr,m=t=>t.hasChildren?t.lastChild:t.rThr,y=(t,e,n,r)=>{const i=t.firstChild,a=i.lExt,o=t.children[e];a.lThr=n;const l=r-n.relX-i.lExtRelX;a.relX+=l,a.prelim-=l,i.lExt=o.lExt,i.lExtRelX=o.lExtRelX},v=(t,e,n,r)=>{const i=t.children[e],a=i.rExt,o=t.children[e-1];a.rThr=n;const l=r-n.relX-i.rExtRelX;a.relX+=l,a.prelim-=l,i.rExt=o.rExt,i.rExtRelX=o.rExtRelX},z=t=>{if(t.hasChildren){const e=t.firstChild,n=t.lastChild,r=(e.prelim+e.relX-e.xSize/2+n.relX+n.prelim+n.xSize/2)/2;Object.assign(t,{prelim:r,lExt:e.lExt,lExtRelX:e.lExtRelX,rExt:n.rExt,rExtRelX:n.rExtRelX})}},S=(t,e,n)=>{for(;null!==n&&t>=n.lowY;)n=n.next;return{lowY:t,index:e,next:n}};function E(t,e,n="c"){const r=(t,i)=>e(t,()=>{var e;null==(e=t[n])||e.forEach(e=>{r(e,t)})},i);r(t)}let X;function k(t){const e=t.data;return Math.max(6-2*e.d,1.5)}function $(t){const e=["<"];return t.forEach(t=>{"text"===t.t?e.push(t.v.replace(/[<|&]/g,t=>`&${t}`)):t.c&&e.push($(t.c))}),e.push(">"),e.join("")}function C(){return this.childNodes}t.markmap=function(t,n,r){const i=((t=t.datum?t:e.select(t)).attr("class")||"").split(" ").filter(Boolean);i.indexOf("markmap")<0&&(i.push("markmap"),t.attr("class",i.join(" ")));const a=t.append("style"),o=t.append("g"),l=e.zoom().on("zoom",(function(){const{transform:t}=e.event;o.attr("transform",t)})),s=t.node(),h={duration:500,nodeFont:"300 16px sans-serif",lineHeight:20,spacingVertical:5,spacingHorizontal:80,autoFit:!1,fitRatio:.95,color:e.scaleOrdinal(e.schemeCategory10),colorDepth:0,...r},u={};return a.text(`.markmap a { fill: #0097e6; }\n.markmap a:hover { fill: #00a8ff; }\n.markmap path { fill: none; }\n.markmap text { font: ${h.nodeFont} }\n.markmap tspan.markmap-em { font-style: italic; }\n.markmap tspan.markmap-strong { font-weight: 500; }\n.markmap g > g { cursor: pointer; }\n`),n&&(p(n),f()),t.call(l),{setData:p,setOptions:d,fit:f};function d(t){Object.assign(h,t)}function p(t,e){!function(t){let e=0,n=0;const{colorDepth:r}=h;E(t,(t,i,a)=>{var o;e+=1,h.color(`${n}`),t.p={i:e,c:n,...t.p,k:`${(null==a||null==(o=a.p)?void 0:o.i)||""}.${e}:${$(t.v)}`},i(),r&&t.d!==r||(n+=1)})}(t),u.data=t,e&&d(e),y(t)}function f(){const{width:n,height:r}=s.getBoundingClientRect(),{minX:i,maxX:a,minY:o,maxY:c}=u,d=c-o,p=a-i,f=Math.min(n/d*h.fitRatio,r/p*h.fitRatio,2),x=e.zoomIdentity.translate((n-d*f)/2-o*f,(r-p*f)/2-i*f).scale(f);t.transition().duration(h.duration).call(l.transform,x)}function x(t){var e;const{data:n}=t;n.p={...n.p,f:!(null==(e=n.p)?void 0:e.f)},y(t.data)}function g(t){e.event.preventDefault(),window.open(t.p.href)}function m(t){return t.selectAll(C).data(t=>t.data.v).enter().each((function(t){!function t(n,r){if("link"===r.t){n.append("a").attr("href",r.p.href).attr("title",r.p.title).on("click",g).selectAll(C).data(t=>t.c).enter().each((function(n){t(e.select(this),n)}))}"text"===r.t&&n.append("tspan").text(r.v).attr("class",t=>{var e;const n=(null==(e=t.p)?void 0:e.style)||{};return[n.em&&"markmap-em",n.strong&&"markmap-strong"].filter(Boolean).join(" ")}).attr("x",t=>{var e;return(null==(e=t.p)?void 0:e.x)+8}).attr("y",t=>{var e;return(null==(e=t.p)?void 0:e.y)-4})}(e.select(this),t)})),t}function y(t){var n,r;if(!u.data)return;const{spacingHorizontal:i}=h,a=c().children(t=>{var e;return!(null==(e=t.p)?void 0:e.f)&&t.c}).nodeSize(t=>{t.outerSize=t.outerSize||function(t,e){X||(X=document.createElement("canvas"));const n=X.getContext("2d");n.font=e.nodeFont;let r=0,i=0,a=e.lineHeight,o=0;const l=t=>{if("text"===t.t){a=(o+1)*e.lineHeight,t.p={...t.p,x:i,y:a},!i&&o&&(t.p.newline=!0);const l=n.measureText(t.v);i+=l.width,r<i&&(r=i)}else"softbreak"===t.t?(i=0,o+=1):"link"===t.t&&t.c.forEach(l)};return t.forEach(l),[r,a]}(t.data.v,h);const[e,n]=t.outerSize;return[n,e+(e?16:0)+i]}).spacing((t,e)=>t.parent===e.parent?h.spacingVertical:2*h.spacingVertical),l=a.hierarchy(u.data);a(l),function(t,e){E(t,(t,n)=>{t.ySizeInner=t.ySize-e,t.y+=e,n()},"children")}(l,i);const s=l.descendants().reverse(),d=l.links(),p=e.linkHorizontal(),g=e.min(s,t=>t.x-t.xSize/2),y=e.max(s,t=>t.x+t.xSize/2),v=e.min(s,t=>t.y),z=e.max(s,t=>t.y+t.ySizeInner);u.minX=g,u.maxX=y,u.minY=v,u.maxY=z,h.autoFit&&f();const S=t?s.find(e=>e.data===t):l,$=null!=(n=S.data.x0)?n:S.x,C=null!=(r=S.data.y0)?r:S.y,w=o.selectAll("g").data(s,t=>t.data.p.k),b=w.enter().append("g").attr("transform",t=>`translate(${C+S.ySizeInner-t.ySizeInner},${$+S.xSize/2-t.xSize})`).on("click",x),R=w.exit().transition().duration(h.duration);R.select("rect").attr("width",0).attr("x",t=>t.ySizeInner),R.select("text").attr("fill-opacity",0),R.attr("transform",t=>`translate(${S.y+S.ySizeInner-t.ySizeInner},${S.x+S.xSize/2-t.xSize})`).remove();const j=w.merge(b);j.transition().duration(h.duration).attr("transform",t=>`translate(${t.y},${t.x-t.xSize/2})`),j.selectAll("rect").data(t=>[t],t=>t.data.p.k).join(t=>t.append("rect").attr("x",t=>t.ySizeInner).attr("y",t=>t.xSize-k(t)/2).attr("width",0).attr("height",k),t=>t,t=>t.remove()).transition().duration(h.duration).attr("x",-1).attr("width",t=>t.ySizeInner+2).attr("fill",t=>h.color(t.data.p.c)),j.selectAll("circle").data(t=>t.data.c?[t]:[],t=>t.data.p.k).join(t=>t.append("circle").attr("stroke-width","1.5").attr("cx",t=>t.ySizeInner).attr("cy",t=>t.xSize).attr("r",0),t=>t,t=>t.remove()).transition().duration(h.duration).attr("r",6).attr("stroke",t=>h.color(t.data.p.c)).attr("fill",t=>{var e;return(null==(e=t.data.p)?void 0:e.f)?h.color(t.data.p.c):"#fff"}),j.selectAll("text").data(t=>[t],t=>t.data.p.k).join(t=>t.append("text").attr("x",8).attr("y",0).attr("text-anchor","start").attr("fill-opacity",0).call(m),t=>t,t=>t.remove()).transition().duration(h.duration).attr("fill-opacity",1),o.selectAll("path").data(d,t=>t.target.data.p.k).join(t=>{const e=[C+S.ySizeInner,$+S.xSize/2];return t.insert("path","g").attr("d",p({source:e,target:e}))},t=>t,t=>{const e=[S.y+S.ySizeInner,S.x+S.xSize/2];return t.transition().duration(h.duration).attr("d",p({source:e,target:e})).remove()}).transition().duration(h.duration).attr("stroke",t=>h.color(t.target.data.p.c)).attr("stroke-width",t=>k(t.target)).attr("d",t=>{const e=[t.source.y+t.source.ySizeInner,t.source.x+t.source.xSize/2],n=[t.target.y,t.target.x+t.target.xSize/2];return p({source:e,target:n})}),s.forEach(t=>{t.data.x0=t.x,t.data.y0=t.y})}}}(this.markmap=this.markmap||{},d3); | ||
/*! markmap-lib v0.6.0 | MIT License */ | ||
!function(t,e){"use strict";function n(t){var e=0,n=t.children,r=n&&n.length;if(r)for(;--r>=0;)e+=n[r].value;else e=1;t.value=e}function r(t,e){var n,r,a,l,c,h=new s(t),d=+t.value&&(h.value=t.value),u=[h];for(null==e&&(e=i);n=u.pop();)if(d&&(n.value=+n.data.value),(a=e(n.data))&&(c=a.length))for(n.children=new Array(c),l=c-1;l>=0;--l)u.push(r=n.children[l]=new s(a[l])),r.parent=n,r.depth=n.depth+1;return h.eachBefore(o)}function i(t){return t.children}function a(t){t.data=t.data.data}function o(t){var e=0;do{t.height=e}while((t=t.parent)&&t.height<++e)}function s(t){this.data=t,this.depth=this.height=0,this.parent=null}s.prototype=r.prototype={constructor:s,count:function(){return this.eachAfter(n)},each:function(t){var e,n,r,i,a=this,o=[a];do{for(e=o.reverse(),o=[];a=e.pop();)if(t(a),n=a.children)for(r=0,i=n.length;r<i;++r)o.push(n[r])}while(o.length);return this},eachAfter:function(t){for(var e,n,r,i=this,a=[i],o=[];i=a.pop();)if(o.push(i),e=i.children)for(n=0,r=e.length;n<r;++n)a.push(e[n]);for(;i=o.pop();)t(i);return this},eachBefore:function(t){for(var e,n,r=this,i=[r];r=i.pop();)if(t(r),e=r.children)for(n=e.length-1;n>=0;--n)i.push(e[n]);return this},sum:function(t){return this.eachAfter((function(e){for(var n=+t(e.data)||0,r=e.children,i=r&&r.length;--i>=0;)n+=r[i].value;e.value=n}))},sort:function(t){return this.eachBefore((function(e){e.children&&e.children.sort(t)}))},path:function(t){for(var e=this,n=function(t,e){if(t===e)return t;var n=t.ancestors(),r=e.ancestors(),i=null;t=n.pop(),e=r.pop();for(;t===e;)i=t,t=n.pop(),e=r.pop();return i}(e,t),r=[e];e!==n;)e=e.parent,r.push(e);for(var i=r.length;t!==n;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e},descendants:function(){var t=[];return this.each((function(e){t.push(e)})),t},leaves:function(){var t=[];return this.eachBefore((function(e){e.children||t.push(e)})),t},links:function(){var t=this,e=[];return t.each((function(n){n!==t&&e.push({source:n.parent,target:n})})),e},copy:function(){return r(this).eachBefore(a)}};const l=Object.freeze({children:t=>t.children,nodeSize:t=>t.data.size,spacing:0});function c(t){const e=Object.assign({},l,t);function n(t){const n=e[t];return"function"==typeof n?n:()=>n}function i(t){const e=o(function(){const t=a(),e=n("nodeSize"),r=n("spacing");return class extends t{constructor(t){super(t),Object.assign(this,{x:0,y:0,relX:0,prelim:0,shift:0,change:0,lExt:this,lExtRelX:0,lThr:null,rExt:this,rExtRelX:0,rThr:null})}get size(){return e(this.data)}spacing(t){return r(this.data,t.data)}get x(){return this.data.x}set x(t){this.data.x=t}get y(){return this.data.y}set y(t){this.data.y=t}update(){return h(this),d(this),this}}}(),t,t=>t.children);return e.update(),e.data}function a(){const t=n("nodeSize"),e=n("spacing");return class n extends r.prototype.constructor{constructor(t){super(t)}copy(){const t=o(this.constructor,this,t=>t.children);return t.each(t=>t.data=t.data.data),t}get size(){return t(this)}spacing(t){return e(this,t)}get nodes(){return this.descendants()}get xSize(){return this.size[0]}get ySize(){return this.size[1]}get top(){return this.y}get bottom(){return this.y+this.ySize}get left(){return this.x-this.xSize/2}get right(){return this.x+this.xSize/2}get root(){const t=this.ancestors();return t[t.length-1]}get numChildren(){return this.hasChildren?this.children.length:0}get hasChildren(){return!this.noChildren}get noChildren(){return null===this.children}get firstChild(){return this.hasChildren?this.children[0]:null}get lastChild(){return this.hasChildren?this.children[this.numChildren-1]:null}get extents(){return(this.children||[]).reduce((t,e)=>n.maxExtents(t,e.extents),this.nodeExtents)}get nodeExtents(){return{top:this.top,bottom:this.bottom,left:this.left,right:this.right}}static maxExtents(t,e){return{top:Math.min(t.top,e.top),bottom:Math.max(t.bottom,e.bottom),left:Math.min(t.left,e.left),right:Math.max(t.right,e.right)}}}}function o(t,e,n){const r=(e,i)=>{const a=new t(e);Object.assign(a,{parent:i,depth:null===i?0:i.depth+1,height:0,length:1});const o=n(e)||[];return a.children=0===o.length?null:o.map(t=>r(t,a)),a.children&&Object.assign(a,a.children.reduce((t,e)=>({height:Math.max(t.height,e.height+1),length:t.length+e.length}),a)),a};return r(e,null)}return Object.assign(i,{nodeSize(t){return arguments.length?(e.nodeSize=t,i):e.nodeSize},spacing(t){return arguments.length?(e.spacing=t,i):e.spacing},children(t){return arguments.length?(e.children=t,i):e.children},hierarchy(t,n){const r=void 0===n?e.children:n;return o(a(),t,r)},dump(t){const e=n("nodeSize"),r=t=>n=>{const i=t+" ",a=t+" ",{x:o,y:s}=n,l=e(n),c=n.children||[],h=0===c.length?" ":`,${i}children: [${a}${c.map(r(a)).join(a)}${i}],${t}`;return`{ size: [${l.join(", ")}],${i}x: ${o}, y: ${s}${h}},`};return r("\n")(t)}}),i}c.version="2.1.1";const h=(t,e=0)=>(t.y=e,(t.children||[]).reduce((e,n)=>{const[r,i]=e;h(n,t.y+t.ySize);const a=(0===r?n.lExt:n.rExt).bottom;return 0!==r&&p(t,r,i),[r+1,S(a,r,i)]},[0,null]),u(t),v(t),t),d=(t,e,n)=>{void 0===e&&(e=-t.relX-t.prelim,n=0);const r=e+t.relX;return t.relX=r+t.prelim-n,t.prelim=0,t.x=n+t.relX,(t.children||[]).forEach(e=>d(e,r,t.x)),t},u=t=>{(t.children||[]).reduce((t,e)=>{const[n,r]=t,i=n+e.shift,a=r+i+e.change;return e.relX+=a,[i,a]},[0,0])},p=(t,e,n)=>{const r=t.children[e-1],i=t.children[e];let a=r,o=r.relX,s=i,l=i.relX,c=!0;for(;a&&s;){a.bottom>n.lowY&&(n=n.next);const r=o+a.prelim-(l+s.prelim)+a.xSize/2+s.xSize/2+a.spacing(s);(r>0||r<0&&c)&&(l+=r,f(i,r),g(t,e,n.index,r)),c=!1;const h=a.bottom,d=s.bottom;h<=d&&(a=m(a),a&&(o+=a.relX)),h>=d&&(s=x(s),s&&(l+=s.relX))}!a&&s?y(t,e,s,l):a&&!s&&z(t,e,a,o)},f=(t,e)=>{t.relX+=e,t.lExtRelX+=e,t.rExtRelX+=e},g=(t,e,n,r)=>{const i=t.children[e],a=e-n;if(a>1){const e=r/a;t.children[n+1].shift+=e,i.shift-=e,i.change-=r-e}},x=t=>t.hasChildren?t.firstChild:t.lThr,m=t=>t.hasChildren?t.lastChild:t.rThr,y=(t,e,n,r)=>{const i=t.firstChild,a=i.lExt,o=t.children[e];a.lThr=n;const s=r-n.relX-i.lExtRelX;a.relX+=s,a.prelim-=s,i.lExt=o.lExt,i.lExtRelX=o.lExtRelX},z=(t,e,n,r)=>{const i=t.children[e],a=i.rExt,o=t.children[e-1];a.rThr=n;const s=r-n.relX-i.rExtRelX;a.relX+=s,a.prelim-=s,i.rExt=o.rExt,i.rExtRelX=o.rExtRelX},v=t=>{if(t.hasChildren){const e=t.firstChild,n=t.lastChild,r=(e.prelim+e.relX-e.xSize/2+n.relX+n.prelim+n.xSize/2)/2;Object.assign(t,{prelim:r,lExt:e.lExt,lExtRelX:e.lExtRelX,rExt:n.rExt,rExtRelX:n.rExtRelX})}},S=(t,e,n)=>{for(;null!==n&&t>=n.lowY;)n=n.next;return{lowY:t,index:e,next:n}},E=Math.random().toString(36).slice(2,8);let X=0;function $(t,e,n="c"){const r=(t,i)=>e(t,()=>{var e;null==(e=t[n])||e.forEach(e=>{r(e,t)})},i);r(t)}function b(t){const e=t.data;return Math.max(6-2*e.d,1.5)}function w(t){const e=[];for(let n=0;n<t.length;n+=1)e.push(t[n]);return e}function C(t){if("string"==typeof t){const e=t;t=t=>t.tagName===e}const e=t;return function(){let t=w(this.childNodes);return e&&(t=t.filter(t=>e(t))),t}}function k(t,...e){const n=(t||"").split(" ").filter(Boolean);return e.forEach(t=>{t&&n.indexOf(t)<0&&n.push(t)}),n.join(" ")}t.markmap=function(t,n,r){const i=(t=t.datum?t:e.select(t)).append("style"),a=e.zoom().on("zoom",(function(){const{transform:t}=e.event;h.attr("transform",t)})),o=t.node(),s={duration:500,nodeFont:"300 16px/20px sans-serif",nodeMinHeight:16,spacingVertical:5,spacingHorizontal:80,autoFit:!1,fitRatio:.95,color:e.scaleOrdinal(e.schemeCategory10),colorDepth:0,paddingX:8,...r},l={id:s.id||(X+=1,`mm-${E}-${X}`)},h=t.append("g").attr("class",`${l.id}-g`);return t.attr("class",k(t.attr("class"),l.id)),i.text(d()),n&&(p(n),f()),t.call(a),{setData:p,setOptions:u,fit:f};function d(){const{style:t}=s;return t?t(l.id):`.${l.id} a { color: #0097e6; }\n.${l.id} a:hover { color: #00a8ff; }\n.${l.id}-g > path { fill: none; }\n.${l.id}-fo > div { font: ${s.nodeFont}; white-space: nowrap; }\n.${l.id}-fo > div > code { padding: .2em .4em; font-size: calc(1em - 2px); color: #555; background-color: #f0f0f0; border-radius: 2px; }\n.${l.id}-fo > div > em { font-style: italic; }\n.${l.id}-fo > div > strong { font-weight: 500; }\n.${l.id}-g > g { cursor: pointer; }\n`}function u(t){Object.assign(s,t)}function p(t,e){!function(t){let e=0,n=0;const{colorDepth:r}=s,i=document.createElement("div"),a=`${l.id}-container`;i.className=k(i.className,`${l.id}-fo`,a);const o=document.createElement("style");o.textContent=`\n${d()}\n.${a} {\n position: absolute;\n width: 0;\n height: 0;\n top: -100px;\n left: -100px;\n overflow: hidden;\n font: ${s.nodeFont};\n}\n.${a} > div {\n display: inline-block;\n}\n`,document.body.append(o,i),$(t,(t,a,o)=>{var l;e+=1,s.color(`${n}`);const c=document.createElement("div");c.innerHTML=t.v,i.append(c),t.p={i:e,c:n,el:c,...t.p,k:`${(null==o||null==(l=o.p)?void 0:l.i)||""}.${e}:${t.v}`},a(),r&&t.d!==r||(n+=1)}),s.processHtml&&s.processHtml(w(i.childNodes)),$(t,(t,e)=>{const n=t.p.el.getBoundingClientRect();t.p.s=[Math.ceil(n.width),Math.max(Math.ceil(n.height),s.nodeMinHeight)],e()}),i.remove(),o.remove()}(t),l.data=t,e&&u(e),x(t)}function f(){const{width:n,height:r}=o.getBoundingClientRect(),{minX:i,maxX:c,minY:h,maxY:d}=l,u=d-h,p=c-i,f=Math.min(n/u*s.fitRatio,r/p*s.fitRatio,2),g=e.zoomIdentity.translate((n-u*f)/2-h*f,(r-p*f)/2-i*f).scale(f);t.transition().duration(s.duration).call(a.transform,g)}function g(t){var e;const{data:n}=t;n.p={...n.p,f:!(null==(e=n.p)?void 0:e.f)},x(t.data)}function x(t){var n,r;if(!l.data)return;const{spacingHorizontal:i}=s,a=c().children(t=>{var e;return!(null==(e=t.p)?void 0:e.f)&&t.c}).nodeSize(t=>{const[e,n]=t.data.p.s;return[n,e+(e?2*s.paddingX:0)+i]}).spacing((t,e)=>t.parent===e.parent?s.spacingVertical:2*s.spacingVertical),o=a.hierarchy(l.data);a(o),function(t,e){$(t,(t,n)=>{t.ySizeInner=t.ySize-e,t.y+=e,n()},"children")}(o,i);const d=o.descendants().reverse(),u=o.links(),p=e.linkHorizontal(),x=e.min(d,t=>t.x-t.xSize/2),m=e.max(d,t=>t.x+t.xSize/2),y=e.min(d,t=>t.y),z=e.max(d,t=>t.y+t.ySizeInner);l.minX=x,l.maxX=m,l.minY=y,l.maxY=z,s.autoFit&&f();const v=t?d.find(e=>e.data===t):o,S=null!=(n=v.data.x0)?n:v.x,E=null!=(r=v.data.y0)?r:v.y,X=h.selectAll(C("g")).data(d,t=>t.data.p.k),w=X.enter().append("g").attr("transform",t=>`translate(${E+v.ySizeInner-t.ySizeInner},${S+v.xSize/2-t.xSize})`).on("click",g),k=X.exit().transition().duration(s.duration);k.select("rect").attr("width",0).attr("x",t=>t.ySizeInner),k.select("foreignObject").style("opacity",0),k.attr("transform",t=>`translate(${v.y+v.ySizeInner-t.ySizeInner},${v.x+v.xSize/2-t.xSize})`).remove();const R=X.merge(w);R.transition().duration(s.duration).attr("transform",t=>`translate(${t.y},${t.x-t.xSize/2})`),R.selectAll(C("rect")).data(t=>[t],t=>t.data.p.k).join(t=>t.append("rect").attr("x",t=>t.ySizeInner).attr("y",t=>t.xSize-b(t)/2).attr("width",0).attr("height",b),t=>t,t=>t.remove()).transition().duration(s.duration).attr("x",-1).attr("width",t=>t.ySizeInner+2).attr("fill",t=>s.color(t.data.p.c)),R.selectAll(C("circle")).data(t=>t.data.c?[t]:[],t=>t.data.p.k).join(t=>t.append("circle").attr("stroke-width","1.5").attr("cx",t=>t.ySizeInner).attr("cy",t=>t.xSize).attr("r",0),t=>t,t=>t.remove()).transition().duration(s.duration).attr("r",6).attr("stroke",t=>s.color(t.data.p.c)).attr("fill",t=>{var e;return(null==(e=t.data.p)?void 0:e.f)?s.color(t.data.p.c):"#fff"}),R.selectAll(C("foreignObject")).data(t=>[t],t=>t.data.p.k).join(t=>{const e=t.append("foreignObject").attr("class",`${l.id}-fo`).attr("x",s.paddingX).attr("y",0).style("opacity",0).attr("height",t=>t.xSize);return e.append("xhtml:div").select((function(t){const e=t.data.p.el.cloneNode(!0);return this.replaceWith(e),e})).attr("xmlns","http://www.w3.org/1999/xhtml"),e},t=>t,t=>t.remove()).attr("width",t=>Math.max(0,t.ySizeInner-2*s.paddingX)).transition().duration(s.duration).style("opacity",1),h.selectAll(C("path")).data(u,t=>t.target.data.p.k).join(t=>{const e=[E+v.ySizeInner,S+v.xSize/2];return t.insert("path","g").attr("d",p({source:e,target:e}))},t=>t,t=>{const e=[v.y+v.ySizeInner,v.x+v.xSize/2];return t.transition().duration(s.duration).attr("d",p({source:e,target:e})).remove()}).transition().duration(s.duration).attr("stroke",t=>s.color(t.target.data.p.c)).attr("stroke-width",t=>b(t.target)).attr("d",t=>{const e=[t.source.y+t.source.ySizeInner,t.source.x+t.source.xSize/2],n=[t.target.y,t.target.x+t.target.xSize/2];return p({source:e,target:n})}),d.forEach(t=>{t.data.x0=t.x,t.data.y0=t.y})}}}(this.markmap=this.markmap||{},d3); |
{ | ||
"name": "markmap-lib", | ||
"version": "0.5.1", | ||
"version": "0.6.0", | ||
"description": "Visualize your Markdown as mindmaps with Markmap", | ||
@@ -5,0 +5,0 @@ "author": "Gerald <i@gerald.top>", |
138
README.md
@@ -11,37 +11,141 @@ # markmap-lib | ||
It is a complete reimplementation with some additional features: | ||
See [online demo](https://markmap.js.org/repl). | ||
- command-line usage | ||
- multiline text | ||
- text styles | ||
- links | ||
- friendly to browsers | ||
## Usage | ||
<img src="https://user-images.githubusercontent.com/3139113/72221499-52476a80-3596-11ea-8d15-c57fdfe04ce0.png" alt="markdown" width="300"> <img src="https://user-images.githubusercontent.com/3139113/72221508-7014cf80-3596-11ea-9b59-b8a97bba8e1c.png" alt="mindmap" width="300"> | ||
### Command-line | ||
## Installation | ||
#### Installation | ||
Install globally: | ||
```sh | ||
$ yarn global add markmap-lib | ||
# or | ||
$ npm i markmap-lib -g | ||
$ npm install markmap-lib -g | ||
``` | ||
## Usage | ||
or use with `npx`: | ||
Suppose you have a Markdown file named `README.md`. | ||
```sh | ||
$ npx markmap-lib | ||
``` | ||
Run the command below: | ||
#### Commands | ||
``` | ||
Usage: markmap [options] <input> | ||
Create a markmap from a Markdown input file | ||
Options: | ||
-V, --version output the version number | ||
-o, --output <output> specify filename of the output HTML | ||
--enable-mathjax enable MathJax support | ||
--no-open do not open the output file after generation | ||
-h, --help display help for command | ||
``` | ||
Suppose you have a Markdown file named `note.md`. | ||
Run the following command to get an interactive mindmap: | ||
```sh | ||
$ markmap README.md | ||
$ markmap note.md | ||
# without installation | ||
$ npx markmap-lib README.md | ||
# without global installation | ||
$ npx markmap-lib note.md | ||
``` | ||
Then you will get a `README.html` in the same directory, and hopefully it will be open in your default browser. | ||
Then you will get a `note.html` in the same directory, and hopefully it will be open in your default browser. | ||
#### MathJax | ||
To enable MathJax support for your Markdown, pass `--enable-mathjax`: | ||
```sh | ||
$ markmap --enable-mathjax note.md | ||
``` | ||
### API | ||
#### Installation | ||
```sh | ||
$ yarn add markmap-lib | ||
# or | ||
$ npm install markmap-lib | ||
``` | ||
#### Transform | ||
Transform Markdown to markmap data: | ||
```js | ||
import { transform } from 'markmap-lib/dist/transform.common'; | ||
const data = transform(markdown); | ||
``` | ||
Now we get the data for rendering in `data`. | ||
#### Render | ||
Render a markmap from transformed data: | ||
Create an SVG element with explicit width and height: | ||
```html | ||
<svg id="markmap" style="width: 800px; height: 800px"></svg> | ||
``` | ||
Render a markmap to the SVG element: | ||
```js | ||
import { markmap } from 'markmap-lib/dist/view.common'; | ||
markmap('#markmap', data); | ||
// or pass an SVG element directly | ||
const svgEl = document.querySelector('#markmap'); | ||
markmap(svgEl, data); | ||
``` | ||
#### MathJax | ||
To enable MathJax, you need to load MathJax before rendering markmap: | ||
```html | ||
<script> | ||
window.MathJax = { | ||
options: { | ||
skipHtmlTags: { | ||
'[-]': ['code', 'pre'] | ||
} | ||
} | ||
}; | ||
</script> | ||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script> | ||
``` | ||
and process Html with MathJax in `options.processHtml`: | ||
```js | ||
import { markmap } from 'markmap-lib/dist/view.common'; | ||
markmap('#markmap', data, { | ||
processHtml: nodes => { | ||
if (window.MathJax.typeset) MathJax.typeset(nodes); | ||
}, | ||
}); | ||
``` | ||
**Note**: | ||
- The `skipHtmlTags` option is required because inline code generated from Markdown is always wrapped in `<code>`, which is ignored by MathJax by default. | ||
- The MathJax library should better be loaded synchronously so that we can just use it in `options.processHtml` without a flash. | ||
## Related | ||
- [coc-markmap](https://github.com/gera2ld/coc-markmap) - Vim / NeoVim plugin powered by [coc.nvim](https://github.com/neoclide/coc.nvim) | ||
- Use with Vim / Neovim: [coc-markmap](https://github.com/gera2ld/coc-markmap) | ||
- Use with GatsbyJS: [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap) |
@@ -1,1 +0,1 @@ | ||
export declare function fillTemplate(data: any): string; | ||
export declare function fillTemplate(data: any, opts?: any): string; |
@@ -6,8 +6,5 @@ export interface IHierachy<T> { | ||
} | ||
export interface IValue extends IHierachy<IValue> { | ||
v?: string; | ||
} | ||
export interface INode extends IHierachy<INode> { | ||
d?: number; | ||
v?: IValue[]; | ||
v: string; | ||
} | ||
@@ -19,7 +16,9 @@ export interface IMarkmapCreateOptions { | ||
output?: string; | ||
mathJax?: boolean; | ||
} | ||
export interface IMarkmapOptions { | ||
id?: string; | ||
duration: number; | ||
nodeFont: string; | ||
lineHeight: number; | ||
nodeMinHeight: number; | ||
spacingVertical: number; | ||
@@ -31,2 +30,13 @@ spacingHorizontal: number; | ||
colorDepth: number; | ||
paddingX: number; | ||
style?: (id: string) => string; | ||
processHtml?: (container: Node[]) => void; | ||
} | ||
export interface IMarkmapState { | ||
id: string; | ||
data?: any; | ||
minX?: number; | ||
maxX?: number; | ||
minY?: number; | ||
maxY?: number; | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
324799
19
151
8452