markmap-view 0.2.7 → 0.13.0-alpha.0

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