markmap-cli 0.18.8 → 0.18.10-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +1 -6
- package/dist/assets/@highlightjs/cdn-assets@11.11.1/styles/default.min.css +9 -0
- package/dist/assets/d3@7.9.0/dist/d3.min.js +2 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/assets/katex@0.16.18/dist/katex.min.css +1 -0
- package/dist/assets/markmap-toolbar@0.18.10-alpha.2+9487f11/dist/index.js +281 -0
- package/dist/assets/markmap-toolbar@0.18.10-alpha.2+9487f11/dist/style.css +37 -0
- package/dist/assets/markmap-view@0.18.10-alpha.2+9487f11/dist/browser/index.js +1482 -0
- package/dist/assets/webfontloader@1.6.28/webfontloader.js +17 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +55 -0
- package/dist/common-CwPtCJvD.js +61 -0
- package/dist/fetch-assets.d.ts +1 -1
- package/dist/fetch-assets.js +81 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +7 -160
- package/dist/{dev-server.d.ts → util/dev-server.d.ts} +1 -1
- package/package.json +9 -9
- /package/dist/{util.d.ts → util/common.d.ts} +0 -0
|
@@ -0,0 +1,1482 @@
|
|
|
1
|
+
(function(exports, d32) {
|
|
2
|
+
"use strict";
|
|
3
|
+
class Hook {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.listeners = [];
|
|
6
|
+
}
|
|
7
|
+
tap(fn) {
|
|
8
|
+
this.listeners.push(fn);
|
|
9
|
+
return () => this.revoke(fn);
|
|
10
|
+
}
|
|
11
|
+
revoke(fn) {
|
|
12
|
+
const i = this.listeners.indexOf(fn);
|
|
13
|
+
if (i >= 0) this.listeners.splice(i, 1);
|
|
14
|
+
}
|
|
15
|
+
revokeAll() {
|
|
16
|
+
this.listeners.splice(0);
|
|
17
|
+
}
|
|
18
|
+
call(...args) {
|
|
19
|
+
for (const fn of this.listeners) {
|
|
20
|
+
fn(...args);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const uniqId = Math.random().toString(36).slice(2, 8);
|
|
25
|
+
let globalIndex = 0;
|
|
26
|
+
function getId() {
|
|
27
|
+
globalIndex += 1;
|
|
28
|
+
return `mm-${uniqId}-${globalIndex}`;
|
|
29
|
+
}
|
|
30
|
+
function noop() {
|
|
31
|
+
}
|
|
32
|
+
function walkTree(tree, callback) {
|
|
33
|
+
const walk = (item, parent) => callback(
|
|
34
|
+
item,
|
|
35
|
+
() => {
|
|
36
|
+
var _a;
|
|
37
|
+
return (_a = item.children) == null ? void 0 : _a.map((child) => walk(child, item));
|
|
38
|
+
},
|
|
39
|
+
parent
|
|
40
|
+
);
|
|
41
|
+
return walk(tree);
|
|
42
|
+
}
|
|
43
|
+
function addClass(className, ...rest) {
|
|
44
|
+
const classList = (className || "").split(" ").filter(Boolean);
|
|
45
|
+
rest.forEach((item) => {
|
|
46
|
+
if (item && classList.indexOf(item) < 0) classList.push(item);
|
|
47
|
+
});
|
|
48
|
+
return classList.join(" ");
|
|
49
|
+
}
|
|
50
|
+
function defer() {
|
|
51
|
+
const obj = {};
|
|
52
|
+
obj.promise = new Promise((resolve, reject) => {
|
|
53
|
+
obj.resolve = resolve;
|
|
54
|
+
obj.reject = reject;
|
|
55
|
+
});
|
|
56
|
+
return obj;
|
|
57
|
+
}
|
|
58
|
+
function memoize(fn) {
|
|
59
|
+
const cache = {};
|
|
60
|
+
return function memoized(...args) {
|
|
61
|
+
const key = `${args[0]}`;
|
|
62
|
+
let data = cache[key];
|
|
63
|
+
if (!data) {
|
|
64
|
+
data = {
|
|
65
|
+
value: fn(...args)
|
|
66
|
+
};
|
|
67
|
+
cache[key] = data;
|
|
68
|
+
}
|
|
69
|
+
return data.value;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function debounce(fn, time) {
|
|
73
|
+
const state = {
|
|
74
|
+
timer: 0
|
|
75
|
+
};
|
|
76
|
+
function reset() {
|
|
77
|
+
if (state.timer) {
|
|
78
|
+
window.clearTimeout(state.timer);
|
|
79
|
+
state.timer = 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function run() {
|
|
83
|
+
reset();
|
|
84
|
+
if (state.args) state.result = fn(...state.args);
|
|
85
|
+
}
|
|
86
|
+
return function debounced(...args) {
|
|
87
|
+
reset();
|
|
88
|
+
state.args = args;
|
|
89
|
+
state.timer = window.setTimeout(run, time);
|
|
90
|
+
return state.result;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/*! @gera2ld/jsx-dom v2.2.2 | ISC License */
|
|
94
|
+
const VTYPE_ELEMENT = 1;
|
|
95
|
+
const VTYPE_FUNCTION = 2;
|
|
96
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
97
|
+
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
98
|
+
const NS_ATTRS = {
|
|
99
|
+
show: XLINK_NS,
|
|
100
|
+
actuate: XLINK_NS,
|
|
101
|
+
href: XLINK_NS
|
|
102
|
+
};
|
|
103
|
+
const isLeaf = (c) => typeof c === "string" || typeof c === "number";
|
|
104
|
+
const isElement = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
|
|
105
|
+
const isRenderFunction = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
|
|
106
|
+
function h(type, props, ...children) {
|
|
107
|
+
props = Object.assign({}, props, {
|
|
108
|
+
children: children.length === 1 ? children[0] : children
|
|
109
|
+
});
|
|
110
|
+
return jsx(type, props);
|
|
111
|
+
}
|
|
112
|
+
function jsx(type, props) {
|
|
113
|
+
let vtype;
|
|
114
|
+
if (typeof type === "string") vtype = VTYPE_ELEMENT;
|
|
115
|
+
else if (typeof type === "function") vtype = VTYPE_FUNCTION;
|
|
116
|
+
else throw new Error("Invalid VNode type");
|
|
117
|
+
return {
|
|
118
|
+
vtype,
|
|
119
|
+
type,
|
|
120
|
+
props
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function Fragment(props) {
|
|
124
|
+
return props.children;
|
|
125
|
+
}
|
|
126
|
+
const DEFAULT_ENV = {
|
|
127
|
+
isSvg: false
|
|
128
|
+
};
|
|
129
|
+
function insertDom(parent, nodes) {
|
|
130
|
+
if (!Array.isArray(nodes)) nodes = [nodes];
|
|
131
|
+
nodes = nodes.filter(Boolean);
|
|
132
|
+
if (nodes.length) parent.append(...nodes);
|
|
133
|
+
}
|
|
134
|
+
function mountAttributes(domElement, props, env) {
|
|
135
|
+
for (const key in props) {
|
|
136
|
+
if (key === "key" || key === "children" || key === "ref") continue;
|
|
137
|
+
if (key === "dangerouslySetInnerHTML") {
|
|
138
|
+
domElement.innerHTML = props[key].__html;
|
|
139
|
+
} else if (key === "innerHTML" || key === "textContent" || key === "innerText" || key === "value" && ["textarea", "select"].includes(domElement.tagName)) {
|
|
140
|
+
const value = props[key];
|
|
141
|
+
if (value != null) domElement[key] = value;
|
|
142
|
+
} else if (key.startsWith("on")) {
|
|
143
|
+
domElement[key.toLowerCase()] = props[key];
|
|
144
|
+
} else {
|
|
145
|
+
setDOMAttribute(domElement, key, props[key], env.isSvg);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const attrMap = {
|
|
150
|
+
className: "class",
|
|
151
|
+
labelFor: "for"
|
|
152
|
+
};
|
|
153
|
+
function setDOMAttribute(el, attr, value, isSVG) {
|
|
154
|
+
attr = attrMap[attr] || attr;
|
|
155
|
+
if (value === true) {
|
|
156
|
+
el.setAttribute(attr, "");
|
|
157
|
+
} else if (value === false) {
|
|
158
|
+
el.removeAttribute(attr);
|
|
159
|
+
} else {
|
|
160
|
+
const namespace = isSVG ? NS_ATTRS[attr] : void 0;
|
|
161
|
+
if (namespace !== void 0) {
|
|
162
|
+
el.setAttributeNS(namespace, attr, value);
|
|
163
|
+
} else {
|
|
164
|
+
el.setAttribute(attr, value);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function flatten(arr) {
|
|
169
|
+
return arr.reduce((prev, item) => prev.concat(item), []);
|
|
170
|
+
}
|
|
171
|
+
function mountChildren(children, env) {
|
|
172
|
+
return Array.isArray(children) ? flatten(children.map((child) => mountChildren(child, env))) : mount(children, env);
|
|
173
|
+
}
|
|
174
|
+
function mount(vnode, env = DEFAULT_ENV) {
|
|
175
|
+
if (vnode == null || typeof vnode === "boolean") {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
if (vnode instanceof Node) {
|
|
179
|
+
return vnode;
|
|
180
|
+
}
|
|
181
|
+
if (isRenderFunction(vnode)) {
|
|
182
|
+
const {
|
|
183
|
+
type,
|
|
184
|
+
props
|
|
185
|
+
} = vnode;
|
|
186
|
+
if (type === Fragment) {
|
|
187
|
+
const node = document.createDocumentFragment();
|
|
188
|
+
if (props.children) {
|
|
189
|
+
const children = mountChildren(props.children, env);
|
|
190
|
+
insertDom(node, children);
|
|
191
|
+
}
|
|
192
|
+
return node;
|
|
193
|
+
}
|
|
194
|
+
const childVNode = type(props);
|
|
195
|
+
return mount(childVNode, env);
|
|
196
|
+
}
|
|
197
|
+
if (isLeaf(vnode)) {
|
|
198
|
+
return document.createTextNode(`${vnode}`);
|
|
199
|
+
}
|
|
200
|
+
if (isElement(vnode)) {
|
|
201
|
+
let node;
|
|
202
|
+
const {
|
|
203
|
+
type,
|
|
204
|
+
props
|
|
205
|
+
} = vnode;
|
|
206
|
+
if (!env.isSvg && type === "svg") {
|
|
207
|
+
env = Object.assign({}, env, {
|
|
208
|
+
isSvg: true
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
if (!env.isSvg) {
|
|
212
|
+
node = document.createElement(type);
|
|
213
|
+
} else {
|
|
214
|
+
node = document.createElementNS(SVG_NS, type);
|
|
215
|
+
}
|
|
216
|
+
mountAttributes(node, props, env);
|
|
217
|
+
if (props.children) {
|
|
218
|
+
let childEnv = env;
|
|
219
|
+
if (env.isSvg && type === "foreignObject") {
|
|
220
|
+
childEnv = Object.assign({}, childEnv, {
|
|
221
|
+
isSvg: false
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const children = mountChildren(props.children, childEnv);
|
|
225
|
+
if (children != null) insertDom(node, children);
|
|
226
|
+
}
|
|
227
|
+
const {
|
|
228
|
+
ref
|
|
229
|
+
} = props;
|
|
230
|
+
if (typeof ref === "function") ref(node);
|
|
231
|
+
return node;
|
|
232
|
+
}
|
|
233
|
+
throw new Error("mount: Invalid Vnode!");
|
|
234
|
+
}
|
|
235
|
+
function mountDom(vnode) {
|
|
236
|
+
return mount(vnode);
|
|
237
|
+
}
|
|
238
|
+
function hm(...args) {
|
|
239
|
+
return mountDom(h(...args));
|
|
240
|
+
}
|
|
241
|
+
const memoizedPreloadJS = memoize((url) => {
|
|
242
|
+
document.head.append(
|
|
243
|
+
hm("link", {
|
|
244
|
+
rel: "preload",
|
|
245
|
+
as: "script",
|
|
246
|
+
href: url
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
const jsCache = {};
|
|
251
|
+
const cssCache = {};
|
|
252
|
+
async function loadJSItem(item, context) {
|
|
253
|
+
var _a;
|
|
254
|
+
const src = item.type === "script" && ((_a = item.data) == null ? void 0 : _a.src) || "";
|
|
255
|
+
item.loaded || (item.loaded = jsCache[src]);
|
|
256
|
+
if (!item.loaded) {
|
|
257
|
+
const deferred = defer();
|
|
258
|
+
item.loaded = deferred.promise;
|
|
259
|
+
if (item.type === "script") {
|
|
260
|
+
document.head.append(
|
|
261
|
+
hm("script", {
|
|
262
|
+
...item.data,
|
|
263
|
+
onLoad: () => deferred.resolve(),
|
|
264
|
+
onError: deferred.reject
|
|
265
|
+
})
|
|
266
|
+
);
|
|
267
|
+
if (!src) {
|
|
268
|
+
deferred.resolve();
|
|
269
|
+
} else {
|
|
270
|
+
jsCache[src] = item.loaded;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (item.type === "iife") {
|
|
274
|
+
const { fn, getParams } = item.data;
|
|
275
|
+
fn(...(getParams == null ? void 0 : getParams(context)) || []);
|
|
276
|
+
deferred.resolve();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
await item.loaded;
|
|
280
|
+
}
|
|
281
|
+
async function loadCSSItem(item) {
|
|
282
|
+
const url = item.type === "stylesheet" && item.data.href || "";
|
|
283
|
+
item.loaded || (item.loaded = cssCache[url]);
|
|
284
|
+
if (!item.loaded) {
|
|
285
|
+
const deferred = defer();
|
|
286
|
+
item.loaded = deferred.promise;
|
|
287
|
+
if (url) cssCache[url] = item.loaded;
|
|
288
|
+
if (item.type === "style") {
|
|
289
|
+
document.head.append(
|
|
290
|
+
hm("style", {
|
|
291
|
+
textContent: item.data
|
|
292
|
+
})
|
|
293
|
+
);
|
|
294
|
+
deferred.resolve();
|
|
295
|
+
} else if (url) {
|
|
296
|
+
document.head.append(
|
|
297
|
+
hm("link", {
|
|
298
|
+
rel: "stylesheet",
|
|
299
|
+
...item.data
|
|
300
|
+
})
|
|
301
|
+
);
|
|
302
|
+
fetch(url).then((res) => {
|
|
303
|
+
if (res.ok) return res.text();
|
|
304
|
+
throw res;
|
|
305
|
+
}).then(() => deferred.resolve(), deferred.reject);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
await item.loaded;
|
|
309
|
+
}
|
|
310
|
+
async function loadJS(items, context) {
|
|
311
|
+
items.forEach((item) => {
|
|
312
|
+
var _a;
|
|
313
|
+
if (item.type === "script" && ((_a = item.data) == null ? void 0 : _a.src)) {
|
|
314
|
+
memoizedPreloadJS(item.data.src);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
context = {
|
|
318
|
+
getMarkmap: () => window.markmap,
|
|
319
|
+
...context
|
|
320
|
+
};
|
|
321
|
+
for (const item of items) {
|
|
322
|
+
await loadJSItem(item, context);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async function loadCSS(items) {
|
|
326
|
+
await Promise.all(items.map((item) => loadCSSItem(item)));
|
|
327
|
+
}
|
|
328
|
+
const isMacintosh = typeof navigator !== "undefined" && navigator.userAgent.includes("Macintosh");
|
|
329
|
+
const defaultColorFn = d32.scaleOrdinal(d32.schemeCategory10);
|
|
330
|
+
const lineWidthFactory = (baseWidth = 1, deltaWidth = 3, k = 2) => (node) => baseWidth + deltaWidth / k ** node.state.depth;
|
|
331
|
+
const defaultOptions = {
|
|
332
|
+
autoFit: false,
|
|
333
|
+
duration: 500,
|
|
334
|
+
embedGlobalCSS: true,
|
|
335
|
+
fitRatio: 0.95,
|
|
336
|
+
maxInitialScale: 2,
|
|
337
|
+
scrollForPan: isMacintosh,
|
|
338
|
+
initialExpandLevel: -1,
|
|
339
|
+
zoom: true,
|
|
340
|
+
pan: true,
|
|
341
|
+
toggleRecursively: false,
|
|
342
|
+
color: (node) => {
|
|
343
|
+
var _a;
|
|
344
|
+
return defaultColorFn(`${((_a = node.state) == null ? void 0 : _a.path) || ""}`);
|
|
345
|
+
},
|
|
346
|
+
lineWidth: lineWidthFactory(),
|
|
347
|
+
maxWidth: 0,
|
|
348
|
+
nodeMinHeight: 16,
|
|
349
|
+
paddingX: 8,
|
|
350
|
+
spacingHorizontal: 80,
|
|
351
|
+
spacingVertical: 5
|
|
352
|
+
};
|
|
353
|
+
function deriveOptions(jsonOptions) {
|
|
354
|
+
const derivedOptions = {};
|
|
355
|
+
const options = { ...jsonOptions };
|
|
356
|
+
const { color, colorFreezeLevel, lineWidth } = options;
|
|
357
|
+
if ((color == null ? void 0 : color.length) === 1) {
|
|
358
|
+
const solidColor = color[0];
|
|
359
|
+
derivedOptions.color = () => solidColor;
|
|
360
|
+
} else if (color == null ? void 0 : color.length) {
|
|
361
|
+
const colorFn = d32.scaleOrdinal(color);
|
|
362
|
+
derivedOptions.color = (node) => colorFn(`${node.state.path}`);
|
|
363
|
+
}
|
|
364
|
+
if (colorFreezeLevel) {
|
|
365
|
+
const color2 = derivedOptions.color || defaultOptions.color;
|
|
366
|
+
derivedOptions.color = (node) => {
|
|
367
|
+
node = {
|
|
368
|
+
...node,
|
|
369
|
+
state: {
|
|
370
|
+
...node.state,
|
|
371
|
+
path: node.state.path.split(".").slice(0, colorFreezeLevel).join(".")
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
return color2(node);
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
if (lineWidth) {
|
|
378
|
+
const args = Array.isArray(lineWidth) ? lineWidth : [lineWidth, 0, 1];
|
|
379
|
+
derivedOptions.lineWidth = lineWidthFactory(
|
|
380
|
+
...args
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
const numberKeys = [
|
|
384
|
+
"duration",
|
|
385
|
+
"fitRatio",
|
|
386
|
+
"initialExpandLevel",
|
|
387
|
+
"maxInitialScale",
|
|
388
|
+
"maxWidth",
|
|
389
|
+
"nodeMinHeight",
|
|
390
|
+
"paddingX",
|
|
391
|
+
"spacingHorizontal",
|
|
392
|
+
"spacingVertical"
|
|
393
|
+
];
|
|
394
|
+
numberKeys.forEach((key) => {
|
|
395
|
+
const value = options[key];
|
|
396
|
+
if (typeof value === "number") derivedOptions[key] = value;
|
|
397
|
+
});
|
|
398
|
+
const booleanKeys = ["zoom", "pan"];
|
|
399
|
+
booleanKeys.forEach((key) => {
|
|
400
|
+
const value = options[key];
|
|
401
|
+
if (value != null) derivedOptions[key] = !!value;
|
|
402
|
+
});
|
|
403
|
+
return derivedOptions;
|
|
404
|
+
}
|
|
405
|
+
function simpleHash(str) {
|
|
406
|
+
let hash = 0;
|
|
407
|
+
for (let i = 0; i < str.length; i++) {
|
|
408
|
+
hash = (hash << 5) - hash + str.charCodeAt(i) | 0;
|
|
409
|
+
}
|
|
410
|
+
return (hash >>> 0).toString(36);
|
|
411
|
+
}
|
|
412
|
+
function childSelector(filter) {
|
|
413
|
+
if (typeof filter === "string") {
|
|
414
|
+
const selector = filter;
|
|
415
|
+
filter = (el) => el.matches(selector);
|
|
416
|
+
}
|
|
417
|
+
const filterFn = filter;
|
|
418
|
+
return function selector() {
|
|
419
|
+
let nodes = Array.from(this.childNodes);
|
|
420
|
+
if (filterFn) nodes = nodes.filter((node) => filterFn(node));
|
|
421
|
+
return nodes;
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function count(node) {
|
|
425
|
+
var sum = 0, children = node.children, i = children && children.length;
|
|
426
|
+
if (!i) sum = 1;
|
|
427
|
+
else while (--i >= 0) sum += children[i].value;
|
|
428
|
+
node.value = sum;
|
|
429
|
+
}
|
|
430
|
+
function node_count() {
|
|
431
|
+
return this.eachAfter(count);
|
|
432
|
+
}
|
|
433
|
+
function node_each(callback) {
|
|
434
|
+
var node = this, current, next = [node], children, i, n;
|
|
435
|
+
do {
|
|
436
|
+
current = next.reverse(), next = [];
|
|
437
|
+
while (node = current.pop()) {
|
|
438
|
+
callback(node), children = node.children;
|
|
439
|
+
if (children) for (i = 0, n = children.length; i < n; ++i) {
|
|
440
|
+
next.push(children[i]);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
} while (next.length);
|
|
444
|
+
return this;
|
|
445
|
+
}
|
|
446
|
+
function node_eachBefore(callback) {
|
|
447
|
+
var node = this, nodes = [node], children, i;
|
|
448
|
+
while (node = nodes.pop()) {
|
|
449
|
+
callback(node), children = node.children;
|
|
450
|
+
if (children) for (i = children.length - 1; i >= 0; --i) {
|
|
451
|
+
nodes.push(children[i]);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return this;
|
|
455
|
+
}
|
|
456
|
+
function node_eachAfter(callback) {
|
|
457
|
+
var node = this, nodes = [node], next = [], children, i, n;
|
|
458
|
+
while (node = nodes.pop()) {
|
|
459
|
+
next.push(node), children = node.children;
|
|
460
|
+
if (children) for (i = 0, n = children.length; i < n; ++i) {
|
|
461
|
+
nodes.push(children[i]);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
while (node = next.pop()) {
|
|
465
|
+
callback(node);
|
|
466
|
+
}
|
|
467
|
+
return this;
|
|
468
|
+
}
|
|
469
|
+
function node_sum(value) {
|
|
470
|
+
return this.eachAfter(function(node) {
|
|
471
|
+
var sum = +value(node.data) || 0, children = node.children, i = children && children.length;
|
|
472
|
+
while (--i >= 0) sum += children[i].value;
|
|
473
|
+
node.value = sum;
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
function node_sort(compare) {
|
|
477
|
+
return this.eachBefore(function(node) {
|
|
478
|
+
if (node.children) {
|
|
479
|
+
node.children.sort(compare);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
function node_path(end) {
|
|
484
|
+
var start = this, ancestor = leastCommonAncestor(start, end), nodes = [start];
|
|
485
|
+
while (start !== ancestor) {
|
|
486
|
+
start = start.parent;
|
|
487
|
+
nodes.push(start);
|
|
488
|
+
}
|
|
489
|
+
var k = nodes.length;
|
|
490
|
+
while (end !== ancestor) {
|
|
491
|
+
nodes.splice(k, 0, end);
|
|
492
|
+
end = end.parent;
|
|
493
|
+
}
|
|
494
|
+
return nodes;
|
|
495
|
+
}
|
|
496
|
+
function leastCommonAncestor(a, b) {
|
|
497
|
+
if (a === b) return a;
|
|
498
|
+
var aNodes = a.ancestors(), bNodes = b.ancestors(), c = null;
|
|
499
|
+
a = aNodes.pop();
|
|
500
|
+
b = bNodes.pop();
|
|
501
|
+
while (a === b) {
|
|
502
|
+
c = a;
|
|
503
|
+
a = aNodes.pop();
|
|
504
|
+
b = bNodes.pop();
|
|
505
|
+
}
|
|
506
|
+
return c;
|
|
507
|
+
}
|
|
508
|
+
function node_ancestors() {
|
|
509
|
+
var node = this, nodes = [node];
|
|
510
|
+
while (node = node.parent) {
|
|
511
|
+
nodes.push(node);
|
|
512
|
+
}
|
|
513
|
+
return nodes;
|
|
514
|
+
}
|
|
515
|
+
function node_descendants() {
|
|
516
|
+
var nodes = [];
|
|
517
|
+
this.each(function(node) {
|
|
518
|
+
nodes.push(node);
|
|
519
|
+
});
|
|
520
|
+
return nodes;
|
|
521
|
+
}
|
|
522
|
+
function node_leaves() {
|
|
523
|
+
var leaves = [];
|
|
524
|
+
this.eachBefore(function(node) {
|
|
525
|
+
if (!node.children) {
|
|
526
|
+
leaves.push(node);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
return leaves;
|
|
530
|
+
}
|
|
531
|
+
function node_links() {
|
|
532
|
+
var root = this, links = [];
|
|
533
|
+
root.each(function(node) {
|
|
534
|
+
if (node !== root) {
|
|
535
|
+
links.push({ source: node.parent, target: node });
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
return links;
|
|
539
|
+
}
|
|
540
|
+
function hierarchy(data, children) {
|
|
541
|
+
var root = new Node$1(data), valued = +data.value && (root.value = data.value), node, nodes = [root], child, childs, i, n;
|
|
542
|
+
if (children == null) children = defaultChildren;
|
|
543
|
+
while (node = nodes.pop()) {
|
|
544
|
+
if (valued) node.value = +node.data.value;
|
|
545
|
+
if ((childs = children(node.data)) && (n = childs.length)) {
|
|
546
|
+
node.children = new Array(n);
|
|
547
|
+
for (i = n - 1; i >= 0; --i) {
|
|
548
|
+
nodes.push(child = node.children[i] = new Node$1(childs[i]));
|
|
549
|
+
child.parent = node;
|
|
550
|
+
child.depth = node.depth + 1;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return root.eachBefore(computeHeight);
|
|
555
|
+
}
|
|
556
|
+
function node_copy() {
|
|
557
|
+
return hierarchy(this).eachBefore(copyData);
|
|
558
|
+
}
|
|
559
|
+
function defaultChildren(d) {
|
|
560
|
+
return d.children;
|
|
561
|
+
}
|
|
562
|
+
function copyData(node) {
|
|
563
|
+
node.data = node.data.data;
|
|
564
|
+
}
|
|
565
|
+
function computeHeight(node) {
|
|
566
|
+
var height = 0;
|
|
567
|
+
do
|
|
568
|
+
node.height = height;
|
|
569
|
+
while ((node = node.parent) && node.height < ++height);
|
|
570
|
+
}
|
|
571
|
+
function Node$1(data) {
|
|
572
|
+
this.data = data;
|
|
573
|
+
this.depth = this.height = 0;
|
|
574
|
+
this.parent = null;
|
|
575
|
+
}
|
|
576
|
+
Node$1.prototype = hierarchy.prototype = {
|
|
577
|
+
constructor: Node$1,
|
|
578
|
+
count: node_count,
|
|
579
|
+
each: node_each,
|
|
580
|
+
eachAfter: node_eachAfter,
|
|
581
|
+
eachBefore: node_eachBefore,
|
|
582
|
+
sum: node_sum,
|
|
583
|
+
sort: node_sort,
|
|
584
|
+
path: node_path,
|
|
585
|
+
ancestors: node_ancestors,
|
|
586
|
+
descendants: node_descendants,
|
|
587
|
+
leaves: node_leaves,
|
|
588
|
+
links: node_links,
|
|
589
|
+
copy: node_copy
|
|
590
|
+
};
|
|
591
|
+
const name = "d3-flextree";
|
|
592
|
+
const version$1 = "2.1.2";
|
|
593
|
+
const main = "build/d3-flextree.js";
|
|
594
|
+
const module = "index";
|
|
595
|
+
const author = { "name": "Chris Maloney", "url": "http://chrismaloney.org" };
|
|
596
|
+
const description = "Flexible tree layout algorithm that allows for variable node sizes.";
|
|
597
|
+
const keywords = ["d3", "d3-module", "layout", "tree", "hierarchy", "d3-hierarchy", "plugin", "d3-plugin", "infovis", "visualization", "2d"];
|
|
598
|
+
const homepage = "https://github.com/klortho/d3-flextree";
|
|
599
|
+
const license = "WTFPL";
|
|
600
|
+
const repository = { "type": "git", "url": "https://github.com/klortho/d3-flextree.git" };
|
|
601
|
+
const scripts = { "clean": "rm -rf build demo test", "build:demo": "rollup -c --environment BUILD:demo", "build:dev": "rollup -c --environment BUILD:dev", "build:prod": "rollup -c --environment BUILD:prod", "build:test": "rollup -c --environment BUILD:test", "build": "rollup -c", "lint": "eslint index.js src", "test:main": "node test/bundle.js", "test:browser": "node test/browser-tests.js", "test": "npm-run-all test:*", "prepare": "npm-run-all clean build lint test" };
|
|
602
|
+
const dependencies = { "d3-hierarchy": "^1.1.5" };
|
|
603
|
+
const devDependencies = { "babel-plugin-external-helpers": "^6.22.0", "babel-preset-es2015-rollup": "^3.0.0", "d3": "^4.13.0", "d3-selection-multi": "^1.0.1", "eslint": "^4.19.1", "jsdom": "^11.6.2", "npm-run-all": "^4.1.2", "rollup": "^0.55.3", "rollup-plugin-babel": "^2.7.1", "rollup-plugin-commonjs": "^8.0.2", "rollup-plugin-copy": "^0.2.3", "rollup-plugin-json": "^2.3.0", "rollup-plugin-node-resolve": "^3.0.2", "rollup-plugin-uglify": "^3.0.0", "uglify-es": "^3.3.9" };
|
|
604
|
+
const packageInfo = {
|
|
605
|
+
name,
|
|
606
|
+
version: version$1,
|
|
607
|
+
main,
|
|
608
|
+
module,
|
|
609
|
+
"jsnext:main": "index",
|
|
610
|
+
author,
|
|
611
|
+
description,
|
|
612
|
+
keywords,
|
|
613
|
+
homepage,
|
|
614
|
+
license,
|
|
615
|
+
repository,
|
|
616
|
+
scripts,
|
|
617
|
+
dependencies,
|
|
618
|
+
devDependencies
|
|
619
|
+
};
|
|
620
|
+
const { version } = packageInfo;
|
|
621
|
+
const defaults = Object.freeze({
|
|
622
|
+
children: (data) => data.children,
|
|
623
|
+
nodeSize: (node) => node.data.size,
|
|
624
|
+
spacing: 0
|
|
625
|
+
});
|
|
626
|
+
function flextree(options) {
|
|
627
|
+
const opts = Object.assign({}, defaults, options);
|
|
628
|
+
function accessor(name2) {
|
|
629
|
+
const opt = opts[name2];
|
|
630
|
+
return typeof opt === "function" ? opt : () => opt;
|
|
631
|
+
}
|
|
632
|
+
function layout(tree) {
|
|
633
|
+
const wtree = wrap(getWrapper(), tree, (node) => node.children);
|
|
634
|
+
wtree.update();
|
|
635
|
+
return wtree.data;
|
|
636
|
+
}
|
|
637
|
+
function getFlexNode() {
|
|
638
|
+
const nodeSize = accessor("nodeSize");
|
|
639
|
+
const spacing = accessor("spacing");
|
|
640
|
+
return class FlexNode extends hierarchy.prototype.constructor {
|
|
641
|
+
constructor(data) {
|
|
642
|
+
super(data);
|
|
643
|
+
}
|
|
644
|
+
copy() {
|
|
645
|
+
const c = wrap(this.constructor, this, (node) => node.children);
|
|
646
|
+
c.each((node) => node.data = node.data.data);
|
|
647
|
+
return c;
|
|
648
|
+
}
|
|
649
|
+
get size() {
|
|
650
|
+
return nodeSize(this);
|
|
651
|
+
}
|
|
652
|
+
spacing(oNode) {
|
|
653
|
+
return spacing(this, oNode);
|
|
654
|
+
}
|
|
655
|
+
get nodes() {
|
|
656
|
+
return this.descendants();
|
|
657
|
+
}
|
|
658
|
+
get xSize() {
|
|
659
|
+
return this.size[0];
|
|
660
|
+
}
|
|
661
|
+
get ySize() {
|
|
662
|
+
return this.size[1];
|
|
663
|
+
}
|
|
664
|
+
get top() {
|
|
665
|
+
return this.y;
|
|
666
|
+
}
|
|
667
|
+
get bottom() {
|
|
668
|
+
return this.y + this.ySize;
|
|
669
|
+
}
|
|
670
|
+
get left() {
|
|
671
|
+
return this.x - this.xSize / 2;
|
|
672
|
+
}
|
|
673
|
+
get right() {
|
|
674
|
+
return this.x + this.xSize / 2;
|
|
675
|
+
}
|
|
676
|
+
get root() {
|
|
677
|
+
const ancs = this.ancestors();
|
|
678
|
+
return ancs[ancs.length - 1];
|
|
679
|
+
}
|
|
680
|
+
get numChildren() {
|
|
681
|
+
return this.hasChildren ? this.children.length : 0;
|
|
682
|
+
}
|
|
683
|
+
get hasChildren() {
|
|
684
|
+
return !this.noChildren;
|
|
685
|
+
}
|
|
686
|
+
get noChildren() {
|
|
687
|
+
return this.children === null;
|
|
688
|
+
}
|
|
689
|
+
get firstChild() {
|
|
690
|
+
return this.hasChildren ? this.children[0] : null;
|
|
691
|
+
}
|
|
692
|
+
get lastChild() {
|
|
693
|
+
return this.hasChildren ? this.children[this.numChildren - 1] : null;
|
|
694
|
+
}
|
|
695
|
+
get extents() {
|
|
696
|
+
return (this.children || []).reduce(
|
|
697
|
+
(acc, kid) => FlexNode.maxExtents(acc, kid.extents),
|
|
698
|
+
this.nodeExtents
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
get nodeExtents() {
|
|
702
|
+
return {
|
|
703
|
+
top: this.top,
|
|
704
|
+
bottom: this.bottom,
|
|
705
|
+
left: this.left,
|
|
706
|
+
right: this.right
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
static maxExtents(e0, e1) {
|
|
710
|
+
return {
|
|
711
|
+
top: Math.min(e0.top, e1.top),
|
|
712
|
+
bottom: Math.max(e0.bottom, e1.bottom),
|
|
713
|
+
left: Math.min(e0.left, e1.left),
|
|
714
|
+
right: Math.max(e0.right, e1.right)
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function getWrapper() {
|
|
720
|
+
const FlexNode = getFlexNode();
|
|
721
|
+
const nodeSize = accessor("nodeSize");
|
|
722
|
+
const spacing = accessor("spacing");
|
|
723
|
+
return class extends FlexNode {
|
|
724
|
+
constructor(data) {
|
|
725
|
+
super(data);
|
|
726
|
+
Object.assign(this, {
|
|
727
|
+
x: 0,
|
|
728
|
+
y: 0,
|
|
729
|
+
relX: 0,
|
|
730
|
+
prelim: 0,
|
|
731
|
+
shift: 0,
|
|
732
|
+
change: 0,
|
|
733
|
+
lExt: this,
|
|
734
|
+
lExtRelX: 0,
|
|
735
|
+
lThr: null,
|
|
736
|
+
rExt: this,
|
|
737
|
+
rExtRelX: 0,
|
|
738
|
+
rThr: null
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
get size() {
|
|
742
|
+
return nodeSize(this.data);
|
|
743
|
+
}
|
|
744
|
+
spacing(oNode) {
|
|
745
|
+
return spacing(this.data, oNode.data);
|
|
746
|
+
}
|
|
747
|
+
get x() {
|
|
748
|
+
return this.data.x;
|
|
749
|
+
}
|
|
750
|
+
set x(v) {
|
|
751
|
+
this.data.x = v;
|
|
752
|
+
}
|
|
753
|
+
get y() {
|
|
754
|
+
return this.data.y;
|
|
755
|
+
}
|
|
756
|
+
set y(v) {
|
|
757
|
+
this.data.y = v;
|
|
758
|
+
}
|
|
759
|
+
update() {
|
|
760
|
+
layoutChildren(this);
|
|
761
|
+
resolveX(this);
|
|
762
|
+
return this;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function wrap(FlexClass, treeData, children) {
|
|
767
|
+
const _wrap = (data, parent) => {
|
|
768
|
+
const node = new FlexClass(data);
|
|
769
|
+
Object.assign(node, {
|
|
770
|
+
parent,
|
|
771
|
+
depth: parent === null ? 0 : parent.depth + 1,
|
|
772
|
+
height: 0,
|
|
773
|
+
length: 1
|
|
774
|
+
});
|
|
775
|
+
const kidsData = children(data) || [];
|
|
776
|
+
node.children = kidsData.length === 0 ? null : kidsData.map((kd) => _wrap(kd, node));
|
|
777
|
+
if (node.children) {
|
|
778
|
+
Object.assign(node, node.children.reduce(
|
|
779
|
+
(hl, kid) => ({
|
|
780
|
+
height: Math.max(hl.height, kid.height + 1),
|
|
781
|
+
length: hl.length + kid.length
|
|
782
|
+
}),
|
|
783
|
+
node
|
|
784
|
+
));
|
|
785
|
+
}
|
|
786
|
+
return node;
|
|
787
|
+
};
|
|
788
|
+
return _wrap(treeData, null);
|
|
789
|
+
}
|
|
790
|
+
Object.assign(layout, {
|
|
791
|
+
nodeSize(arg) {
|
|
792
|
+
return arguments.length ? (opts.nodeSize = arg, layout) : opts.nodeSize;
|
|
793
|
+
},
|
|
794
|
+
spacing(arg) {
|
|
795
|
+
return arguments.length ? (opts.spacing = arg, layout) : opts.spacing;
|
|
796
|
+
},
|
|
797
|
+
children(arg) {
|
|
798
|
+
return arguments.length ? (opts.children = arg, layout) : opts.children;
|
|
799
|
+
},
|
|
800
|
+
hierarchy(treeData, children) {
|
|
801
|
+
const kids = typeof children === "undefined" ? opts.children : children;
|
|
802
|
+
return wrap(getFlexNode(), treeData, kids);
|
|
803
|
+
},
|
|
804
|
+
dump(tree) {
|
|
805
|
+
const nodeSize = accessor("nodeSize");
|
|
806
|
+
const _dump = (i0) => (node) => {
|
|
807
|
+
const i1 = i0 + " ";
|
|
808
|
+
const i2 = i0 + " ";
|
|
809
|
+
const { x, y } = node;
|
|
810
|
+
const size = nodeSize(node);
|
|
811
|
+
const kids = node.children || [];
|
|
812
|
+
const kdumps = kids.length === 0 ? " " : `,${i1}children: [${i2}${kids.map(_dump(i2)).join(i2)}${i1}],${i0}`;
|
|
813
|
+
return `{ size: [${size.join(", ")}],${i1}x: ${x}, y: ${y}${kdumps}},`;
|
|
814
|
+
};
|
|
815
|
+
return _dump("\n")(tree);
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
return layout;
|
|
819
|
+
}
|
|
820
|
+
flextree.version = version;
|
|
821
|
+
const layoutChildren = (w, y = 0) => {
|
|
822
|
+
w.y = y;
|
|
823
|
+
(w.children || []).reduce((acc, kid) => {
|
|
824
|
+
const [i, lastLows] = acc;
|
|
825
|
+
layoutChildren(kid, w.y + w.ySize);
|
|
826
|
+
const lowY = (i === 0 ? kid.lExt : kid.rExt).bottom;
|
|
827
|
+
if (i !== 0) separate(w, i, lastLows);
|
|
828
|
+
const lows = updateLows(lowY, i, lastLows);
|
|
829
|
+
return [i + 1, lows];
|
|
830
|
+
}, [0, null]);
|
|
831
|
+
shiftChange(w);
|
|
832
|
+
positionRoot(w);
|
|
833
|
+
return w;
|
|
834
|
+
};
|
|
835
|
+
const resolveX = (w, prevSum, parentX) => {
|
|
836
|
+
if (typeof prevSum === "undefined") {
|
|
837
|
+
prevSum = -w.relX - w.prelim;
|
|
838
|
+
parentX = 0;
|
|
839
|
+
}
|
|
840
|
+
const sum = prevSum + w.relX;
|
|
841
|
+
w.relX = sum + w.prelim - parentX;
|
|
842
|
+
w.prelim = 0;
|
|
843
|
+
w.x = parentX + w.relX;
|
|
844
|
+
(w.children || []).forEach((k) => resolveX(k, sum, w.x));
|
|
845
|
+
return w;
|
|
846
|
+
};
|
|
847
|
+
const shiftChange = (w) => {
|
|
848
|
+
(w.children || []).reduce((acc, child) => {
|
|
849
|
+
const [lastShiftSum, lastChangeSum] = acc;
|
|
850
|
+
const shiftSum = lastShiftSum + child.shift;
|
|
851
|
+
const changeSum = lastChangeSum + shiftSum + child.change;
|
|
852
|
+
child.relX += changeSum;
|
|
853
|
+
return [shiftSum, changeSum];
|
|
854
|
+
}, [0, 0]);
|
|
855
|
+
};
|
|
856
|
+
const separate = (w, i, lows) => {
|
|
857
|
+
const lSib = w.children[i - 1];
|
|
858
|
+
const curSubtree = w.children[i];
|
|
859
|
+
let rContour = lSib;
|
|
860
|
+
let rSumMods = lSib.relX;
|
|
861
|
+
let lContour = curSubtree;
|
|
862
|
+
let lSumMods = curSubtree.relX;
|
|
863
|
+
let isFirst = true;
|
|
864
|
+
while (rContour && lContour) {
|
|
865
|
+
if (rContour.bottom > lows.lowY) lows = lows.next;
|
|
866
|
+
const dist = rSumMods + rContour.prelim - (lSumMods + lContour.prelim) + rContour.xSize / 2 + lContour.xSize / 2 + rContour.spacing(lContour);
|
|
867
|
+
if (dist > 0 || dist < 0 && isFirst) {
|
|
868
|
+
lSumMods += dist;
|
|
869
|
+
moveSubtree(curSubtree, dist);
|
|
870
|
+
distributeExtra(w, i, lows.index, dist);
|
|
871
|
+
}
|
|
872
|
+
isFirst = false;
|
|
873
|
+
const rightBottom = rContour.bottom;
|
|
874
|
+
const leftBottom = lContour.bottom;
|
|
875
|
+
if (rightBottom <= leftBottom) {
|
|
876
|
+
rContour = nextRContour(rContour);
|
|
877
|
+
if (rContour) rSumMods += rContour.relX;
|
|
878
|
+
}
|
|
879
|
+
if (rightBottom >= leftBottom) {
|
|
880
|
+
lContour = nextLContour(lContour);
|
|
881
|
+
if (lContour) lSumMods += lContour.relX;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
if (!rContour && lContour) setLThr(w, i, lContour, lSumMods);
|
|
885
|
+
else if (rContour && !lContour) setRThr(w, i, rContour, rSumMods);
|
|
886
|
+
};
|
|
887
|
+
const moveSubtree = (subtree, distance) => {
|
|
888
|
+
subtree.relX += distance;
|
|
889
|
+
subtree.lExtRelX += distance;
|
|
890
|
+
subtree.rExtRelX += distance;
|
|
891
|
+
};
|
|
892
|
+
const distributeExtra = (w, curSubtreeI, leftSibI, dist) => {
|
|
893
|
+
const curSubtree = w.children[curSubtreeI];
|
|
894
|
+
const n = curSubtreeI - leftSibI;
|
|
895
|
+
if (n > 1) {
|
|
896
|
+
const delta = dist / n;
|
|
897
|
+
w.children[leftSibI + 1].shift += delta;
|
|
898
|
+
curSubtree.shift -= delta;
|
|
899
|
+
curSubtree.change -= dist - delta;
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
const nextLContour = (w) => {
|
|
903
|
+
return w.hasChildren ? w.firstChild : w.lThr;
|
|
904
|
+
};
|
|
905
|
+
const nextRContour = (w) => {
|
|
906
|
+
return w.hasChildren ? w.lastChild : w.rThr;
|
|
907
|
+
};
|
|
908
|
+
const setLThr = (w, i, lContour, lSumMods) => {
|
|
909
|
+
const firstChild = w.firstChild;
|
|
910
|
+
const lExt = firstChild.lExt;
|
|
911
|
+
const curSubtree = w.children[i];
|
|
912
|
+
lExt.lThr = lContour;
|
|
913
|
+
const diff = lSumMods - lContour.relX - firstChild.lExtRelX;
|
|
914
|
+
lExt.relX += diff;
|
|
915
|
+
lExt.prelim -= diff;
|
|
916
|
+
firstChild.lExt = curSubtree.lExt;
|
|
917
|
+
firstChild.lExtRelX = curSubtree.lExtRelX;
|
|
918
|
+
};
|
|
919
|
+
const setRThr = (w, i, rContour, rSumMods) => {
|
|
920
|
+
const curSubtree = w.children[i];
|
|
921
|
+
const rExt = curSubtree.rExt;
|
|
922
|
+
const lSib = w.children[i - 1];
|
|
923
|
+
rExt.rThr = rContour;
|
|
924
|
+
const diff = rSumMods - rContour.relX - curSubtree.rExtRelX;
|
|
925
|
+
rExt.relX += diff;
|
|
926
|
+
rExt.prelim -= diff;
|
|
927
|
+
curSubtree.rExt = lSib.rExt;
|
|
928
|
+
curSubtree.rExtRelX = lSib.rExtRelX;
|
|
929
|
+
};
|
|
930
|
+
const positionRoot = (w) => {
|
|
931
|
+
if (w.hasChildren) {
|
|
932
|
+
const k0 = w.firstChild;
|
|
933
|
+
const kf = w.lastChild;
|
|
934
|
+
const prelim = (k0.prelim + k0.relX - k0.xSize / 2 + kf.relX + kf.prelim + kf.xSize / 2) / 2;
|
|
935
|
+
Object.assign(w, {
|
|
936
|
+
prelim,
|
|
937
|
+
lExt: k0.lExt,
|
|
938
|
+
lExtRelX: k0.lExtRelX,
|
|
939
|
+
rExt: kf.rExt,
|
|
940
|
+
rExtRelX: kf.rExtRelX
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
const updateLows = (lowY, index, lastLows) => {
|
|
945
|
+
while (lastLows !== null && lowY >= lastLows.lowY)
|
|
946
|
+
lastLows = lastLows.next;
|
|
947
|
+
return {
|
|
948
|
+
lowY,
|
|
949
|
+
index,
|
|
950
|
+
next: lastLows
|
|
951
|
+
};
|
|
952
|
+
};
|
|
953
|
+
const css = ".markmap {\n --markmap-max-width: 9999px;\n --markmap-a-color: #0097e6;\n --markmap-a-hover-color: #00a8ff;\n --markmap-code-bg: #f0f0f0;\n --markmap-code-color: #555;\n --markmap-highlight-bg: #ffeaa7;\n --markmap-table-border: 1px solid currentColor;\n --markmap-font: 300 16px/20px sans-serif;\n --markmap-circle-open-bg: #fff;\n --markmap-text-color: #333;\n --markmap-highlight-node-bg: #ff02;\n\n font: var(--markmap-font);\n color: var(--markmap-text-color);\n}\n\n .markmap-link {\n fill: none;\n }\n\n .markmap-node > circle {\n cursor: pointer;\n }\n\n .markmap-foreign {\n display: inline-block;\n }\n\n .markmap-foreign p {\n margin: 0;\n }\n\n .markmap-foreign a {\n color: var(--markmap-a-color);\n }\n\n .markmap-foreign a:hover {\n color: var(--markmap-a-hover-color);\n }\n\n .markmap-foreign code {\n padding: 0.25em;\n font-size: calc(1em - 2px);\n color: var(--markmap-code-color);\n background-color: var(--markmap-code-bg);\n border-radius: 2px;\n }\n\n .markmap-foreign pre {\n margin: 0;\n }\n\n .markmap-foreign pre > code {\n display: block;\n }\n\n .markmap-foreign del {\n text-decoration: line-through;\n }\n\n .markmap-foreign em {\n font-style: italic;\n }\n\n .markmap-foreign strong {\n font-weight: bold;\n }\n\n .markmap-foreign mark {\n background: var(--markmap-highlight-bg);\n }\n\n .markmap-foreign table,\n .markmap-foreign th,\n .markmap-foreign td {\n border-collapse: collapse;\n border: var(--markmap-table-border);\n }\n\n .markmap-foreign img {\n display: inline-block;\n }\n\n .markmap-foreign svg {\n fill: currentColor;\n }\n\n .markmap-foreign > div {\n width: var(--markmap-max-width);\n text-align: left;\n }\n\n .markmap-foreign > div > div {\n display: inline-block;\n }\n\n .markmap-highlight rect {\n fill: var(--markmap-highlight-node-bg);\n }\n\n.markmap-dark .markmap {\n --markmap-code-bg: #1a1b26;\n --markmap-code-color: #ddd;\n --markmap-circle-open-bg: #444;\n --markmap-text-color: #eee;\n}\n";
|
|
954
|
+
const globalCSS = css;
|
|
955
|
+
const SELECTOR_NODE = "g.markmap-node";
|
|
956
|
+
const SELECTOR_LINK = "path.markmap-link";
|
|
957
|
+
const SELECTOR_HIGHLIGHT = "g.markmap-highlight";
|
|
958
|
+
const linkShape = d32.linkHorizontal();
|
|
959
|
+
function minBy(numbers, by) {
|
|
960
|
+
const index = d32.minIndex(numbers, by);
|
|
961
|
+
return numbers[index];
|
|
962
|
+
}
|
|
963
|
+
function stopPropagation(e) {
|
|
964
|
+
e.stopPropagation();
|
|
965
|
+
}
|
|
966
|
+
const refreshHook = new Hook();
|
|
967
|
+
class Markmap {
|
|
968
|
+
constructor(svg, opts) {
|
|
969
|
+
this.options = { ...defaultOptions };
|
|
970
|
+
this._disposeList = [];
|
|
971
|
+
this.handleZoom = (e) => {
|
|
972
|
+
const { transform } = e;
|
|
973
|
+
this.g.attr("transform", transform);
|
|
974
|
+
};
|
|
975
|
+
this.handlePan = (e) => {
|
|
976
|
+
e.preventDefault();
|
|
977
|
+
const transform = d32.zoomTransform(this.svg.node());
|
|
978
|
+
const newTransform = transform.translate(
|
|
979
|
+
-e.deltaX / transform.k,
|
|
980
|
+
-e.deltaY / transform.k
|
|
981
|
+
);
|
|
982
|
+
this.svg.call(this.zoom.transform, newTransform);
|
|
983
|
+
};
|
|
984
|
+
this.handleClick = (e, d) => {
|
|
985
|
+
let recursive = this.options.toggleRecursively;
|
|
986
|
+
if (isMacintosh ? e.metaKey : e.ctrlKey) recursive = !recursive;
|
|
987
|
+
this.toggleNode(d, recursive);
|
|
988
|
+
};
|
|
989
|
+
this.ensureView = this.ensureVisible;
|
|
990
|
+
this.svg = svg.datum ? svg : d32.select(svg);
|
|
991
|
+
this.styleNode = this.svg.append("style");
|
|
992
|
+
this.zoom = d32.zoom().filter((event) => {
|
|
993
|
+
if (this.options.scrollForPan) {
|
|
994
|
+
if (event.type === "wheel") return event.ctrlKey && !event.button;
|
|
995
|
+
}
|
|
996
|
+
return (!event.ctrlKey || event.type === "wheel") && !event.button;
|
|
997
|
+
}).on("zoom", this.handleZoom);
|
|
998
|
+
this.setOptions(opts);
|
|
999
|
+
this.state = {
|
|
1000
|
+
id: this.options.id || this.svg.attr("id") || getId(),
|
|
1001
|
+
rect: { x1: 0, y1: 0, x2: 0, y2: 0 }
|
|
1002
|
+
};
|
|
1003
|
+
this.g = this.svg.append("g");
|
|
1004
|
+
this.g.append("g").attr("class", "markmap-highlight");
|
|
1005
|
+
this._observer = new ResizeObserver(
|
|
1006
|
+
debounce(() => {
|
|
1007
|
+
this.renderData();
|
|
1008
|
+
}, 100)
|
|
1009
|
+
);
|
|
1010
|
+
this._disposeList.push(
|
|
1011
|
+
refreshHook.tap(() => {
|
|
1012
|
+
this.setData();
|
|
1013
|
+
}),
|
|
1014
|
+
() => this._observer.disconnect()
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
getStyleContent() {
|
|
1018
|
+
const { style } = this.options;
|
|
1019
|
+
const { id } = this.state;
|
|
1020
|
+
const styleText = typeof style === "function" ? style(id) : "";
|
|
1021
|
+
return [this.options.embedGlobalCSS && css, styleText].filter(Boolean).join("\n");
|
|
1022
|
+
}
|
|
1023
|
+
updateStyle() {
|
|
1024
|
+
this.svg.attr(
|
|
1025
|
+
"class",
|
|
1026
|
+
addClass(this.svg.attr("class"), "markmap", this.state.id)
|
|
1027
|
+
);
|
|
1028
|
+
const style = this.getStyleContent();
|
|
1029
|
+
this.styleNode.text(style);
|
|
1030
|
+
}
|
|
1031
|
+
async toggleNode(data, recursive = false) {
|
|
1032
|
+
var _a, _b;
|
|
1033
|
+
const fold = ((_a = data.payload) == null ? void 0 : _a.fold) ? 0 : 1;
|
|
1034
|
+
if (recursive) {
|
|
1035
|
+
walkTree(data, (item, next) => {
|
|
1036
|
+
item.payload = {
|
|
1037
|
+
...item.payload,
|
|
1038
|
+
fold
|
|
1039
|
+
};
|
|
1040
|
+
next();
|
|
1041
|
+
});
|
|
1042
|
+
} else {
|
|
1043
|
+
data.payload = {
|
|
1044
|
+
...data.payload,
|
|
1045
|
+
fold: ((_b = data.payload) == null ? void 0 : _b.fold) ? 0 : 1
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
await this.renderData(data);
|
|
1049
|
+
}
|
|
1050
|
+
_initializeData(node) {
|
|
1051
|
+
let nodeId = 0;
|
|
1052
|
+
const { color, initialExpandLevel } = this.options;
|
|
1053
|
+
let foldRecursively = 0;
|
|
1054
|
+
let depth = 0;
|
|
1055
|
+
walkTree(node, (item, next, parent) => {
|
|
1056
|
+
var _a, _b, _c, _d;
|
|
1057
|
+
depth += 1;
|
|
1058
|
+
item.children = (_a = item.children) == null ? void 0 : _a.map((child) => ({ ...child }));
|
|
1059
|
+
nodeId += 1;
|
|
1060
|
+
item.state = {
|
|
1061
|
+
...item.state,
|
|
1062
|
+
depth,
|
|
1063
|
+
id: nodeId,
|
|
1064
|
+
rect: {
|
|
1065
|
+
x: 0,
|
|
1066
|
+
y: 0,
|
|
1067
|
+
width: 0,
|
|
1068
|
+
height: 0
|
|
1069
|
+
},
|
|
1070
|
+
size: [0, 0]
|
|
1071
|
+
};
|
|
1072
|
+
item.state.key = [(_b = parent == null ? void 0 : parent.state) == null ? void 0 : _b.id, item.state.id].filter(Boolean).join(".") + simpleHash(item.content);
|
|
1073
|
+
item.state.path = [(_c = parent == null ? void 0 : parent.state) == null ? void 0 : _c.path, item.state.id].filter(Boolean).join(".");
|
|
1074
|
+
color(item);
|
|
1075
|
+
const isFoldRecursively = ((_d = item.payload) == null ? void 0 : _d.fold) === 2;
|
|
1076
|
+
if (isFoldRecursively) {
|
|
1077
|
+
foldRecursively += 1;
|
|
1078
|
+
} else if (foldRecursively || initialExpandLevel >= 0 && item.state.depth >= initialExpandLevel) {
|
|
1079
|
+
item.payload = { ...item.payload, fold: 1 };
|
|
1080
|
+
}
|
|
1081
|
+
next();
|
|
1082
|
+
if (isFoldRecursively) foldRecursively -= 1;
|
|
1083
|
+
depth -= 1;
|
|
1084
|
+
});
|
|
1085
|
+
return node;
|
|
1086
|
+
}
|
|
1087
|
+
_relayout() {
|
|
1088
|
+
if (!this.state.data) return;
|
|
1089
|
+
this.g.selectAll(childSelector(SELECTOR_NODE)).selectAll(
|
|
1090
|
+
childSelector("foreignObject")
|
|
1091
|
+
).each(function(d) {
|
|
1092
|
+
var _a;
|
|
1093
|
+
const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
|
|
1094
|
+
const newSize = [el.scrollWidth, el.scrollHeight];
|
|
1095
|
+
d.state.size = newSize;
|
|
1096
|
+
});
|
|
1097
|
+
const { lineWidth, paddingX, spacingHorizontal, spacingVertical } = this.options;
|
|
1098
|
+
const layout = flextree({}).children((d) => {
|
|
1099
|
+
var _a;
|
|
1100
|
+
if (!((_a = d.payload) == null ? void 0 : _a.fold)) return d.children;
|
|
1101
|
+
}).nodeSize((node) => {
|
|
1102
|
+
const [width, height] = node.data.state.size;
|
|
1103
|
+
return [height, width + (width ? paddingX * 2 : 0) + spacingHorizontal];
|
|
1104
|
+
}).spacing((a, b) => {
|
|
1105
|
+
return (a.parent === b.parent ? spacingVertical : spacingVertical * 2) + lineWidth(a.data);
|
|
1106
|
+
});
|
|
1107
|
+
const tree = layout.hierarchy(this.state.data);
|
|
1108
|
+
layout(tree);
|
|
1109
|
+
const fnodes = tree.descendants();
|
|
1110
|
+
fnodes.forEach((fnode) => {
|
|
1111
|
+
const node = fnode.data;
|
|
1112
|
+
node.state.rect = {
|
|
1113
|
+
x: fnode.y,
|
|
1114
|
+
y: fnode.x - fnode.xSize / 2,
|
|
1115
|
+
width: fnode.ySize - spacingHorizontal,
|
|
1116
|
+
height: fnode.xSize
|
|
1117
|
+
};
|
|
1118
|
+
});
|
|
1119
|
+
this.state.rect = {
|
|
1120
|
+
x1: d32.min(fnodes, (fnode) => fnode.data.state.rect.x) || 0,
|
|
1121
|
+
y1: d32.min(fnodes, (fnode) => fnode.data.state.rect.y) || 0,
|
|
1122
|
+
x2: d32.max(
|
|
1123
|
+
fnodes,
|
|
1124
|
+
(fnode) => fnode.data.state.rect.x + fnode.data.state.rect.width
|
|
1125
|
+
) || 0,
|
|
1126
|
+
y2: d32.max(
|
|
1127
|
+
fnodes,
|
|
1128
|
+
(fnode) => fnode.data.state.rect.y + fnode.data.state.rect.height
|
|
1129
|
+
) || 0
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
setOptions(opts) {
|
|
1133
|
+
this.options = {
|
|
1134
|
+
...this.options,
|
|
1135
|
+
...opts
|
|
1136
|
+
};
|
|
1137
|
+
if (this.options.zoom) {
|
|
1138
|
+
this.svg.call(this.zoom);
|
|
1139
|
+
} else {
|
|
1140
|
+
this.svg.on(".zoom", null);
|
|
1141
|
+
}
|
|
1142
|
+
if (this.options.pan) {
|
|
1143
|
+
this.svg.on("wheel", this.handlePan);
|
|
1144
|
+
} else {
|
|
1145
|
+
this.svg.on("wheel", null);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
async setData(data, opts) {
|
|
1149
|
+
if (opts) this.setOptions(opts);
|
|
1150
|
+
if (data) this.state.data = this._initializeData(data);
|
|
1151
|
+
if (!this.state.data) return;
|
|
1152
|
+
this.updateStyle();
|
|
1153
|
+
await this.renderData();
|
|
1154
|
+
}
|
|
1155
|
+
async setHighlight(node) {
|
|
1156
|
+
this.state.highlight = node || void 0;
|
|
1157
|
+
await this.renderData();
|
|
1158
|
+
}
|
|
1159
|
+
_getHighlightRect(highlight) {
|
|
1160
|
+
const svgNode = this.svg.node();
|
|
1161
|
+
const transform = d32.zoomTransform(svgNode);
|
|
1162
|
+
const padding = 4 / transform.k;
|
|
1163
|
+
const rect = {
|
|
1164
|
+
...highlight.state.rect
|
|
1165
|
+
};
|
|
1166
|
+
rect.x -= padding;
|
|
1167
|
+
rect.y -= padding;
|
|
1168
|
+
rect.width += 2 * padding;
|
|
1169
|
+
rect.height += 2 * padding;
|
|
1170
|
+
return rect;
|
|
1171
|
+
}
|
|
1172
|
+
async renderData(originData) {
|
|
1173
|
+
const { paddingX, autoFit, color, maxWidth, lineWidth } = this.options;
|
|
1174
|
+
const rootNode = this.state.data;
|
|
1175
|
+
if (!rootNode) return;
|
|
1176
|
+
const nodeMap = {};
|
|
1177
|
+
const parentMap = {};
|
|
1178
|
+
const nodes = [];
|
|
1179
|
+
walkTree(rootNode, (item, next, parent) => {
|
|
1180
|
+
var _a;
|
|
1181
|
+
if (!((_a = item.payload) == null ? void 0 : _a.fold)) next();
|
|
1182
|
+
nodeMap[item.state.id] = item;
|
|
1183
|
+
if (parent) parentMap[item.state.id] = parent.state.id;
|
|
1184
|
+
nodes.push(item);
|
|
1185
|
+
});
|
|
1186
|
+
const originMap = {};
|
|
1187
|
+
const sourceRectMap = {};
|
|
1188
|
+
const setOriginNode = (originNode) => {
|
|
1189
|
+
if (!originNode || originMap[originNode.state.id]) return;
|
|
1190
|
+
walkTree(originNode, (item, next) => {
|
|
1191
|
+
originMap[item.state.id] = originNode.state.id;
|
|
1192
|
+
next();
|
|
1193
|
+
});
|
|
1194
|
+
};
|
|
1195
|
+
const getOriginSourceRect = (node) => {
|
|
1196
|
+
const rect = sourceRectMap[originMap[node.state.id]];
|
|
1197
|
+
return rect || rootNode.state.rect;
|
|
1198
|
+
};
|
|
1199
|
+
const getOriginTargetRect = (node) => (nodeMap[originMap[node.state.id]] || rootNode).state.rect;
|
|
1200
|
+
sourceRectMap[rootNode.state.id] = rootNode.state.rect;
|
|
1201
|
+
if (originData) setOriginNode(originData);
|
|
1202
|
+
let { highlight } = this.state;
|
|
1203
|
+
if (highlight && !nodeMap[highlight.state.id]) highlight = void 0;
|
|
1204
|
+
let highlightNodes = this.g.selectAll(childSelector(SELECTOR_HIGHLIGHT)).selectAll(childSelector("rect")).data(highlight ? [this._getHighlightRect(highlight)] : []).join("rect").attr("x", (d) => d.x).attr("y", (d) => d.y).attr("width", (d) => d.width).attr("height", (d) => d.height);
|
|
1205
|
+
const mmG = this.g.selectAll(childSelector(SELECTOR_NODE)).each((d) => {
|
|
1206
|
+
sourceRectMap[d.state.id] = d.state.rect;
|
|
1207
|
+
}).data(nodes, (d) => d.state.key);
|
|
1208
|
+
const mmGEnter = mmG.enter().append("g").attr("data-depth", (d) => d.state.depth).attr("data-path", (d) => d.state.path).each((d) => {
|
|
1209
|
+
setOriginNode(nodeMap[parentMap[d.state.id]]);
|
|
1210
|
+
});
|
|
1211
|
+
const mmGExit = mmG.exit().each((d) => {
|
|
1212
|
+
setOriginNode(nodeMap[parentMap[d.state.id]]);
|
|
1213
|
+
});
|
|
1214
|
+
const mmGMerge = mmG.merge(mmGEnter).attr(
|
|
1215
|
+
"class",
|
|
1216
|
+
(d) => {
|
|
1217
|
+
var _a;
|
|
1218
|
+
return ["markmap-node", ((_a = d.payload) == null ? void 0 : _a.fold) && "markmap-fold"].filter(Boolean).join(" ");
|
|
1219
|
+
}
|
|
1220
|
+
);
|
|
1221
|
+
const mmLine = mmGMerge.selectAll(childSelector("line")).data(
|
|
1222
|
+
(d) => [d],
|
|
1223
|
+
(d) => d.state.key
|
|
1224
|
+
);
|
|
1225
|
+
const mmLineEnter = mmLine.enter().append("line").attr("stroke", (d) => color(d)).attr("stroke-width", 0);
|
|
1226
|
+
const mmLineMerge = mmLine.merge(mmLineEnter);
|
|
1227
|
+
const mmCircle = mmGMerge.selectAll(childSelector("circle")).data(
|
|
1228
|
+
(d) => {
|
|
1229
|
+
var _a;
|
|
1230
|
+
return ((_a = d.children) == null ? void 0 : _a.length) ? [d] : [];
|
|
1231
|
+
},
|
|
1232
|
+
(d) => d.state.key
|
|
1233
|
+
);
|
|
1234
|
+
const mmCircleEnter = mmCircle.enter().append("circle").attr("stroke-width", 0).attr("r", 0).on("click", (e, d) => this.handleClick(e, d)).on("mousedown", stopPropagation);
|
|
1235
|
+
const mmCircleMerge = mmCircleEnter.merge(mmCircle).attr("stroke", (d) => color(d)).attr(
|
|
1236
|
+
"fill",
|
|
1237
|
+
(d) => {
|
|
1238
|
+
var _a;
|
|
1239
|
+
return ((_a = d.payload) == null ? void 0 : _a.fold) && d.children ? color(d) : "var(--markmap-circle-open-bg)";
|
|
1240
|
+
}
|
|
1241
|
+
);
|
|
1242
|
+
const observer = this._observer;
|
|
1243
|
+
const mmFo = mmGMerge.selectAll(childSelector("foreignObject")).data(
|
|
1244
|
+
(d) => [d],
|
|
1245
|
+
(d) => d.state.key
|
|
1246
|
+
);
|
|
1247
|
+
const mmFoEnter = mmFo.enter().append("foreignObject").attr("class", "markmap-foreign").attr("x", paddingX).attr("y", 0).style("opacity", 0).on("mousedown", stopPropagation).on("dblclick", stopPropagation);
|
|
1248
|
+
mmFoEnter.append("xhtml:div").append("xhtml:div").html((d) => d.content).attr("xmlns", "http://www.w3.org/1999/xhtml");
|
|
1249
|
+
mmFoEnter.each(function() {
|
|
1250
|
+
var _a;
|
|
1251
|
+
const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
|
|
1252
|
+
observer.observe(el);
|
|
1253
|
+
});
|
|
1254
|
+
const mmFoExit = mmGExit.selectAll(
|
|
1255
|
+
childSelector("foreignObject")
|
|
1256
|
+
);
|
|
1257
|
+
mmFoExit.each(function() {
|
|
1258
|
+
var _a;
|
|
1259
|
+
const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
|
|
1260
|
+
observer.unobserve(el);
|
|
1261
|
+
});
|
|
1262
|
+
const mmFoMerge = mmFoEnter.merge(mmFo);
|
|
1263
|
+
const links = nodes.flatMap(
|
|
1264
|
+
(node) => {
|
|
1265
|
+
var _a;
|
|
1266
|
+
return ((_a = node.payload) == null ? void 0 : _a.fold) ? [] : node.children.map((child) => ({ source: node, target: child }));
|
|
1267
|
+
}
|
|
1268
|
+
);
|
|
1269
|
+
const mmPath = this.g.selectAll(childSelector(SELECTOR_LINK)).data(links, (d) => d.target.state.key);
|
|
1270
|
+
const mmPathExit = mmPath.exit();
|
|
1271
|
+
const mmPathEnter = mmPath.enter().insert("path", "g").attr("class", "markmap-link").attr("data-depth", (d) => d.target.state.depth).attr("data-path", (d) => d.target.state.path).attr("d", (d) => {
|
|
1272
|
+
const originRect = getOriginSourceRect(d.target);
|
|
1273
|
+
const pathOrigin = [
|
|
1274
|
+
originRect.x + originRect.width,
|
|
1275
|
+
originRect.y + originRect.height
|
|
1276
|
+
];
|
|
1277
|
+
return linkShape({ source: pathOrigin, target: pathOrigin });
|
|
1278
|
+
}).attr("stroke-width", 0);
|
|
1279
|
+
const mmPathMerge = mmPathEnter.merge(mmPath);
|
|
1280
|
+
this.svg.style(
|
|
1281
|
+
"--markmap-max-width",
|
|
1282
|
+
maxWidth ? `${maxWidth}px` : null
|
|
1283
|
+
);
|
|
1284
|
+
await new Promise(requestAnimationFrame);
|
|
1285
|
+
this._relayout();
|
|
1286
|
+
highlightNodes = highlightNodes.data(highlight ? [this._getHighlightRect(highlight)] : []).join("rect");
|
|
1287
|
+
this.transition(highlightNodes).attr("x", (d) => d.x).attr("y", (d) => d.y).attr("width", (d) => d.width).attr("height", (d) => d.height);
|
|
1288
|
+
mmGEnter.attr("transform", (d) => {
|
|
1289
|
+
const originRect = getOriginSourceRect(d);
|
|
1290
|
+
return `translate(${originRect.x + originRect.width - d.state.rect.width},${originRect.y + originRect.height - d.state.rect.height})`;
|
|
1291
|
+
});
|
|
1292
|
+
this.transition(mmGExit).attr("transform", (d) => {
|
|
1293
|
+
const targetRect = getOriginTargetRect(d);
|
|
1294
|
+
const targetX = targetRect.x + targetRect.width - d.state.rect.width;
|
|
1295
|
+
const targetY = targetRect.y + targetRect.height - d.state.rect.height;
|
|
1296
|
+
return `translate(${targetX},${targetY})`;
|
|
1297
|
+
}).remove();
|
|
1298
|
+
this.transition(mmGMerge).attr(
|
|
1299
|
+
"transform",
|
|
1300
|
+
(d) => `translate(${d.state.rect.x},${d.state.rect.y})`
|
|
1301
|
+
);
|
|
1302
|
+
const mmLineExit = mmGExit.selectAll(
|
|
1303
|
+
childSelector("line")
|
|
1304
|
+
);
|
|
1305
|
+
this.transition(mmLineExit).attr("x1", (d) => d.state.rect.width).attr("stroke-width", 0);
|
|
1306
|
+
mmLineEnter.attr("x1", (d) => d.state.rect.width).attr("x2", (d) => d.state.rect.width);
|
|
1307
|
+
mmLineMerge.attr("y1", (d) => d.state.rect.height + lineWidth(d) / 2).attr("y2", (d) => d.state.rect.height + lineWidth(d) / 2);
|
|
1308
|
+
this.transition(mmLineMerge).attr("x1", -1).attr("x2", (d) => d.state.rect.width + 2).attr("stroke", (d) => color(d)).attr("stroke-width", lineWidth);
|
|
1309
|
+
const mmCircleExit = mmGExit.selectAll(
|
|
1310
|
+
childSelector("circle")
|
|
1311
|
+
);
|
|
1312
|
+
this.transition(mmCircleExit).attr("r", 0).attr("stroke-width", 0);
|
|
1313
|
+
mmCircleMerge.attr("cx", (d) => d.state.rect.width).attr("cy", (d) => d.state.rect.height + lineWidth(d) / 2);
|
|
1314
|
+
this.transition(mmCircleMerge).attr("r", 6).attr("stroke-width", "1.5");
|
|
1315
|
+
this.transition(mmFoExit).style("opacity", 0);
|
|
1316
|
+
mmFoMerge.attr("width", (d) => Math.max(0, d.state.rect.width - paddingX * 2)).attr("height", (d) => d.state.rect.height);
|
|
1317
|
+
this.transition(mmFoMerge).style("opacity", 1);
|
|
1318
|
+
this.transition(mmPathExit).attr("d", (d) => {
|
|
1319
|
+
const targetRect = getOriginTargetRect(d.target);
|
|
1320
|
+
const pathTarget = [
|
|
1321
|
+
targetRect.x + targetRect.width,
|
|
1322
|
+
targetRect.y + targetRect.height + lineWidth(d.target) / 2
|
|
1323
|
+
];
|
|
1324
|
+
return linkShape({ source: pathTarget, target: pathTarget });
|
|
1325
|
+
}).attr("stroke-width", 0).remove();
|
|
1326
|
+
this.transition(mmPathMerge).attr("stroke", (d) => color(d.target)).attr("stroke-width", (d) => lineWidth(d.target)).attr("d", (d) => {
|
|
1327
|
+
const origSource = d.source;
|
|
1328
|
+
const origTarget = d.target;
|
|
1329
|
+
const source = [
|
|
1330
|
+
origSource.state.rect.x + origSource.state.rect.width,
|
|
1331
|
+
origSource.state.rect.y + origSource.state.rect.height + lineWidth(origSource) / 2
|
|
1332
|
+
];
|
|
1333
|
+
const target = [
|
|
1334
|
+
origTarget.state.rect.x,
|
|
1335
|
+
origTarget.state.rect.y + origTarget.state.rect.height + lineWidth(origTarget) / 2
|
|
1336
|
+
];
|
|
1337
|
+
return linkShape({ source, target });
|
|
1338
|
+
});
|
|
1339
|
+
if (autoFit) this.fit();
|
|
1340
|
+
}
|
|
1341
|
+
transition(sel) {
|
|
1342
|
+
const { duration } = this.options;
|
|
1343
|
+
return sel.transition().duration(duration);
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* Fit the content to the viewport.
|
|
1347
|
+
*/
|
|
1348
|
+
async fit(maxScale = this.options.maxInitialScale) {
|
|
1349
|
+
const svgNode = this.svg.node();
|
|
1350
|
+
const { width: offsetWidth, height: offsetHeight } = svgNode.getBoundingClientRect();
|
|
1351
|
+
const { fitRatio } = this.options;
|
|
1352
|
+
const { x1, y1, x2, y2 } = this.state.rect;
|
|
1353
|
+
const naturalWidth = x2 - x1;
|
|
1354
|
+
const naturalHeight = y2 - y1;
|
|
1355
|
+
const scale = Math.min(
|
|
1356
|
+
offsetWidth / naturalWidth * fitRatio,
|
|
1357
|
+
offsetHeight / naturalHeight * fitRatio,
|
|
1358
|
+
maxScale
|
|
1359
|
+
);
|
|
1360
|
+
const initialZoom = d32.zoomIdentity.translate(
|
|
1361
|
+
(offsetWidth - naturalWidth * scale) / 2 - x1 * scale,
|
|
1362
|
+
(offsetHeight - naturalHeight * scale) / 2 - y1 * scale
|
|
1363
|
+
).scale(scale);
|
|
1364
|
+
return this.transition(this.svg).call(this.zoom.transform, initialZoom).end().catch(noop);
|
|
1365
|
+
}
|
|
1366
|
+
findElement(node) {
|
|
1367
|
+
let result;
|
|
1368
|
+
this.g.selectAll(childSelector(SELECTOR_NODE)).each(function walk(d) {
|
|
1369
|
+
if (d === node) {
|
|
1370
|
+
result = {
|
|
1371
|
+
data: d,
|
|
1372
|
+
g: this
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
return result;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Pan the content to make the provided node visible in the viewport.
|
|
1380
|
+
*/
|
|
1381
|
+
async ensureVisible(node, padding) {
|
|
1382
|
+
var _a;
|
|
1383
|
+
const itemData = (_a = this.findElement(node)) == null ? void 0 : _a.data;
|
|
1384
|
+
if (!itemData) return;
|
|
1385
|
+
const svgNode = this.svg.node();
|
|
1386
|
+
const relRect = svgNode.getBoundingClientRect();
|
|
1387
|
+
const transform = d32.zoomTransform(svgNode);
|
|
1388
|
+
const [left, right] = [
|
|
1389
|
+
itemData.state.rect.x,
|
|
1390
|
+
itemData.state.rect.x + itemData.state.rect.width + 2
|
|
1391
|
+
].map((x) => x * transform.k + transform.x);
|
|
1392
|
+
const [top, bottom] = [
|
|
1393
|
+
itemData.state.rect.y,
|
|
1394
|
+
itemData.state.rect.y + itemData.state.rect.height
|
|
1395
|
+
].map((y) => y * transform.k + transform.y);
|
|
1396
|
+
const pd = {
|
|
1397
|
+
left: 0,
|
|
1398
|
+
right: 0,
|
|
1399
|
+
top: 0,
|
|
1400
|
+
bottom: 0,
|
|
1401
|
+
...padding
|
|
1402
|
+
};
|
|
1403
|
+
const dxs = [pd.left - left, relRect.width - pd.right - right];
|
|
1404
|
+
const dys = [pd.top - top, relRect.height - pd.bottom - bottom];
|
|
1405
|
+
const dx = dxs[0] * dxs[1] > 0 ? minBy(dxs, Math.abs) / transform.k : 0;
|
|
1406
|
+
const dy = dys[0] * dys[1] > 0 ? minBy(dys, Math.abs) / transform.k : 0;
|
|
1407
|
+
if (dx || dy) {
|
|
1408
|
+
const newTransform = transform.translate(dx, dy);
|
|
1409
|
+
return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(noop);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
async centerNode(node, padding) {
|
|
1413
|
+
var _a;
|
|
1414
|
+
const itemData = (_a = this.findElement(node)) == null ? void 0 : _a.data;
|
|
1415
|
+
if (!itemData) return;
|
|
1416
|
+
const svgNode = this.svg.node();
|
|
1417
|
+
const relRect = svgNode.getBoundingClientRect();
|
|
1418
|
+
const transform = d32.zoomTransform(svgNode);
|
|
1419
|
+
const x = (itemData.state.rect.x + itemData.state.rect.width / 2) * transform.k + transform.x;
|
|
1420
|
+
const y = (itemData.state.rect.y + itemData.state.rect.height / 2) * transform.k + transform.y;
|
|
1421
|
+
const pd = {
|
|
1422
|
+
left: 0,
|
|
1423
|
+
right: 0,
|
|
1424
|
+
top: 0,
|
|
1425
|
+
bottom: 0,
|
|
1426
|
+
...padding
|
|
1427
|
+
};
|
|
1428
|
+
const cx = (pd.left + relRect.width - pd.right) / 2;
|
|
1429
|
+
const cy = (pd.top + relRect.height - pd.bottom) / 2;
|
|
1430
|
+
const dx = (cx - x) / transform.k;
|
|
1431
|
+
const dy = (cy - y) / transform.k;
|
|
1432
|
+
if (dx || dy) {
|
|
1433
|
+
const newTransform = transform.translate(dx, dy);
|
|
1434
|
+
return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(noop);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Scale content with it pinned at the center of the viewport.
|
|
1439
|
+
*/
|
|
1440
|
+
async rescale(scale) {
|
|
1441
|
+
const svgNode = this.svg.node();
|
|
1442
|
+
const { width: offsetWidth, height: offsetHeight } = svgNode.getBoundingClientRect();
|
|
1443
|
+
const halfWidth = offsetWidth / 2;
|
|
1444
|
+
const halfHeight = offsetHeight / 2;
|
|
1445
|
+
const transform = d32.zoomTransform(svgNode);
|
|
1446
|
+
const newTransform = transform.translate(
|
|
1447
|
+
(halfWidth - transform.x) * (1 - scale) / transform.k,
|
|
1448
|
+
(halfHeight - transform.y) * (1 - scale) / transform.k
|
|
1449
|
+
).scale(scale);
|
|
1450
|
+
return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(noop);
|
|
1451
|
+
}
|
|
1452
|
+
destroy() {
|
|
1453
|
+
this.svg.on(".zoom", null);
|
|
1454
|
+
this.svg.html(null);
|
|
1455
|
+
this._disposeList.forEach((fn) => {
|
|
1456
|
+
fn();
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
static create(svg, opts, data = null) {
|
|
1460
|
+
const mm = new Markmap(svg, opts);
|
|
1461
|
+
if (data) {
|
|
1462
|
+
mm.setData(data).then(() => {
|
|
1463
|
+
mm.fit();
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
return mm;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
exports.Markmap = Markmap;
|
|
1470
|
+
exports.childSelector = childSelector;
|
|
1471
|
+
exports.defaultColorFn = defaultColorFn;
|
|
1472
|
+
exports.defaultOptions = defaultOptions;
|
|
1473
|
+
exports.deriveOptions = deriveOptions;
|
|
1474
|
+
exports.globalCSS = globalCSS;
|
|
1475
|
+
exports.isMacintosh = isMacintosh;
|
|
1476
|
+
exports.lineWidthFactory = lineWidthFactory;
|
|
1477
|
+
exports.loadCSS = loadCSS;
|
|
1478
|
+
exports.loadJS = loadJS;
|
|
1479
|
+
exports.refreshHook = refreshHook;
|
|
1480
|
+
exports.simpleHash = simpleHash;
|
|
1481
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
1482
|
+
})(this.markmap = this.markmap || {}, d3);
|