markmap-view 0.17.3-alpha.1 → 0.17.3-beta.3

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.
@@ -103,28 +103,28 @@
103
103
  };
104
104
  }
105
105
  /*! @gera2ld/jsx-dom v2.2.2 | ISC License */
106
- const VTYPE_ELEMENT$1 = 1;
107
- const VTYPE_FUNCTION$1 = 2;
108
- const SVG_NS$1 = "http://www.w3.org/2000/svg";
109
- const XLINK_NS$1 = "http://www.w3.org/1999/xlink";
110
- const NS_ATTRS$1 = {
111
- show: XLINK_NS$1,
112
- actuate: XLINK_NS$1,
113
- href: XLINK_NS$1
106
+ const VTYPE_ELEMENT = 1;
107
+ const VTYPE_FUNCTION = 2;
108
+ const SVG_NS = "http://www.w3.org/2000/svg";
109
+ const XLINK_NS = "http://www.w3.org/1999/xlink";
110
+ const NS_ATTRS = {
111
+ show: XLINK_NS,
112
+ actuate: XLINK_NS,
113
+ href: XLINK_NS
114
114
  };
115
- const isLeaf$1 = (c) => typeof c === "string" || typeof c === "number";
116
- const isElement$1 = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT$1;
117
- const isRenderFunction$1 = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION$1;
115
+ const isLeaf = (c) => typeof c === "string" || typeof c === "number";
116
+ const isElement = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
117
+ const isRenderFunction = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
118
118
  function h(type, props, ...children) {
119
119
  props = Object.assign({}, props, {
120
120
  children: children.length === 1 ? children[0] : children
121
121
  });
122
- return jsx$1(type, props);
122
+ return jsx(type, props);
123
123
  }
124
- function jsx$1(type, props) {
124
+ function jsx(type, props) {
125
125
  let vtype;
126
- if (typeof type === "string") vtype = VTYPE_ELEMENT$1;
127
- else if (typeof type === "function") vtype = VTYPE_FUNCTION$1;
126
+ if (typeof type === "string") vtype = VTYPE_ELEMENT;
127
+ else if (typeof type === "function") vtype = VTYPE_FUNCTION;
128
128
  else throw new Error("Invalid VNode type");
129
129
  return {
130
130
  vtype,
@@ -132,18 +132,18 @@
132
132
  props
133
133
  };
134
134
  }
135
- function Fragment$1(props) {
135
+ function Fragment(props) {
136
136
  return props.children;
137
137
  }
138
- const DEFAULT_ENV$1 = {
138
+ const DEFAULT_ENV = {
139
139
  isSvg: false
140
140
  };
141
- function insertDom$1(parent, nodes) {
141
+ function insertDom(parent, nodes) {
142
142
  if (!Array.isArray(nodes)) nodes = [nodes];
143
143
  nodes = nodes.filter(Boolean);
144
144
  if (nodes.length) parent.append(...nodes);
145
145
  }
146
- function mountAttributes$1(domElement, props, env) {
146
+ function mountAttributes(domElement, props, env) {
147
147
  for (const key in props) {
148
148
  if (key === "key" || key === "children" || key === "ref") continue;
149
149
  if (key === "dangerouslySetInnerHTML") {
@@ -154,22 +154,22 @@
154
154
  } else if (key.startsWith("on")) {
155
155
  domElement[key.toLowerCase()] = props[key];
156
156
  } else {
157
- setDOMAttribute$1(domElement, key, props[key], env.isSvg);
157
+ setDOMAttribute(domElement, key, props[key], env.isSvg);
158
158
  }
159
159
  }
160
160
  }
161
- const attrMap$1 = {
161
+ const attrMap = {
162
162
  className: "class",
163
163
  labelFor: "for"
164
164
  };
165
- function setDOMAttribute$1(el, attr, value, isSVG) {
166
- attr = attrMap$1[attr] || attr;
165
+ function setDOMAttribute(el, attr, value, isSVG) {
166
+ attr = attrMap[attr] || attr;
167
167
  if (value === true) {
168
168
  el.setAttribute(attr, "");
169
169
  } else if (value === false) {
170
170
  el.removeAttribute(attr);
171
171
  } else {
172
- const namespace = isSVG ? NS_ATTRS$1[attr] : void 0;
172
+ const namespace = isSVG ? NS_ATTRS[attr] : void 0;
173
173
  if (namespace !== void 0) {
174
174
  el.setAttributeNS(namespace, attr, value);
175
175
  } else {
@@ -177,39 +177,39 @@
177
177
  }
178
178
  }
179
179
  }
180
- function flatten$1(arr) {
180
+ function flatten(arr) {
181
181
  return arr.reduce((prev, item) => prev.concat(item), []);
182
182
  }
183
- function mountChildren$1(children, env) {
184
- return Array.isArray(children) ? flatten$1(children.map((child) => mountChildren$1(child, env))) : mount$1(children, env);
183
+ function mountChildren(children, env) {
184
+ return Array.isArray(children) ? flatten(children.map((child) => mountChildren(child, env))) : mount(children, env);
185
185
  }
186
- function mount$1(vnode, env = DEFAULT_ENV$1) {
186
+ function mount(vnode, env = DEFAULT_ENV) {
187
187
  if (vnode == null || typeof vnode === "boolean") {
188
188
  return null;
189
189
  }
190
190
  if (vnode instanceof Node) {
191
191
  return vnode;
192
192
  }
193
- if (isRenderFunction$1(vnode)) {
193
+ if (isRenderFunction(vnode)) {
194
194
  const {
195
195
  type,
196
196
  props
197
197
  } = vnode;
198
- if (type === Fragment$1) {
198
+ if (type === Fragment) {
199
199
  const node = document.createDocumentFragment();
200
200
  if (props.children) {
201
- const children = mountChildren$1(props.children, env);
202
- insertDom$1(node, children);
201
+ const children = mountChildren(props.children, env);
202
+ insertDom(node, children);
203
203
  }
204
204
  return node;
205
205
  }
206
206
  const childVNode = type(props);
207
- return mount$1(childVNode, env);
207
+ return mount(childVNode, env);
208
208
  }
209
- if (isLeaf$1(vnode)) {
209
+ if (isLeaf(vnode)) {
210
210
  return document.createTextNode(`${vnode}`);
211
211
  }
212
- if (isElement$1(vnode)) {
212
+ if (isElement(vnode)) {
213
213
  let node;
214
214
  const {
215
215
  type,
@@ -223,9 +223,9 @@
223
223
  if (!env.isSvg) {
224
224
  node = document.createElement(type);
225
225
  } else {
226
- node = document.createElementNS(SVG_NS$1, type);
226
+ node = document.createElementNS(SVG_NS, type);
227
227
  }
228
- mountAttributes$1(node, props, env);
228
+ mountAttributes(node, props, env);
229
229
  if (props.children) {
230
230
  let childEnv = env;
231
231
  if (env.isSvg && type === "foreignObject") {
@@ -233,8 +233,8 @@
233
233
  isSvg: false
234
234
  });
235
235
  }
236
- const children = mountChildren$1(props.children, childEnv);
237
- if (children != null) insertDom$1(node, children);
236
+ const children = mountChildren(props.children, childEnv);
237
+ if (children != null) insertDom(node, children);
238
238
  }
239
239
  const {
240
240
  ref
@@ -244,11 +244,11 @@
244
244
  }
245
245
  throw new Error("mount: Invalid Vnode!");
246
246
  }
247
- function mountDom$1(vnode) {
248
- return mount$1(vnode);
247
+ function mountDom(vnode) {
248
+ return mount(vnode);
249
249
  }
250
250
  function hm(...args) {
251
- return mountDom$1(h(...args));
251
+ return mountDom(h(...args));
252
252
  }
253
253
  const memoizedPreloadJS = memoize((url) => {
254
254
  document.head.append(
@@ -406,144 +406,12 @@
406
406
  });
407
407
  return derivedOptions;
408
408
  }
409
- /*! @gera2ld/jsx-dom v2.2.2 | ISC License */
410
- const VTYPE_ELEMENT = 1;
411
- const VTYPE_FUNCTION = 2;
412
- const SVG_NS = "http://www.w3.org/2000/svg";
413
- const XLINK_NS = "http://www.w3.org/1999/xlink";
414
- const NS_ATTRS = {
415
- show: XLINK_NS,
416
- actuate: XLINK_NS,
417
- href: XLINK_NS
418
- };
419
- const isLeaf = (c) => typeof c === "string" || typeof c === "number";
420
- const isElement = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
421
- const isRenderFunction = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
422
- function jsx(type, props) {
423
- let vtype;
424
- if (typeof type === "string") vtype = VTYPE_ELEMENT;
425
- else if (typeof type === "function") vtype = VTYPE_FUNCTION;
426
- else throw new Error("Invalid VNode type");
427
- return {
428
- vtype,
429
- type,
430
- props
431
- };
432
- }
433
- function Fragment(props) {
434
- return props.children;
435
- }
436
- const DEFAULT_ENV = {
437
- isSvg: false
438
- };
439
- function insertDom(parent, nodes) {
440
- if (!Array.isArray(nodes)) nodes = [nodes];
441
- nodes = nodes.filter(Boolean);
442
- if (nodes.length) parent.append(...nodes);
443
- }
444
- function mountAttributes(domElement, props, env) {
445
- for (const key in props) {
446
- if (key === "key" || key === "children" || key === "ref") continue;
447
- if (key === "dangerouslySetInnerHTML") {
448
- domElement.innerHTML = props[key].__html;
449
- } else if (key === "innerHTML" || key === "textContent" || key === "innerText" || key === "value" && ["textarea", "select"].includes(domElement.tagName)) {
450
- const value = props[key];
451
- if (value != null) domElement[key] = value;
452
- } else if (key.startsWith("on")) {
453
- domElement[key.toLowerCase()] = props[key];
454
- } else {
455
- setDOMAttribute(domElement, key, props[key], env.isSvg);
456
- }
409
+ function simpleHash(str) {
410
+ let hash = 0;
411
+ for (let i = 0; i < str.length; i++) {
412
+ hash = (hash << 5) - hash + str.charCodeAt(i) | 0;
457
413
  }
458
- }
459
- const attrMap = {
460
- className: "class",
461
- labelFor: "for"
462
- };
463
- function setDOMAttribute(el, attr, value, isSVG) {
464
- attr = attrMap[attr] || attr;
465
- if (value === true) {
466
- el.setAttribute(attr, "");
467
- } else if (value === false) {
468
- el.removeAttribute(attr);
469
- } else {
470
- const namespace = isSVG ? NS_ATTRS[attr] : void 0;
471
- if (namespace !== void 0) {
472
- el.setAttributeNS(namespace, attr, value);
473
- } else {
474
- el.setAttribute(attr, value);
475
- }
476
- }
477
- }
478
- function flatten(arr) {
479
- return arr.reduce((prev, item) => prev.concat(item), []);
480
- }
481
- function mountChildren(children, env) {
482
- return Array.isArray(children) ? flatten(children.map((child) => mountChildren(child, env))) : mount(children, env);
483
- }
484
- function mount(vnode, env = DEFAULT_ENV) {
485
- if (vnode == null || typeof vnode === "boolean") {
486
- return null;
487
- }
488
- if (vnode instanceof Node) {
489
- return vnode;
490
- }
491
- if (isRenderFunction(vnode)) {
492
- const {
493
- type,
494
- props
495
- } = vnode;
496
- if (type === Fragment) {
497
- const node = document.createDocumentFragment();
498
- if (props.children) {
499
- const children = mountChildren(props.children, env);
500
- insertDom(node, children);
501
- }
502
- return node;
503
- }
504
- const childVNode = type(props);
505
- return mount(childVNode, env);
506
- }
507
- if (isLeaf(vnode)) {
508
- return document.createTextNode(`${vnode}`);
509
- }
510
- if (isElement(vnode)) {
511
- let node;
512
- const {
513
- type,
514
- props
515
- } = vnode;
516
- if (!env.isSvg && type === "svg") {
517
- env = Object.assign({}, env, {
518
- isSvg: true
519
- });
520
- }
521
- if (!env.isSvg) {
522
- node = document.createElement(type);
523
- } else {
524
- node = document.createElementNS(SVG_NS, type);
525
- }
526
- mountAttributes(node, props, env);
527
- if (props.children) {
528
- let childEnv = env;
529
- if (env.isSvg && type === "foreignObject") {
530
- childEnv = Object.assign({}, childEnv, {
531
- isSvg: false
532
- });
533
- }
534
- const children = mountChildren(props.children, childEnv);
535
- if (children != null) insertDom(node, children);
536
- }
537
- const {
538
- ref
539
- } = props;
540
- if (typeof ref === "function") ref(node);
541
- return node;
542
- }
543
- throw new Error("mount: Invalid Vnode!");
544
- }
545
- function mountDom(vnode) {
546
- return mount(vnode);
414
+ return (hash >>> 0).toString(36);
547
415
  }
548
416
  function count(node) {
549
417
  var sum = 0, children = node.children, i = children && children.length;
@@ -1122,11 +990,10 @@
1122
990
  next: lastLows
1123
991
  };
1124
992
  };
1125
- const containerCSS = "/* used for pre-rendering to get the size of each node */\n.markmap-container {\n position: absolute;\n width: 0;\n height: 0;\n top: -100px;\n left: -100px;\n overflow: hidden;\n}\n.markmap-container > .markmap-foreign {\n display: inline-block;\n }\n/* first-child for line wrapping, last-child for max-width detection */\n.markmap-container > .markmap-foreign > div:last-child,\n \n .markmap-container > .markmap-foreign > div:last-child :not(pre) {\n white-space: nowrap;\n }\n.markmap-container > .markmap-foreign > div:last-child code {\n white-space: inherit;\n }\n";
1126
- const css = ".markmap {\n --markmap-max-width: none;\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\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-testing-max {\n max-width: var(--markmap-max-width);\n }\n\n .markmap-foreign-testing-max img {\n max-width: var(--markmap-max-width);\n max-height: none;\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";
993
+ 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\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 }\n\n .markmap-foreign > div > div {\n display: inline-block;\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";
1127
994
  const globalCSS = css;
1128
- function linkWidth(nodeData) {
1129
- const data = nodeData.data;
995
+ const linkShape = d32.linkHorizontal();
996
+ function linkWidth(data) {
1130
997
  return Math.max(4 - 2 * data.state.depth, 1.5);
1131
998
  }
1132
999
  function minBy(numbers, by) {
@@ -1141,7 +1008,6 @@
1141
1008
  constructor(svg, opts) {
1142
1009
  this.options = defaultOptions;
1143
1010
  this.revokers = [];
1144
- this.imgCache = {};
1145
1011
  this.handleZoom = (e) => {
1146
1012
  const { transform } = e;
1147
1013
  this.g.attr("transform", transform);
@@ -1158,7 +1024,7 @@
1158
1024
  this.handleClick = (e, d) => {
1159
1025
  let recursive = this.options.toggleRecursively;
1160
1026
  if (isMacintosh ? e.metaKey : e.ctrlKey) recursive = !recursive;
1161
- this.toggleNode(d.data, recursive);
1027
+ this.toggleNode(d, recursive);
1162
1028
  };
1163
1029
  this.svg = svg.datum ? svg : d32.select(svg);
1164
1030
  this.styleNode = this.svg.append("style");
@@ -1171,13 +1037,14 @@
1171
1037
  this.setOptions(opts);
1172
1038
  this.state = {
1173
1039
  id: this.options.id || this.svg.attr("id") || getId(),
1174
- minX: 0,
1175
- maxX: 0,
1176
- minY: 0,
1177
- maxY: 0
1040
+ rect: { x1: 0, y1: 0, x2: 0, y2: 0 }
1178
1041
  };
1179
1042
  this.g = this.svg.append("g");
1180
- this.debouncedRefresh = debounce(() => this.setData(), 200);
1043
+ this.observer = new ResizeObserver(
1044
+ debounce(() => {
1045
+ this.renderData();
1046
+ }, 100)
1047
+ );
1181
1048
  this.revokers.push(
1182
1049
  refreshHook.tap(() => {
1183
1050
  this.setData();
@@ -1198,7 +1065,7 @@
1198
1065
  const style = this.getStyleContent();
1199
1066
  this.styleNode.text(style);
1200
1067
  }
1201
- toggleNode(data, recursive = false) {
1068
+ async toggleNode(data, recursive = false) {
1202
1069
  var _a, _b;
1203
1070
  const fold = ((_a = data.payload) == null ? void 0 : _a.fold) ? 0 : 1;
1204
1071
  if (recursive) {
@@ -1215,47 +1082,34 @@
1215
1082
  fold: ((_b = data.payload) == null ? void 0 : _b.fold) ? 0 : 1
1216
1083
  };
1217
1084
  }
1218
- this.renderData(data);
1085
+ await this.renderData(data);
1219
1086
  }
1220
- initializeData(node) {
1087
+ _initializeData(node) {
1221
1088
  let nodeId = 0;
1222
- const { color, nodeMinHeight, maxWidth, initialExpandLevel } = this.options;
1223
- const { id } = this.state;
1224
- const container = mountDom(
1225
- /* @__PURE__ */ jsx("div", { className: `markmap-container markmap ${id}-g` })
1226
- );
1227
- const style = mountDom(
1228
- /* @__PURE__ */ jsx("style", { children: [this.getStyleContent(), containerCSS].join("\n") })
1229
- );
1230
- document.body.append(container, style);
1231
- const groupStyle = maxWidth ? `--markmap-max-width: ${maxWidth}px` : "";
1089
+ const { color, initialExpandLevel } = this.options;
1232
1090
  let foldRecursively = 0;
1233
1091
  let depth = 0;
1234
1092
  walkTree(node, (item, next, parent) => {
1235
- var _a, _b, _c;
1093
+ var _a, _b, _c, _d;
1236
1094
  depth += 1;
1237
1095
  item.children = (_a = item.children) == null ? void 0 : _a.map((child) => ({ ...child }));
1238
1096
  nodeId += 1;
1239
- const group = mountDom(
1240
- /* @__PURE__ */ jsx(
1241
- "div",
1242
- {
1243
- className: "markmap-foreign markmap-foreign-testing-max",
1244
- style: groupStyle,
1245
- children: /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: item.content } })
1246
- }
1247
- )
1248
- );
1249
- container.append(group);
1250
1097
  item.state = {
1251
1098
  ...item.state,
1252
1099
  depth,
1253
1100
  id: nodeId,
1254
- el: group.firstChild
1101
+ rect: {
1102
+ x: 0,
1103
+ y: 0,
1104
+ width: 0,
1105
+ height: 0
1106
+ },
1107
+ size: [0, 0]
1255
1108
  };
1256
- item.state.path = [(_b = parent == null ? void 0 : parent.state) == null ? void 0 : _b.path, item.state.id].filter(Boolean).join(".");
1109
+ item.state.key = [(_b = parent == null ? void 0 : parent.state) == null ? void 0 : _b.id, item.state.id].filter(Boolean).join(".") + simpleHash(item.content);
1110
+ item.state.path = [(_c = parent == null ? void 0 : parent.state) == null ? void 0 : _c.path, item.state.id].filter(Boolean).join(".");
1257
1111
  color(item);
1258
- const isFoldRecursively = ((_c = item.payload) == null ? void 0 : _c.fold) === 2;
1112
+ const isFoldRecursively = ((_d = item.payload) == null ? void 0 : _d.fold) === 2;
1259
1113
  if (isFoldRecursively) {
1260
1114
  foldRecursively += 1;
1261
1115
  } else if (foldRecursively || initialExpandLevel >= 0 && item.state.depth >= initialExpandLevel) {
@@ -1265,48 +1119,50 @@
1265
1119
  if (isFoldRecursively) foldRecursively -= 1;
1266
1120
  depth -= 1;
1267
1121
  });
1268
- const nodes = Array.from(container.childNodes).map(
1269
- (group) => group.firstChild
1270
- );
1271
- this._checkImages(container);
1272
- nodes.forEach((node2) => {
1122
+ }
1123
+ _relayout() {
1124
+ if (!this.state.data) return;
1125
+ this.g.selectAll(childSelector("g")).selectAll(
1126
+ childSelector("foreignObject")
1127
+ ).each(function(d) {
1273
1128
  var _a;
1274
- (_a = node2.parentNode) == null ? void 0 : _a.append(node2.cloneNode(true));
1129
+ const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
1130
+ const newSize = [el.scrollWidth, el.scrollHeight];
1131
+ d.state.size = newSize;
1275
1132
  });
1276
- walkTree(node, (item, next, parent) => {
1133
+ const { spacingHorizontal, paddingX, spacingVertical } = this.options;
1134
+ const layout = flextree({}).children((d) => {
1277
1135
  var _a;
1278
- const state = item.state;
1279
- const rect = state.el.getBoundingClientRect();
1280
- item.content = state.el.innerHTML;
1281
- state.size = [
1282
- Math.ceil(rect.width) + 1,
1283
- Math.max(Math.ceil(rect.height), nodeMinHeight)
1284
- ];
1285
- state.key = [(_a = parent == null ? void 0 : parent.state) == null ? void 0 : _a.id, state.id].filter(Boolean).join(".") + // FIXME: find a way to check content hash
1286
- item.content;
1287
- next();
1136
+ if (!((_a = d.payload) == null ? void 0 : _a.fold)) return d.children;
1137
+ }).nodeSize((node) => {
1138
+ const [width, height] = node.data.state.size;
1139
+ return [height, width + (width ? paddingX * 2 : 0) + spacingHorizontal];
1140
+ }).spacing((a, b) => {
1141
+ return a.parent === b.parent ? spacingVertical : spacingVertical * 2;
1288
1142
  });
1289
- container.remove();
1290
- style.remove();
1291
- }
1292
- _checkImages(container) {
1293
- container.querySelectorAll("img").forEach((img) => {
1294
- if (img.width) return;
1295
- const size = this.imgCache[img.src];
1296
- if (size == null ? void 0 : size[0]) {
1297
- [img.width, img.height] = size;
1298
- } else if (!size) {
1299
- this._loadImage(img.src);
1300
- }
1143
+ const tree = layout.hierarchy(this.state.data);
1144
+ layout(tree);
1145
+ const fnodes = tree.descendants();
1146
+ fnodes.forEach((fnode) => {
1147
+ const node = fnode.data;
1148
+ node.state.rect = {
1149
+ x: fnode.y,
1150
+ y: fnode.x,
1151
+ width: fnode.ySize - spacingHorizontal,
1152
+ height: fnode.xSize
1153
+ };
1301
1154
  });
1302
- }
1303
- _loadImage(src) {
1304
- this.imgCache[src] = [0, 0];
1305
- const img = new Image();
1306
- img.src = src;
1307
- img.onload = () => {
1308
- this.imgCache[src] = [img.naturalWidth, img.naturalHeight];
1309
- this.debouncedRefresh();
1155
+ this.state.rect = {
1156
+ x1: d32.min(fnodes, (fnode) => fnode.data.state.rect.x) || 0,
1157
+ y1: d32.min(fnodes, (fnode) => fnode.data.state.rect.y) || 0,
1158
+ x2: d32.max(
1159
+ fnodes,
1160
+ (fnode) => fnode.data.state.rect.x + fnode.data.state.rect.width
1161
+ ) || 0,
1162
+ y2: d32.max(
1163
+ fnodes,
1164
+ (fnode) => fnode.data.state.rect.y + fnode.data.state.rect.height
1165
+ ) || 0
1310
1166
  };
1311
1167
  }
1312
1168
  setOptions(opts) {
@@ -1325,161 +1181,147 @@
1325
1181
  this.svg.on("wheel", null);
1326
1182
  }
1327
1183
  }
1328
- setData(data, opts) {
1184
+ async setData(data, opts) {
1329
1185
  if (opts) this.setOptions(opts);
1330
1186
  if (data) this.state.data = data;
1331
1187
  if (!this.state.data) return;
1332
- this.initializeData(this.state.data);
1188
+ this._initializeData(this.state.data);
1333
1189
  this.updateStyle();
1334
- this.renderData();
1190
+ await this.renderData();
1335
1191
  }
1336
- renderData(originData) {
1192
+ async renderData(originData) {
1193
+ const { paddingX, autoFit, color, maxWidth } = this.options;
1337
1194
  if (!this.state.data) return;
1338
- const { spacingHorizontal, paddingX, spacingVertical, autoFit, color } = this.options;
1339
- const layout = flextree({}).children((d) => {
1195
+ const nodes = [];
1196
+ walkTree(this.state.data, (item, next) => {
1340
1197
  var _a;
1341
- if (!((_a = d.payload) == null ? void 0 : _a.fold)) return d.children;
1342
- }).nodeSize((node2) => {
1343
- const [width, height] = node2.data.state.size;
1344
- return [height, width + (width ? paddingX * 2 : 0) + spacingHorizontal];
1345
- }).spacing((a, b) => {
1346
- return a.parent === b.parent ? spacingVertical : spacingVertical * 2;
1347
- });
1348
- const tree = layout.hierarchy(this.state.data);
1349
- layout(tree);
1350
- const descendants = tree.descendants().reverse();
1351
- const links = tree.links();
1352
- const linkShape = d32.linkHorizontal();
1353
- const minX = d32.min(descendants, (d) => d.x - d.xSize / 2);
1354
- const maxX = d32.max(descendants, (d) => d.x + d.xSize / 2);
1355
- const minY = d32.min(descendants, (d) => d.y);
1356
- const maxY = d32.max(descendants, (d) => d.y + d.ySize - spacingHorizontal);
1357
- Object.assign(this.state, {
1358
- minX,
1359
- maxX,
1360
- minY,
1361
- maxY
1198
+ if (!((_a = item.payload) == null ? void 0 : _a.fold)) next();
1199
+ nodes.push(item);
1362
1200
  });
1363
- if (autoFit) this.fit();
1364
- const origin = originData && descendants.find((item) => item.data === originData) || tree;
1365
- const x0 = origin.data.state.x0 ?? origin.x;
1366
- const y0 = origin.data.state.y0 ?? origin.y;
1367
- const node = this.g.selectAll(childSelector("g")).data(descendants, (d) => d.data.state.key);
1368
- const nodeEnter = node.enter().append("g").attr("data-depth", (d) => d.data.state.depth).attr("data-path", (d) => d.data.state.path).attr(
1369
- "transform",
1370
- (d) => `translate(${y0 + origin.ySize - d.ySize},${x0 + origin.xSize / 2 - d.xSize})`
1371
- );
1372
- const nodeExit = this.transition(node.exit());
1373
- nodeExit.select("line").attr("x1", (d) => d.ySize - spacingHorizontal).attr("x2", (d) => d.ySize - spacingHorizontal);
1374
- nodeExit.select("foreignObject").style("opacity", 0);
1375
- nodeExit.attr(
1376
- "transform",
1377
- (d) => `translate(${origin.y + origin.ySize - d.ySize},${origin.x + origin.xSize / 2 - d.xSize})`
1378
- ).remove();
1379
- const nodeMerge = node.merge(nodeEnter).attr(
1201
+ const origin = originData || this.state.data;
1202
+ const originRect = origin.state.rect;
1203
+ const mmG = this.g.selectAll(childSelector("g")).data(nodes, (d) => d.state.key);
1204
+ const mmGEnter = mmG.enter().append("g").attr("data-depth", (d) => d.state.depth).attr("data-path", (d) => d.state.path);
1205
+ const mmGExit = mmG.exit();
1206
+ const mmGMerge = mmG.merge(mmGEnter).attr(
1380
1207
  "class",
1381
1208
  (d) => {
1382
1209
  var _a;
1383
- return ["markmap-node", ((_a = d.data.payload) == null ? void 0 : _a.fold) && "markmap-fold"].filter(Boolean).join(" ");
1210
+ return ["markmap-node", ((_a = d.payload) == null ? void 0 : _a.fold) && "markmap-fold"].filter(Boolean).join(" ");
1384
1211
  }
1385
1212
  );
1386
- this.transition(nodeMerge).attr(
1387
- "transform",
1388
- (d) => `translate(${d.y},${d.x - d.xSize / 2})`
1213
+ const mmLine = mmGMerge.selectAll(childSelector("line")).data(
1214
+ (d) => [d],
1215
+ (d) => d.state.key
1389
1216
  );
1390
- const line = nodeMerge.selectAll(
1217
+ const mmLineEnter = mmLine.enter().append("line");
1218
+ const mmLineExit = mmGExit.selectAll(
1391
1219
  childSelector("line")
1392
- ).data(
1393
- (d) => [d],
1394
- (d) => d.data.state.key
1395
- ).join(
1396
- (enter) => {
1397
- return enter.append("line").attr("x1", (d) => d.ySize - spacingHorizontal).attr("x2", (d) => d.ySize - spacingHorizontal);
1398
- },
1399
- (update) => update,
1400
- (exit) => exit.remove()
1401
1220
  );
1402
- this.transition(line).attr("x1", -1).attr("x2", (d) => d.ySize - spacingHorizontal + 2).attr("y1", (d) => d.xSize).attr("y2", (d) => d.xSize).attr("stroke", (d) => color(d.data)).attr("stroke-width", linkWidth);
1403
- const circle = nodeMerge.selectAll(
1221
+ const mmLineMerge = mmLine.merge(mmLineEnter);
1222
+ const mmCircle = mmGMerge.selectAll(
1404
1223
  childSelector("circle")
1405
1224
  ).data(
1406
1225
  (d) => {
1407
1226
  var _a;
1408
- return ((_a = d.data.children) == null ? void 0 : _a.length) ? [d] : [];
1227
+ return ((_a = d.children) == null ? void 0 : _a.length) ? [d] : [];
1409
1228
  },
1410
- (d) => d.data.state.key
1229
+ (d) => d.state.key
1411
1230
  ).join(
1412
1231
  (enter) => {
1413
- return enter.append("circle").attr("stroke-width", "1.5").attr("cx", (d) => d.ySize - spacingHorizontal).attr("cy", (d) => d.xSize).attr("r", 0).on("click", (e, d) => this.handleClick(e, d)).on("mousedown", stopPropagation);
1232
+ return enter.append("circle").attr("stroke-width", "1.5").attr("r", 0).on("click", (e, d) => this.handleClick(e, d)).on("mousedown", stopPropagation);
1414
1233
  },
1415
1234
  (update) => update,
1416
1235
  (exit) => exit.remove()
1417
1236
  );
1418
- this.transition(circle).attr("r", 6).attr("cx", (d) => d.ySize - spacingHorizontal).attr("cy", (d) => d.xSize).attr("stroke", (d) => color(d.data)).attr(
1237
+ const observer = this.observer;
1238
+ const mmFo = mmGMerge.selectAll(childSelector("foreignObject")).data(
1239
+ (d) => [d],
1240
+ (d) => d.state.key
1241
+ );
1242
+ 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);
1243
+ mmFoEnter.append("xhtml:div").append("xhtml:div").html((d) => d.content).attr("xmlns", "http://www.w3.org/1999/xhtml");
1244
+ mmFoEnter.each(function() {
1245
+ var _a;
1246
+ const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
1247
+ observer.observe(el);
1248
+ });
1249
+ const mmFoExit = mmGExit.selectAll(
1250
+ childSelector("foreignObject")
1251
+ );
1252
+ mmFoExit.each(function() {
1253
+ var _a;
1254
+ const el = (_a = this.firstChild) == null ? void 0 : _a.firstChild;
1255
+ observer.unobserve(el);
1256
+ });
1257
+ const mmFoMerge = mmFoEnter.merge(mmFo);
1258
+ const links = nodes.flatMap(
1259
+ (node) => {
1260
+ var _a;
1261
+ return ((_a = node.payload) == null ? void 0 : _a.fold) ? [] : node.children.map((child) => ({ source: node, target: child }));
1262
+ }
1263
+ );
1264
+ const mmPath = this.g.selectAll(childSelector("path")).data(links, (d) => d.target.state.key);
1265
+ const mmPathExit = mmPath.exit();
1266
+ 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);
1267
+ const mmPathMerge = mmPathEnter.merge(mmPath);
1268
+ this.svg.style(
1269
+ "--markmap-max-width",
1270
+ maxWidth ? `${maxWidth}px` : null
1271
+ );
1272
+ await new Promise(requestAnimationFrame);
1273
+ this._relayout();
1274
+ this.transition(mmGExit).attr("transform", (d) => {
1275
+ const targetX = originRect.x + originRect.width - d.state.rect.width;
1276
+ const targetY = originRect.y + originRect.height / 2 - d.state.rect.height;
1277
+ return `translate(${targetX},${targetY})`;
1278
+ }).remove();
1279
+ mmGEnter.attr(
1280
+ "transform",
1281
+ (d) => `translate(${originRect.x + originRect.width - d.state.rect.width},${originRect.y + originRect.height / 2 - d.state.rect.height})`
1282
+ );
1283
+ this.transition(mmGMerge).attr(
1284
+ "transform",
1285
+ (d) => `translate(${d.state.rect.x},${d.state.rect.y - d.state.rect.height / 2})`
1286
+ );
1287
+ this.transition(mmLineExit).attr("x1", (d) => d.state.rect.width).attr("x2", (d) => d.state.rect.width);
1288
+ mmLineEnter.attr("x1", (d) => d.state.rect.width).attr("x2", (d) => d.state.rect.width);
1289
+ mmLineMerge.attr("y1", (d) => d.state.rect.height).attr("y2", (d) => d.state.rect.height).attr("stroke", (d) => color(d));
1290
+ this.transition(mmLineMerge).attr("x1", -1).attr("x2", (d) => d.state.rect.width + 2).attr("stroke-width", linkWidth);
1291
+ mmCircle.attr("cx", (d) => d.state.rect.width).attr("cy", (d) => d.state.rect.height).attr("stroke", (d) => color(d)).attr(
1419
1292
  "fill",
1420
1293
  (d) => {
1421
1294
  var _a;
1422
- return ((_a = d.data.payload) == null ? void 0 : _a.fold) && d.data.children ? color(d.data) : "var(--markmap-circle-open-bg)";
1295
+ return ((_a = d.payload) == null ? void 0 : _a.fold) && d.children ? color(d) : "var(--markmap-circle-open-bg)";
1423
1296
  }
1424
1297
  );
1425
- const foreignObject = nodeMerge.selectAll(
1426
- childSelector("foreignObject")
1427
- ).data(
1428
- (d) => [d],
1429
- (d) => d.data.state.key
1430
- ).join(
1431
- (enter) => {
1432
- const fo = enter.append("foreignObject").attr("class", "markmap-foreign").attr("x", paddingX).attr("y", 0).style("opacity", 0).on("mousedown", stopPropagation).on("dblclick", stopPropagation);
1433
- fo.append("xhtml:div").select(function select2(d) {
1434
- const clone = d.data.state.el.cloneNode(true);
1435
- this.replaceWith(clone);
1436
- return clone;
1437
- }).attr("xmlns", "http://www.w3.org/1999/xhtml");
1438
- return fo;
1439
- },
1440
- (update) => update,
1441
- (exit) => exit.remove()
1442
- ).attr(
1443
- "width",
1444
- (d) => Math.max(0, d.ySize - spacingHorizontal - paddingX * 2)
1445
- ).attr("height", (d) => d.xSize);
1446
- this.transition(foreignObject).style("opacity", 1);
1447
- const path = this.g.selectAll(
1448
- childSelector("path")
1449
- ).data(links, (d) => d.target.data.state.key).join(
1450
- (enter) => {
1451
- const source = [
1452
- y0 + origin.ySize - spacingHorizontal,
1453
- x0 + origin.xSize / 2
1454
- ];
1455
- return enter.insert("path", "g").attr("class", "markmap-link").attr("data-depth", (d) => d.target.data.state.depth).attr("data-path", (d) => d.target.data.state.path).attr("d", linkShape({ source, target: source }));
1456
- },
1457
- (update) => update,
1458
- (exit) => {
1459
- const source = [
1460
- origin.y + origin.ySize - spacingHorizontal,
1461
- origin.x + origin.xSize / 2
1462
- ];
1463
- return this.transition(exit).attr("d", linkShape({ source, target: source })).remove();
1464
- }
1298
+ this.transition(mmCircle).attr("r", 6);
1299
+ this.transition(mmFoExit).style("opacity", 0);
1300
+ mmFoMerge.attr("width", (d) => Math.max(0, d.state.rect.width - paddingX * 2)).attr("height", (d) => d.state.rect.height);
1301
+ this.transition(mmFoMerge).style("opacity", 1);
1302
+ const pathOrigin = [
1303
+ originRect.x + originRect.width,
1304
+ originRect.y + originRect.height / 2
1305
+ ];
1306
+ this.transition(mmPathExit).attr("d", linkShape({ source: pathOrigin, target: pathOrigin })).remove();
1307
+ mmPathEnter.attr(
1308
+ "d",
1309
+ linkShape({ source: pathOrigin, target: pathOrigin })
1465
1310
  );
1466
- this.transition(path).attr("stroke", (d) => color(d.target.data)).attr("stroke-width", (d) => linkWidth(d.target)).attr("d", (d) => {
1311
+ this.transition(mmPathMerge).attr("stroke", (d) => color(d.target)).attr("stroke-width", (d) => linkWidth(d.target)).attr("d", (d) => {
1467
1312
  const origSource = d.source;
1468
1313
  const origTarget = d.target;
1469
1314
  const source = [
1470
- origSource.y + origSource.ySize - spacingHorizontal,
1471
- origSource.x + origSource.xSize / 2
1315
+ origSource.state.rect.x + origSource.state.rect.width,
1316
+ origSource.state.rect.y + origSource.state.rect.height / 2
1472
1317
  ];
1473
1318
  const target = [
1474
- origTarget.y,
1475
- origTarget.x + origTarget.xSize / 2
1319
+ origTarget.state.rect.x,
1320
+ origTarget.state.rect.y + origTarget.state.rect.height / 2
1476
1321
  ];
1477
1322
  return linkShape({ source, target });
1478
1323
  });
1479
- descendants.forEach((d) => {
1480
- d.data.state.x0 = d.x;
1481
- d.data.state.y0 = d.y;
1482
- });
1324
+ if (autoFit) this.fit();
1483
1325
  }
1484
1326
  transition(sel) {
1485
1327
  const { duration } = this.options;
@@ -1492,24 +1334,24 @@
1492
1334
  const svgNode = this.svg.node();
1493
1335
  const { width: offsetWidth, height: offsetHeight } = svgNode.getBoundingClientRect();
1494
1336
  const { fitRatio } = this.options;
1495
- const { minX, maxX, minY, maxY } = this.state;
1496
- const naturalWidth = maxY - minY;
1497
- const naturalHeight = maxX - minX;
1337
+ const { x1, y1, x2, y2 } = this.state.rect;
1338
+ const naturalWidth = x2 - x1;
1339
+ const naturalHeight = y2 - y1;
1498
1340
  const scale = Math.min(
1499
1341
  offsetWidth / naturalWidth * fitRatio,
1500
1342
  offsetHeight / naturalHeight * fitRatio,
1501
1343
  maxScale
1502
1344
  );
1503
1345
  const initialZoom = d32.zoomIdentity.translate(
1504
- (offsetWidth - naturalWidth * scale) / 2 - minY * scale,
1505
- (offsetHeight - naturalHeight * scale) / 2 - minX * scale
1346
+ (offsetWidth - naturalWidth * scale) / 2 - x1 * scale,
1347
+ (offsetHeight - naturalHeight * scale) / 2 - y1 * scale
1506
1348
  ).scale(scale);
1507
1349
  return this.transition(this.svg).call(this.zoom.transform, initialZoom).end().catch(noop);
1508
1350
  }
1509
1351
  findElement(node) {
1510
1352
  let result;
1511
1353
  this.g.selectAll(childSelector("g")).each(function walk(d) {
1512
- if (d.data === node) {
1354
+ if (d === node) {
1513
1355
  result = {
1514
1356
  data: d,
1515
1357
  g: this
@@ -1526,16 +1368,15 @@
1526
1368
  const itemData = (_a = this.findElement(node)) == null ? void 0 : _a.data;
1527
1369
  if (!itemData) return;
1528
1370
  const svgNode = this.svg.node();
1529
- const { spacingHorizontal } = this.options;
1530
1371
  const relRect = svgNode.getBoundingClientRect();
1531
1372
  const transform = d32.zoomTransform(svgNode);
1532
1373
  const [left, right] = [
1533
- itemData.y,
1534
- itemData.y + itemData.ySize - spacingHorizontal + 2
1374
+ itemData.state.rect.x,
1375
+ itemData.state.rect.x + itemData.state.rect.width + 2
1535
1376
  ].map((x) => x * transform.k + transform.x);
1536
1377
  const [top, bottom] = [
1537
- itemData.x - itemData.xSize / 2,
1538
- itemData.x + itemData.xSize / 2
1378
+ itemData.state.rect.y - itemData.state.rect.height / 2,
1379
+ itemData.state.rect.y + itemData.state.rect.height / 2
1539
1380
  ].map((y) => y * transform.k + transform.y);
1540
1381
  const pd = {
1541
1382
  left: 0,
@@ -1578,8 +1419,7 @@
1578
1419
  static create(svg, opts, data = null) {
1579
1420
  const mm = new Markmap(svg, opts);
1580
1421
  if (data) {
1581
- mm.setData(data);
1582
- requestAnimationFrame(() => {
1422
+ mm.setData(data).then(() => {
1583
1423
  mm.fit();
1584
1424
  });
1585
1425
  }
@@ -1595,5 +1435,6 @@
1595
1435
  exports.loadCSS = loadCSS;
1596
1436
  exports.loadJS = loadJS;
1597
1437
  exports.refreshHook = refreshHook;
1438
+ exports.simpleHash = simpleHash;
1598
1439
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
1599
1440
  })(this.markmap = this.markmap || {}, d3);