@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
package/es/jsmind.screenshot.js
CHANGED
|
@@ -1,138 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import t from
|
|
9
|
-
import e from 'dom-to-image';
|
|
10
|
-
if (!t) throw new Error('jsMind is not defined');
|
|
11
|
-
if (!e) throw new Error('dom-to-image is required');
|
|
12
|
-
const i = t.$,
|
|
13
|
-
n = {
|
|
14
|
-
filename: null,
|
|
15
|
-
watermark: { left: i.w.location, right: 'https://github.com/UmbraCi/jsmind' },
|
|
16
|
-
background: 'transparent',
|
|
17
|
-
};
|
|
18
|
-
class r {
|
|
19
|
-
constructor(e, i) {
|
|
20
|
-
var r = {};
|
|
21
|
-
t.util.json.merge(r, n),
|
|
22
|
-
t.util.json.merge(r, i),
|
|
23
|
-
(this.version = '0.2.0'),
|
|
24
|
-
(this.jm = e),
|
|
25
|
-
(this.options = r),
|
|
26
|
-
(this.dpr = e.view.device_pixel_ratio);
|
|
27
|
-
}
|
|
28
|
-
shoot() {
|
|
29
|
-
let t = this.create_canvas(),
|
|
30
|
-
e = t.getContext('2d');
|
|
31
|
-
e.scale(this.dpr, this.dpr),
|
|
32
|
-
Promise.resolve(e)
|
|
33
|
-
.then(() => this.draw_background(e))
|
|
34
|
-
.then(() => this.draw_lines(e))
|
|
35
|
-
.then(() => this.draw_nodes(e))
|
|
36
|
-
.then(() => this.draw_watermark(t, e))
|
|
37
|
-
.then(() => this.download(t))
|
|
38
|
-
.then(() => this.clear(t));
|
|
39
|
-
}
|
|
40
|
-
create_canvas() {
|
|
41
|
-
let t = i.c('canvas');
|
|
42
|
-
const e = this.jm.view.size.w,
|
|
43
|
-
n = this.jm.view.size.h;
|
|
44
|
-
return (
|
|
45
|
-
(t.width = e * this.dpr),
|
|
46
|
-
(t.height = n * this.dpr),
|
|
47
|
-
(t.style.width = e + 'px'),
|
|
48
|
-
(t.style.height = n + 'px'),
|
|
49
|
-
(t.style.visibility = 'hidden'),
|
|
50
|
-
this.jm.view.e_panel.appendChild(t),
|
|
51
|
-
t
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
clear(t) {
|
|
55
|
-
t.parentNode.removeChild(t);
|
|
56
|
-
}
|
|
57
|
-
draw_background(t) {
|
|
58
|
-
return new Promise(
|
|
59
|
-
function (e, i) {
|
|
60
|
-
const n = this.options.background;
|
|
61
|
-
n &&
|
|
62
|
-
'transparent' !== n &&
|
|
63
|
-
((t.fillStyle = this.options.background),
|
|
64
|
-
t.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h)),
|
|
65
|
-
e(t);
|
|
66
|
-
}.bind(this)
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
draw_lines(t) {
|
|
70
|
-
return new Promise(
|
|
71
|
-
function (e, i) {
|
|
72
|
-
this.jm.view.graph.copy_to(t, function () {
|
|
73
|
-
e(t);
|
|
74
|
-
});
|
|
75
|
-
}.bind(this)
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
draw_nodes(t) {
|
|
79
|
-
return e
|
|
80
|
-
.toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })
|
|
81
|
-
.then(this.load_image)
|
|
82
|
-
.then(function (e) {
|
|
83
|
-
return t.drawImage(e, 0, 0), t;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
draw_watermark(t, e) {
|
|
87
|
-
return (
|
|
88
|
-
(e.textBaseline = 'bottom'),
|
|
89
|
-
(e.fillStyle = '#000'),
|
|
90
|
-
(e.font = '11px Verdana,Arial,Helvetica,sans-serif'),
|
|
91
|
-
this.options.watermark.left &&
|
|
92
|
-
((e.textAlign = 'left'),
|
|
93
|
-
e.fillText(this.options.watermark.left, 5.5, t.height - 2.5)),
|
|
94
|
-
this.options.watermark.right &&
|
|
95
|
-
((e.textAlign = 'right'),
|
|
96
|
-
e.fillText(this.options.watermark.right, t.width - 5.5, t.height - 2.5)),
|
|
97
|
-
e
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
load_image(t) {
|
|
101
|
-
return new Promise(function (e, i) {
|
|
102
|
-
let n = new Image();
|
|
103
|
-
(n.onload = function () {
|
|
104
|
-
e(n);
|
|
105
|
-
}),
|
|
106
|
-
(n.onerror = i),
|
|
107
|
-
(n.src = t);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
download(t) {
|
|
111
|
-
var e = (this.options.filename || this.jm.mind.name) + '.png';
|
|
112
|
-
if (navigator.msSaveBlob && t.msToBlob) {
|
|
113
|
-
var n = t.msToBlob();
|
|
114
|
-
navigator.msSaveBlob(n, e);
|
|
115
|
-
} else {
|
|
116
|
-
var r = t.toDataURL(),
|
|
117
|
-
o = i.c('a');
|
|
118
|
-
if ('download' in o) {
|
|
119
|
-
(o.style.visibility = 'hidden'),
|
|
120
|
-
(o.href = r),
|
|
121
|
-
(o.download = e),
|
|
122
|
-
i.d.body.appendChild(o);
|
|
123
|
-
var s = i.d.createEvent('MouseEvents');
|
|
124
|
-
s.initEvent('click', !0, !0), o.dispatchEvent(s), i.d.body.removeChild(o);
|
|
125
|
-
} else location.href = r;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const o = new t.plugin('screenshot', function (t, e) {
|
|
130
|
-
var i = new r(t, e);
|
|
131
|
-
(t.screenshot = i),
|
|
132
|
-
(t.shoot = function () {
|
|
133
|
-
i.shoot();
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
t.register_plugin(o);
|
|
137
|
-
export { r as JmScreenshot, r as default, o as screenshot_plugin };
|
|
2
|
+
* @license BSD-3-Clause
|
|
3
|
+
* @copyright 2014-2025 hizzgdev@163.com
|
|
4
|
+
*
|
|
5
|
+
* Project Home:
|
|
6
|
+
* https://github.com/hizzgdev/jsmind/
|
|
7
|
+
*/
|
|
8
|
+
import t from"@umbraci/jsmind";import e from"dom-to-image";"function"!=typeof String.prototype.startsWith&&(String.prototype.startsWith=function(t){return this.slice(0,t.length)===t});class i{static instanceName="";static preload=!1;constructor({jm:t,pluginOpt:e}){this.jm=t,this.options=e||{}}beforePluginRemove(){}beforePluginDestroy(){this.beforePluginRemove()}}if(!t)throw new Error("jsMind is not defined");if(!e)throw new Error("dom-to-image is required");const s=t.$,n={filename:null,watermark:{left:s.w.location,right:"https://github.com/UmbraCi/jsmind"},background:"transparent"};class o{constructor(e,i){var s={};t.util.json.merge(s,n),t.util.json.merge(s,i),this.version="0.2.0",this.jm=e,this.options=s,this.dpr=e.view.device_pixel_ratio}shoot(){let t=this.create_canvas(),e=t.getContext("2d");e.scale(this.dpr,this.dpr),Promise.resolve(e).then(()=>this.draw_background(e)).then(()=>this.draw_lines(e)).then(()=>this.draw_nodes(e)).then(()=>this.draw_watermark(t,e)).then(()=>this.download(t)).then(()=>this.clear(t))}create_canvas(){let t=s.c("canvas");const e=this.jm.view.size.w,i=this.jm.view.size.h;return t.width=e*this.dpr,t.height=i*this.dpr,t.style.width=e+"px",t.style.height=i+"px",t.style.visibility="hidden",this.jm.view.e_panel.appendChild(t),t}clear(t){t.parentNode.removeChild(t)}draw_background(t){return new Promise(function(e,i){const s=this.options.background;s&&"transparent"!==s&&(t.fillStyle=this.options.background,t.fillRect(0,0,this.jm.view.size.w,this.jm.view.size.h)),e(t)}.bind(this))}draw_lines(t){return new Promise(function(e,i){this.jm.view.graph.copy_to(t,function(){e(t)})}.bind(this))}draw_nodes(t){return e.toSvg(this.jm.view.e_nodes,{style:{zoom:1}}).then(this.load_image).then(function(e){return t.drawImage(e,0,0),t})}draw_watermark(t,e){return e.textBaseline="bottom",e.fillStyle="#000",e.font="11px Verdana,Arial,Helvetica,sans-serif",this.options.watermark.left&&(e.textAlign="left",e.fillText(this.options.watermark.left,5.5,t.height-2.5)),this.options.watermark.right&&(e.textAlign="right",e.fillText(this.options.watermark.right,t.width-5.5,t.height-2.5)),e}load_image(t){return new Promise(function(e,i){let s=new Image;s.onload=function(){e(s)},s.onerror=i,s.src=t})}download(t){var e=(this.options.filename||this.jm.mind.name)+".png";if(navigator.msSaveBlob&&t.msToBlob){var i=t.msToBlob();navigator.msSaveBlob(i,e)}else{var n=t.toDataURL(),o=s.c("a");if("download"in o){o.style.visibility="hidden",o.href=n,o.download=e,s.d.body.appendChild(o);var r=s.d.createEvent("MouseEvents");r.initEvent("click",!0,!0),o.dispatchEvent(r),s.d.body.removeChild(o)}else location.href=n}}}class r extends i{static instanceName="screenshot";static preload=!1;constructor({jm:t,pluginOpt:e}){super({jm:t,pluginOpt:e}),this.screenshot=new o(t,e),t.screenshot=this.screenshot,t.shoot=()=>{this.screenshot.shoot()}}beforePluginRemove(){delete this.jm.shoot,delete this.jm.screenshot}}t.usePlugin(r);export{o as JmScreenshot,r as ScreenshotPlugin,o as default};
|
|
138
9
|
//# sourceMappingURL=jsmind.screenshot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsmind.screenshot.js","sources":["../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\nimport domtoimage from 'dom-to-image';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nif (!domtoimage) {\n throw new Error('dom-to-image is required');\n}\n\nconst $ = jsMind.$;\n\n/**\n * Default options for screenshot plugin.\n * @typedef {Object} ScreenshotOptions\n * @property {string|null} [filename]\n * @property {{left?:string|Location,right?:string}} [watermark]\n * @property {string} [background]\n */\nconst DEFAULT_OPTIONS = {\n filename: null,\n watermark: {\n left: $.w.location,\n right: 'https://github.com/UmbraCi/jsmind',\n },\n background: 'transparent',\n};\n\n/**\n * Screenshot plugin for jsMind.\n */\nexport class JmScreenshot {\n /**\n * Create screenshot plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<ScreenshotOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.2.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {ScreenshotOptions} */\n this.options = opts;\n /** @type {number} */\n this.dpr = jm.view.device_pixel_ratio;\n }\n\n /** Take a screenshot of the mind map. */\n shoot() {\n let c = this.create_canvas();\n let ctx = c.getContext('2d');\n ctx.scale(this.dpr, this.dpr);\n Promise.resolve(ctx)\n .then(() => this.draw_background(ctx))\n .then(() => this.draw_lines(ctx))\n .then(() => this.draw_nodes(ctx))\n .then(() => this.draw_watermark(c, ctx))\n .then(() => this.download(c))\n .then(() => this.clear(c));\n }\n\n /**\n * Create canvas for screenshot.\n * @returns {HTMLCanvasElement} Canvas element\n */\n create_canvas() {\n let c = $.c('canvas');\n const w = this.jm.view.size.w;\n const h = this.jm.view.size.h;\n c.width = w * this.dpr;\n c.height = h * this.dpr;\n c.style.width = w + 'px';\n c.style.height = h + 'px';\n\n c.style.visibility = 'hidden';\n this.jm.view.e_panel.appendChild(c);\n return c;\n }\n\n /**\n * Clean up canvas element.\n * @param {HTMLCanvasElement} c - Canvas to remove\n */\n clear(c) {\n c.parentNode.removeChild(c);\n }\n\n /**\n * Draw background on canvas.\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\n */\n draw_background(ctx) {\n return new Promise(\n function (resolve, _) {\n const bg = this.options.background;\n if (!!bg && bg !== 'transparent') {\n ctx.fillStyle = this.options.background;\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n resolve(ctx);\n }.bind(this)\n );\n }\n\n /**\n * Draw connection lines on canvas by copying from view graph.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_lines(ctx) {\n return new Promise(\n function (resolve, _) {\n this.jm.view.graph.copy_to(ctx, function () {\n resolve(ctx);\n });\n }.bind(this)\n );\n }\n\n /**\n * Draw node DOM into canvas via SVG snapshot.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_nodes(ctx) {\n return domtoimage\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\n .then(this.load_image)\n .then(function (img) {\n ctx.drawImage(img, 0, 0);\n return ctx;\n });\n }\n\n /**\n * Draw watermark text on canvas.\n * @param {HTMLCanvasElement} c\n * @param {CanvasRenderingContext2D} ctx\n * @returns {CanvasRenderingContext2D}\n */\n draw_watermark(c, ctx) {\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n if (!!this.options.watermark.left) {\n ctx.textAlign = 'left';\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\n }\n if (!!this.options.watermark.right) {\n ctx.textAlign = 'right';\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\n }\n return ctx;\n }\n\n /**\n * Load image from URL and resolve img element.\n * @param {string} url\n * @returns {Promise<HTMLImageElement>}\n */\n load_image(url) {\n return new Promise(function (resolve, reject) {\n let img = new Image();\n img.onload = function () {\n resolve(img);\n };\n img.onerror = reject;\n img.src = url;\n });\n }\n\n /**\n * Trigger download of canvas content as PNG.\n * @param {HTMLCanvasElement} c\n */\n download(c) {\n var name = (this.options.filename || this.jm.mind.name) + '.png';\n\n if (navigator.msSaveBlob && !!c.msToBlob) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var blob_url = c.toDataURL();\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/**\n * Screenshot plugin registration.\n * @type {import('../jsmind.plugin.js').Plugin<Partial<ScreenshotOptions>>}\n */\nexport const screenshot_plugin = new jsMind.plugin('screenshot', function (jm, options) {\n var jmss = new JmScreenshot(jm, options);\n jm.screenshot = jmss;\n jm.shoot = function () {\n jmss.shoot();\n };\n});\n\njsMind.register_plugin(screenshot_plugin);\n\nexport default JmScreenshot;\n"],"names":["jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","constructor","jm","options","opts","util","json","merge","this","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","screenshot_plugin","plugin","jmss","screenshot","register_plugin"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"jsmind.screenshot.js","sources":["../src/jsmind.common.js","../src/jsmind.plugin.js","../src/plugins/jsmind.screenshot.js"],"sourcesContent":["/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\n/**\n * Library version string.\n * @type {string}\n */\nexport const __version__ = '0.9.1';\n/**\n * Library author.\n * @type {string}\n */\nexport const __author__ = 'UmbraCi';\n\nif (typeof String.prototype.startsWith != 'function') {\n String.prototype.startsWith = function (p) {\n return this.slice(0, p.length) === p;\n };\n}\n\n/**\n * Direction constants and parser.\n * @typedef {{left:number,center:number,right:number,of:(dir:(string|number))=>number|undefined}} DirectionType\n */\n/** @type {DirectionType} */\nexport const Direction = {\n left: -1,\n center: 0,\n right: 1,\n of: function (dir) {\n if (!dir || dir === -1 || dir === 0 || dir === 1) {\n return dir;\n }\n if (dir === '-1' || dir === '0' || dir === '1') {\n return parseInt(dir);\n }\n if (dir.toLowerCase() === 'left') {\n return this.left;\n }\n if (dir.toLowerCase() === 'right') {\n return this.right;\n }\n if (dir.toLowerCase() === 'center') {\n return this.center;\n }\n },\n};\n/** @enum {number} */\nexport const EventType = { show: 1, resize: 2, edit: 3, select: 4, reset: 5, history_change: 6 };\n/** @enum {number} */\nexport const Key = { meta: 1 << 13, ctrl: 1 << 12, alt: 1 << 11, shift: 1 << 10 };\n/** @enum {number} */\nexport const LogLevel = { debug: 1, info: 2, warn: 3, error: 4, disable: 9 };\n\n// an noop function define\nvar _noop = function () {};\n/**\n * Logger facade with dynamic level.\n * @type {{level:(lvl:number)=>void,log:Function,debug:Function,info:Function,warn:Function,error:Function}}\n */\nexport let logger =\n typeof console === 'undefined'\n ? {\n level: _noop,\n log: _noop,\n debug: _noop,\n info: _noop,\n warn: _noop,\n error: _noop,\n }\n : {\n level: setup_logger_level,\n log: console.log,\n debug: console.debug,\n info: console.info,\n warn: console.warn,\n error: console.error,\n };\n\n/**\n * Set logger level.\n * @param {number} log_level\n */\nfunction setup_logger_level(log_level) {\n if (log_level > LogLevel.debug) {\n logger.debug = _noop;\n } else {\n logger.debug = console.debug;\n }\n if (log_level > LogLevel.info) {\n logger.info = _noop;\n } else {\n logger.info = console.info;\n }\n if (log_level > LogLevel.warn) {\n logger.warn = _noop;\n } else {\n logger.warn = console.warn;\n }\n if (log_level > LogLevel.error) {\n logger.error = _noop;\n } else {\n logger.error = console.error;\n }\n}\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport { logger } from './jsmind.common.js';\n\n/**\n * Plugin Manager\n * Manages plugin lifecycle with synchronous initialization,\n * preload support, and lifecycle hooks.\n */\nexport class PluginManager {\n /**\n * @param {import('./jsmind.js').default} jm - jsMind instance\n */\n constructor(jm) {\n this.jm = jm;\n /** @type {Map<string, Plugin>} */\n this.plugins = new Map();\n }\n\n /**\n * Initialize preload plugins (before core modules)\n */\n initPreloadPlugins() {\n const preloadPlugins = this.jm.constructor.pluginList.filter(d => d.preload);\n logger.info('Initializing ' + preloadPlugins.length + ' preload plugins');\n preloadPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Initialize normal plugins (after core modules)\n */\n initNormalPlugins() {\n const normalPlugins = this.jm.constructor.pluginList.filter(d => !d.preload);\n logger.info('Initializing ' + normalPlugins.length + ' normal plugins');\n normalPlugins.forEach(descriptor => {\n this._initPlugin(descriptor);\n });\n }\n\n /**\n * Internal method: Initialize a single plugin\n * @param {PluginDescriptor} descriptor\n * @private\n */\n _initPlugin(descriptor) {\n try {\n const { PluginClass, pluginOpt } = descriptor;\n\n if (!PluginClass.instanceName) {\n throw new Error('Plugin ' + PluginClass.name + ' must define static instanceName');\n }\n if (this.plugins.has(PluginClass.instanceName)) {\n logger.warn(\n 'Plugin ' + PluginClass.instanceName + ' already exists, will be replaced'\n );\n }\n\n const instance = new PluginClass({\n jm: this.jm,\n pluginOpt: pluginOpt || {},\n });\n\n this.plugins.set(PluginClass.instanceName, instance);\n this.jm[PluginClass.instanceName] = instance;\n descriptor.instance = instance;\n\n logger.info('Plugin ' + PluginClass.instanceName + ' initialized');\n } catch (error) {\n logger.error('Failed to initialize plugin ' + descriptor.PluginClass.name + ':', error);\n }\n }\n\n /**\n * Remove a plugin\n * @param {typeof Plugin} PluginClass\n */\n removePlugin(PluginClass) {\n const instanceName = PluginClass.instanceName;\n if (!instanceName) {\n return;\n }\n\n const instance = this.plugins.get(instanceName);\n if (!instance) {\n return;\n }\n\n try {\n if (typeof instance.beforePluginRemove === 'function') {\n instance.beforePluginRemove();\n }\n\n this.plugins.delete(instanceName);\n delete this.jm[instanceName];\n\n const list = this.jm.constructor.pluginList;\n const index = list.findIndex(d => d.PluginClass === PluginClass);\n if (index !== -1) {\n list.splice(index, 1);\n }\n\n logger.info('Plugin ' + instanceName + ' removed');\n } catch (error) {\n logger.error('Failed to remove plugin ' + instanceName + ':', error);\n }\n }\n\n /**\n * Destroy all plugins\n */\n destroyAllPlugins() {\n this.plugins.forEach((instance, instanceName) => {\n try {\n if (typeof instance.beforePluginDestroy === 'function') {\n instance.beforePluginDestroy();\n }\n } catch (error) {\n logger.error('Failed to destroy plugin ' + instanceName + ':', error);\n }\n });\n\n this.plugins.clear();\n }\n\n /**\n * Get plugin instance by name\n * @param {string} instanceName\n * @returns {Plugin | undefined}\n */\n getPlugin(instanceName) {\n return this.plugins.get(instanceName);\n }\n}\n\n/**\n * Plugin Base Class\n * Provides standard plugin interface.\n */\nexport class Plugin {\n /**\n * Plugin instance name (must be defined by subclass)\n * @type {string}\n */\n static instanceName = '';\n\n /**\n * Whether to initialize before core modules\n * @type {boolean}\n */\n static preload = false;\n\n /**\n * @param {{ jm: import('./jsmind.js').default, pluginOpt: object }} params\n */\n constructor({ jm, pluginOpt }) {\n this.jm = jm;\n this.options = pluginOpt || {};\n }\n\n /**\n * Called before plugin is removed\n */\n beforePluginRemove() {}\n\n /**\n * Called before jsMind instance is destroyed\n */\n beforePluginDestroy() {\n this.beforePluginRemove();\n }\n}\n\n/**\n * Plugin descriptor\n * @typedef {object} PluginDescriptor\n * @property {typeof Plugin} PluginClass - Plugin class\n * @property {string} instanceName - Plugin instance name\n * @property {boolean} preload - Whether to preload\n * @property {object} pluginOpt - Plugin options\n * @property {Plugin | null} instance - Plugin instance (after initialization)\n */\n","/**\n * @license BSD\n * @copyright 2014-2025 UmbraCi\n *\n * Project Home:\n * https://github.com/UmbraCi/jsmind/\n */\n\nimport jsMind from '@umbraci/jsmind';\nimport domtoimage from 'dom-to-image';\nimport { Plugin } from '../jsmind.plugin.js';\n\nif (!jsMind) {\n throw new Error('jsMind is not defined');\n}\n\nif (!domtoimage) {\n throw new Error('dom-to-image is required');\n}\n\nconst $ = jsMind.$;\n\n/**\n * Default options for screenshot plugin.\n * @typedef {Object} ScreenshotOptions\n * @property {string|null} [filename]\n * @property {{left?:string|Location,right?:string}} [watermark]\n * @property {string} [background]\n */\nconst DEFAULT_OPTIONS = {\n filename: null,\n watermark: {\n left: $.w.location,\n right: 'https://github.com/UmbraCi/jsmind',\n },\n background: 'transparent',\n};\n\n/**\n * Screenshot plugin for jsMind.\n */\nexport class JmScreenshot {\n /**\n * Create screenshot plugin instance.\n * @param {import('../jsmind.js').default} jm - jsMind instance\n * @param {Partial<ScreenshotOptions>} options - Plugin options\n */\n constructor(jm, options) {\n var opts = {};\n jsMind.util.json.merge(opts, DEFAULT_OPTIONS);\n jsMind.util.json.merge(opts, options);\n\n this.version = '0.2.0';\n /** @type {import('../jsmind.js').default} */\n this.jm = jm;\n /** @type {ScreenshotOptions} */\n this.options = opts;\n /** @type {number} */\n this.dpr = jm.view.device_pixel_ratio;\n }\n\n /** Take a screenshot of the mind map. */\n shoot() {\n let c = this.create_canvas();\n let ctx = c.getContext('2d');\n ctx.scale(this.dpr, this.dpr);\n Promise.resolve(ctx)\n .then(() => this.draw_background(ctx))\n .then(() => this.draw_lines(ctx))\n .then(() => this.draw_nodes(ctx))\n .then(() => this.draw_watermark(c, ctx))\n .then(() => this.download(c))\n .then(() => this.clear(c));\n }\n\n /**\n * Create canvas for screenshot.\n * @returns {HTMLCanvasElement} Canvas element\n */\n create_canvas() {\n let c = $.c('canvas');\n const w = this.jm.view.size.w;\n const h = this.jm.view.size.h;\n c.width = w * this.dpr;\n c.height = h * this.dpr;\n c.style.width = w + 'px';\n c.style.height = h + 'px';\n\n c.style.visibility = 'hidden';\n this.jm.view.e_panel.appendChild(c);\n return c;\n }\n\n /**\n * Clean up canvas element.\n * @param {HTMLCanvasElement} c - Canvas to remove\n */\n clear(c) {\n c.parentNode.removeChild(c);\n }\n\n /**\n * Draw background on canvas.\n * @param {CanvasRenderingContext2D} ctx - Canvas context\n * @returns {Promise<CanvasRenderingContext2D>} Promise resolving to context\n */\n draw_background(ctx) {\n return new Promise(\n function (resolve, _) {\n const bg = this.options.background;\n if (!!bg && bg !== 'transparent') {\n ctx.fillStyle = this.options.background;\n ctx.fillRect(0, 0, this.jm.view.size.w, this.jm.view.size.h);\n }\n resolve(ctx);\n }.bind(this)\n );\n }\n\n /**\n * Draw connection lines on canvas by copying from view graph.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_lines(ctx) {\n return new Promise(\n function (resolve, _) {\n this.jm.view.graph.copy_to(ctx, function () {\n resolve(ctx);\n });\n }.bind(this)\n );\n }\n\n /**\n * Draw node DOM into canvas via SVG snapshot.\n * @param {CanvasRenderingContext2D} ctx\n * @returns {Promise<CanvasRenderingContext2D>}\n */\n draw_nodes(ctx) {\n return domtoimage\n .toSvg(this.jm.view.e_nodes, { style: { zoom: 1 } })\n .then(this.load_image)\n .then(function (img) {\n ctx.drawImage(img, 0, 0);\n return ctx;\n });\n }\n\n /**\n * Draw watermark text on canvas.\n * @param {HTMLCanvasElement} c\n * @param {CanvasRenderingContext2D} ctx\n * @returns {CanvasRenderingContext2D}\n */\n draw_watermark(c, ctx) {\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n if (!!this.options.watermark.left) {\n ctx.textAlign = 'left';\n ctx.fillText(this.options.watermark.left, 5.5, c.height - 2.5);\n }\n if (!!this.options.watermark.right) {\n ctx.textAlign = 'right';\n ctx.fillText(this.options.watermark.right, c.width - 5.5, c.height - 2.5);\n }\n return ctx;\n }\n\n /**\n * Load image from URL and resolve img element.\n * @param {string} url\n * @returns {Promise<HTMLImageElement>}\n */\n load_image(url) {\n return new Promise(function (resolve, reject) {\n let img = new Image();\n img.onload = function () {\n resolve(img);\n };\n img.onerror = reject;\n img.src = url;\n });\n }\n\n /**\n * Trigger download of canvas content as PNG.\n * @param {HTMLCanvasElement} c\n */\n download(c) {\n var name = (this.options.filename || this.jm.mind.name) + '.png';\n\n if (navigator.msSaveBlob && !!c.msToBlob) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var blob_url = c.toDataURL();\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/**\n * Screenshot plugin for unified plugin system.\n */\nexport class ScreenshotPlugin extends Plugin {\n static instanceName = 'screenshot';\n static preload = false;\n\n /**\n * @param {{ jm: import('../jsmind.js').default, pluginOpt: Partial<ScreenshotOptions> }} params\n */\n constructor({ jm, pluginOpt }) {\n super({ jm, pluginOpt });\n this.screenshot = new JmScreenshot(jm, pluginOpt);\n jm.screenshot = this.screenshot;\n jm.shoot = () => {\n this.screenshot.shoot();\n };\n }\n\n beforePluginRemove() {\n delete this.jm.shoot;\n delete this.jm.screenshot;\n }\n}\n\njsMind.usePlugin(ScreenshotPlugin);\n\nexport default JmScreenshot;\n"],"names":["String","prototype","startsWith","p","this","slice","length","Plugin","static","constructor","jm","pluginOpt","options","beforePluginRemove","beforePluginDestroy","jsMind","Error","domtoimage","$","DEFAULT_OPTIONS","filename","watermark","left","w","location","right","background","JmScreenshot","opts","util","json","merge","version","dpr","view","device_pixel_ratio","shoot","c","create_canvas","ctx","getContext","scale","Promise","resolve","then","draw_background","draw_lines","draw_nodes","draw_watermark","download","clear","size","h","width","height","style","visibility","e_panel","appendChild","parentNode","removeChild","_","bg","fillStyle","fillRect","bind","graph","copy_to","toSvg","e_nodes","zoom","load_image","img","drawImage","textBaseline","font","textAlign","fillText","url","reject","Image","onload","onerror","src","name","mind","navigator","msSaveBlob","msToBlob","blob","blob_url","toDataURL","anchor","href","d","body","evt","createEvent","initEvent","dispatchEvent","ScreenshotPlugin","super","screenshot","usePlugin"],"mappings":"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"}
|