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