markmap-view 0.14.0 → 0.14.2-alpha.4

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/dist/index.cjs.js CHANGED
@@ -1,6 +1,7 @@
1
- /*! markmap-view v0.14.0 | MIT License */
1
+ /*! markmap-view v0.14.2-alpha.4+569dd11 | MIT License */
2
2
  'use strict';
3
3
 
4
+ var markmapCommon = require('markmap-common');
4
5
  var d3 = require('d3');
5
6
 
6
7
  function _interopNamespace(e) {
@@ -17,209 +18,6 @@ return Object.freeze(n);
17
18
 
18
19
  var d3__namespace = /*#__PURE__*/_interopNamespace(d3);
19
20
 
20
- /*! markmap-common v0.14.0 | MIT License */
21
- class Hook {
22
- constructor() {
23
- this.listeners = [];
24
- }
25
-
26
- tap(fn) {
27
- this.listeners.push(fn);
28
- return () => this.revoke(fn);
29
- }
30
-
31
- revoke(fn) {
32
- const i = this.listeners.indexOf(fn);
33
- if (i >= 0) this.listeners.splice(i, 1);
34
- }
35
-
36
- revokeAll() {
37
- this.listeners.splice(0);
38
- }
39
-
40
- call(...args) {
41
- for (const fn of this.listeners) {
42
- fn(...args);
43
- }
44
- }
45
-
46
- }
47
-
48
- function _extends$1() {
49
- _extends$1 = Object.assign || function (target) {
50
- for (var i = 1; i < arguments.length; i++) {
51
- var source = arguments[i];
52
-
53
- for (var key in source) {
54
- if (Object.prototype.hasOwnProperty.call(source, key)) {
55
- target[key] = source[key];
56
- }
57
- }
58
- }
59
-
60
- return target;
61
- };
62
-
63
- return _extends$1.apply(this, arguments);
64
- }
65
-
66
- const uniqId = Math.random().toString(36).slice(2, 8);
67
- let globalIndex = 0;
68
-
69
- function getId() {
70
- globalIndex += 1;
71
- return `mm-${uniqId}-${globalIndex}`;
72
- }
73
-
74
- function noop() {// noop
75
- }
76
-
77
- function walkTree(tree, callback, key = 'children') {
78
- const walk = (item, parent) => callback(item, () => {
79
- var _item$key;
80
-
81
- (_item$key = item[key]) == null ? void 0 : _item$key.forEach(child => {
82
- walk(child, item);
83
- });
84
- }, parent);
85
-
86
- walk(tree);
87
- }
88
-
89
- function arrayFrom(arrayLike) {
90
- if (Array.from) return Array.from(arrayLike);
91
- const array = [];
92
-
93
- for (let i = 0; i < arrayLike.length; i += 1) {
94
- array.push(arrayLike[i]);
95
- }
96
-
97
- return array;
98
- }
99
-
100
- function addClass(className, ...rest) {
101
- const classList = (className || '').split(' ').filter(Boolean);
102
- rest.forEach(item => {
103
- if (item && classList.indexOf(item) < 0) classList.push(item);
104
- });
105
- return classList.join(' ');
106
- }
107
-
108
- function childSelector(filter) {
109
- if (typeof filter === 'string') {
110
- const tagName = filter;
111
-
112
- filter = el => el.tagName === tagName;
113
- }
114
-
115
- const filterFn = filter;
116
- return function selector() {
117
- let nodes = arrayFrom(this.childNodes);
118
- if (filterFn) nodes = nodes.filter(node => filterFn(node));
119
- return nodes;
120
- };
121
- }
122
-
123
- function memoize(fn) {
124
- const cache = {};
125
- return function memoized(...args) {
126
- const key = `${args[0]}`;
127
- let data = cache[key];
128
-
129
- if (!data) {
130
- data = {
131
- value: fn(...args)
132
- };
133
- cache[key] = data;
134
- }
135
-
136
- return data.value;
137
- };
138
- }
139
-
140
- function createElement(tagName, props, attrs) {
141
- const el = document.createElement(tagName);
142
-
143
- if (props) {
144
- Object.entries(props).forEach(([key, value]) => {
145
- el[key] = value;
146
- });
147
- }
148
-
149
- if (attrs) {
150
- Object.entries(attrs).forEach(([key, value]) => {
151
- el.setAttribute(key, value);
152
- });
153
- }
154
-
155
- return el;
156
- }
157
-
158
- const memoizedPreloadJS = memoize(url => {
159
- document.head.append(createElement('link', {
160
- rel: 'preload',
161
- as: 'script',
162
- href: url
163
- }));
164
- });
165
-
166
- function loadJSItem(item, context) {
167
- if (item.type === 'script') {
168
- return new Promise((resolve, reject) => {
169
- var _item$data;
170
-
171
- document.head.append(createElement('script', _extends$1({}, item.data, {
172
- onload: resolve,
173
- onerror: reject
174
- }))); // Run inline script synchronously
175
-
176
- if (!((_item$data = item.data) != null && _item$data.src)) resolve();
177
- });
178
- }
179
-
180
- if (item.type === 'iife') {
181
- const {
182
- fn,
183
- getParams
184
- } = item.data;
185
- fn(...((getParams == null ? void 0 : getParams(context)) || []));
186
- }
187
- }
188
-
189
- function loadCSSItem(item) {
190
- if (item.type === 'style') {
191
- document.head.append(createElement('style', {
192
- textContent: item.data
193
- }));
194
- } else if (item.type === 'stylesheet') {
195
- document.head.append(createElement('link', _extends$1({
196
- rel: 'stylesheet'
197
- }, item.data)));
198
- }
199
- }
200
-
201
- async function loadJS(items, context) {
202
- const needPreload = items.filter(item => {
203
- var _item$data2;
204
-
205
- return item.type === 'script' && ((_item$data2 = item.data) == null ? void 0 : _item$data2.src);
206
- });
207
- if (needPreload.length > 1) needPreload.forEach(item => memoizedPreloadJS(item.data.src));
208
- context = _extends$1({
209
- getMarkmap: () => window.markmap
210
- }, context);
211
-
212
- for (const item of items) {
213
- await loadJSItem(item, context);
214
- }
215
- }
216
-
217
- function loadCSS(items) {
218
- for (const item of items) {
219
- loadCSSItem(item);
220
- }
221
- }
222
-
223
21
  function _extends() {
224
22
  _extends = Object.assign || function (target) {
225
23
  for (var i = 1; i < arguments.length; i++) {
@@ -1230,7 +1028,7 @@ function linkWidth(nodeData) {
1230
1028
  }
1231
1029
 
1232
1030
  function adjustSpacing(tree, spacing) {
1233
- walkTree(tree, (d, next) => {
1031
+ markmapCommon.walkTree(tree, (d, next) => {
1234
1032
  d.ySizeInner = d.ySize - spacing;
1235
1033
  d.y += spacing;
1236
1034
  next();
@@ -1248,7 +1046,7 @@ function stopPropagation(e) {
1248
1046
 
1249
1047
  function createViewHooks() {
1250
1048
  return {
1251
- transformHtml: new Hook()
1049
+ transformHtml: new markmapCommon.Hook()
1252
1050
  };
1253
1051
  }
1254
1052
  /**
@@ -1256,7 +1054,7 @@ function createViewHooks() {
1256
1054
  */
1257
1055
 
1258
1056
 
1259
- const refreshHook = new Hook();
1057
+ const refreshHook = new markmapCommon.Hook();
1260
1058
  const defaultColorFn = d3__namespace.scaleOrdinal(d3__namespace.schemeCategory10);
1261
1059
  const isMacintosh = typeof navigator !== 'undefined' && navigator.userAgent.includes('Macintosh');
1262
1060
  class Markmap {
@@ -1278,11 +1076,10 @@ class Markmap {
1278
1076
  }).on('zoom', this.handleZoom);
1279
1077
  this.setOptions(opts);
1280
1078
  this.state = {
1281
- id: this.options.id || this.svg.attr('id') || getId()
1079
+ id: this.options.id || this.svg.attr('id') || markmapCommon.getId()
1282
1080
  };
1283
1081
  this.g = this.svg.append('g');
1284
1082
  this.updateStyle();
1285
- this.svg.call(this.zoom).on('wheel', this.handlePan);
1286
1083
  this.revokers.push(refreshHook.tap(() => {
1287
1084
  this.setData();
1288
1085
  }));
@@ -1300,7 +1097,7 @@ class Markmap {
1300
1097
  }
1301
1098
 
1302
1099
  updateStyle() {
1303
- this.svg.attr('class', addClass(this.svg.attr('class'), 'markmap', this.state.id));
1100
+ this.svg.attr('class', markmapCommon.addClass(this.svg.attr('class'), 'markmap', this.state.id));
1304
1101
  const style = this.getStyleContent();
1305
1102
  this.styleNode.text(style);
1306
1103
  }
@@ -1351,8 +1148,8 @@ class Markmap {
1351
1148
  document.body.append(container, style);
1352
1149
  const groupStyle = maxWidth ? `max-width: ${maxWidth}px` : '';
1353
1150
  let foldRecursively = 0;
1354
- walkTree(node, (item, next) => {
1355
- var _item$children, _item$payload;
1151
+ markmapCommon.walkTree(node, (item, next, parent) => {
1152
+ var _item$children, _parent$state, _item$payload;
1356
1153
 
1357
1154
  item.children = (_item$children = item.children) == null ? void 0 : _item$children.map(child => _extends({}, child));
1358
1155
  nodeId += 1;
@@ -1368,7 +1165,8 @@ class Markmap {
1368
1165
  container.append(group);
1369
1166
  item.state = _extends({}, item.state, {
1370
1167
  id: nodeId,
1371
- el: group.firstChild
1168
+ el: group.firstChild,
1169
+ path: [parent == null ? void 0 : (_parent$state = parent.state) == null ? void 0 : _parent$state.path, item.state.id].filter(Boolean).join('.')
1372
1170
  });
1373
1171
  color(item); // preload colors
1374
1172
 
@@ -1385,7 +1183,7 @@ class Markmap {
1385
1183
  next();
1386
1184
  if (isFoldRecursively) foldRecursively -= 1;
1387
1185
  });
1388
- const nodes = arrayFrom(container.childNodes).map(group => group.firstChild);
1186
+ const nodes = markmapCommon.arrayFrom(container.childNodes).map(group => group.firstChild);
1389
1187
  this.viewHooks.transformHtml.call(this, nodes); // Clone the rendered HTML and set `white-space: nowrap` to it to detect its max-width.
1390
1188
  // The parent node will have a width of the max-width and the original content without
1391
1189
  // `white-space: nowrap` gets re-layouted, then we will get the expected layout, with
@@ -1394,13 +1192,12 @@ class Markmap {
1394
1192
  nodes.forEach(node => {
1395
1193
  node.parentNode.append(node.cloneNode(true));
1396
1194
  });
1397
- walkTree(node, (item, next, parent) => {
1398
- var _parent$state, _parent$state2;
1195
+ markmapCommon.walkTree(node, (item, next, parent) => {
1196
+ var _parent$state2;
1399
1197
 
1400
1198
  const rect = item.state.el.getBoundingClientRect();
1401
1199
  item.content = item.state.el.innerHTML;
1402
1200
  item.state.size = [Math.ceil(rect.width) + 1, Math.max(Math.ceil(rect.height), nodeMinHeight)];
1403
- item.state.path = [parent == null ? void 0 : (_parent$state = parent.state) == null ? void 0 : _parent$state.path, item.state.id].filter(Boolean).join('.');
1404
1201
  item.state.key = [parent == null ? void 0 : (_parent$state2 = parent.state) == null ? void 0 : _parent$state2.id, item.state.id].filter(Boolean).join('.') + // FIXME: find a way to check content hash
1405
1202
  item.content;
1406
1203
  next();
@@ -1411,6 +1208,14 @@ class Markmap {
1411
1208
 
1412
1209
  setOptions(opts) {
1413
1210
  this.options = _extends({}, Markmap.defaultOptions, opts);
1211
+
1212
+ if (this.options.zoom) {
1213
+ this.svg.call(this.zoom);
1214
+ } else {
1215
+ this.svg.on('.zoom', null);
1216
+ }
1217
+
1218
+ this.svg.on('wheel', this.options.pan ? this.handlePan : null);
1414
1219
  }
1415
1220
 
1416
1221
  setData(data, opts) {
@@ -1462,7 +1267,7 @@ class Markmap {
1462
1267
  const x0 = (_origin$data$state$x = origin.data.state.x0) != null ? _origin$data$state$x : origin.x;
1463
1268
  const y0 = (_origin$data$state$y = origin.data.state.y0) != null ? _origin$data$state$y : origin.y; // Update the nodes
1464
1269
 
1465
- const node = this.g.selectAll(childSelector('g')).data(descendants, d => d.data.state.key);
1270
+ const node = this.g.selectAll(markmapCommon.childSelector('g')).data(descendants, d => d.data.state.key);
1466
1271
  const nodeEnter = node.enter().append('g').attr('data-depth', d => d.data.depth).attr('data-path', d => d.data.state.path).attr('transform', d => `translate(${y0 + origin.ySizeInner - d.ySizeInner},${x0 + origin.xSize / 2 - d.xSize})`);
1467
1272
  const nodeExit = this.transition(node.exit());
1468
1273
  nodeExit.select('line').attr('x1', d => d.ySizeInner).attr('x2', d => d.ySizeInner);
@@ -1475,12 +1280,12 @@ class Markmap {
1475
1280
  });
1476
1281
  this.transition(nodeMerge).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`); // Update lines under the content
1477
1282
 
1478
- const line = nodeMerge.selectAll(childSelector('line')).data(d => [d], d => d.data.state.key).join(enter => {
1283
+ const line = nodeMerge.selectAll(markmapCommon.childSelector('line')).data(d => [d], d => d.data.state.key).join(enter => {
1479
1284
  return enter.append('line').attr('x1', d => d.ySizeInner).attr('x2', d => d.ySizeInner);
1480
1285
  }, update => update, exit => exit.remove());
1481
1286
  this.transition(line).attr('x1', -1).attr('x2', d => d.ySizeInner + 2).attr('y1', d => d.xSize).attr('y2', d => d.xSize).attr('stroke', d => color(d.data)).attr('stroke-width', linkWidth); // Circle to link to children of the node
1482
1287
 
1483
- const circle = nodeMerge.selectAll(childSelector('circle')).data(d => d.data.children ? [d] : [], d => d.data.state.key).join(enter => {
1288
+ const circle = nodeMerge.selectAll(markmapCommon.childSelector('circle')).data(d => d.data.children ? [d] : [], d => d.data.state.key).join(enter => {
1484
1289
  return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('r', 0).on('click', (e, d) => this.handleClick(e, d));
1485
1290
  }, update => update, exit => exit.remove());
1486
1291
  this.transition(circle).attr('r', 6).attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('stroke', d => color(d.data)).attr('fill', d => {
@@ -1488,7 +1293,7 @@ class Markmap {
1488
1293
 
1489
1294
  return (_d$data$payload2 = d.data.payload) != null && _d$data$payload2.fold && d.data.children ? color(d.data) : '#fff';
1490
1295
  });
1491
- const foreignObject = nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.state.key).join(enter => {
1296
+ const foreignObject = nodeMerge.selectAll(markmapCommon.childSelector('foreignObject')).data(d => [d], d => d.data.state.key).join(enter => {
1492
1297
  const fo = enter.append('foreignObject').attr('class', 'markmap-foreign').attr('x', paddingX).attr('y', 0).style('opacity', 0).on('mousedown', stopPropagation).on('dblclick', stopPropagation);
1493
1298
  fo.append('xhtml:div').select(function select(d) {
1494
1299
  const clone = d.data.state.el.cloneNode(true);
@@ -1499,7 +1304,7 @@ class Markmap {
1499
1304
  }, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - paddingX * 2)).attr('height', d => d.xSize);
1500
1305
  this.transition(foreignObject).style('opacity', 1); // Update the links
1501
1306
 
1502
- const path = this.g.selectAll(childSelector('path')).data(links, d => d.target.data.state.key).join(enter => {
1307
+ const path = this.g.selectAll(markmapCommon.childSelector('path')).data(links, d => d.target.data.state.key).join(enter => {
1503
1308
  const source = [y0 + origin.ySizeInner, x0 + origin.xSize / 2];
1504
1309
  return enter.insert('path', 'g').attr('class', 'markmap-link').attr('data-depth', d => d.target.data.depth).attr('data-path', d => d.target.data.state.path).attr('d', linkShape({
1505
1310
  source,
@@ -1556,7 +1361,7 @@ class Markmap {
1556
1361
  const naturalHeight = maxX - minX;
1557
1362
  const scale = Math.min(offsetWidth / naturalWidth * fitRatio, offsetHeight / naturalHeight * fitRatio, 2);
1558
1363
  const initialZoom = d3__namespace.zoomIdentity.translate((offsetWidth - naturalWidth * scale) / 2 - minY * scale, (offsetHeight - naturalHeight * scale) / 2 - minX * scale).scale(scale);
1559
- return this.transition(this.svg).call(this.zoom.transform, initialZoom).end().catch(noop);
1364
+ return this.transition(this.svg).call(this.zoom.transform, initialZoom).end().catch(markmapCommon.noop);
1560
1365
  }
1561
1366
  /**
1562
1367
  * Pan the content to make the provided node visible in the viewport.
@@ -1566,7 +1371,7 @@ class Markmap {
1566
1371
  async ensureView(node, padding) {
1567
1372
  let g;
1568
1373
  let itemData;
1569
- this.g.selectAll(childSelector('g')).each(function walk(d) {
1374
+ this.g.selectAll(markmapCommon.childSelector('g')).each(function walk(d) {
1570
1375
  if (d.data === node) {
1571
1376
  g = this;
1572
1377
  itemData = d;
@@ -1593,7 +1398,7 @@ class Markmap {
1593
1398
 
1594
1399
  if (dx || dy) {
1595
1400
  const newTransform = transform.translate(dx, dy);
1596
- return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(noop);
1401
+ return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(markmapCommon.noop);
1597
1402
  }
1598
1403
  }
1599
1404
  /**
@@ -1611,7 +1416,7 @@ class Markmap {
1611
1416
  const halfHeight = offsetHeight / 2;
1612
1417
  const transform = d3__namespace.zoomTransform(svgNode);
1613
1418
  const newTransform = transform.translate((halfWidth - transform.x) * (1 - scale) / transform.k, (halfHeight - transform.y) * (1 - scale) / transform.k).scale(scale);
1614
- return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(noop);
1419
+ return this.transition(this.svg).call(this.zoom.transform, newTransform).end().catch(markmapCommon.noop);
1615
1420
  }
1616
1421
 
1617
1422
  destroy() {
@@ -1636,7 +1441,7 @@ class Markmap {
1636
1441
  }
1637
1442
  Markmap.defaultOptions = {
1638
1443
  autoFit: false,
1639
- color: node => defaultColorFn(`${node.state.id}`),
1444
+ color: node => defaultColorFn(`${node.state.path}`),
1640
1445
  duration: 500,
1641
1446
  embedGlobalCSS: true,
1642
1447
  fitRatio: 0.95,
@@ -1646,13 +1451,16 @@ Markmap.defaultOptions = {
1646
1451
  scrollForPan: isMacintosh,
1647
1452
  spacingHorizontal: 80,
1648
1453
  spacingVertical: 5,
1649
- initialExpandLevel: -1
1454
+ initialExpandLevel: -1,
1455
+ zoom: true,
1456
+ pan: true
1650
1457
  };
1651
1458
  function deriveOptions(jsonOptions) {
1652
1459
  const opts = {};
1653
1460
  jsonOptions || (jsonOptions = {});
1654
1461
  const {
1655
- color
1462
+ color,
1463
+ colorFreezeLevel
1656
1464
  } = jsonOptions;
1657
1465
 
1658
1466
  if ((color == null ? void 0 : color.length) === 1) {
@@ -1662,7 +1470,20 @@ function deriveOptions(jsonOptions) {
1662
1470
  } else if (color != null && color.length) {
1663
1471
  const colorFn = d3__namespace.scaleOrdinal(color);
1664
1472
 
1665
- opts.color = node => colorFn(`${node.state.id}`);
1473
+ opts.color = node => colorFn(`${node.state.path}`);
1474
+ }
1475
+
1476
+ if (colorFreezeLevel) {
1477
+ const color = opts.color || Markmap.defaultOptions.color;
1478
+
1479
+ opts.color = node => {
1480
+ node = _extends({}, node, {
1481
+ state: _extends({}, node.state, {
1482
+ path: node.state.path.split('.').slice(0, colorFreezeLevel + 1).join('.')
1483
+ })
1484
+ });
1485
+ return color(node);
1486
+ };
1666
1487
  }
1667
1488
 
1668
1489
  const numberKeys = ['duration', 'maxWidth', 'initialExpandLevel'];
@@ -1670,13 +1491,18 @@ function deriveOptions(jsonOptions) {
1670
1491
  const value = jsonOptions[key];
1671
1492
  if (typeof value === 'number') opts[key] = value;
1672
1493
  });
1494
+ const booleanKeys = ['zoom', 'pan'];
1495
+ booleanKeys.forEach(key => {
1496
+ const value = jsonOptions[key];
1497
+ if (value != null) opts[key] = !!value;
1498
+ });
1673
1499
  return opts;
1674
1500
  }
1675
1501
 
1502
+ exports.loadCSS = markmapCommon.loadCSS;
1503
+ exports.loadJS = markmapCommon.loadJS;
1676
1504
  exports.Markmap = Markmap;
1677
1505
  exports.defaultColorFn = defaultColorFn;
1678
1506
  exports.deriveOptions = deriveOptions;
1679
1507
  exports.globalCSS = globalCSS;
1680
- exports.loadCSS = loadCSS;
1681
- exports.loadJS = loadJS;
1682
1508
  exports.refreshHook = refreshHook;