@umbraci/jsmind 0.10.18 → 1.0.0-beta
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/README.md +7 -7
- package/dist/jsmind.draggable-node.js +7 -472
- package/dist/jsmind.draggable-node.js.map +1 -1
- package/dist/jsmind.history.js +7 -980
- package/dist/jsmind.history.js.map +1 -1
- package/dist/jsmind.js +7 -2624
- package/dist/jsmind.js.map +1 -1
- package/dist/jsmind.multi-select.js +7 -671
- package/dist/jsmind.multi-select.js.map +1 -1
- package/dist/jsmind.multiline-text.js +7 -156
- package/dist/jsmind.multiline-text.js.map +1 -1
- package/dist/jsmind.screenshot.js +7 -156
- package/dist/jsmind.screenshot.js.map +1 -1
- package/es/jsmind.draggable-node.js +7 -443
- package/es/jsmind.draggable-node.js.map +1 -1
- package/es/jsmind.history.js +7 -944
- package/es/jsmind.history.js.map +1 -1
- package/es/jsmind.js +7 -2570
- package/es/jsmind.js.map +1 -1
- package/es/jsmind.multi-select.js +7 -621
- package/es/jsmind.multi-select.js.map +1 -1
- package/es/jsmind.multiline-text.js +7 -136
- package/es/jsmind.multiline-text.js.map +1 -1
- package/es/jsmind.screenshot.js +7 -136
- package/es/jsmind.screenshot.js.map +1 -1
- package/lib/jsmind.draggable-node.js +7 -450
- package/lib/jsmind.draggable-node.js.map +1 -1
- package/lib/jsmind.history.js +7 -946
- package/lib/jsmind.history.js.map +1 -1
- package/lib/jsmind.js +7 -2571
- package/lib/jsmind.js.map +1 -1
- package/lib/jsmind.multi-select.js +7 -623
- package/lib/jsmind.multi-select.js.map +1 -1
- package/lib/jsmind.multiline-text.js +7 -141
- package/lib/jsmind.multiline-text.js.map +1 -1
- package/lib/jsmind.screenshot.js +7 -145
- package/lib/jsmind.screenshot.js.map +1 -1
- package/package.json +26 -25
- package/types/generated/jsmind.d.ts +21 -24
- package/types/generated/jsmind.mind.d.ts +7 -0
- package/types/generated/{jsmind.enhanced-plugin.d.ts → jsmind.plugin-system.d.ts} +10 -10
- package/types/generated/jsmind.plugin.d.ts +93 -13
- package/types/generated/jsmind.view_provider.d.ts +1 -1
- package/types/generated/plugins/history/history-diff.d.ts +10 -0
- package/types/generated/plugins/history/jsmind.history.d.ts +2 -2
- package/types/generated/plugins/jsmind.draggable-node.d.ts +13 -3
- package/types/generated/plugins/jsmind.multi-select.d.ts +3 -3
- package/types/generated/plugins/jsmind.multiline-text.d.ts +67 -21
- package/types/generated/plugins/jsmind.screenshot.d.ts +12 -3
- package/types/tsconfig.declaration.json +6 -1
- package/dist/jsmind.copy-paste.js +0 -283
- package/dist/jsmind.copy-paste.js.map +0 -1
- package/es/jsmind.copy-paste.js +0 -260
- package/es/jsmind.copy-paste.js.map +0 -1
- package/types/generated/plugins/jsmind.multiline-text-v2.d.ts +0 -58
|
@@ -5,7 +5,7 @@ export type DiffOptions = import("./history-diff.js").DiffOptions;
|
|
|
5
5
|
/**
|
|
6
6
|
* HistoryPlugin skeleton (Task 1)
|
|
7
7
|
*/
|
|
8
|
-
export class HistoryPlugin extends
|
|
8
|
+
export class HistoryPlugin extends Plugin {
|
|
9
9
|
/**
|
|
10
10
|
* @param {{ jm: JsMind, pluginOpt?: any }} params
|
|
11
11
|
*/
|
|
@@ -38,7 +38,7 @@ export class HistoryPlugin extends EnhancedPlugin {
|
|
|
38
38
|
/** Mount public API on jm.history (placeholder defaults) */
|
|
39
39
|
_mountAPI(): void;
|
|
40
40
|
}
|
|
41
|
-
import {
|
|
41
|
+
import { Plugin } from '../../jsmind.plugin.js';
|
|
42
42
|
declare class HistoryCore {
|
|
43
43
|
/** @param {JsMind} jm @param {any} options */
|
|
44
44
|
constructor(jm: JsMind, options: any);
|
|
@@ -241,10 +241,19 @@ export class DraggableNode {
|
|
|
241
241
|
jm_event_handle(type: number | string, data?: object): void;
|
|
242
242
|
}
|
|
243
243
|
/**
|
|
244
|
-
* Draggable node plugin
|
|
245
|
-
* @type {import('../jsmind.plugin.js').Plugin<Partial<DraggableNodeOptions>>}
|
|
244
|
+
* Draggable node plugin for unified plugin system.
|
|
246
245
|
*/
|
|
247
|
-
export
|
|
246
|
+
export class DraggableNodePlugin extends Plugin {
|
|
247
|
+
/**
|
|
248
|
+
* @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<DraggableNodeOptions> }} params
|
|
249
|
+
*/
|
|
250
|
+
constructor({ jm, pluginOpt }: {
|
|
251
|
+
jm: import("../jsmind.js").default;
|
|
252
|
+
pluginOpt: Partial<DraggableNodeOptions>;
|
|
253
|
+
});
|
|
254
|
+
draggable: DraggableNode;
|
|
255
|
+
_eventHandle: (type: any, data: any) => void;
|
|
256
|
+
}
|
|
248
257
|
export default DraggableNode;
|
|
249
258
|
/**
|
|
250
259
|
* Default options for draggable node plugin.
|
|
@@ -260,3 +269,4 @@ export type DraggableNodeOptions = {
|
|
|
260
269
|
shadow_node_class_name?: string;
|
|
261
270
|
validate_drag?: (draggedNode: import("../jsmind.node.js").Node, targetNode: import("../jsmind.node.js").Node | null) => boolean;
|
|
262
271
|
};
|
|
272
|
+
import { Plugin } from '../jsmind.plugin.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Multi-Select Plugin -
|
|
2
|
+
* Multi-Select Plugin - Plugin for jsMind
|
|
3
3
|
*/
|
|
4
|
-
export class MultiSelectPlugin extends
|
|
4
|
+
export class MultiSelectPlugin extends Plugin {
|
|
5
5
|
/**
|
|
6
6
|
* @param {{ jm: import('../jsmind.js').default, pluginOpt: object }} params
|
|
7
7
|
*/
|
|
@@ -50,7 +50,7 @@ export type MultiSelectOptions = {
|
|
|
50
50
|
*/
|
|
51
51
|
filter?: ((node: import("../jsmind.node.js").Node) => boolean) | null;
|
|
52
52
|
};
|
|
53
|
-
import {
|
|
53
|
+
import { Plugin } from '../jsmind.plugin.js';
|
|
54
54
|
/**
|
|
55
55
|
* Multi-Select Core - Handles all multi-select logic
|
|
56
56
|
*/
|
|
@@ -1,24 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Create a custom node render function for multiline text
|
|
3
|
-
* @param {MultilineTextOptions} [options={}] - Plugin options
|
|
4
|
-
* @
|
|
5
|
-
* @param {string} [options.line_height='1.5'] - Line height for text
|
|
6
|
-
* @returns {function(jsMind, HTMLElement, Node): boolean} Custom render function
|
|
7
|
-
* @example
|
|
8
|
-
* const options = {
|
|
9
|
-
* view: {
|
|
10
|
-
* custom_node_render: createMultilineRender({
|
|
11
|
-
* text_width: 250,
|
|
12
|
-
* line_height: '1.6',
|
|
13
|
-
* })
|
|
14
|
-
* }
|
|
15
|
-
* };
|
|
3
|
+
* @param {Partial<MultilineTextOptions>} [options={}] - Plugin options
|
|
4
|
+
* @returns {function(jsMind, HTMLElement, import('../jsmind.node.js').Node): boolean} Custom render function
|
|
16
5
|
*/
|
|
17
|
-
export function createMultilineRender(options?: MultilineTextOptions): (arg0: jsMind, arg1: HTMLElement, arg2: Node) => boolean;
|
|
6
|
+
export function createMultilineRender(options?: Partial<MultilineTextOptions>): (arg0: jsMind, arg1: HTMLElement, arg2: import("../jsmind.node.js").Node) => boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Plugin initialization function
|
|
9
|
+
* @param {import('../jsmind.js').default} jm - jsMind instance
|
|
10
|
+
* @param {Partial<MultilineTextOptions>} options - Plugin options
|
|
11
|
+
* @returns {MultilineTextPlugin}
|
|
12
|
+
*/
|
|
13
|
+
export function init(jm: import("../jsmind.js").default, options: Partial<MultilineTextOptions>): MultilineTextPlugin;
|
|
14
|
+
/**
|
|
15
|
+
* Multiline text plugin for unified plugin system.
|
|
16
|
+
*/
|
|
17
|
+
export class MultilineTextPlugin extends Plugin {
|
|
18
|
+
/**
|
|
19
|
+
* @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<MultilineTextOptions> }} params
|
|
20
|
+
*/
|
|
21
|
+
constructor({ jm, pluginOpt }: {
|
|
22
|
+
jm: import("../jsmind.js").default;
|
|
23
|
+
pluginOpt: Partial<MultilineTextOptions>;
|
|
24
|
+
});
|
|
25
|
+
options: {
|
|
26
|
+
text_width: number;
|
|
27
|
+
min_height: number;
|
|
28
|
+
line_height: string;
|
|
29
|
+
editor_border_color: string;
|
|
30
|
+
editor_border_width: string;
|
|
31
|
+
auto_resize: boolean;
|
|
32
|
+
} & Partial<MultilineTextOptions>;
|
|
33
|
+
editing_node: import("@umbraci/jsmind").Node;
|
|
34
|
+
multiline_editor: HTMLElement;
|
|
35
|
+
_original_custom_render: Function | ((jm: import("../jsmind.js").default, ele: HTMLElement, node: import("@umbraci/jsmind").Node) => void);
|
|
36
|
+
_original_edit_node_begin: any;
|
|
37
|
+
_original_edit_node_end: any;
|
|
38
|
+
_view_ready_timer: number;
|
|
39
|
+
setupCustomRenderInOptions(): void;
|
|
40
|
+
setupCustomRender(): void;
|
|
41
|
+
setupEditHandlers(): void;
|
|
42
|
+
_createCustomRender(originalCustomRender: any): (jm: any, element: any, node: any) => boolean;
|
|
43
|
+
_rerender_all_nodes(): void;
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('../jsmind.node.js').Node} node
|
|
46
|
+
*/
|
|
47
|
+
edit_node_begin(node: import("../jsmind.node.js").Node): void;
|
|
48
|
+
edit_node_end(): void;
|
|
49
|
+
cancel_editing(): void;
|
|
50
|
+
_cleanup_editor(): void;
|
|
51
|
+
}
|
|
18
52
|
declare namespace _default {
|
|
19
53
|
export let name: string;
|
|
20
54
|
export { init };
|
|
21
55
|
export { createMultilineRender };
|
|
56
|
+
export { MultilineTextPlugin as PluginClass };
|
|
22
57
|
}
|
|
23
58
|
export default _default;
|
|
24
59
|
/**
|
|
@@ -29,15 +64,26 @@ export type MultilineTextOptions = {
|
|
|
29
64
|
* - Maximum width for multiline text nodes (default: 200)
|
|
30
65
|
*/
|
|
31
66
|
text_width: number;
|
|
67
|
+
/**
|
|
68
|
+
* - Minimum editor height in pixels (default: 30)
|
|
69
|
+
*/
|
|
70
|
+
min_height: number;
|
|
32
71
|
/**
|
|
33
72
|
* - Line height for text (default: '1.5')
|
|
34
73
|
*/
|
|
35
74
|
line_height: string;
|
|
75
|
+
/**
|
|
76
|
+
* - Editor border color (default: '#4CAF50')
|
|
77
|
+
*/
|
|
78
|
+
editor_border_color: string;
|
|
79
|
+
/**
|
|
80
|
+
* - Editor border width (default: '2px')
|
|
81
|
+
*/
|
|
82
|
+
editor_border_width: string;
|
|
83
|
+
/**
|
|
84
|
+
* - Auto resize editor on input (default: true)
|
|
85
|
+
*/
|
|
86
|
+
auto_resize: boolean;
|
|
36
87
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* @param {import('../jsmind.js').default} jm - jsMind instance
|
|
40
|
-
* @param {MultilineTextOptions} options - Plugin options
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
|
-
declare function init(jm: import("../jsmind.js").default, options: MultilineTextOptions): void;
|
|
88
|
+
import jsMind from '@umbraci/jsmind';
|
|
89
|
+
import { Plugin } from '../jsmind.plugin.js';
|
|
@@ -65,10 +65,18 @@ export class JmScreenshot {
|
|
|
65
65
|
download(c: HTMLCanvasElement): void;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Screenshot plugin
|
|
69
|
-
* @type {import('../jsmind.plugin.js').Plugin<Partial<ScreenshotOptions>>}
|
|
68
|
+
* Screenshot plugin for unified plugin system.
|
|
70
69
|
*/
|
|
71
|
-
export
|
|
70
|
+
export class ScreenshotPlugin extends Plugin {
|
|
71
|
+
/**
|
|
72
|
+
* @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<ScreenshotOptions> }} params
|
|
73
|
+
*/
|
|
74
|
+
constructor({ jm, pluginOpt }: {
|
|
75
|
+
jm: import("../jsmind.js").default;
|
|
76
|
+
pluginOpt: Partial<ScreenshotOptions>;
|
|
77
|
+
});
|
|
78
|
+
screenshot: JmScreenshot;
|
|
79
|
+
}
|
|
72
80
|
export default JmScreenshot;
|
|
73
81
|
/**
|
|
74
82
|
* Default options for screenshot plugin.
|
|
@@ -81,3 +89,4 @@ export type ScreenshotOptions = {
|
|
|
81
89
|
};
|
|
82
90
|
background?: string;
|
|
83
91
|
};
|
|
92
|
+
import { Plugin } from '../jsmind.plugin.js';
|
|
@@ -12,8 +12,13 @@
|
|
|
12
12
|
"allowJs": true,
|
|
13
13
|
"checkJs": false,
|
|
14
14
|
"rootDirs": ["../src"],
|
|
15
|
+
"paths": {
|
|
16
|
+
"@umbraci/jsmind": ["../src/index.ts"],
|
|
17
|
+
"@umbraci/jsmind/*": ["../src/plugins/*"]
|
|
18
|
+
},
|
|
15
19
|
"outDir": "./generated",
|
|
16
20
|
"baseUrl": "."
|
|
17
21
|
},
|
|
18
|
-
"include" : ["../src/**/*.ts", "../src/**/*.js"]
|
|
22
|
+
"include" : ["../src/**/*.ts", "../src/**/*.js"],
|
|
23
|
+
"exclude": ["./generated/**/*"]
|
|
19
24
|
}
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license BSD-3-Clause
|
|
3
|
-
* @copyright 2014-2025 hizzgdev@163.com
|
|
4
|
-
*
|
|
5
|
-
* Project Home:
|
|
6
|
-
* https://github.com/hizzgdev/jsmind/
|
|
7
|
-
*/
|
|
8
|
-
!(function (e, t) {
|
|
9
|
-
'object' == typeof exports && 'undefined' != typeof module
|
|
10
|
-
? t(exports, require('@umbraci/jsmind'))
|
|
11
|
-
: 'function' == typeof define && define.amd
|
|
12
|
-
? define(['exports', '@umbraci/jsmind'], t)
|
|
13
|
-
: t(
|
|
14
|
-
((e = 'undefined' != typeof globalThis ? globalThis : e || self).jsMindCopyPaste =
|
|
15
|
-
{}),
|
|
16
|
-
e.jsMind
|
|
17
|
-
);
|
|
18
|
-
})(this, function (e, t) {
|
|
19
|
-
'use strict';
|
|
20
|
-
function i(e) {
|
|
21
|
-
return e && 'object' == typeof e && 'default' in e ? e : { default: e };
|
|
22
|
-
}
|
|
23
|
-
var n = i(t);
|
|
24
|
-
const o = new (class {
|
|
25
|
-
constructor(e) {
|
|
26
|
-
(this.w = e),
|
|
27
|
-
(this.d = e.document),
|
|
28
|
-
(this.g = function (e) {
|
|
29
|
-
return this.d.getElementById(e);
|
|
30
|
-
}),
|
|
31
|
-
(this.c = function (e) {
|
|
32
|
-
return this.d.createElement(e);
|
|
33
|
-
}),
|
|
34
|
-
(this.t = function (e, t) {
|
|
35
|
-
e.hasChildNodes()
|
|
36
|
-
? (e.firstChild.nodeValue = t)
|
|
37
|
-
: e.appendChild(this.d.createTextNode(t));
|
|
38
|
-
}),
|
|
39
|
-
(this.h = function (e, t) {
|
|
40
|
-
t instanceof HTMLElement
|
|
41
|
-
? ((e.innerHTML = ''), e.appendChild(t))
|
|
42
|
-
: (e.innerHTML = t);
|
|
43
|
-
}),
|
|
44
|
-
(this.i = function (e) {
|
|
45
|
-
return (
|
|
46
|
-
!!e &&
|
|
47
|
-
'object' == typeof e &&
|
|
48
|
-
1 === e.nodeType &&
|
|
49
|
-
'object' == typeof e.style &&
|
|
50
|
-
'object' == typeof e.ownerDocument
|
|
51
|
-
);
|
|
52
|
-
}),
|
|
53
|
-
(this.on = function (e, t, i) {
|
|
54
|
-
e.addEventListener
|
|
55
|
-
? e.addEventListener(t, i, !1)
|
|
56
|
-
: e.attachEvent('on' + t, i);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
})(window),
|
|
60
|
-
a = {
|
|
61
|
-
file: {
|
|
62
|
-
read: function (e, t) {
|
|
63
|
-
var i = new FileReader();
|
|
64
|
-
(i.onload = function () {
|
|
65
|
-
'function' == typeof t && t(this.result, e.name);
|
|
66
|
-
}),
|
|
67
|
-
i.readAsText(e);
|
|
68
|
-
},
|
|
69
|
-
save: function (e, t, i) {
|
|
70
|
-
var n;
|
|
71
|
-
if ('function' == typeof o.w.Blob) n = new Blob([e], { type: t });
|
|
72
|
-
else {
|
|
73
|
-
var a = new (o.w.BlobBuilder ||
|
|
74
|
-
o.w.MozBlobBuilder ||
|
|
75
|
-
o.w.WebKitBlobBuilder ||
|
|
76
|
-
o.w.MSBlobBuilder)();
|
|
77
|
-
a.append(e), (n = a.getBlob(t));
|
|
78
|
-
}
|
|
79
|
-
if (navigator.msSaveBlob) navigator.msSaveBlob(n, i);
|
|
80
|
-
else {
|
|
81
|
-
var r = (o.w.URL || o.w.webkitURL).createObjectURL(n),
|
|
82
|
-
s = o.c('a');
|
|
83
|
-
if ('download' in s) {
|
|
84
|
-
(s.style.visibility = 'hidden'),
|
|
85
|
-
(s.href = r),
|
|
86
|
-
(s.download = i),
|
|
87
|
-
o.d.body.appendChild(s);
|
|
88
|
-
var d = o.d.createEvent('MouseEvents');
|
|
89
|
-
d.initEvent('click', !0, !0),
|
|
90
|
-
s.dispatchEvent(d),
|
|
91
|
-
o.d.body.removeChild(s);
|
|
92
|
-
} else location.href = r;
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
json: {
|
|
97
|
-
json2string: function (e) {
|
|
98
|
-
return JSON.stringify(e);
|
|
99
|
-
},
|
|
100
|
-
string2json: function (e) {
|
|
101
|
-
return JSON.parse(e);
|
|
102
|
-
},
|
|
103
|
-
merge: function (e, t) {
|
|
104
|
-
for (var i in t)
|
|
105
|
-
i in e
|
|
106
|
-
? 'object' != typeof e[i] ||
|
|
107
|
-
'[object object]' !=
|
|
108
|
-
Object.prototype.toString.call(e[i]).toLowerCase() ||
|
|
109
|
-
e[i].length
|
|
110
|
-
? (e[i] = t[i])
|
|
111
|
-
: a.json.merge(e[i], t[i])
|
|
112
|
-
: (e[i] = t[i]);
|
|
113
|
-
return e;
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
uuid: {
|
|
117
|
-
newid: function () {
|
|
118
|
-
return (
|
|
119
|
-
new Date().getTime().toString(16) + Math.random().toString(16).substring(2)
|
|
120
|
-
).substring(2, 18);
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
text: {
|
|
124
|
-
is_empty: function (e) {
|
|
125
|
-
return !e || 0 == e.replace(/\s*/, '').length;
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
class r {
|
|
130
|
-
constructor(e, t = {}) {
|
|
131
|
-
(this.jsMind = e),
|
|
132
|
-
(this.options = {
|
|
133
|
-
enabled: !0,
|
|
134
|
-
shortcuts: { copy: 'meta+c', paste: 'meta+v', cut: 'meta+x' },
|
|
135
|
-
...t,
|
|
136
|
-
}),
|
|
137
|
-
(this.clipboardData = null),
|
|
138
|
-
(this.logger = {
|
|
139
|
-
info: e => console.info('[CopyPaste]', e),
|
|
140
|
-
warn: e => console.warn('[CopyPaste]', e),
|
|
141
|
-
error: e => console.error('[CopyPaste]', e),
|
|
142
|
-
debug: e => console.debug('[CopyPaste]', e),
|
|
143
|
-
}),
|
|
144
|
-
this.init();
|
|
145
|
-
}
|
|
146
|
-
init() {
|
|
147
|
-
return this.logger.info('CopyPaste plugin initialized'), !0;
|
|
148
|
-
}
|
|
149
|
-
handleCopy(e) {
|
|
150
|
-
if (!this.options.enabled) return;
|
|
151
|
-
const t = this.jsMind.get_selected_node();
|
|
152
|
-
if (t)
|
|
153
|
-
try {
|
|
154
|
-
e.preventDefault(),
|
|
155
|
-
(this.clipboardData = {
|
|
156
|
-
id: t.id,
|
|
157
|
-
topic: t.topic,
|
|
158
|
-
data: t.data || {},
|
|
159
|
-
direction: t.direction,
|
|
160
|
-
expanded: t.expanded,
|
|
161
|
-
children: this.copyChildren(t),
|
|
162
|
-
}),
|
|
163
|
-
this.logger.info('Node copied:', t.topic),
|
|
164
|
-
this.showMessage('节点已复制');
|
|
165
|
-
} catch (e) {
|
|
166
|
-
this.logger.error('Copy failed:', e), this.showMessage('复制失败', 'error');
|
|
167
|
-
}
|
|
168
|
-
else this.logger.warn('No node selected for copying');
|
|
169
|
-
}
|
|
170
|
-
handlePaste(e) {
|
|
171
|
-
if (!this.options.enabled) return;
|
|
172
|
-
if (!this.clipboardData)
|
|
173
|
-
return (
|
|
174
|
-
this.logger.warn('No data in clipboard'),
|
|
175
|
-
void this.showMessage('剪贴板为空,请先复制节点', 'warning')
|
|
176
|
-
);
|
|
177
|
-
const t = this.jsMind.get_selected_node();
|
|
178
|
-
if (!t)
|
|
179
|
-
return (
|
|
180
|
-
this.logger.warn('No target node selected for pasting'),
|
|
181
|
-
void this.showMessage('请选择目标节点', 'warning')
|
|
182
|
-
);
|
|
183
|
-
try {
|
|
184
|
-
e.preventDefault();
|
|
185
|
-
const i = this.prepareBatchData(this.clipboardData),
|
|
186
|
-
n = this.jsMind.add_nodes(t, [i]);
|
|
187
|
-
n &&
|
|
188
|
-
n.length > 0 &&
|
|
189
|
-
(this.logger.info('Nodes pasted successfully:', this.clipboardData.topic),
|
|
190
|
-
this.showMessage('粘贴成功'));
|
|
191
|
-
} catch (e) {
|
|
192
|
-
this.logger.error('Paste failed:', e), this.showMessage('粘贴失败', 'error');
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
handleCut(e) {
|
|
196
|
-
if (!this.options.enabled) return;
|
|
197
|
-
const t = this.jsMind.get_selected_node();
|
|
198
|
-
if (t) {
|
|
199
|
-
if (t.isroot)
|
|
200
|
-
return (
|
|
201
|
-
this.logger.warn('Cannot cut root node'),
|
|
202
|
-
void this.showMessage('不能剪切根节点', 'warning')
|
|
203
|
-
);
|
|
204
|
-
try {
|
|
205
|
-
e.preventDefault(),
|
|
206
|
-
(this.clipboardData = {
|
|
207
|
-
id: t.id,
|
|
208
|
-
topic: t.topic,
|
|
209
|
-
data: t.data || {},
|
|
210
|
-
direction: t.direction,
|
|
211
|
-
expanded: t.expanded,
|
|
212
|
-
children: this.copyChildren(t),
|
|
213
|
-
});
|
|
214
|
-
this.jsMind.remove_node(t) &&
|
|
215
|
-
(this.logger.info('Node cut:', t.topic), this.showMessage('节点已剪切'));
|
|
216
|
-
} catch (e) {
|
|
217
|
-
this.logger.error('Cut failed:', e), this.showMessage('剪切失败', 'error');
|
|
218
|
-
}
|
|
219
|
-
} else this.logger.warn('No node selected for cutting');
|
|
220
|
-
}
|
|
221
|
-
copyChildren(e) {
|
|
222
|
-
return e.children && 0 !== e.children.length
|
|
223
|
-
? e.children.map(e => ({
|
|
224
|
-
id: e.id,
|
|
225
|
-
topic: e.topic,
|
|
226
|
-
data: e.data || {},
|
|
227
|
-
direction: e.direction,
|
|
228
|
-
expanded: e.expanded,
|
|
229
|
-
children: this.copyChildren(e),
|
|
230
|
-
}))
|
|
231
|
-
: [];
|
|
232
|
-
}
|
|
233
|
-
prepareBatchData(e) {
|
|
234
|
-
return {
|
|
235
|
-
id: a.uuid.newid(),
|
|
236
|
-
topic: e.topic,
|
|
237
|
-
data: e.data || {},
|
|
238
|
-
children:
|
|
239
|
-
e.children && e.children.length > 0
|
|
240
|
-
? e.children.map(e => this.prepareBatchData(e))
|
|
241
|
-
: void 0,
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
pasteChildren(e, t) {
|
|
245
|
-
if (!t || 0 === t.length) return [];
|
|
246
|
-
const i = t.map(e => this.prepareBatchData(e));
|
|
247
|
-
return this.jsMind.add_nodes(e, i);
|
|
248
|
-
}
|
|
249
|
-
showMessage(e, t = 'info') {
|
|
250
|
-
console.log(`[CopyPaste ${t.toUpperCase()}]: ${e}`);
|
|
251
|
-
}
|
|
252
|
-
clear() {
|
|
253
|
-
(this.clipboardData = null), this.logger.info('Clipboard cleared');
|
|
254
|
-
}
|
|
255
|
-
getStatus() {
|
|
256
|
-
return { hasData: !!this.clipboardData, data: this.clipboardData };
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
const s = new n.default.plugin('copy-paste', function (e, t) {
|
|
260
|
-
var i = t || {};
|
|
261
|
-
i.shortcuts = i.shortcuts || { copy: 'meta+c', paste: 'meta+v', cut: 'meta+x' };
|
|
262
|
-
var n = new r(e, i);
|
|
263
|
-
e.view &&
|
|
264
|
-
e.view.e_panel &&
|
|
265
|
-
e.view.e_panel.addEventListener('keydown', function (e) {
|
|
266
|
-
(!e.metaKey && !e.ctrlKey) || 'c' !== e.key || e.shiftKey || e.altKey
|
|
267
|
-
? (!e.metaKey && !e.ctrlKey) || 'v' !== e.key || e.shiftKey || e.altKey
|
|
268
|
-
? (!e.metaKey && !e.ctrlKey) ||
|
|
269
|
-
'x' !== e.key ||
|
|
270
|
-
e.shiftKey ||
|
|
271
|
-
e.altKey ||
|
|
272
|
-
n.handleCut(e)
|
|
273
|
-
: n.handlePaste(e)
|
|
274
|
-
: n.handleCopy(e);
|
|
275
|
-
}),
|
|
276
|
-
(e.copy_paste_handler = n);
|
|
277
|
-
});
|
|
278
|
-
n.default.register_plugin(s),
|
|
279
|
-
(e.copy_paste_plugin = s),
|
|
280
|
-
(e.default = r),
|
|
281
|
-
Object.defineProperty(e, '__esModule', { value: !0 });
|
|
282
|
-
});
|
|
283
|
-
//# sourceMappingURL=jsmind.copy-paste.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.copy-paste.js","sources":["../src/jsmind.dom.js","../src/jsmind.util.js","../src/plugins/copy-paste/copy-paste-plugin-simple.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Lightweight DOM helpers bound to a window.\n */\nclass Dom {\n /**\n * @param {Window} w\n */\n constructor(w) {\n /** @type {Window} */\n this.w = w;\n /** @type {Document} */\n this.d = w.document;\n /**\n * Get element by id.\n * @param {string} id\n * @returns {HTMLElement|null}\n */\n this.g = function (id) {\n return this.d.getElementById(id);\n };\n /**\n * Create element with given tag.\n * @param {string} tag\n * @returns {HTMLElement}\n */\n this.c = function (tag) {\n return this.d.createElement(tag);\n };\n /**\n * Set text content for element.\n * @param {HTMLElement} n\n * @param {string} t\n */\n this.t = function (n, t) {\n if (n.hasChildNodes()) {\n n.firstChild.nodeValue = t;\n } else {\n n.appendChild(this.d.createTextNode(t));\n }\n };\n\n /**\n * Set inner HTML or append element.\n * @param {HTMLElement} n\n * @param {string|HTMLElement} t\n */\n this.h = function (n, t) {\n if (t instanceof HTMLElement) {\n n.innerHTML = '';\n n.appendChild(t);\n } else {\n n.innerHTML = t;\n }\n };\n // detect isElement\n /**\n * Runtime check for HTMLElement.\n * @param {unknown} el\n * @returns {el is HTMLElement}\n */\n this.i = function (el) {\n return (\n !!el &&\n typeof el === 'object' &&\n el.nodeType === 1 &&\n typeof el.style === 'object' &&\n typeof el.ownerDocument === 'object'\n );\n };\n\n //target,eventType,handler\n /**\n * Add event listener with legacy fallback.\n * @param {HTMLElement} t\n * @param {string} e\n * @param {(ev:Event)=>void} h\n */\n this.on = function (t, e, h) {\n if (!!t.addEventListener) {\n t.addEventListener(e, h, false);\n } else {\n t.attachEvent('on' + e, h);\n }\n };\n }\n}\n\nexport const $ = new Dom(window);\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { $ } from './jsmind.dom.js';\n\n/**\n * Misc utility collection.\n * @type {{\n * file: { read: (file: File, cb:(result:string,name:string)=>void)=>void, save:(data:string,type:string,name:string)=>void},\n * json: { json2string:(v:unknown)=>string, string2json:(s:string)=>unknown, merge:(b:object,a:object)=>object },\n * uuid: { newid:()=>string },\n * text: { is_empty:(s?:string)=>boolean }\n * }}\n */\nexport const util = {\n file: {\n read: function (file_data, fn_callback) {\n var reader = new FileReader();\n reader.onload = function () {\n if (typeof fn_callback === 'function') {\n fn_callback(this.result, file_data.name);\n }\n };\n reader.readAsText(file_data);\n },\n\n save: function (file_data, type, name) {\n var blob;\n if (typeof $.w.Blob === 'function') {\n blob = new Blob([file_data], { type: type });\n } else {\n var BlobBuilder =\n $.w.BlobBuilder ||\n $.w.MozBlobBuilder ||\n $.w.WebKitBlobBuilder ||\n $.w.MSBlobBuilder;\n var bb = new BlobBuilder();\n bb.append(file_data);\n blob = bb.getBlob(type);\n }\n if (navigator.msSaveBlob) {\n navigator.msSaveBlob(blob, name);\n } else {\n var URL = $.w.URL || $.w.webkitURL;\n var blob_url = URL.createObjectURL(blob);\n var anchor = $.c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = blob_url;\n anchor.download = name;\n $.d.body.appendChild(anchor);\n var evt = $.d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $.d.body.removeChild(anchor);\n } else {\n location.href = blob_url;\n }\n }\n },\n },\n\n json: {\n json2string: function (json) {\n return JSON.stringify(json);\n },\n string2json: function (json_str) {\n return JSON.parse(json_str);\n },\n merge: function (b, a) {\n for (var o in a) {\n if (o in b) {\n if (\n typeof b[o] === 'object' &&\n Object.prototype.toString.call(b[o]).toLowerCase() == '[object object]' &&\n !b[o].length\n ) {\n util.json.merge(b[o], a[o]);\n } else {\n b[o] = a[o];\n }\n } else {\n b[o] = a[o];\n }\n }\n return b;\n },\n },\n\n uuid: {\n newid: function () {\n return (\n new Date().getTime().toString(16) + Math.random().toString(16).substring(2)\n ).substring(2, 18);\n },\n },\n\n text: {\n is_empty: function (s) {\n if (!s) {\n return true;\n }\n return s.replace(/\\s*/, '').length == 0;\n },\n },\n};\n","/**\n * @license BSD-3-Clause\n * @copyright 2014-2025 hizzgdev@163.com\n *\n * Project Home:\n * https://github.com/hizzgdev/jsmind/\n */\n\nimport { Plugin } from '../../jsmind.plugin.js';\nimport { util } from '../../jsmind.util.js';\nimport jsMind from '@umbraci/jsmind';\n\n/**\n * 简化版复制粘贴插件\n */\n\nclass CopyPasteHandler {\n constructor(jm, options = {}) {\n this.jsMind = jm;\n this.options = {\n enabled: true,\n shortcuts: {\n copy: 'meta+c',\n paste: 'meta+v',\n cut: 'meta+x'\n },\n ...options\n };\n this.clipboardData = null;\n\n this.logger = {\n info: (msg) => console.info('[CopyPaste]', msg),\n warn: (msg) => console.warn('[CopyPaste]', msg),\n error: (msg) => console.error('[CopyPaste]', msg),\n debug: (msg) => console.debug('[CopyPaste]', msg)\n };\n\n this.init();\n }\n\n init() {\n this.logger.info('CopyPaste plugin initialized');\n return true;\n }\n\n handleCopy(event) {\n if (!this.options.enabled) return;\n\n const selectedNode = this.jsMind.get_selected_node();\n if (!selectedNode) {\n this.logger.warn('No node selected for copying');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 复制节点数据\n this.clipboardData = {\n id: selectedNode.id,\n topic: selectedNode.topic,\n data: selectedNode.data || {},\n direction: selectedNode.direction,\n expanded: selectedNode.expanded,\n children: this.copyChildren(selectedNode)\n };\n\n this.logger.info('Node copied:', selectedNode.topic);\n\n // 显示成功消息\n this.showMessage('节点已复制');\n\n } catch (error) {\n this.logger.error('Copy failed:', error);\n this.showMessage('复制失败', 'error');\n }\n }\n\n handlePaste(event) {\n if (!this.options.enabled) return;\n if (!this.clipboardData) {\n this.logger.warn('No data in clipboard');\n this.showMessage('剪贴板为空,请先复制节点', 'warning');\n return;\n }\n\n const targetNode = this.jsMind.get_selected_node();\n if (!targetNode) {\n this.logger.warn('No target node selected for pasting');\n this.showMessage('请选择目标节点', 'warning');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 准备批量数据(包含所有子节点)\n const batchData = this.prepareBatchData(this.clipboardData);\n\n // 使用 add_nodes 批量创建节点\n const createdNodes = this.jsMind.add_nodes(targetNode, [batchData]);\n\n if (createdNodes && createdNodes.length > 0) {\n this.logger.info('Nodes pasted successfully:', this.clipboardData.topic);\n this.showMessage('粘贴成功');\n }\n\n } catch (error) {\n this.logger.error('Paste failed:', error);\n this.showMessage('粘贴失败', 'error');\n }\n }\n\n handleCut(event) {\n if (!this.options.enabled) return;\n\n const selectedNode = this.jsMind.get_selected_node();\n if (!selectedNode) {\n this.logger.warn('No node selected for cutting');\n return;\n }\n\n if (selectedNode.isroot) {\n this.logger.warn('Cannot cut root node');\n this.showMessage('不能剪切根节点', 'warning');\n return;\n }\n\n try {\n event.preventDefault();\n\n // 先复制到剪贴板\n this.clipboardData = {\n id: selectedNode.id,\n topic: selectedNode.topic,\n data: selectedNode.data || {},\n direction: selectedNode.direction,\n expanded: selectedNode.expanded,\n children: this.copyChildren(selectedNode)\n };\n\n // 删除原节点\n const removed = this.jsMind.remove_node(selectedNode);\n\n if (removed) {\n this.logger.info('Node cut:', selectedNode.topic);\n this.showMessage('节点已剪切');\n }\n\n } catch (error) {\n this.logger.error('Cut failed:', error);\n this.showMessage('剪切失败', 'error');\n }\n }\n\n copyChildren(node) {\n if (!node.children || node.children.length === 0) {\n return [];\n }\n\n return node.children.map(child => ({\n id: child.id,\n topic: child.topic,\n data: child.data || {},\n direction: child.direction,\n expanded: child.expanded,\n children: this.copyChildren(child)\n }));\n }\n\n /**\n * 准备批量数据,将节点数据转换为 add_nodes 所需的格式\n * @param {Object} nodeData - 节点数据\n * @returns {Object} - 格式化后的批量数据\n */\n prepareBatchData(nodeData) {\n return {\n id: util.uuid.newid(),\n topic: nodeData.topic,\n data: nodeData.data || {},\n children: nodeData.children && nodeData.children.length > 0\n ? nodeData.children.map(child => this.prepareBatchData(child))\n : undefined\n };\n }\n\n pasteChildren(parentNode, children) {\n // 保留此方法以备兼容性,但新的实现不再使用递归方式\n if (!children || children.length === 0) return [];\n\n const batchData = children.map(child => this.prepareBatchData(child));\n return this.jsMind.add_nodes(parentNode, batchData);\n }\n\n showMessage(message, type = 'info') {\n // 简单的消息显示\n console.log(`[CopyPaste ${type.toUpperCase()}]: ${message}`);\n }\n\n clear() {\n this.clipboardData = null;\n this.logger.info('Clipboard cleared');\n }\n\n getStatus() {\n return {\n hasData: !!this.clipboardData,\n data: this.clipboardData\n };\n }\n}\n\n/**\n * 复制粘贴插件注册\n */\nexport const copy_paste_plugin = new jsMind.plugin('copy-paste', function (jm, options) {\n // 确保options存在且包含shortcuts\n var pluginOptions = options || {};\n pluginOptions.shortcuts = pluginOptions.shortcuts || {\n copy: 'meta+c',\n paste: 'meta+v',\n cut: 'meta+x'\n };\n\n var handler = new CopyPasteHandler(jm, pluginOptions);\n\n // 直接注册键盘事件监听器,而不是使用不存在的add_shortcut方法\n if (jm.view && jm.view.e_panel) {\n jm.view.e_panel.addEventListener('keydown', function(event) {\n // 检查是否按下了复制快捷键\n if ((event.metaKey || event.ctrlKey) && event.key === 'c' && !event.shiftKey && !event.altKey) {\n handler.handleCopy(event);\n }\n // 检查是否按下了粘贴快捷键\n else if ((event.metaKey || event.ctrlKey) && event.key === 'v' && !event.shiftKey && !event.altKey) {\n handler.handlePaste(event);\n }\n // 检查是否按下了剪切快捷键\n else if ((event.metaKey || event.ctrlKey) && event.key === 'x' && !event.shiftKey && !event.altKey) {\n handler.handleCut(event);\n }\n });\n }\n\n // 将处理器实例附加到jm对象,方便外部调用\n jm.copy_paste_handler = handler;\n});\n\n// 注册插件\njsMind.register_plugin(copy_paste_plugin);\n\nexport default CopyPasteHandler;"],"names":["$","constructor","w","this","d","document","g","id","getElementById","c","tag","createElement","t","n","hasChildNodes","firstChild","nodeValue","appendChild","createTextNode","h","HTMLElement","innerHTML","i","el","nodeType","style","ownerDocument","on","e","addEventListener","attachEvent","window","util","file","read","file_data","fn_callback","reader","FileReader","onload","result","name","readAsText","save","type","blob","Blob","bb","BlobBuilder","MozBlobBuilder","WebKitBlobBuilder","MSBlobBuilder","append","getBlob","navigator","msSaveBlob","blob_url","URL","webkitURL","createObjectURL","anchor","visibility","href","download","body","evt","createEvent","initEvent","dispatchEvent","removeChild","location","json","json2string","JSON","stringify","string2json","json_str","parse","merge","b","a","o","Object","prototype","toString","call","toLowerCase","length","uuid","newid","Date","getTime","Math","random","substring","text","is_empty","s","replace","CopyPasteHandler","jm","options","jsMind","enabled","shortcuts","copy","paste","cut","clipboardData","logger","info","msg","console","warn","error","debug","init","handleCopy","event","selectedNode","get_selected_node","preventDefault","topic","data","direction","expanded","children","copyChildren","showMessage","handlePaste","targetNode","batchData","prepareBatchData","createdNodes","add_nodes","handleCut","isroot","remove_node","node","map","child","nodeData","undefined","pasteChildren","parentNode","message","log","toUpperCase","clear","getStatus","hasData","copy_paste_plugin","plugin","pluginOptions","handler","view","e_panel","metaKey","ctrlKey","key","shiftKey","altKey","copy_paste_handler","register_plugin"],"mappings":"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"}
|