view.js 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. /*! markmap-lib v0.7.8 | MIT License */
  2. (function (exports, d3) {
  3. 'use strict';
  4. function count(node) {
  5. var sum = 0,
  6. children = node.children,
  7. i = children && children.length;
  8. if (!i) sum = 1;
  9. else while (--i >= 0) sum += children[i].value;
  10. node.value = sum;
  11. }
  12. function node_count() {
  13. return this.eachAfter(count);
  14. }
  15. function node_each(callback) {
  16. var node = this, current, next = [node], children, i, n;
  17. do {
  18. current = next.reverse(), next = [];
  19. while (node = current.pop()) {
  20. callback(node), children = node.children;
  21. if (children) for (i = 0, n = children.length; i < n; ++i) {
  22. next.push(children[i]);
  23. }
  24. }
  25. } while (next.length);
  26. return this;
  27. }
  28. function node_eachBefore(callback) {
  29. var node = this, nodes = [node], children, i;
  30. while (node = nodes.pop()) {
  31. callback(node), children = node.children;
  32. if (children) for (i = children.length - 1; i >= 0; --i) {
  33. nodes.push(children[i]);
  34. }
  35. }
  36. return this;
  37. }
  38. function node_eachAfter(callback) {
  39. var node = this, nodes = [node], next = [], children, i, n;
  40. while (node = nodes.pop()) {
  41. next.push(node), children = node.children;
  42. if (children) for (i = 0, n = children.length; i < n; ++i) {
  43. nodes.push(children[i]);
  44. }
  45. }
  46. while (node = next.pop()) {
  47. callback(node);
  48. }
  49. return this;
  50. }
  51. function node_sum(value) {
  52. return this.eachAfter(function(node) {
  53. var sum = +value(node.data) || 0,
  54. children = node.children,
  55. i = children && children.length;
  56. while (--i >= 0) sum += children[i].value;
  57. node.value = sum;
  58. });
  59. }
  60. function node_sort(compare) {
  61. return this.eachBefore(function(node) {
  62. if (node.children) {
  63. node.children.sort(compare);
  64. }
  65. });
  66. }
  67. function node_path(end) {
  68. var start = this,
  69. ancestor = leastCommonAncestor(start, end),
  70. nodes = [start];
  71. while (start !== ancestor) {
  72. start = start.parent;
  73. nodes.push(start);
  74. }
  75. var k = nodes.length;
  76. while (end !== ancestor) {
  77. nodes.splice(k, 0, end);
  78. end = end.parent;
  79. }
  80. return nodes;
  81. }
  82. function leastCommonAncestor(a, b) {
  83. if (a === b) return a;
  84. var aNodes = a.ancestors(),
  85. bNodes = b.ancestors(),
  86. c = null;
  87. a = aNodes.pop();
  88. b = bNodes.pop();
  89. while (a === b) {
  90. c = a;
  91. a = aNodes.pop();
  92. b = bNodes.pop();
  93. }
  94. return c;
  95. }
  96. function node_ancestors() {
  97. var node = this, nodes = [node];
  98. while (node = node.parent) {
  99. nodes.push(node);
  100. }
  101. return nodes;
  102. }
  103. function node_descendants() {
  104. var nodes = [];
  105. this.each(function(node) {
  106. nodes.push(node);
  107. });
  108. return nodes;
  109. }
  110. function node_leaves() {
  111. var leaves = [];
  112. this.eachBefore(function(node) {
  113. if (!node.children) {
  114. leaves.push(node);
  115. }
  116. });
  117. return leaves;
  118. }
  119. function node_links() {
  120. var root = this, links = [];
  121. root.each(function(node) {
  122. if (node !== root) { // Don’t include the root’s parent, if any.
  123. links.push({source: node.parent, target: node});
  124. }
  125. });
  126. return links;
  127. }
  128. function hierarchy(data, children) {
  129. var root = new Node(data),
  130. valued = +data.value && (root.value = data.value),
  131. node,
  132. nodes = [root],
  133. child,
  134. childs,
  135. i,
  136. n;
  137. if (children == null) children = defaultChildren;
  138. while (node = nodes.pop()) {
  139. if (valued) node.value = +node.data.value;
  140. if ((childs = children(node.data)) && (n = childs.length)) {
  141. node.children = new Array(n);
  142. for (i = n - 1; i >= 0; --i) {
  143. nodes.push(child = node.children[i] = new Node(childs[i]));
  144. child.parent = node;
  145. child.depth = node.depth + 1;
  146. }
  147. }
  148. }
  149. return root.eachBefore(computeHeight);
  150. }
  151. function node_copy() {
  152. return hierarchy(this).eachBefore(copyData);
  153. }
  154. function defaultChildren(d) {
  155. return d.children;
  156. }
  157. function copyData(node) {
  158. node.data = node.data.data;
  159. }
  160. function computeHeight(node) {
  161. var height = 0;
  162. do node.height = height;
  163. while ((node = node.parent) && (node.height < ++height));
  164. }
  165. function Node(data) {
  166. this.data = data;
  167. this.depth =
  168. this.height = 0;
  169. this.parent = null;
  170. }
  171. Node.prototype = hierarchy.prototype = {
  172. constructor: Node,
  173. count: node_count,
  174. each: node_each,
  175. eachAfter: node_eachAfter,
  176. eachBefore: node_eachBefore,
  177. sum: node_sum,
  178. sort: node_sort,
  179. path: node_path,
  180. ancestors: node_ancestors,
  181. descendants: node_descendants,
  182. leaves: node_leaves,
  183. links: node_links,
  184. copy: node_copy
  185. };
  186. var version = "2.1.1";
  187. const defaults = Object.freeze({
  188. children: data => data.children,
  189. nodeSize: node => node.data.size,
  190. spacing: 0,
  191. });
  192. // Create a layout function with customizable options. Per D3-style, the
  193. // options can be set at any time using setter methods. The layout function
  194. // will compute the tree node positions based on the options in effect at the
  195. // time it is called.
  196. function flextree(options) {
  197. const opts = Object.assign({}, defaults, options);
  198. function accessor(name) {
  199. const opt = opts[name];
  200. return typeof opt === 'function' ? opt : () => opt;
  201. }
  202. function layout(tree) {
  203. const wtree = wrap(getWrapper(), tree, node=>node.children);
  204. wtree.update();
  205. return wtree.data;
  206. }
  207. function getFlexNode() {
  208. const nodeSize = accessor('nodeSize');
  209. const spacing = accessor('spacing');
  210. return class FlexNode extends hierarchy.prototype.constructor {
  211. constructor(data) {
  212. super(data);
  213. }
  214. copy() {
  215. const c = wrap(this.constructor, this, node=>node.children);
  216. c.each(node => node.data = node.data.data);
  217. return c;
  218. }
  219. get size() { return nodeSize(this); }
  220. spacing(oNode) { return spacing(this, oNode); }
  221. get nodes() { return this.descendants(); }
  222. get xSize() { return this.size[0]; }
  223. get ySize() { return this.size[1]; }
  224. get top() { return this.y; }
  225. get bottom() { return this.y + this.ySize; }
  226. get left() { return this.x - this.xSize / 2; }
  227. get right() { return this.x + this.xSize / 2; }
  228. get root() {
  229. const ancs = this.ancestors();
  230. return ancs[ancs.length - 1];
  231. }
  232. get numChildren() {
  233. return this.hasChildren ? this.children.length : 0;
  234. }
  235. get hasChildren() { return !this.noChildren; }
  236. get noChildren() { return this.children === null; }
  237. get firstChild() {
  238. return this.hasChildren ? this.children[0] : null;
  239. }
  240. get lastChild() {
  241. return this.hasChildren ? this.children[this.numChildren - 1] : null;
  242. }
  243. get extents() {
  244. return (this.children || []).reduce(
  245. (acc, kid) => FlexNode.maxExtents(acc, kid.extents),
  246. this.nodeExtents);
  247. }
  248. get nodeExtents() {
  249. return {
  250. top: this.top,
  251. bottom: this.bottom,
  252. left: this.left,
  253. right: this.right,
  254. };
  255. }
  256. static maxExtents(e0, e1) {
  257. return {
  258. top: Math.min(e0.top, e1.top),
  259. bottom: Math.max(e0.bottom, e1.bottom),
  260. left: Math.min(e0.left, e1.left),
  261. right: Math.max(e0.right, e1.right),
  262. };
  263. }
  264. };
  265. }
  266. function getWrapper() {
  267. const FlexNode = getFlexNode();
  268. const nodeSize = accessor('nodeSize');
  269. const spacing = accessor('spacing');
  270. return class extends FlexNode {
  271. constructor(data) {
  272. super(data);
  273. Object.assign(this, {
  274. x: 0, y: 0,
  275. relX: 0, prelim: 0, shift: 0, change: 0,
  276. lExt: this, lExtRelX: 0, lThr: null,
  277. rExt: this, rExtRelX: 0, rThr: null,
  278. });
  279. }
  280. get size() { return nodeSize(this.data); }
  281. spacing(oNode) { return spacing(this.data, oNode.data); }
  282. get x() { return this.data.x; }
  283. set x(v) { this.data.x = v; }
  284. get y() { return this.data.y; }
  285. set y(v) { this.data.y = v; }
  286. update() {
  287. layoutChildren(this);
  288. resolveX(this);
  289. return this;
  290. }
  291. };
  292. }
  293. function wrap(FlexClass, treeData, children) {
  294. const _wrap = (data, parent) => {
  295. const node = new FlexClass(data);
  296. Object.assign(node, {
  297. parent,
  298. depth: parent === null ? 0 : parent.depth + 1,
  299. height: 0,
  300. length: 1,
  301. });
  302. const kidsData = children(data) || [];
  303. node.children = kidsData.length === 0 ? null
  304. : kidsData.map(kd => _wrap(kd, node));
  305. if (node.children) {
  306. Object.assign(node, node.children.reduce(
  307. (hl, kid) => ({
  308. height: Math.max(hl.height, kid.height + 1),
  309. length: hl.length + kid.length,
  310. }), node
  311. ));
  312. }
  313. return node;
  314. };
  315. return _wrap(treeData, null);
  316. }
  317. Object.assign(layout, {
  318. nodeSize(arg) {
  319. return arguments.length ? (opts.nodeSize = arg, layout) : opts.nodeSize;
  320. },
  321. spacing(arg) {
  322. return arguments.length ? (opts.spacing = arg, layout) : opts.spacing;
  323. },
  324. children(arg) {
  325. return arguments.length ? (opts.children = arg, layout) : opts.children;
  326. },
  327. hierarchy(treeData, children) {
  328. const kids = typeof children === 'undefined' ? opts.children : children;
  329. return wrap(getFlexNode(), treeData, kids);
  330. },
  331. dump(tree) {
  332. const nodeSize = accessor('nodeSize');
  333. const _dump = i0 => node => {
  334. const i1 = i0 + ' ';
  335. const i2 = i0 + ' ';
  336. const {x, y} = node;
  337. const size = nodeSize(node);
  338. const kids = (node.children || []);
  339. const kdumps = (kids.length === 0) ? ' ' :
  340. `,${i1}children: [${i2}${kids.map(_dump(i2)).join(i2)}${i1}],${i0}`;
  341. return `{ size: [${size.join(', ')}],${i1}x: ${x}, y: ${y}${kdumps}},`;
  342. };
  343. return _dump('\n')(tree);
  344. },
  345. });
  346. return layout;
  347. }
  348. flextree.version = version;
  349. const layoutChildren = (w, y = 0) => {
  350. w.y = y;
  351. (w.children || []).reduce((acc, kid) => {
  352. const [i, lastLows] = acc;
  353. layoutChildren(kid, w.y + w.ySize);
  354. // The lowest vertical coordinate while extreme nodes still point
  355. // in current subtree.
  356. const lowY = (i === 0 ? kid.lExt : kid.rExt).bottom;
  357. if (i !== 0) separate(w, i, lastLows);
  358. const lows = updateLows(lowY, i, lastLows);
  359. return [i + 1, lows];
  360. }, [0, null]);
  361. shiftChange(w);
  362. positionRoot(w);
  363. return w;
  364. };
  365. // Resolves the relative coordinate properties - relX and prelim --
  366. // to set the final, absolute x coordinate for each node. This also sets
  367. // `prelim` to 0, so that `relX` for each node is its x-coordinate relative
  368. // to its parent.
  369. const resolveX = (w, prevSum, parentX) => {
  370. // A call to resolveX without arguments is assumed to be for the root of
  371. // the tree. This will set the root's x-coord to zero.
  372. if (typeof prevSum === 'undefined') {
  373. prevSum = -w.relX - w.prelim;
  374. parentX = 0;
  375. }
  376. const sum = prevSum + w.relX;
  377. w.relX = sum + w.prelim - parentX;
  378. w.prelim = 0;
  379. w.x = parentX + w.relX;
  380. (w.children || []).forEach(k => resolveX(k, sum, w.x));
  381. return w;
  382. };
  383. // Process shift and change for all children, to add intermediate spacing to
  384. // each child's modifier.
  385. const shiftChange = w => {
  386. (w.children || []).reduce((acc, child) => {
  387. const [lastShiftSum, lastChangeSum] = acc;
  388. const shiftSum = lastShiftSum + child.shift;
  389. const changeSum = lastChangeSum + shiftSum + child.change;
  390. child.relX += changeSum;
  391. return [shiftSum, changeSum];
  392. }, [0, 0]);
  393. };
  394. // Separates the latest child from its previous sibling
  395. /* eslint-disable complexity */
  396. const separate = (w, i, lows) => {
  397. const lSib = w.children[i - 1];
  398. const curSubtree = w.children[i];
  399. let rContour = lSib;
  400. let rSumMods = lSib.relX;
  401. let lContour = curSubtree;
  402. let lSumMods = curSubtree.relX;
  403. let isFirst = true;
  404. while (rContour && lContour) {
  405. if (rContour.bottom > lows.lowY) lows = lows.next;
  406. // How far to the left of the right side of rContour is the left side
  407. // of lContour? First compute the center-to-center distance, then add
  408. // the "spacing"
  409. const dist =
  410. (rSumMods + rContour.prelim) - (lSumMods + lContour.prelim) +
  411. rContour.xSize / 2 + lContour.xSize / 2 +
  412. rContour.spacing(lContour);
  413. if (dist > 0 || (dist < 0 && isFirst)) {
  414. lSumMods += dist;
  415. // Move subtree by changing relX.
  416. moveSubtree(curSubtree, dist);
  417. distributeExtra(w, i, lows.index, dist);
  418. }
  419. isFirst = false;
  420. // Advance highest node(s) and sum(s) of modifiers
  421. const rightBottom = rContour.bottom;
  422. const leftBottom = lContour.bottom;
  423. if (rightBottom <= leftBottom) {
  424. rContour = nextRContour(rContour);
  425. if (rContour) rSumMods += rContour.relX;
  426. }
  427. if (rightBottom >= leftBottom) {
  428. lContour = nextLContour(lContour);
  429. if (lContour) lSumMods += lContour.relX;
  430. }
  431. }
  432. // Set threads and update extreme nodes. In the first case, the
  433. // current subtree is taller than the left siblings.
  434. if (!rContour && lContour) setLThr(w, i, lContour, lSumMods);
  435. // In the next case, the left siblings are taller than the current subtree
  436. else if (rContour && !lContour) setRThr(w, i, rContour, rSumMods);
  437. };
  438. /* eslint-enable complexity */
  439. // Move subtree by changing relX.
  440. const moveSubtree = (subtree, distance) => {
  441. subtree.relX += distance;
  442. subtree.lExtRelX += distance;
  443. subtree.rExtRelX += distance;
  444. };
  445. const distributeExtra = (w, curSubtreeI, leftSibI, dist) => {
  446. const curSubtree = w.children[curSubtreeI];
  447. const n = curSubtreeI - leftSibI;
  448. // Are there intermediate children?
  449. if (n > 1) {
  450. const delta = dist / n;
  451. w.children[leftSibI + 1].shift += delta;
  452. curSubtree.shift -= delta;
  453. curSubtree.change -= dist - delta;
  454. }
  455. };
  456. const nextLContour = w => {
  457. return w.hasChildren ? w.firstChild : w.lThr;
  458. };
  459. const nextRContour = w => {
  460. return w.hasChildren ? w.lastChild : w.rThr;
  461. };
  462. const setLThr = (w, i, lContour, lSumMods) => {
  463. const firstChild = w.firstChild;
  464. const lExt = firstChild.lExt;
  465. const curSubtree = w.children[i];
  466. lExt.lThr = lContour;
  467. // Change relX so that the sum of modifier after following thread is correct.
  468. const diff = lSumMods - lContour.relX - firstChild.lExtRelX;
  469. lExt.relX += diff;
  470. // Change preliminary x coordinate so that the node does not move.
  471. lExt.prelim -= diff;
  472. // Update extreme node and its sum of modifiers.
  473. firstChild.lExt = curSubtree.lExt;
  474. firstChild.lExtRelX = curSubtree.lExtRelX;
  475. };
  476. // Mirror image of setLThr.
  477. const setRThr = (w, i, rContour, rSumMods) => {
  478. const curSubtree = w.children[i];
  479. const rExt = curSubtree.rExt;
  480. const lSib = w.children[i - 1];
  481. rExt.rThr = rContour;
  482. const diff = rSumMods - rContour.relX - curSubtree.rExtRelX;
  483. rExt.relX += diff;
  484. rExt.prelim -= diff;
  485. curSubtree.rExt = lSib.rExt;
  486. curSubtree.rExtRelX = lSib.rExtRelX;
  487. };
  488. // Position root between children, taking into account their modifiers
  489. const positionRoot = w => {
  490. if (w.hasChildren) {
  491. const k0 = w.firstChild;
  492. const kf = w.lastChild;
  493. const prelim = (k0.prelim + k0.relX - k0.xSize / 2 +
  494. kf.relX + kf.prelim + kf.xSize / 2 ) / 2;
  495. Object.assign(w, {
  496. prelim,
  497. lExt: k0.lExt, lExtRelX: k0.lExtRelX,
  498. rExt: kf.rExt, rExtRelX: kf.rExtRelX,
  499. });
  500. }
  501. };
  502. // Make/maintain a linked list of the indexes of left siblings and their
  503. // lowest vertical coordinate.
  504. const updateLows = (lowY, index, lastLows) => {
  505. // Remove siblings that are hidden by the new subtree.
  506. while (lastLows !== null && lowY >= lastLows.lowY)
  507. lastLows = lastLows.next;
  508. // Prepend the new subtree.
  509. return {
  510. lowY,
  511. index,
  512. next: lastLows,
  513. };
  514. };
  515. const uniqId = Math.random().toString(36).slice(2, 8);
  516. let globalIndex = 0;
  517. function getId() {
  518. globalIndex += 1;
  519. return `mm-${uniqId}-${globalIndex}`;
  520. }
  521. function walkTree(tree, callback, key = 'c') {
  522. const walk = (item, parent) => callback(item, () => {
  523. var _item$key;
  524. (_item$key = item[key]) == null ? void 0 : _item$key.forEach(child => {
  525. walk(child, item);
  526. });
  527. }, parent);
  528. walk(tree);
  529. }
  530. function arrayFrom(arrayLike) {
  531. if (Array.from) return Array.from(arrayLike);
  532. const array = [];
  533. for (let i = 0; i < arrayLike.length; i += 1) {
  534. array.push(arrayLike[i]);
  535. }
  536. return array;
  537. }
  538. function flatMap(arrayLike, callback) {
  539. if (arrayLike.flatMap) return arrayLike.flatMap(callback);
  540. const array = [];
  541. for (let i = 0; i < arrayLike.length; i += 1) {
  542. const result = callback(arrayLike[i], i, arrayLike);
  543. if (Array.isArray(result)) array.push(...result);else array.push(result);
  544. }
  545. return array;
  546. }
  547. function addClass(className, ...rest) {
  548. const classList = (className || '').split(' ').filter(Boolean);
  549. rest.forEach(item => {
  550. if (item && classList.indexOf(item) < 0) classList.push(item);
  551. });
  552. return classList.join(' ');
  553. }
  554. function childSelector(filter) {
  555. if (typeof filter === 'string') {
  556. const tagName = filter;
  557. filter = el => el.tagName === tagName;
  558. }
  559. const filterFn = filter;
  560. return function selector() {
  561. let nodes = arrayFrom(this.childNodes);
  562. if (filterFn) nodes = nodes.filter(node => filterFn(node));
  563. return nodes;
  564. };
  565. }
  566. function memoize(fn) {
  567. const cache = {};
  568. return function memoized(...args) {
  569. const key = `${args[0]}`;
  570. let data = cache[key];
  571. if (!data) {
  572. data = {
  573. value: fn(...args)
  574. };
  575. cache[key] = data;
  576. }
  577. return data.value;
  578. };
  579. }
  580. function createElement(tagName, props, attrs) {
  581. const el = document.createElement(tagName);
  582. if (props) {
  583. Object.entries(props).forEach(([key, value]) => {
  584. el[key] = value;
  585. });
  586. }
  587. if (attrs) {
  588. Object.entries(attrs).forEach(([key, value]) => {
  589. el.setAttribute(key, value);
  590. });
  591. }
  592. return el;
  593. }
  594. const memoizedPreloadJS = memoize(url => {
  595. document.head.append(createElement('link', {
  596. rel: 'preload',
  597. as: 'script',
  598. href: url
  599. }));
  600. });
  601. function loadJSItem(item, context) {
  602. if (item.type === 'script') {
  603. return new Promise((resolve, reject) => {
  604. document.head.append(createElement('script', Object.assign(Object.assign({}, item.data), {}, {
  605. onload: resolve,
  606. onerror: reject
  607. })));
  608. });
  609. } else if (item.type === 'iife') {
  610. const {
  611. fn,
  612. getParams
  613. } = item.data;
  614. fn(...((getParams == null ? void 0 : getParams(context)) || []));
  615. }
  616. }
  617. function loadCSSItem(item) {
  618. if (item.type === 'style') {
  619. document.head.append(createElement('style', {
  620. textContent: item.data
  621. }));
  622. } else if (item.type === 'stylesheet') {
  623. document.head.append(createElement('link', Object.assign({
  624. rel: 'stylesheet'
  625. }, item.data)));
  626. }
  627. }
  628. async function loadJS(items, options) {
  629. const needPreload = items.filter(item => item.type === 'script');
  630. if (needPreload.length > 1) needPreload.forEach(item => memoizedPreloadJS(item.data.src));
  631. for (const item of items) {
  632. await loadJSItem(item, options);
  633. }
  634. }
  635. function loadCSS(items) {
  636. for (const item of items) {
  637. loadCSSItem(item);
  638. }
  639. }
  640. async function initializePlugins(Markmap, plugins, options) {
  641. options = Object.assign({}, options);
  642. await Promise.all(plugins.map(plugin => {
  643. loadCSS(plugin.styles);
  644. return loadJS(plugin.scripts, options);
  645. }));
  646. for (const {
  647. initialize
  648. } of plugins) {
  649. if (initialize) initialize(Markmap, options);
  650. }
  651. }
  652. const styles = [];
  653. const scripts = [{
  654. type: 'iife',
  655. data: {
  656. fn: mathJax => {
  657. mathJax.options = Object.assign({
  658. skipHtmlTags: {
  659. '[-]': ['code', 'pre']
  660. }
  661. }, mathJax.options);
  662. mathJax.startup = Object.assign({
  663. typeset: false
  664. }, mathJax.startup);
  665. window.MathJax = mathJax;
  666. },
  667. getParams: context => [Object.assign({}, context.mathJax)]
  668. }
  669. }, {
  670. type: 'script',
  671. data: {
  672. src: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js'
  673. }
  674. }];
  675. function initialize(Markmap, options) {
  676. Markmap.transformHtml.tap((mm, nodes) => {
  677. var _MathJax$typeset, _MathJax;
  678. (_MathJax$typeset = (_MathJax = window.MathJax).typeset) == null ? void 0 : _MathJax$typeset.call(_MathJax, nodes);
  679. });
  680. }
  681. const plugin = {
  682. styles,
  683. scripts,
  684. initialize
  685. };
  686. const styles$1 = [{
  687. type: 'stylesheet',
  688. data: {
  689. href: 'https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.css'
  690. }
  691. }];
  692. const scripts$1 = [{
  693. type: 'iife',
  694. data: {
  695. fn: () => {
  696. window.Prism = {
  697. manual: true
  698. };
  699. }
  700. }
  701. }, {
  702. type: 'script',
  703. data: {
  704. src: 'https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js'
  705. }
  706. }, // components will be added by paths relative to path of autoloader
  707. {
  708. type: 'script',
  709. data: {
  710. src: 'https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js'
  711. }
  712. }];
  713. function initialize$1(Markmap, options) {
  714. Markmap.transformHtml.tap((mm, nodes) => {
  715. const {
  716. Prism
  717. } = window;
  718. const langs = flatMap(nodes, node => arrayFrom(node.querySelectorAll('code[class*=language-]'))).map(code => {
  719. const lang = code.className.match(/(?:^|\s)language-(\S+)|$/)[1];
  720. if (Prism.languages[lang]) {
  721. Prism.highlightElement(code);
  722. } else {
  723. return lang;
  724. }
  725. }).filter(Boolean);
  726. if (langs.length) {
  727. Prism.plugins.autoloader.loadLanguages(langs, () => {
  728. mm.setData();
  729. mm.fit();
  730. });
  731. }
  732. });
  733. }
  734. const plugin$1 = {
  735. styles: styles$1,
  736. scripts: scripts$1,
  737. initialize: initialize$1
  738. };
  739. var plugins = /*#__PURE__*/Object.freeze({
  740. __proto__: null,
  741. mathJax: plugin,
  742. prism: plugin$1
  743. });
  744. class Hook {
  745. constructor() {
  746. this.listeners = [];
  747. }
  748. tap(fn) {
  749. this.listeners.push(fn);
  750. }
  751. call(...args) {
  752. for (const fn of this.listeners) {
  753. fn(...args);
  754. }
  755. }
  756. }
  757. function linkWidth(nodeData) {
  758. const data = nodeData.data;
  759. return Math.max(6 - 2 * data.d, 1.5);
  760. }
  761. function adjustSpacing(tree, spacing) {
  762. walkTree(tree, (d, next) => {
  763. d.ySizeInner = d.ySize - spacing;
  764. d.y += spacing;
  765. next();
  766. }, 'children');
  767. }
  768. class Markmap {
  769. constructor(svg, opts) {
  770. this.options = void 0;
  771. this.state = void 0;
  772. this.svg = void 0;
  773. this.styleNode = void 0;
  774. this.g = void 0;
  775. this.zoom = void 0;
  776. ['handleZoom', 'handleClick'].forEach(key => {
  777. this[key] = this[key].bind(this);
  778. });
  779. this.svg = svg.datum ? svg : d3.select(svg);
  780. this.styleNode = this.svg.append('style');
  781. this.zoom = d3.zoom().on('zoom', this.handleZoom);
  782. this.options = Object.assign({
  783. duration: 500,
  784. nodeFont: '300 16px/20px sans-serif',
  785. nodeMinHeight: 16,
  786. spacingVertical: 5,
  787. spacingHorizontal: 80,
  788. autoFit: false,
  789. fitRatio: 0.95,
  790. color: (colorFn => node => colorFn(node.p.i))(d3.scaleOrdinal(d3.schemeCategory10)),
  791. paddingX: 8
  792. }, opts);
  793. this.state = {
  794. id: this.options.id || getId()
  795. };
  796. this.g = this.svg.append('g').attr('class', `${this.state.id}-g`);
  797. this.updateStyle();
  798. this.svg.call(this.zoom);
  799. }
  800. getStyleContent() {
  801. const {
  802. style,
  803. nodeFont
  804. } = this.options;
  805. const {
  806. id
  807. } = this.state;
  808. const extraStyle = typeof style === 'function' ? style(id) : '';
  809. const styleText = `\
  810. .${id} a { color: #0097e6; }
  811. .${id} a:hover { color: #00a8ff; }
  812. .${id}-g > path { fill: none; }
  813. .${id}-fo > div { font: ${nodeFont}; white-space: nowrap; }
  814. .${id}-fo code { padding: .2em .4em; font-size: calc(1em - 2px); color: #555; background-color: #f0f0f0; border-radius: 2px; }
  815. .${id}-fo del { text-decoration: line-through; }
  816. .${id}-fo em { font-style: italic; }
  817. .${id}-fo strong { font-weight: 500; }
  818. .${id}-fo pre { margin: 0; }
  819. .${id}-fo pre[class*=language-] { padding: 0; }
  820. .${id}-g > g { cursor: pointer; }
  821. ${extraStyle}
  822. `;
  823. return styleText;
  824. }
  825. updateStyle() {
  826. this.svg.attr('class', addClass(this.svg.attr('class'), this.state.id));
  827. this.styleNode.text(this.getStyleContent());
  828. }
  829. handleZoom() {
  830. const {
  831. transform
  832. } = d3.event;
  833. this.g.attr('transform', transform);
  834. }
  835. handleClick(d) {
  836. var _data$p;
  837. const {
  838. data
  839. } = d;
  840. data.p = Object.assign(Object.assign({}, data.p), {}, {
  841. f: !((_data$p = data.p) == null ? void 0 : _data$p.f)
  842. });
  843. this.renderData(d.data);
  844. }
  845. initializeData(node) {
  846. let i = 0;
  847. const {
  848. nodeFont,
  849. color,
  850. nodeMinHeight
  851. } = this.options;
  852. const {
  853. id
  854. } = this.state;
  855. const container = document.createElement('div');
  856. const containerClass = `${id}-container`;
  857. container.className = addClass(container.className, `${id}-fo`, containerClass);
  858. const style = document.createElement('style');
  859. style.textContent = `
  860. ${this.getStyleContent()}
  861. .${containerClass} {
  862. position: absolute;
  863. width: 0;
  864. height: 0;
  865. top: -100px;
  866. left: -100px;
  867. overflow: hidden;
  868. font: ${nodeFont};
  869. }
  870. .${containerClass} > div {
  871. display: inline-block;
  872. }
  873. `;
  874. document.body.append(style, container);
  875. walkTree(node, (item, next) => {
  876. var _item$c;
  877. item.c = (_item$c = item.c) == null ? void 0 : _item$c.map(child => Object.assign({}, child));
  878. i += 1;
  879. const el = document.createElement('div');
  880. el.innerHTML = item.v;
  881. container.append(el);
  882. item.p = Object.assign(Object.assign({}, item.p), {}, {
  883. // unique ID
  884. i,
  885. el
  886. });
  887. color(item); // preload colors
  888. next();
  889. });
  890. const nodes = arrayFrom(container.childNodes);
  891. this.constructor.transformHtml.call(this, nodes);
  892. walkTree(node, (item, next, parent) => {
  893. var _parent$p;
  894. const rect = item.p.el.getBoundingClientRect();
  895. item.v = item.p.el.innerHTML;
  896. item.p.s = [Math.ceil(rect.width), Math.max(Math.ceil(rect.height), nodeMinHeight)]; // TODO keep keys for unchanged objects
  897. // unique key, should be based on content
  898. item.p.k = `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${item.p.i}:${item.v}`;
  899. next();
  900. });
  901. container.remove();
  902. style.remove();
  903. }
  904. setOptions(opts) {
  905. Object.assign(this.options, opts);
  906. }
  907. setData(data, opts) {
  908. if (!data) data = Object.assign({}, this.state.data);
  909. this.state.data = data;
  910. this.initializeData(data);
  911. if (opts) this.setOptions(opts);
  912. this.renderData();
  913. }
  914. renderData(originData) {
  915. var _origin$data$p$x, _origin$data$p$y;
  916. if (!this.state.data) return;
  917. const {
  918. spacingHorizontal,
  919. paddingX,
  920. spacingVertical,
  921. autoFit,
  922. color
  923. } = this.options;
  924. const {
  925. id
  926. } = this.state;
  927. const layout = flextree().children(d => {
  928. var _d$p;
  929. return !((_d$p = d.p) == null ? void 0 : _d$p.f) && d.c;
  930. }).nodeSize(d => {
  931. const [width, height] = d.data.p.s;
  932. return [height, width + (width ? paddingX * 2 : 0) + spacingHorizontal];
  933. }).spacing((a, b) => {
  934. return a.parent === b.parent ? spacingVertical : spacingVertical * 2;
  935. });
  936. const tree = layout.hierarchy(this.state.data);
  937. layout(tree);
  938. adjustSpacing(tree, spacingHorizontal);
  939. const descendants = tree.descendants().reverse();
  940. const links = tree.links();
  941. const linkShape = d3.linkHorizontal();
  942. const minX = d3.min(descendants, d => d.x - d.xSize / 2);
  943. const maxX = d3.max(descendants, d => d.x + d.xSize / 2);
  944. const minY = d3.min(descendants, d => d.y);
  945. const maxY = d3.max(descendants, d => d.y + d.ySizeInner);
  946. Object.assign(this.state, {
  947. minX,
  948. maxX,
  949. minY,
  950. maxY
  951. });
  952. if (autoFit) this.fit();
  953. const origin = originData && descendants.find(item => item.data === originData) || tree;
  954. const x0 = (_origin$data$p$x = origin.data.p.x0) != null ? _origin$data$p$x : origin.x;
  955. const y0 = (_origin$data$p$y = origin.data.p.y0) != null ? _origin$data$p$y : origin.y; // Update the nodes
  956. const node = this.g.selectAll(childSelector('g')).data(descendants, d => d.data.p.k);
  957. const nodeEnter = node.enter().append('g').attr('transform', d => `translate(${y0 + origin.ySizeInner - d.ySizeInner},${x0 + origin.xSize / 2 - d.xSize})`).on('click', this.handleClick);
  958. const nodeExit = this.transition(node.exit());
  959. nodeExit.select('rect').attr('width', 0).attr('x', d => d.ySizeInner);
  960. nodeExit.select('foreignObject').style('opacity', 0);
  961. nodeExit.attr('transform', d => `translate(${origin.y + origin.ySizeInner - d.ySizeInner},${origin.x + origin.xSize / 2 - d.xSize})`).remove();
  962. const nodeMerge = node.merge(nodeEnter);
  963. this.transition(nodeMerge).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`);
  964. const rect = nodeMerge.selectAll(childSelector('rect')).data(d => [d], d => d.data.p.k).join(enter => {
  965. return enter.append('rect').attr('x', d => d.ySizeInner).attr('y', d => d.xSize - linkWidth(d) / 2).attr('width', 0).attr('height', linkWidth);
  966. }, update => update, exit => exit.remove());
  967. this.transition(rect).attr('x', -1).attr('width', d => d.ySizeInner + 2).attr('fill', d => color(d.data));
  968. const circle = nodeMerge.selectAll(childSelector('circle')).data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => {
  969. return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('r', 0);
  970. }, update => update, exit => exit.remove());
  971. this.transition(circle).attr('r', 6).attr('stroke', d => color(d.data)).attr('fill', d => {
  972. var _d$data$p;
  973. return ((_d$data$p = d.data.p) == null ? void 0 : _d$data$p.f) ? color(d.data) : '#fff';
  974. });
  975. const foreignObject = nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.p.k).join(enter => {
  976. const fo = enter.append('foreignObject').attr('class', `${id}-fo`).attr('x', paddingX).attr('y', 0).style('opacity', 0).attr('height', d => d.xSize);
  977. fo.append('xhtml:div').select(function (d) {
  978. const node = d.data.p.el.cloneNode(true);
  979. this.replaceWith(node);
  980. return node;
  981. }).attr('xmlns', 'http://www.w3.org/1999/xhtml');
  982. return fo;
  983. }, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - paddingX * 2));
  984. this.transition(foreignObject).style('opacity', 1); // Update the links
  985. const path = this.g.selectAll(childSelector('path')).data(links, d => d.target.data.p.k).join(enter => {
  986. const source = [y0 + origin.ySizeInner, x0 + origin.xSize / 2];
  987. return enter.insert('path', 'g').attr('d', linkShape({
  988. source,
  989. target: source
  990. }));
  991. }, update => update, exit => {
  992. const source = [origin.y + origin.ySizeInner, origin.x + origin.xSize / 2];
  993. return this.transition(exit).attr('d', linkShape({
  994. source,
  995. target: source
  996. })).remove();
  997. });
  998. this.transition(path).attr('stroke', d => color(d.target.data)).attr('stroke-width', d => linkWidth(d.target)).attr('d', d => {
  999. const source = [d.source.y + d.source.ySizeInner, d.source.x + d.source.xSize / 2];
  1000. const target = [d.target.y, d.target.x + d.target.xSize / 2];
  1001. return linkShape({
  1002. source,
  1003. target
  1004. });
  1005. });
  1006. descendants.forEach(d => {
  1007. d.data.p.x0 = d.x;
  1008. d.data.p.y0 = d.y;
  1009. });
  1010. }
  1011. transition(sel) {
  1012. const {
  1013. duration
  1014. } = this.options;
  1015. return sel.transition().duration(duration);
  1016. }
  1017. fit() {
  1018. const svgNode = this.svg.node();
  1019. const {
  1020. width: offsetWidth,
  1021. height: offsetHeight
  1022. } = svgNode.getBoundingClientRect();
  1023. const {
  1024. fitRatio
  1025. } = this.options;
  1026. const {
  1027. minX,
  1028. maxX,
  1029. minY,
  1030. maxY
  1031. } = this.state;
  1032. const naturalWidth = maxY - minY;
  1033. const naturalHeight = maxX - minX;
  1034. const scale = Math.min(offsetWidth / naturalWidth * fitRatio, offsetHeight / naturalHeight * fitRatio, 2);
  1035. const initialZoom = d3.zoomIdentity.translate((offsetWidth - naturalWidth * scale) / 2 - minY * scale, (offsetHeight - naturalHeight * scale) / 2 - minX * scale).scale(scale);
  1036. return this.transition(this.svg).call(this.zoom.transform, initialZoom).end();
  1037. }
  1038. rescale(scale) {
  1039. const svgNode = this.svg.node();
  1040. const {
  1041. width: offsetWidth,
  1042. height: offsetHeight
  1043. } = svgNode.getBoundingClientRect();
  1044. const halfWidth = offsetWidth / 2;
  1045. const halfHeight = offsetHeight / 2;
  1046. const transform = d3.zoomTransform(svgNode);
  1047. const newTransform = transform.translate((halfWidth - transform.x) * (1 - scale) / transform.k, (halfHeight - transform.y) * (1 - scale) / transform.k).scale(scale);
  1048. return this.transition(this.svg).call(this.zoom.transform, newTransform).end();
  1049. }
  1050. static create(svg, opts, data) {
  1051. const mm = new Markmap(svg, opts);
  1052. if (data) {
  1053. mm.setData(data);
  1054. mm.fit(); // always fit for the first render
  1055. }
  1056. return mm;
  1057. }
  1058. }
  1059. Markmap.transformHtml = new Hook();
  1060. function markmap(svg, data, opts) {
  1061. return Markmap.create(svg, opts, data);
  1062. }
  1063. async function loadPlugins(items, options) {
  1064. items = items.map(item => {
  1065. if (typeof item === 'string') {
  1066. const name = item;
  1067. item = plugins[name];
  1068. if (!item) {
  1069. console.warn(`[markmap] Unknown plugin: ${name}`);
  1070. }
  1071. }
  1072. return item;
  1073. }).filter(Boolean);
  1074. return initializePlugins(Markmap, items, options);
  1075. }
  1076. exports.Markmap = Markmap;
  1077. exports.loadPlugins = loadPlugins;
  1078. exports.markmap = markmap;
  1079. exports.plugins = plugins;
  1080. }(this.markmap = this.markmap || {}, d3));