markmap-view 0.2.7 → 0.13.1

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.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! markmap-view v0.2.7 | MIT License */
1
+ /*! markmap-view v0.13.1 | MIT License */
2
2
  (function (exports, d3) {
3
3
  'use strict';
4
4
 
@@ -16,6 +16,34 @@ return Object.freeze(n);
16
16
 
17
17
  var d3__namespace = /*#__PURE__*/_interopNamespace(d3);
18
18
 
19
+ /*! markmap-common v0.13.0 | MIT License */
20
+ class Hook {
21
+ constructor() {
22
+ this.listeners = [];
23
+ }
24
+
25
+ tap(fn) {
26
+ this.listeners.push(fn);
27
+ return () => this.revoke(fn);
28
+ }
29
+
30
+ revoke(fn) {
31
+ const i = this.listeners.indexOf(fn);
32
+ if (i >= 0) this.listeners.splice(i, 1);
33
+ }
34
+
35
+ revokeAll() {
36
+ this.listeners.splice(0);
37
+ }
38
+
39
+ call(...args) {
40
+ for (const fn of this.listeners) {
41
+ fn(...args);
42
+ }
43
+ }
44
+
45
+ }
46
+
19
47
  function _extends$1() {
20
48
  _extends$1 = Object.assign || function (target) {
21
49
  for (var i = 1; i < arguments.length; i++) {
@@ -34,6 +62,181 @@ function _extends$1() {
34
62
  return _extends$1.apply(this, arguments);
35
63
  }
36
64
 
65
+ const uniqId = Math.random().toString(36).slice(2, 8);
66
+ let globalIndex = 0;
67
+
68
+ function getId() {
69
+ globalIndex += 1;
70
+ return `mm-${uniqId}-${globalIndex}`;
71
+ }
72
+
73
+ function noop() {// noop
74
+ }
75
+
76
+ function walkTree(tree, callback, key = 'children') {
77
+ const walk = (item, parent) => callback(item, () => {
78
+ var _item$key;
79
+
80
+ (_item$key = item[key]) == null ? void 0 : _item$key.forEach(child => {
81
+ walk(child, item);
82
+ });
83
+ }, parent);
84
+
85
+ walk(tree);
86
+ }
87
+
88
+ function arrayFrom(arrayLike) {
89
+ if (Array.from) return Array.from(arrayLike);
90
+ const array = [];
91
+
92
+ for (let i = 0; i < arrayLike.length; i += 1) {
93
+ array.push(arrayLike[i]);
94
+ }
95
+
96
+ return array;
97
+ }
98
+
99
+ function addClass(className, ...rest) {
100
+ const classList = (className || '').split(' ').filter(Boolean);
101
+ rest.forEach(item => {
102
+ if (item && classList.indexOf(item) < 0) classList.push(item);
103
+ });
104
+ return classList.join(' ');
105
+ }
106
+
107
+ function childSelector(filter) {
108
+ if (typeof filter === 'string') {
109
+ const tagName = filter;
110
+
111
+ filter = el => el.tagName === tagName;
112
+ }
113
+
114
+ const filterFn = filter;
115
+ return function selector() {
116
+ let nodes = arrayFrom(this.childNodes);
117
+ if (filterFn) nodes = nodes.filter(node => filterFn(node));
118
+ return nodes;
119
+ };
120
+ }
121
+
122
+ function memoize(fn) {
123
+ const cache = {};
124
+ return function memoized(...args) {
125
+ const key = `${args[0]}`;
126
+ let data = cache[key];
127
+
128
+ if (!data) {
129
+ data = {
130
+ value: fn(...args)
131
+ };
132
+ cache[key] = data;
133
+ }
134
+
135
+ return data.value;
136
+ };
137
+ }
138
+
139
+ function createElement(tagName, props, attrs) {
140
+ const el = document.createElement(tagName);
141
+
142
+ if (props) {
143
+ Object.entries(props).forEach(([key, value]) => {
144
+ el[key] = value;
145
+ });
146
+ }
147
+
148
+ if (attrs) {
149
+ Object.entries(attrs).forEach(([key, value]) => {
150
+ el.setAttribute(key, value);
151
+ });
152
+ }
153
+
154
+ return el;
155
+ }
156
+
157
+ const memoizedPreloadJS = memoize(url => {
158
+ document.head.append(createElement('link', {
159
+ rel: 'preload',
160
+ as: 'script',
161
+ href: url
162
+ }));
163
+ });
164
+
165
+ function loadJSItem(item, context) {
166
+ if (item.type === 'script') {
167
+ return new Promise((resolve, reject) => {
168
+ var _item$data;
169
+
170
+ document.head.append(createElement('script', _extends$1({}, item.data, {
171
+ onload: resolve,
172
+ onerror: reject
173
+ }))); // Run inline script synchronously
174
+
175
+ if (!((_item$data = item.data) != null && _item$data.src)) resolve();
176
+ });
177
+ }
178
+
179
+ if (item.type === 'iife') {
180
+ const {
181
+ fn,
182
+ getParams
183
+ } = item.data;
184
+ fn(...((getParams == null ? void 0 : getParams(context)) || []));
185
+ }
186
+ }
187
+
188
+ function loadCSSItem(item) {
189
+ if (item.type === 'style') {
190
+ document.head.append(createElement('style', {
191
+ textContent: item.data
192
+ }));
193
+ } else if (item.type === 'stylesheet') {
194
+ document.head.append(createElement('link', _extends$1({
195
+ rel: 'stylesheet'
196
+ }, item.data)));
197
+ }
198
+ }
199
+
200
+ async function loadJS(items, context) {
201
+ const needPreload = items.filter(item => {
202
+ var _item$data2;
203
+
204
+ return item.type === 'script' && ((_item$data2 = item.data) == null ? void 0 : _item$data2.src);
205
+ });
206
+ if (needPreload.length > 1) needPreload.forEach(item => memoizedPreloadJS(item.data.src));
207
+ context = _extends$1({
208
+ getMarkmap: () => window.markmap
209
+ }, context);
210
+
211
+ for (const item of items) {
212
+ await loadJSItem(item, context);
213
+ }
214
+ }
215
+
216
+ function loadCSS(items) {
217
+ for (const item of items) {
218
+ loadCSSItem(item);
219
+ }
220
+ }
221
+
222
+ function _extends() {
223
+ _extends = Object.assign || function (target) {
224
+ for (var i = 1; i < arguments.length; i++) {
225
+ var source = arguments[i];
226
+
227
+ for (var key in source) {
228
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
229
+ target[key] = source[key];
230
+ }
231
+ }
232
+ }
233
+
234
+ return target;
235
+ };
236
+
237
+ return _extends.apply(this, arguments);
238
+ }
239
+
37
240
  function count(node) {
38
241
  var sum = 0,
39
242
  children = node.children,
@@ -208,7 +411,7 @@ function node_links () {
208
411
  }
209
412
 
210
413
  function hierarchy(data, children) {
211
- var root = new Node(data),
414
+ var root = new Node$1(data),
212
415
  valued = +data.value && (root.value = data.value),
213
416
  node,
214
417
  nodes = [root],
@@ -225,7 +428,7 @@ function hierarchy(data, children) {
225
428
  node.children = new Array(n);
226
429
 
227
430
  for (i = n - 1; i >= 0; --i) {
228
- nodes.push(child = node.children[i] = new Node(childs[i]));
431
+ nodes.push(child = node.children[i] = new Node$1(childs[i]));
229
432
  child.parent = node;
230
433
  child.depth = node.depth + 1;
231
434
  }
@@ -252,13 +455,13 @@ function computeHeight(node) {
252
455
 
253
456
  do node.height = height; while ((node = node.parent) && node.height < ++height);
254
457
  }
255
- function Node(data) {
458
+ function Node$1(data) {
256
459
  this.data = data;
257
460
  this.depth = this.height = 0;
258
461
  this.parent = null;
259
462
  }
260
- Node.prototype = hierarchy.prototype = {
261
- constructor: Node,
463
+ Node$1.prototype = hierarchy.prototype = {
464
+ constructor: Node$1,
262
465
  count: node_count,
263
466
  each: node_each,
264
467
  eachAfter: node_eachAfter,
@@ -784,212 +987,245 @@ const updateLows = (lowY, index, lastLows) => {
784
987
  };
785
988
  };
786
989
 
787
- /*! markmap-common v0.1.6 | MIT License */
788
- class Hook {
789
- constructor() {
790
- this.listeners = [];
791
- }
990
+ /*! @gera2ld/jsx-dom v2.1.1 | ISC License */
991
+ var VTYPE_ELEMENT = 1;
992
+ var VTYPE_FUNCTION = 2;
993
+ var MOUNT_SINGLE = 1;
994
+ var MOUNT_ARRAY = 4;
995
+ var SVG_NS = 'http://www.w3.org/2000/svg';
996
+ var XLINK_NS = 'http://www.w3.org/1999/xlink';
997
+ var NS_ATTRS = {
998
+ show: XLINK_NS,
999
+ actuate: XLINK_NS,
1000
+ href: XLINK_NS
1001
+ };
792
1002
 
793
- tap(fn) {
794
- this.listeners.push(fn);
795
- return () => this.revoke(fn);
796
- }
1003
+ var isLeaf = function isLeaf(c) {
1004
+ return typeof c === 'string' || typeof c === 'number';
1005
+ };
797
1006
 
798
- revoke(fn) {
799
- const i = this.listeners.indexOf(fn);
800
- if (i >= 0) this.listeners.splice(i, 1);
801
- }
1007
+ var isElement = function isElement(c) {
1008
+ return (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
1009
+ };
802
1010
 
803
- revokeAll() {
804
- this.listeners.splice(0);
1011
+ var isRenderFunction = function isRenderFunction(c) {
1012
+ return (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
1013
+ };
1014
+
1015
+ function jsx(type, props) {
1016
+ var vtype;
1017
+ if (typeof type === 'string') vtype = VTYPE_ELEMENT;else if (typeof type === 'function') vtype = VTYPE_FUNCTION;else throw new Error('Invalid VNode type');
1018
+ return {
1019
+ vtype: vtype,
1020
+ type: type,
1021
+ props: props
1022
+ };
1023
+ }
1024
+
1025
+ function Fragment(props) {
1026
+ return props.children;
1027
+ }
1028
+
1029
+ var DEFAULT_ENV = {
1030
+ isSvg: false
1031
+ };
1032
+
1033
+ function insertDom(parent, ref) {
1034
+ if (ref.type === MOUNT_SINGLE) {
1035
+ if (ref.node != null) parent.append(ref.node);
1036
+ } else if (ref.type === MOUNT_ARRAY) {
1037
+ ref.children.forEach(function (ch) {
1038
+ insertDom(parent, ch);
1039
+ });
1040
+ } else {
1041
+ throw new Error("Unkown ref type " + JSON.stringify(ref));
805
1042
  }
1043
+ }
806
1044
 
807
- call(...args) {
808
- for (const fn of this.listeners) {
809
- fn(...args);
1045
+ function mountAttributes(domElement, props, env) {
1046
+ for (var key in props) {
1047
+ if (key === 'key' || key === 'children' || key === 'ref') continue;
1048
+
1049
+ if (key === 'dangerouslySetInnerHTML') {
1050
+ domElement.innerHTML = props[key].__html;
1051
+ } else if (key === 'innerHTML' || key === 'textContent' || key === 'innerText') {
1052
+ domElement[key] = props[key];
1053
+ } else if (key.startsWith('on')) {
1054
+ domElement[key.toLowerCase()] = props[key];
1055
+ } else {
1056
+ setDOMAttribute(domElement, key, props[key], env.isSvg);
810
1057
  }
811
1058
  }
812
-
813
1059
  }
814
1060
 
815
- function _extends() {
816
- _extends = Object.assign || function (target) {
817
- for (var i = 1; i < arguments.length; i++) {
818
- var source = arguments[i];
1061
+ var attrMap = {
1062
+ className: 'class',
1063
+ labelFor: 'for'
1064
+ };
819
1065
 
820
- for (var key in source) {
821
- if (Object.prototype.hasOwnProperty.call(source, key)) {
822
- target[key] = source[key];
823
- }
824
- }
825
- }
1066
+ function setDOMAttribute(el, attr, value, isSVG) {
1067
+ attr = attrMap[attr] || attr;
826
1068
 
827
- return target;
828
- };
1069
+ if (value === true) {
1070
+ el.setAttribute(attr, '');
1071
+ } else if (value === false) {
1072
+ el.removeAttribute(attr);
1073
+ } else {
1074
+ var namespace = isSVG ? NS_ATTRS[attr] : undefined;
829
1075
 
830
- return _extends.apply(this, arguments);
1076
+ if (namespace !== undefined) {
1077
+ el.setAttributeNS(namespace, attr, value);
1078
+ } else {
1079
+ el.setAttribute(attr, value);
1080
+ }
1081
+ }
831
1082
  }
832
1083
 
833
- const uniqId = Math.random().toString(36).slice(2, 8);
834
- let globalIndex = 0;
1084
+ function mount(vnode, env) {
1085
+ if (env === void 0) {
1086
+ env = DEFAULT_ENV;
1087
+ }
835
1088
 
836
- function getId() {
837
- globalIndex += 1;
838
- return `mm-${uniqId}-${globalIndex}`;
839
- }
1089
+ if (vnode == null || typeof vnode === 'boolean') {
1090
+ return {
1091
+ type: MOUNT_SINGLE,
1092
+ node: null
1093
+ };
1094
+ }
840
1095
 
841
- function noop() {// noop
842
- }
1096
+ if (vnode instanceof Node) {
1097
+ return {
1098
+ type: MOUNT_SINGLE,
1099
+ node: vnode
1100
+ };
1101
+ }
843
1102
 
844
- function walkTree(tree, callback, key = 'c') {
845
- const walk = (item, parent) => callback(item, () => {
846
- var _item$key;
1103
+ if (isRenderFunction(vnode)) {
1104
+ var _ref = vnode,
1105
+ type = _ref.type,
1106
+ props = _ref.props;
847
1107
 
848
- (_item$key = item[key]) == null ? void 0 : _item$key.forEach(child => {
849
- walk(child, item);
850
- });
851
- }, parent);
1108
+ if (type === Fragment) {
1109
+ var node = document.createDocumentFragment();
852
1110
 
853
- walk(tree);
854
- }
1111
+ if (props.children) {
1112
+ var childrenRef = mount(props.children, env);
1113
+ insertDom(node, childrenRef);
1114
+ }
855
1115
 
856
- function arrayFrom(arrayLike) {
857
- if (Array.from) return Array.from(arrayLike);
858
- const array = [];
1116
+ return {
1117
+ type: MOUNT_SINGLE,
1118
+ node: node
1119
+ };
1120
+ }
859
1121
 
860
- for (let i = 0; i < arrayLike.length; i += 1) {
861
- array.push(arrayLike[i]);
1122
+ var childVNode = type(props);
1123
+ return mount(childVNode, env);
862
1124
  }
863
1125
 
864
- return array;
865
- }
1126
+ if (isLeaf(vnode)) {
1127
+ return {
1128
+ type: MOUNT_SINGLE,
1129
+ node: document.createTextNode("" + vnode)
1130
+ };
1131
+ }
866
1132
 
867
- function addClass(className, ...rest) {
868
- const classList = (className || '').split(' ').filter(Boolean);
869
- rest.forEach(item => {
870
- if (item && classList.indexOf(item) < 0) classList.push(item);
871
- });
872
- return classList.join(' ');
873
- }
1133
+ if (isElement(vnode)) {
1134
+ var _node;
874
1135
 
875
- function childSelector(filter) {
876
- if (typeof filter === 'string') {
877
- const tagName = filter;
1136
+ var _ref2 = vnode,
1137
+ _type = _ref2.type,
1138
+ _props = _ref2.props;
878
1139
 
879
- filter = el => el.tagName === tagName;
880
- }
1140
+ if (!env.isSvg && _type === 'svg') {
1141
+ env = Object.assign({}, env, {
1142
+ isSvg: true
1143
+ });
1144
+ }
881
1145
 
882
- const filterFn = filter;
883
- return function selector() {
884
- let nodes = arrayFrom(this.childNodes);
885
- if (filterFn) nodes = nodes.filter(node => filterFn(node));
886
- return nodes;
887
- };
888
- }
1146
+ if (!env.isSvg) {
1147
+ _node = document.createElement(_type);
1148
+ } else {
1149
+ _node = document.createElementNS(SVG_NS, _type);
1150
+ }
889
1151
 
890
- function memoize(fn) {
891
- const cache = {};
892
- return function memoized(...args) {
893
- const key = `${args[0]}`;
894
- let data = cache[key];
1152
+ mountAttributes(_node, _props, env);
895
1153
 
896
- if (!data) {
897
- data = {
898
- value: fn(...args)
899
- };
900
- cache[key] = data;
901
- }
1154
+ var _childrenRef;
902
1155
 
903
- return data.value;
904
- };
905
- }
1156
+ if (_props.children) {
1157
+ var childEnv = env;
906
1158
 
907
- function createElement(tagName, props, attrs) {
908
- const el = document.createElement(tagName);
1159
+ if (env.isSvg && _type === 'foreignObject') {
1160
+ childEnv = Object.assign({}, childEnv, {
1161
+ isSvg: false
1162
+ });
1163
+ }
909
1164
 
910
- if (props) {
911
- Object.entries(props).forEach(([key, value]) => {
912
- el[key] = value;
913
- });
1165
+ _childrenRef = mount(_props.children, childEnv);
1166
+ }
1167
+
1168
+ if (_childrenRef != null) insertDom(_node, _childrenRef);
1169
+ var ref = _props.ref;
1170
+ if (typeof ref === 'function') ref(_node);
1171
+ return {
1172
+ type: MOUNT_SINGLE,
1173
+ node: _node
1174
+ };
914
1175
  }
915
1176
 
916
- if (attrs) {
917
- Object.entries(attrs).forEach(([key, value]) => {
918
- el.setAttribute(key, value);
919
- });
1177
+ if (Array.isArray(vnode)) {
1178
+ return {
1179
+ type: MOUNT_ARRAY,
1180
+ children: vnode.map(function (child) {
1181
+ return mount(child, env);
1182
+ })
1183
+ };
920
1184
  }
921
1185
 
922
- return el;
1186
+ throw new Error('mount: Invalid Vnode!');
923
1187
  }
924
1188
 
925
- const memoizedPreloadJS = memoize(url => {
926
- document.head.append(createElement('link', {
927
- rel: 'preload',
928
- as: 'script',
929
- href: url
930
- }));
931
- });
932
-
933
- function loadJSItem(item, context) {
934
- if (item.type === 'script') {
935
- return new Promise((resolve, reject) => {
936
- var _item$data;
1189
+ function flattenWithoutNull(array) {
1190
+ var result = [];
937
1191
 
938
- document.head.append(createElement('script', _extends({}, item.data, {
939
- onload: resolve,
940
- onerror: reject
941
- }))); // Run inline script synchronously
942
-
943
- if (!((_item$data = item.data) != null && _item$data.src)) resolve();
944
- });
1192
+ for (var i = 0; i < array.length; i += 1) {
1193
+ var item = array[i];
1194
+ if (Array.isArray(item)) result = result.concat(flattenWithoutNull(item));else if (item != null) result.push(item);
945
1195
  }
946
1196
 
947
- if (item.type === 'iife') {
948
- const {
949
- fn,
950
- getParams
951
- } = item.data;
952
- fn(...((getParams == null ? void 0 : getParams(context)) || []));
953
- }
1197
+ return result;
954
1198
  }
955
1199
 
956
- function loadCSSItem(item) {
957
- if (item.type === 'style') {
958
- document.head.append(createElement('style', {
959
- textContent: item.data
960
- }));
961
- } else if (item.type === 'stylesheet') {
962
- document.head.append(createElement('link', _extends({
963
- rel: 'stylesheet'
964
- }, item.data)));
1200
+ function asDom(result) {
1201
+ if (result.type === MOUNT_SINGLE) {
1202
+ return result.node;
965
1203
  }
966
- }
967
1204
 
968
- async function loadJS(items, context) {
969
- const needPreload = items.filter(item => {
970
- var _item$data2;
1205
+ return result.children.map(asDom);
1206
+ }
1207
+ /**
1208
+ * Mount vdom as real DOM nodes.
1209
+ */
971
1210
 
972
- return item.type === 'script' && ((_item$data2 = item.data) == null ? void 0 : _item$data2.src);
973
- });
974
- if (needPreload.length > 1) needPreload.forEach(item => memoizedPreloadJS(item.data.src));
975
- context = _extends({
976
- getMarkmap: () => window.markmap
977
- }, context);
978
1211
 
979
- for (const item of items) {
980
- await loadJSItem(item, context);
1212
+ function mountDom(vnode) {
1213
+ if (Array.isArray(vnode)) {
1214
+ return flattenWithoutNull(vnode.map(mountDom));
981
1215
  }
982
- }
983
1216
 
984
- function loadCSS(items) {
985
- for (const item of items) {
986
- loadCSSItem(item);
987
- }
1217
+ return asDom(mount(vnode));
988
1218
  }
989
1219
 
1220
+ var css_248z$1 = ".markmap{font:300 16px/20px sans-serif}.markmap-link{fill:none}.markmap-node>circle{cursor:pointer}.markmap-foreign{display:inline-block}.markmap-foreign a{color:#0097e6}.markmap-foreign a:hover{color:#00a8ff}.markmap-foreign code{background-color:#f0f0f0;border-radius:2px;color:#555;font-size:calc(1em - 2px)}.markmap-foreign :not(pre)>code{padding:.2em .4em}.markmap-foreign del{text-decoration:line-through}.markmap-foreign em{font-style:italic}.markmap-foreign strong{font-weight:bolder}.markmap-foreign mark{background:#ffeaa7}.markmap-foreign pre,.markmap-foreign pre[class*=language-]{margin:0;padding:.2em .4em}";
1221
+
1222
+ var css_248z = ".markmap-container{height:0;left:-100px;overflow:hidden;position:absolute;top:-100px;width:0}.markmap-container>.markmap-foreign{display:inline-block}.markmap-container>.markmap-foreign>div:last-child{white-space:nowrap}";
1223
+
1224
+ const globalCSS = css_248z$1;
1225
+
990
1226
  function linkWidth(nodeData) {
991
1227
  const data = nodeData.data;
992
- return Math.max(6 - 2 * data.d, 1.5);
1228
+ return Math.max(6 - 2 * data.depth, 1.5);
993
1229
  }
994
1230
 
995
1231
  function adjustSpacing(tree, spacing) {
@@ -1020,23 +1256,32 @@ function createViewHooks() {
1020
1256
 
1021
1257
 
1022
1258
  const refreshHook = new Hook();
1259
+ const defaultColorFn = d3__namespace.scaleOrdinal(d3__namespace.schemeCategory10);
1260
+ const isMacintosh = typeof navigator !== 'undefined' && navigator.userAgent.includes('Macintosh');
1023
1261
  class Markmap {
1024
1262
  constructor(svg, opts) {
1025
1263
  this.revokers = [];
1026
- ['handleZoom', 'handleClick'].forEach(key => {
1264
+ ['handleZoom', 'handleClick', 'handlePan'].forEach(key => {
1027
1265
  this[key] = this[key].bind(this);
1028
1266
  });
1029
1267
  this.viewHooks = createViewHooks();
1030
1268
  this.svg = svg.datum ? svg : d3__namespace.select(svg);
1031
1269
  this.styleNode = this.svg.append('style');
1032
- this.zoom = d3__namespace.zoom().on('zoom', this.handleZoom);
1033
- this.options = _extends$1({}, Markmap.defaultOptions, opts);
1270
+ this.zoom = d3__namespace.zoom().filter(event => {
1271
+ if (this.options.scrollForPan) {
1272
+ // Pan with wheels, zoom with ctrl+wheels
1273
+ if (event.type === 'wheel') return event.ctrlKey && !event.button;
1274
+ }
1275
+
1276
+ return (!event.ctrlKey || event.type === 'wheel') && !event.button;
1277
+ }).on('zoom', this.handleZoom);
1278
+ this.setOptions(opts);
1034
1279
  this.state = {
1035
- id: this.options.id || getId()
1280
+ id: this.options.id || this.svg.attr('id') || getId()
1036
1281
  };
1037
- this.g = this.svg.append('g').attr('class', `${this.state.id}-g`);
1282
+ this.g = this.svg.append('g');
1038
1283
  this.updateStyle();
1039
- this.svg.call(this.zoom);
1284
+ this.svg.call(this.zoom).on('wheel', this.handlePan);
1040
1285
  this.revokers.push(refreshHook.tap(() => {
1041
1286
  this.setData();
1042
1287
  }));
@@ -1044,34 +1289,19 @@ class Markmap {
1044
1289
 
1045
1290
  getStyleContent() {
1046
1291
  const {
1047
- style,
1048
- nodeFont
1292
+ style
1049
1293
  } = this.options;
1050
1294
  const {
1051
1295
  id
1052
1296
  } = this.state;
1053
- const extraStyle = typeof style === 'function' ? style(id) : '';
1054
- const styleText = `\
1055
- .${id} { line-height: 1; }
1056
- .${id} a { color: #0097e6; }
1057
- .${id} a:hover { color: #00a8ff; }
1058
- .${id}-g > path { fill: none; }
1059
- .${id}-g > g > circle { cursor: pointer; }
1060
- .${id}-fo > div { display: inline-block; font: ${nodeFont}; white-space: nowrap; }
1061
- .${id}-fo code { font-size: calc(1em - 2px); color: #555; background-color: #f0f0f0; border-radius: 2px; }
1062
- .${id}-fo :not(pre) > code { padding: .2em .4em; }
1063
- .${id}-fo del { text-decoration: line-through; }
1064
- .${id}-fo em { font-style: italic; }
1065
- .${id}-fo strong { font-weight: bolder; }
1066
- .${id}-fo pre { margin: 0; padding: .2em .4em; }
1067
- ${extraStyle}
1068
- `;
1069
- return styleText;
1297
+ const styleText = typeof style === 'function' ? style(id) : '';
1298
+ return [this.options.embedGlobalCSS && css_248z$1, styleText].filter(Boolean).join('\n');
1070
1299
  }
1071
1300
 
1072
1301
  updateStyle() {
1073
- this.svg.attr('class', addClass(this.svg.attr('class'), this.state.id));
1074
- this.styleNode.text(this.getStyleContent());
1302
+ this.svg.attr('class', addClass(this.svg.attr('class'), 'markmap', this.state.id));
1303
+ const style = this.getStyleContent();
1304
+ this.styleNode.text(style);
1075
1305
  }
1076
1306
 
1077
1307
  handleZoom(e) {
@@ -1081,76 +1311,84 @@ ${extraStyle}
1081
1311
  this.g.attr('transform', transform);
1082
1312
  }
1083
1313
 
1084
- handleClick(e, d) {
1085
- var _data$p;
1314
+ handlePan(e) {
1315
+ e.preventDefault();
1316
+ const transform = d3__namespace.zoomTransform(this.svg.node());
1317
+ const newTransform = transform.translate(-e.deltaX, -e.deltaY);
1318
+ this.svg.call(this.zoom.transform, newTransform);
1319
+ }
1320
+
1321
+ handleClick(_, d) {
1322
+ var _data$payload;
1086
1323
 
1087
1324
  const {
1088
1325
  data
1089
1326
  } = d;
1090
- data.p = _extends$1({}, data.p, {
1091
- f: !((_data$p = data.p) != null && _data$p.f)
1327
+ data.payload = _extends({}, data.payload, {
1328
+ fold: !((_data$payload = data.payload) != null && _data$payload.fold)
1092
1329
  });
1093
1330
  this.renderData(d.data);
1094
1331
  }
1095
1332
 
1096
1333
  initializeData(node) {
1097
- let i = 0;
1334
+ let nodeId = 0;
1098
1335
  const {
1099
- nodeFont,
1100
1336
  color,
1101
- nodeMinHeight
1337
+ nodeMinHeight,
1338
+ maxWidth
1102
1339
  } = this.options;
1103
1340
  const {
1104
1341
  id
1105
1342
  } = this.state;
1106
- const container = document.createElement('div');
1107
- const containerClass = `${id}-container`;
1108
- container.className = addClass(container.className, `${id}-fo`, containerClass);
1109
- const style = document.createElement('style');
1110
- style.textContent = `
1111
- ${this.getStyleContent()}
1112
- .${containerClass} {
1113
- position: absolute;
1114
- width: 0;
1115
- height: 0;
1116
- top: -100px;
1117
- left: -100px;
1118
- overflow: hidden;
1119
- font: ${nodeFont};
1120
- }
1121
- .${containerClass} > div {
1122
- display: inline-block;
1123
- }
1124
- `;
1125
- document.body.append(style, container);
1343
+ const container = mountDom(jsx("div", {
1344
+ className: `markmap-container markmap ${id}-g`
1345
+ }));
1346
+ const style = mountDom(jsx("style", {
1347
+ children: [this.getStyleContent(), css_248z].join('\n')
1348
+ }));
1349
+ document.body.append(container, style);
1350
+ const groupStyle = maxWidth ? `max-width: ${maxWidth}px` : '';
1126
1351
  walkTree(node, (item, next) => {
1127
- var _item$c;
1128
-
1129
- item.c = (_item$c = item.c) == null ? void 0 : _item$c.map(child => _extends$1({}, child));
1130
- i += 1;
1131
- const el = document.createElement('div');
1132
- el.innerHTML = item.v;
1133
- container.append(el);
1134
- item.p = _extends$1({}, item.p, {
1135
- // unique ID
1136
- i,
1137
- el
1352
+ var _item$children;
1353
+
1354
+ item.children = (_item$children = item.children) == null ? void 0 : _item$children.map(child => _extends({}, child));
1355
+ nodeId += 1;
1356
+ const group = mountDom(jsx("div", {
1357
+ className: "markmap-foreign",
1358
+ style: groupStyle,
1359
+ children: jsx("div", {
1360
+ dangerouslySetInnerHTML: {
1361
+ __html: item.content
1362
+ }
1363
+ })
1364
+ }));
1365
+ container.append(group);
1366
+ item.state = _extends({}, item.state, {
1367
+ id: nodeId,
1368
+ el: group.firstChild
1138
1369
  });
1139
1370
  color(item); // preload colors
1140
1371
 
1141
1372
  next();
1142
1373
  });
1143
- const nodes = arrayFrom(container.childNodes);
1144
- this.viewHooks.transformHtml.call(this, nodes);
1374
+ const nodes = arrayFrom(container.childNodes).map(group => group.firstChild);
1375
+ this.viewHooks.transformHtml.call(this, nodes); // Clone the rendered HTML and set `white-space: nowrap` to it to detect its max-width.
1376
+ // The parent node will have a width of the max-width and the original content without
1377
+ // `white-space: nowrap` gets re-layouted, then we will get the expected layout, with
1378
+ // content in one line as much as possible, and subjecting to the given max-width.
1379
+
1380
+ nodes.forEach(node => {
1381
+ node.parentNode.append(node.cloneNode(true));
1382
+ });
1145
1383
  walkTree(node, (item, next, parent) => {
1146
- var _parent$p;
1147
-
1148
- const rect = item.p.el.getBoundingClientRect();
1149
- item.v = item.p.el.innerHTML;
1150
- item.p.s = [Math.ceil(rect.width), Math.max(Math.ceil(rect.height), nodeMinHeight)]; // TODO keep keys for unchanged objects
1151
- // unique key, should be based on content
1152
-
1153
- item.p.k = `${(parent == null ? void 0 : (_parent$p = parent.p) == null ? void 0 : _parent$p.i) || ''}.${item.p.i}:${item.v}`;
1384
+ var _parent$state, _parent$state2;
1385
+
1386
+ const rect = item.state.el.getBoundingClientRect();
1387
+ item.content = item.state.el.innerHTML;
1388
+ item.state.size = [Math.ceil(rect.width) + 1, Math.max(Math.ceil(rect.height), nodeMinHeight)];
1389
+ item.state.path = [parent == null ? void 0 : (_parent$state = parent.state) == null ? void 0 : _parent$state.path, item.state.id].filter(Boolean).join('.');
1390
+ 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
1391
+ item.content;
1154
1392
  next();
1155
1393
  });
1156
1394
  container.remove();
@@ -1158,18 +1396,18 @@ ${this.getStyleContent()}
1158
1396
  }
1159
1397
 
1160
1398
  setOptions(opts) {
1161
- Object.assign(this.options, opts);
1399
+ this.options = _extends({}, Markmap.defaultOptions, opts);
1162
1400
  }
1163
1401
 
1164
1402
  setData(data, opts) {
1165
1403
  if (data) this.state.data = data;
1166
- this.initializeData(this.state.data);
1167
1404
  if (opts) this.setOptions(opts);
1405
+ this.initializeData(this.state.data);
1168
1406
  this.renderData();
1169
1407
  }
1170
1408
 
1171
1409
  renderData(originData) {
1172
- var _origin$data$p$x, _origin$data$p$y;
1410
+ var _origin$data$state$x, _origin$data$state$y;
1173
1411
 
1174
1412
  if (!this.state.data) return;
1175
1413
  const {
@@ -1179,15 +1417,12 @@ ${this.getStyleContent()}
1179
1417
  autoFit,
1180
1418
  color
1181
1419
  } = this.options;
1182
- const {
1183
- id
1184
- } = this.state;
1185
1420
  const layout = flextree().children(d => {
1186
- var _d$p;
1421
+ var _d$payload;
1187
1422
 
1188
- return !((_d$p = d.p) != null && _d$p.f) && d.c;
1423
+ return !((_d$payload = d.payload) != null && _d$payload.fold) && d.children;
1189
1424
  }).nodeSize(d => {
1190
- const [width, height] = d.data.p.s;
1425
+ const [width, height] = d.data.state.size;
1191
1426
  return [height, width + (width ? paddingX * 2 : 0) + spacingHorizontal];
1192
1427
  }).spacing((a, b) => {
1193
1428
  return a.parent === b.parent ? spacingVertical : spacingVertical * 2;
@@ -1210,43 +1445,45 @@ ${this.getStyleContent()}
1210
1445
  });
1211
1446
  if (autoFit) this.fit();
1212
1447
  const origin = originData && descendants.find(item => item.data === originData) || tree;
1213
- const x0 = (_origin$data$p$x = origin.data.p.x0) != null ? _origin$data$p$x : origin.x;
1214
- const y0 = (_origin$data$p$y = origin.data.p.y0) != null ? _origin$data$p$y : origin.y; // Update the nodes
1448
+ const x0 = (_origin$data$state$x = origin.data.state.x0) != null ? _origin$data$state$x : origin.x;
1449
+ const y0 = (_origin$data$state$y = origin.data.state.y0) != null ? _origin$data$state$y : origin.y; // Update the nodes
1215
1450
 
1216
- const node = this.g.selectAll(childSelector('g')).data(descendants, d => d.data.p.k);
1217
- const nodeEnter = node.enter().append('g').attr('transform', d => `translate(${y0 + origin.ySizeInner - d.ySizeInner},${x0 + origin.xSize / 2 - d.xSize})`);
1451
+ const node = this.g.selectAll(childSelector('g')).data(descendants, d => d.data.state.key);
1452
+ const nodeEnter = node.enter().append('g').attr('class', 'markmap-node').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})`);
1218
1453
  const nodeExit = this.transition(node.exit());
1219
- nodeExit.select('rect').attr('width', 0).attr('x', d => d.ySizeInner);
1454
+ nodeExit.select('line').attr('x1', d => d.ySizeInner).attr('x2', d => d.ySizeInner);
1220
1455
  nodeExit.select('foreignObject').style('opacity', 0);
1221
1456
  nodeExit.attr('transform', d => `translate(${origin.y + origin.ySizeInner - d.ySizeInner},${origin.x + origin.xSize / 2 - d.xSize})`).remove();
1222
1457
  const nodeMerge = node.merge(nodeEnter);
1223
- this.transition(nodeMerge).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`);
1224
- const rect = nodeMerge.selectAll(childSelector('rect')).data(d => [d], d => d.data.p.k).join(enter => {
1225
- return enter.append('rect').attr('x', d => d.ySizeInner).attr('y', d => d.xSize - linkWidth(d) / 2).attr('width', 0).attr('height', linkWidth);
1458
+ this.transition(nodeMerge).attr('transform', d => `translate(${d.y},${d.x - d.xSize / 2})`); // Update lines under the content
1459
+
1460
+ const line = nodeMerge.selectAll(childSelector('line')).data(d => [d], d => d.data.state.key).join(enter => {
1461
+ return enter.append('line').attr('x1', d => d.ySizeInner).attr('x2', d => d.ySizeInner);
1226
1462
  }, update => update, exit => exit.remove());
1227
- this.transition(rect).attr('x', -1).attr('width', d => d.ySizeInner + 2).attr('fill', d => color(d.data));
1228
- const circle = nodeMerge.selectAll(childSelector('circle')).data(d => d.data.c ? [d] : [], d => d.data.p.k).join(enter => {
1463
+ 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
1464
+
1465
+ const circle = nodeMerge.selectAll(childSelector('circle')).data(d => d.data.children ? [d] : [], d => d.data.state.key).join(enter => {
1229
1466
  return enter.append('circle').attr('stroke-width', '1.5').attr('cx', d => d.ySizeInner).attr('cy', d => d.xSize).attr('r', 0).on('click', this.handleClick);
1230
1467
  }, update => update, exit => exit.remove());
1231
1468
  this.transition(circle).attr('r', 6).attr('stroke', d => color(d.data)).attr('fill', d => {
1232
- var _d$data$p;
1469
+ var _d$data$payload;
1233
1470
 
1234
- return (_d$data$p = d.data.p) != null && _d$data$p.f && d.data.c ? color(d.data) : '#fff';
1471
+ return (_d$data$payload = d.data.payload) != null && _d$data$payload.fold && d.data.children ? color(d.data) : '#fff';
1235
1472
  });
1236
- const foreignObject = nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.p.k).join(enter => {
1237
- const fo = enter.append('foreignObject').attr('class', `${id}-fo`).attr('x', paddingX).attr('y', 0).style('opacity', 0).attr('height', d => d.xSize).on('mousedown', stopPropagation).on('dblclick', stopPropagation);
1473
+ const foreignObject = nodeMerge.selectAll(childSelector('foreignObject')).data(d => [d], d => d.data.state.key).join(enter => {
1474
+ const fo = enter.append('foreignObject').attr('class', 'markmap-foreign').attr('x', paddingX).attr('y', 0).style('opacity', 0).on('mousedown', stopPropagation).on('dblclick', stopPropagation);
1238
1475
  fo.append('xhtml:div').select(function select(d) {
1239
- const clone = d.data.p.el.cloneNode(true);
1476
+ const clone = d.data.state.el.cloneNode(true);
1240
1477
  this.replaceWith(clone);
1241
1478
  return clone;
1242
1479
  }).attr('xmlns', 'http://www.w3.org/1999/xhtml');
1243
1480
  return fo;
1244
- }, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - paddingX * 2));
1481
+ }, update => update, exit => exit.remove()).attr('width', d => Math.max(0, d.ySizeInner - paddingX * 2)).attr('height', d => d.xSize);
1245
1482
  this.transition(foreignObject).style('opacity', 1); // Update the links
1246
1483
 
1247
- const path = this.g.selectAll(childSelector('path')).data(links, d => d.target.data.p.k).join(enter => {
1484
+ const path = this.g.selectAll(childSelector('path')).data(links, d => d.target.data.state.key).join(enter => {
1248
1485
  const source = [y0 + origin.ySizeInner, x0 + origin.xSize / 2];
1249
- return enter.insert('path', 'g').attr('d', linkShape({
1486
+ 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({
1250
1487
  source,
1251
1488
  target: source
1252
1489
  }));
@@ -1266,8 +1503,8 @@ ${this.getStyleContent()}
1266
1503
  });
1267
1504
  });
1268
1505
  descendants.forEach(d => {
1269
- d.data.p.x0 = d.x;
1270
- d.data.p.y0 = d.y;
1506
+ d.data.state.x0 = d.x;
1507
+ d.data.state.y0 = d.y;
1271
1508
  });
1272
1509
  }
1273
1510
 
@@ -1324,7 +1561,7 @@ ${this.getStyleContent()}
1324
1561
  const [left, right] = [itemData.y, itemData.y + itemData.ySizeInner + 2].map(x => x * transform.k + transform.x);
1325
1562
  const [top, bottom] = [itemData.x - itemData.xSize / 2, itemData.x + itemData.xSize / 2].map(y => y * transform.k + transform.y); // Skip if the node includes or is included in the container.
1326
1563
 
1327
- const pd = _extends$1({
1564
+ const pd = _extends({
1328
1565
  left: 0,
1329
1566
  right: 0,
1330
1567
  top: 0,
@@ -1360,7 +1597,8 @@ ${this.getStyleContent()}
1360
1597
  }
1361
1598
 
1362
1599
  destroy() {
1363
- this.svg.remove();
1600
+ this.svg.on('.zoom', null);
1601
+ this.svg.html(null);
1364
1602
  this.revokers.forEach(fn => {
1365
1603
  fn();
1366
1604
  });
@@ -1379,18 +1617,55 @@ ${this.getStyleContent()}
1379
1617
 
1380
1618
  }
1381
1619
  Markmap.defaultOptions = {
1620
+ autoFit: false,
1621
+ color: node => defaultColorFn(`${node.state.id}`),
1382
1622
  duration: 500,
1383
- nodeFont: '300 16px/20px sans-serif',
1623
+ embedGlobalCSS: true,
1624
+ fitRatio: 0.95,
1625
+ maxWidth: 0,
1384
1626
  nodeMinHeight: 16,
1385
- spacingVertical: 5,
1627
+ paddingX: 8,
1628
+ scrollForPan: isMacintosh,
1386
1629
  spacingHorizontal: 80,
1387
- autoFit: false,
1388
- fitRatio: 0.95,
1389
- color: (colorFn => node => colorFn(node.p.i))(d3__namespace.scaleOrdinal(d3__namespace.schemeCategory10)),
1390
- paddingX: 8
1630
+ spacingVertical: 5
1391
1631
  };
1632
+ function deriveOptions(jsonOptions) {
1633
+ const {
1634
+ color,
1635
+ duration,
1636
+ maxWidth
1637
+ } = jsonOptions || {};
1638
+ let opts;
1639
+
1640
+ if (typeof color === 'string') {
1641
+ opts = _extends({}, opts, {
1642
+ color: () => color
1643
+ });
1644
+ } else if (color != null && color.length) {
1645
+ opts = _extends({}, opts, {
1646
+ color: node => color[node.state.id % color.length]
1647
+ });
1648
+ }
1649
+
1650
+ if (typeof duration === 'number') {
1651
+ opts = _extends({}, opts, {
1652
+ duration
1653
+ });
1654
+ }
1655
+
1656
+ if (typeof maxWidth === 'number') {
1657
+ opts = _extends({}, opts, {
1658
+ maxWidth
1659
+ });
1660
+ }
1661
+
1662
+ return opts;
1663
+ }
1392
1664
 
1393
1665
  exports.Markmap = Markmap;
1666
+ exports.defaultColorFn = defaultColorFn;
1667
+ exports.deriveOptions = deriveOptions;
1668
+ exports.globalCSS = globalCSS;
1394
1669
  exports.loadCSS = loadCSS;
1395
1670
  exports.loadJS = loadJS;
1396
1671
  exports.refreshHook = refreshHook;