remons-markdown-editor 1.0.0 → 2.0.0-beta.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/MarkdownEditor.d.ts +24 -5
- package/dist/components/Dialog/EditDialog.d.ts +6 -3
- package/dist/components/Editor/codemirrorExtensions.d.ts +4 -4
- package/dist/components/Editor/containerWidget.d.ts +24 -8
- package/dist/components/Editor/index.d.ts +2 -1
- package/dist/components/Icon/config.d.ts +9 -0
- package/dist/components/Preview/index.d.ts +6 -5
- package/dist/components/Toolbar/buttons.d.ts +3 -3
- package/dist/components/Toolbar/config.d.ts +9 -2
- package/dist/components/Toolbar/hooks/useToolbar.d.ts +3 -1
- package/dist/components/Toolbar/index.d.ts +6 -3
- package/dist/components/Toolbar/renderers/TablePicker/TableDropdown.d.ts +1 -2
- package/dist/hooks/useRegisterToolbar.d.ts +3 -0
- package/dist/hooks/useScrollSync.d.ts +5 -2
- package/dist/index.cjs +2101 -406
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +51 -80
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2123 -409
- package/dist/index.js.map +1 -1
- package/dist/registry/componentRegistry.d.ts +17 -4
- package/dist/types/index.d.ts +19 -10
- package/dist/utils/parseContainer.d.ts +26 -6
- package/dist/utils/writeContainer.d.ts +11 -7
- package/package.json +12 -15
- package/readme.md +26 -22
- package/dist/App.d.ts +0 -2
- package/dist/main.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Button, ColorPicker, DatePicker, Dropdown, Form, Input, InputNumber, Modal, Rate, Select, Slider, Splitter, Switch, Tooltip, message } from "antd";
|
|
1
|
+
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
2
|
+
import { App, Button, ColorPicker, DatePicker, Dropdown, Form, Input, InputNumber, Modal, Rate, Select, Slider, Splitter, Switch, Tooltip, message } from "antd";
|
|
3
3
|
import { EditorView, basicSetup } from "codemirror";
|
|
4
|
-
import { EditorState, Facet } from "@codemirror/state";
|
|
4
|
+
import { EditorState, Facet, StateEffect } from "@codemirror/state";
|
|
5
5
|
import { Decoration, EditorView as EditorView$1, ViewPlugin, WidgetType, keymap } from "@codemirror/view";
|
|
6
6
|
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
|
|
7
7
|
import { markdown } from "@codemirror/lang-markdown";
|
|
@@ -11,83 +11,1217 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
import RenderMarkdown, { initHighlighter, languagesCommon } from "remons-render-markdown";
|
|
12
12
|
import "remons-render-markdown/dist/index.css";
|
|
13
13
|
import { BoldOutlined, CheckSquareOutlined, CodeOutlined, DownOutlined, FontSizeOutlined, FullscreenExitOutlined, FullscreenOutlined, ItalicOutlined, LinkOutlined, MinusOutlined, OrderedListOutlined, PictureOutlined, ReadOutlined, StrikethroughOutlined, TableOutlined, UnderlineOutlined, UnorderedListOutlined, createFromIconfontCN } from "@ant-design/icons";
|
|
14
|
-
//#region
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
return props;
|
|
30
|
-
} catch {
|
|
31
|
-
return {};
|
|
14
|
+
//#region \0rolldown/runtime.js
|
|
15
|
+
var __create = Object.create;
|
|
16
|
+
var __defProp = Object.defineProperty;
|
|
17
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
18
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
19
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
20
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
21
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
24
|
+
key = keys[i];
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
26
|
+
get: ((k) => from[k]).bind(null, key),
|
|
27
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
28
|
+
});
|
|
32
29
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
30
|
+
return to;
|
|
31
|
+
};
|
|
32
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
33
|
+
value: mod,
|
|
34
|
+
enumerable: true
|
|
35
|
+
}) : target, mod));
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/registry/componentRegistry.tsx
|
|
38
|
+
var import_dist = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
39
|
+
(function(global, factory) {
|
|
40
|
+
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.JSON5 = factory();
|
|
41
|
+
})(exports, (function() {
|
|
42
|
+
"use strict";
|
|
43
|
+
function createCommonjsModule(fn, module$1) {
|
|
44
|
+
return module$1 = { exports: {} }, fn(module$1, module$1.exports), module$1.exports;
|
|
45
|
+
}
|
|
46
|
+
var _global = createCommonjsModule(function(module$2) {
|
|
47
|
+
var global = module$2.exports = typeof window != "undefined" && window.Math == Math ? window : typeof self != "undefined" && self.Math == Math ? self : Function("return this")();
|
|
48
|
+
if (typeof __g == "number") __g = global;
|
|
49
|
+
});
|
|
50
|
+
var _core = createCommonjsModule(function(module$3) {
|
|
51
|
+
var core = module$3.exports = { version: "2.6.5" };
|
|
52
|
+
if (typeof __e == "number") __e = core;
|
|
53
|
+
});
|
|
54
|
+
_core.version;
|
|
55
|
+
var _isObject = function(it) {
|
|
56
|
+
return typeof it === "object" ? it !== null : typeof it === "function";
|
|
57
|
+
};
|
|
58
|
+
var _anObject = function(it) {
|
|
59
|
+
if (!_isObject(it)) throw TypeError(it + " is not an object!");
|
|
60
|
+
return it;
|
|
61
|
+
};
|
|
62
|
+
var _fails = function(exec) {
|
|
63
|
+
try {
|
|
64
|
+
return !!exec();
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var _descriptors = !_fails(function() {
|
|
70
|
+
return Object.defineProperty({}, "a", { get: function() {
|
|
71
|
+
return 7;
|
|
72
|
+
} }).a != 7;
|
|
73
|
+
});
|
|
74
|
+
var document = _global.document;
|
|
75
|
+
var is = _isObject(document) && _isObject(document.createElement);
|
|
76
|
+
var _domCreate = function(it) {
|
|
77
|
+
return is ? document.createElement(it) : {};
|
|
78
|
+
};
|
|
79
|
+
var _ie8DomDefine = !_descriptors && !_fails(function() {
|
|
80
|
+
return Object.defineProperty(_domCreate("div"), "a", { get: function() {
|
|
81
|
+
return 7;
|
|
82
|
+
} }).a != 7;
|
|
83
|
+
});
|
|
84
|
+
var _toPrimitive = function(it, S) {
|
|
85
|
+
if (!_isObject(it)) return it;
|
|
86
|
+
var fn, val;
|
|
87
|
+
if (S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) return val;
|
|
88
|
+
if (typeof (fn = it.valueOf) == "function" && !_isObject(val = fn.call(it))) return val;
|
|
89
|
+
if (!S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) return val;
|
|
90
|
+
throw TypeError("Can't convert object to primitive value");
|
|
91
|
+
};
|
|
92
|
+
var dP = Object.defineProperty;
|
|
93
|
+
var _objectDp = { f: _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
|
|
94
|
+
_anObject(O);
|
|
95
|
+
P = _toPrimitive(P, true);
|
|
96
|
+
_anObject(Attributes);
|
|
97
|
+
if (_ie8DomDefine) try {
|
|
98
|
+
return dP(O, P, Attributes);
|
|
99
|
+
} catch (e) {}
|
|
100
|
+
if ("get" in Attributes || "set" in Attributes) throw TypeError("Accessors not supported!");
|
|
101
|
+
if ("value" in Attributes) O[P] = Attributes.value;
|
|
102
|
+
return O;
|
|
103
|
+
} };
|
|
104
|
+
var _propertyDesc = function(bitmap, value) {
|
|
105
|
+
return {
|
|
106
|
+
enumerable: !(bitmap & 1),
|
|
107
|
+
configurable: !(bitmap & 2),
|
|
108
|
+
writable: !(bitmap & 4),
|
|
109
|
+
value
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
var _hide = _descriptors ? function(object, key, value) {
|
|
113
|
+
return _objectDp.f(object, key, _propertyDesc(1, value));
|
|
114
|
+
} : function(object, key, value) {
|
|
115
|
+
object[key] = value;
|
|
116
|
+
return object;
|
|
117
|
+
};
|
|
118
|
+
var hasOwnProperty = {}.hasOwnProperty;
|
|
119
|
+
var _has = function(it, key) {
|
|
120
|
+
return hasOwnProperty.call(it, key);
|
|
121
|
+
};
|
|
122
|
+
var id = 0;
|
|
123
|
+
var px = Math.random();
|
|
124
|
+
var _uid = function(key) {
|
|
125
|
+
return "Symbol(".concat(key === void 0 ? "" : key, ")_", (++id + px).toString(36));
|
|
126
|
+
};
|
|
127
|
+
var _library = false;
|
|
128
|
+
var _functionToString = createCommonjsModule(function(module$4) {
|
|
129
|
+
var SHARED = "__core-js_shared__";
|
|
130
|
+
var store = _global[SHARED] || (_global[SHARED] = {});
|
|
131
|
+
(module$4.exports = function(key, value) {
|
|
132
|
+
return store[key] || (store[key] = value !== void 0 ? value : {});
|
|
133
|
+
})("versions", []).push({
|
|
134
|
+
version: _core.version,
|
|
135
|
+
mode: _library ? "pure" : "global",
|
|
136
|
+
copyright: "© 2019 Denis Pushkarev (zloirock.ru)"
|
|
137
|
+
});
|
|
138
|
+
})("native-function-to-string", Function.toString);
|
|
139
|
+
var _redefine = createCommonjsModule(function(module$5) {
|
|
140
|
+
var SRC = _uid("src");
|
|
141
|
+
var TO_STRING = "toString";
|
|
142
|
+
var TPL = ("" + _functionToString).split(TO_STRING);
|
|
143
|
+
_core.inspectSource = function(it) {
|
|
144
|
+
return _functionToString.call(it);
|
|
145
|
+
};
|
|
146
|
+
(module$5.exports = function(O, key, val, safe) {
|
|
147
|
+
var isFunction = typeof val == "function";
|
|
148
|
+
if (isFunction) _has(val, "name") || _hide(val, "name", key);
|
|
149
|
+
if (O[key] === val) return;
|
|
150
|
+
if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? "" + O[key] : TPL.join(String(key)));
|
|
151
|
+
if (O === _global) O[key] = val;
|
|
152
|
+
else if (!safe) {
|
|
153
|
+
delete O[key];
|
|
154
|
+
_hide(O, key, val);
|
|
155
|
+
} else if (O[key]) O[key] = val;
|
|
156
|
+
else _hide(O, key, val);
|
|
157
|
+
})(Function.prototype, TO_STRING, function toString() {
|
|
158
|
+
return typeof this == "function" && this[SRC] || _functionToString.call(this);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
var _aFunction = function(it) {
|
|
162
|
+
if (typeof it != "function") throw TypeError(it + " is not a function!");
|
|
163
|
+
return it;
|
|
164
|
+
};
|
|
165
|
+
var _ctx = function(fn, that, length) {
|
|
166
|
+
_aFunction(fn);
|
|
167
|
+
if (that === void 0) return fn;
|
|
168
|
+
switch (length) {
|
|
169
|
+
case 1: return function(a) {
|
|
170
|
+
return fn.call(that, a);
|
|
171
|
+
};
|
|
172
|
+
case 2: return function(a, b) {
|
|
173
|
+
return fn.call(that, a, b);
|
|
174
|
+
};
|
|
175
|
+
case 3: return function(a, b, c) {
|
|
176
|
+
return fn.call(that, a, b, c);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return function() {
|
|
180
|
+
return fn.apply(that, arguments);
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
var PROTOTYPE = "prototype";
|
|
184
|
+
var $export = function(type, name, source) {
|
|
185
|
+
var IS_FORCED = type & $export.F;
|
|
186
|
+
var IS_GLOBAL = type & $export.G;
|
|
187
|
+
var IS_STATIC = type & $export.S;
|
|
188
|
+
var IS_PROTO = type & $export.P;
|
|
189
|
+
var IS_BIND = type & $export.B;
|
|
190
|
+
var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE];
|
|
191
|
+
var exports$1 = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
|
|
192
|
+
var expProto = exports$1[PROTOTYPE] || (exports$1[PROTOTYPE] = {});
|
|
193
|
+
var key, own, out, exp;
|
|
194
|
+
if (IS_GLOBAL) source = name;
|
|
195
|
+
for (key in source) {
|
|
196
|
+
own = !IS_FORCED && target && target[key] !== void 0;
|
|
197
|
+
out = (own ? target : source)[key];
|
|
198
|
+
exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == "function" ? _ctx(Function.call, out) : out;
|
|
199
|
+
if (target) _redefine(target, key, out, type & $export.U);
|
|
200
|
+
if (exports$1[key] != out) _hide(exports$1, key, exp);
|
|
201
|
+
if (IS_PROTO && expProto[key] != out) expProto[key] = out;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
_global.core = _core;
|
|
205
|
+
$export.F = 1;
|
|
206
|
+
$export.G = 2;
|
|
207
|
+
$export.S = 4;
|
|
208
|
+
$export.P = 8;
|
|
209
|
+
$export.B = 16;
|
|
210
|
+
$export.W = 32;
|
|
211
|
+
$export.U = 64;
|
|
212
|
+
$export.R = 128;
|
|
213
|
+
var _export = $export;
|
|
214
|
+
var ceil = Math.ceil;
|
|
215
|
+
var floor = Math.floor;
|
|
216
|
+
var _toInteger = function(it) {
|
|
217
|
+
return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
|
|
218
|
+
};
|
|
219
|
+
var _defined = function(it) {
|
|
220
|
+
if (it == void 0) throw TypeError("Can't call method on " + it);
|
|
221
|
+
return it;
|
|
222
|
+
};
|
|
223
|
+
var _stringAt = function(TO_STRING) {
|
|
224
|
+
return function(that, pos) {
|
|
225
|
+
var s = String(_defined(that));
|
|
226
|
+
var i = _toInteger(pos);
|
|
227
|
+
var l = s.length;
|
|
228
|
+
var a, b;
|
|
229
|
+
if (i < 0 || i >= l) return TO_STRING ? "" : void 0;
|
|
230
|
+
a = s.charCodeAt(i);
|
|
231
|
+
return a < 55296 || a > 56319 || i + 1 === l || (b = s.charCodeAt(i + 1)) < 56320 || b > 57343 ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 55296 << 10) + (b - 56320) + 65536;
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
var $at = _stringAt(false);
|
|
235
|
+
_export(_export.P, "String", { codePointAt: function codePointAt(pos) {
|
|
236
|
+
return $at(this, pos);
|
|
237
|
+
} });
|
|
238
|
+
_core.String.codePointAt;
|
|
239
|
+
var max = Math.max;
|
|
240
|
+
var min = Math.min;
|
|
241
|
+
var _toAbsoluteIndex = function(index, length) {
|
|
242
|
+
index = _toInteger(index);
|
|
243
|
+
return index < 0 ? max(index + length, 0) : min(index, length);
|
|
244
|
+
};
|
|
245
|
+
var fromCharCode = String.fromCharCode;
|
|
246
|
+
var $fromCodePoint = String.fromCodePoint;
|
|
247
|
+
_export(_export.S + _export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), "String", { fromCodePoint: function fromCodePoint(x) {
|
|
248
|
+
var arguments$1 = arguments;
|
|
249
|
+
var res = [];
|
|
250
|
+
var aLen = arguments.length;
|
|
251
|
+
var i = 0;
|
|
252
|
+
var code;
|
|
253
|
+
while (aLen > i) {
|
|
254
|
+
code = +arguments$1[i++];
|
|
255
|
+
if (_toAbsoluteIndex(code, 1114111) !== code) throw RangeError(code + " is not a valid code point");
|
|
256
|
+
res.push(code < 65536 ? fromCharCode(code) : fromCharCode(((code -= 65536) >> 10) + 55296, code % 1024 + 56320));
|
|
257
|
+
}
|
|
258
|
+
return res.join("");
|
|
259
|
+
} });
|
|
260
|
+
_core.String.fromCodePoint;
|
|
261
|
+
var unicode = {
|
|
262
|
+
Space_Separator: /[\u1680\u2000-\u200A\u202F\u205F\u3000]/,
|
|
263
|
+
ID_Start: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,
|
|
264
|
+
ID_Continue: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
|
|
265
|
+
};
|
|
266
|
+
var util = {
|
|
267
|
+
isSpaceSeparator: function isSpaceSeparator(c) {
|
|
268
|
+
return typeof c === "string" && unicode.Space_Separator.test(c);
|
|
269
|
+
},
|
|
270
|
+
isIdStartChar: function isIdStartChar(c) {
|
|
271
|
+
return typeof c === "string" && (c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "$" || c === "_" || unicode.ID_Start.test(c));
|
|
272
|
+
},
|
|
273
|
+
isIdContinueChar: function isIdContinueChar(c) {
|
|
274
|
+
return typeof c === "string" && (c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c >= "0" && c <= "9" || c === "$" || c === "_" || c === "" || c === "" || unicode.ID_Continue.test(c));
|
|
275
|
+
},
|
|
276
|
+
isDigit: function isDigit(c) {
|
|
277
|
+
return typeof c === "string" && /[0-9]/.test(c);
|
|
278
|
+
},
|
|
279
|
+
isHexDigit: function isHexDigit(c) {
|
|
280
|
+
return typeof c === "string" && /[0-9A-Fa-f]/.test(c);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
var source;
|
|
284
|
+
var parseState;
|
|
285
|
+
var stack;
|
|
286
|
+
var pos;
|
|
287
|
+
var line;
|
|
288
|
+
var column;
|
|
289
|
+
var token;
|
|
290
|
+
var key;
|
|
291
|
+
var root;
|
|
292
|
+
var parse = function parse(text, reviver) {
|
|
293
|
+
source = String(text);
|
|
294
|
+
parseState = "start";
|
|
295
|
+
stack = [];
|
|
296
|
+
pos = 0;
|
|
297
|
+
line = 1;
|
|
298
|
+
column = 0;
|
|
299
|
+
token = void 0;
|
|
300
|
+
key = void 0;
|
|
301
|
+
root = void 0;
|
|
302
|
+
do {
|
|
303
|
+
token = lex();
|
|
304
|
+
parseStates[parseState]();
|
|
305
|
+
} while (token.type !== "eof");
|
|
306
|
+
if (typeof reviver === "function") return internalize({ "": root }, "", reviver);
|
|
307
|
+
return root;
|
|
308
|
+
};
|
|
309
|
+
function internalize(holder, name, reviver) {
|
|
310
|
+
var value = holder[name];
|
|
311
|
+
if (value != null && typeof value === "object") {
|
|
312
|
+
if (Array.isArray(value)) for (var i = 0; i < value.length; i++) {
|
|
313
|
+
var key = String(i);
|
|
314
|
+
var replacement = internalize(value, key, reviver);
|
|
315
|
+
if (replacement === void 0) delete value[key];
|
|
316
|
+
else Object.defineProperty(value, key, {
|
|
317
|
+
value: replacement,
|
|
318
|
+
writable: true,
|
|
319
|
+
enumerable: true,
|
|
320
|
+
configurable: true
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
else for (var key$1 in value) {
|
|
324
|
+
var replacement$1 = internalize(value, key$1, reviver);
|
|
325
|
+
if (replacement$1 === void 0) delete value[key$1];
|
|
326
|
+
else Object.defineProperty(value, key$1, {
|
|
327
|
+
value: replacement$1,
|
|
328
|
+
writable: true,
|
|
329
|
+
enumerable: true,
|
|
330
|
+
configurable: true
|
|
331
|
+
});
|
|
55
332
|
}
|
|
56
333
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
334
|
+
return reviver.call(holder, name, value);
|
|
335
|
+
}
|
|
336
|
+
var lexState;
|
|
337
|
+
var buffer;
|
|
338
|
+
var doubleQuote;
|
|
339
|
+
var sign;
|
|
340
|
+
var c;
|
|
341
|
+
function lex() {
|
|
342
|
+
lexState = "default";
|
|
343
|
+
buffer = "";
|
|
344
|
+
doubleQuote = false;
|
|
345
|
+
sign = 1;
|
|
346
|
+
for (;;) {
|
|
347
|
+
c = peek();
|
|
348
|
+
var token = lexStates[lexState]();
|
|
349
|
+
if (token) return token;
|
|
64
350
|
}
|
|
65
|
-
containers.push({
|
|
66
|
-
startPos: charPos,
|
|
67
|
-
typeName,
|
|
68
|
-
propsLineFrom,
|
|
69
|
-
propsLineTo,
|
|
70
|
-
props,
|
|
71
|
-
endPos
|
|
72
|
-
});
|
|
73
351
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
352
|
+
function peek() {
|
|
353
|
+
if (source[pos]) return String.fromCodePoint(source.codePointAt(pos));
|
|
354
|
+
}
|
|
355
|
+
function read() {
|
|
356
|
+
var c = peek();
|
|
357
|
+
if (c === "\n") {
|
|
358
|
+
line++;
|
|
359
|
+
column = 0;
|
|
360
|
+
} else if (c) column += c.length;
|
|
361
|
+
else column++;
|
|
362
|
+
if (c) pos += c.length;
|
|
363
|
+
return c;
|
|
364
|
+
}
|
|
365
|
+
var lexStates = {
|
|
366
|
+
default: function default$1() {
|
|
367
|
+
switch (c) {
|
|
368
|
+
case " ":
|
|
369
|
+
case "\v":
|
|
370
|
+
case "\f":
|
|
371
|
+
case " ":
|
|
372
|
+
case "\xA0":
|
|
373
|
+
case "":
|
|
374
|
+
case "\n":
|
|
375
|
+
case "\r":
|
|
376
|
+
case "\u2028":
|
|
377
|
+
case "\u2029":
|
|
378
|
+
read();
|
|
379
|
+
return;
|
|
380
|
+
case "/":
|
|
381
|
+
read();
|
|
382
|
+
lexState = "comment";
|
|
383
|
+
return;
|
|
384
|
+
case void 0:
|
|
385
|
+
read();
|
|
386
|
+
return newToken("eof");
|
|
387
|
+
}
|
|
388
|
+
if (util.isSpaceSeparator(c)) {
|
|
389
|
+
read();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
return lexStates[parseState]();
|
|
393
|
+
},
|
|
394
|
+
comment: function comment() {
|
|
395
|
+
switch (c) {
|
|
396
|
+
case "*":
|
|
397
|
+
read();
|
|
398
|
+
lexState = "multiLineComment";
|
|
399
|
+
return;
|
|
400
|
+
case "/":
|
|
401
|
+
read();
|
|
402
|
+
lexState = "singleLineComment";
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
throw invalidChar(read());
|
|
406
|
+
},
|
|
407
|
+
multiLineComment: function multiLineComment() {
|
|
408
|
+
switch (c) {
|
|
409
|
+
case "*":
|
|
410
|
+
read();
|
|
411
|
+
lexState = "multiLineCommentAsterisk";
|
|
412
|
+
return;
|
|
413
|
+
case void 0: throw invalidChar(read());
|
|
414
|
+
}
|
|
415
|
+
read();
|
|
416
|
+
},
|
|
417
|
+
multiLineCommentAsterisk: function multiLineCommentAsterisk() {
|
|
418
|
+
switch (c) {
|
|
419
|
+
case "*":
|
|
420
|
+
read();
|
|
421
|
+
return;
|
|
422
|
+
case "/":
|
|
423
|
+
read();
|
|
424
|
+
lexState = "default";
|
|
425
|
+
return;
|
|
426
|
+
case void 0: throw invalidChar(read());
|
|
427
|
+
}
|
|
428
|
+
read();
|
|
429
|
+
lexState = "multiLineComment";
|
|
430
|
+
},
|
|
431
|
+
singleLineComment: function singleLineComment() {
|
|
432
|
+
switch (c) {
|
|
433
|
+
case "\n":
|
|
434
|
+
case "\r":
|
|
435
|
+
case "\u2028":
|
|
436
|
+
case "\u2029":
|
|
437
|
+
read();
|
|
438
|
+
lexState = "default";
|
|
439
|
+
return;
|
|
440
|
+
case void 0:
|
|
441
|
+
read();
|
|
442
|
+
return newToken("eof");
|
|
443
|
+
}
|
|
444
|
+
read();
|
|
445
|
+
},
|
|
446
|
+
value: function value() {
|
|
447
|
+
switch (c) {
|
|
448
|
+
case "{":
|
|
449
|
+
case "[": return newToken("punctuator", read());
|
|
450
|
+
case "n":
|
|
451
|
+
read();
|
|
452
|
+
literal("ull");
|
|
453
|
+
return newToken("null", null);
|
|
454
|
+
case "t":
|
|
455
|
+
read();
|
|
456
|
+
literal("rue");
|
|
457
|
+
return newToken("boolean", true);
|
|
458
|
+
case "f":
|
|
459
|
+
read();
|
|
460
|
+
literal("alse");
|
|
461
|
+
return newToken("boolean", false);
|
|
462
|
+
case "-":
|
|
463
|
+
case "+":
|
|
464
|
+
if (read() === "-") sign = -1;
|
|
465
|
+
lexState = "sign";
|
|
466
|
+
return;
|
|
467
|
+
case ".":
|
|
468
|
+
buffer = read();
|
|
469
|
+
lexState = "decimalPointLeading";
|
|
470
|
+
return;
|
|
471
|
+
case "0":
|
|
472
|
+
buffer = read();
|
|
473
|
+
lexState = "zero";
|
|
474
|
+
return;
|
|
475
|
+
case "1":
|
|
476
|
+
case "2":
|
|
477
|
+
case "3":
|
|
478
|
+
case "4":
|
|
479
|
+
case "5":
|
|
480
|
+
case "6":
|
|
481
|
+
case "7":
|
|
482
|
+
case "8":
|
|
483
|
+
case "9":
|
|
484
|
+
buffer = read();
|
|
485
|
+
lexState = "decimalInteger";
|
|
486
|
+
return;
|
|
487
|
+
case "I":
|
|
488
|
+
read();
|
|
489
|
+
literal("nfinity");
|
|
490
|
+
return newToken("numeric", Infinity);
|
|
491
|
+
case "N":
|
|
492
|
+
read();
|
|
493
|
+
literal("aN");
|
|
494
|
+
return newToken("numeric", NaN);
|
|
495
|
+
case "\"":
|
|
496
|
+
case "'":
|
|
497
|
+
doubleQuote = read() === "\"";
|
|
498
|
+
buffer = "";
|
|
499
|
+
lexState = "string";
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
throw invalidChar(read());
|
|
503
|
+
},
|
|
504
|
+
identifierNameStartEscape: function identifierNameStartEscape() {
|
|
505
|
+
if (c !== "u") throw invalidChar(read());
|
|
506
|
+
read();
|
|
507
|
+
var u = unicodeEscape();
|
|
508
|
+
switch (u) {
|
|
509
|
+
case "$":
|
|
510
|
+
case "_": break;
|
|
511
|
+
default: if (!util.isIdStartChar(u)) throw invalidIdentifier();
|
|
512
|
+
}
|
|
513
|
+
buffer += u;
|
|
514
|
+
lexState = "identifierName";
|
|
515
|
+
},
|
|
516
|
+
identifierName: function identifierName() {
|
|
517
|
+
switch (c) {
|
|
518
|
+
case "$":
|
|
519
|
+
case "_":
|
|
520
|
+
case "":
|
|
521
|
+
case "":
|
|
522
|
+
buffer += read();
|
|
523
|
+
return;
|
|
524
|
+
case "\\":
|
|
525
|
+
read();
|
|
526
|
+
lexState = "identifierNameEscape";
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (util.isIdContinueChar(c)) {
|
|
530
|
+
buffer += read();
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
return newToken("identifier", buffer);
|
|
534
|
+
},
|
|
535
|
+
identifierNameEscape: function identifierNameEscape() {
|
|
536
|
+
if (c !== "u") throw invalidChar(read());
|
|
537
|
+
read();
|
|
538
|
+
var u = unicodeEscape();
|
|
539
|
+
switch (u) {
|
|
540
|
+
case "$":
|
|
541
|
+
case "_":
|
|
542
|
+
case "":
|
|
543
|
+
case "": break;
|
|
544
|
+
default: if (!util.isIdContinueChar(u)) throw invalidIdentifier();
|
|
545
|
+
}
|
|
546
|
+
buffer += u;
|
|
547
|
+
lexState = "identifierName";
|
|
548
|
+
},
|
|
549
|
+
sign: function sign$1() {
|
|
550
|
+
switch (c) {
|
|
551
|
+
case ".":
|
|
552
|
+
buffer = read();
|
|
553
|
+
lexState = "decimalPointLeading";
|
|
554
|
+
return;
|
|
555
|
+
case "0":
|
|
556
|
+
buffer = read();
|
|
557
|
+
lexState = "zero";
|
|
558
|
+
return;
|
|
559
|
+
case "1":
|
|
560
|
+
case "2":
|
|
561
|
+
case "3":
|
|
562
|
+
case "4":
|
|
563
|
+
case "5":
|
|
564
|
+
case "6":
|
|
565
|
+
case "7":
|
|
566
|
+
case "8":
|
|
567
|
+
case "9":
|
|
568
|
+
buffer = read();
|
|
569
|
+
lexState = "decimalInteger";
|
|
570
|
+
return;
|
|
571
|
+
case "I":
|
|
572
|
+
read();
|
|
573
|
+
literal("nfinity");
|
|
574
|
+
return newToken("numeric", sign * Infinity);
|
|
575
|
+
case "N":
|
|
576
|
+
read();
|
|
577
|
+
literal("aN");
|
|
578
|
+
return newToken("numeric", NaN);
|
|
579
|
+
}
|
|
580
|
+
throw invalidChar(read());
|
|
581
|
+
},
|
|
582
|
+
zero: function zero() {
|
|
583
|
+
switch (c) {
|
|
584
|
+
case ".":
|
|
585
|
+
buffer += read();
|
|
586
|
+
lexState = "decimalPoint";
|
|
587
|
+
return;
|
|
588
|
+
case "e":
|
|
589
|
+
case "E":
|
|
590
|
+
buffer += read();
|
|
591
|
+
lexState = "decimalExponent";
|
|
592
|
+
return;
|
|
593
|
+
case "x":
|
|
594
|
+
case "X":
|
|
595
|
+
buffer += read();
|
|
596
|
+
lexState = "hexadecimal";
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
return newToken("numeric", sign * 0);
|
|
600
|
+
},
|
|
601
|
+
decimalInteger: function decimalInteger() {
|
|
602
|
+
switch (c) {
|
|
603
|
+
case ".":
|
|
604
|
+
buffer += read();
|
|
605
|
+
lexState = "decimalPoint";
|
|
606
|
+
return;
|
|
607
|
+
case "e":
|
|
608
|
+
case "E":
|
|
609
|
+
buffer += read();
|
|
610
|
+
lexState = "decimalExponent";
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (util.isDigit(c)) {
|
|
614
|
+
buffer += read();
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
return newToken("numeric", sign * Number(buffer));
|
|
618
|
+
},
|
|
619
|
+
decimalPointLeading: function decimalPointLeading() {
|
|
620
|
+
if (util.isDigit(c)) {
|
|
621
|
+
buffer += read();
|
|
622
|
+
lexState = "decimalFraction";
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
throw invalidChar(read());
|
|
626
|
+
},
|
|
627
|
+
decimalPoint: function decimalPoint() {
|
|
628
|
+
switch (c) {
|
|
629
|
+
case "e":
|
|
630
|
+
case "E":
|
|
631
|
+
buffer += read();
|
|
632
|
+
lexState = "decimalExponent";
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
if (util.isDigit(c)) {
|
|
636
|
+
buffer += read();
|
|
637
|
+
lexState = "decimalFraction";
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
return newToken("numeric", sign * Number(buffer));
|
|
641
|
+
},
|
|
642
|
+
decimalFraction: function decimalFraction() {
|
|
643
|
+
switch (c) {
|
|
644
|
+
case "e":
|
|
645
|
+
case "E":
|
|
646
|
+
buffer += read();
|
|
647
|
+
lexState = "decimalExponent";
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (util.isDigit(c)) {
|
|
651
|
+
buffer += read();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
return newToken("numeric", sign * Number(buffer));
|
|
655
|
+
},
|
|
656
|
+
decimalExponent: function decimalExponent() {
|
|
657
|
+
switch (c) {
|
|
658
|
+
case "+":
|
|
659
|
+
case "-":
|
|
660
|
+
buffer += read();
|
|
661
|
+
lexState = "decimalExponentSign";
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
if (util.isDigit(c)) {
|
|
665
|
+
buffer += read();
|
|
666
|
+
lexState = "decimalExponentInteger";
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
throw invalidChar(read());
|
|
670
|
+
},
|
|
671
|
+
decimalExponentSign: function decimalExponentSign() {
|
|
672
|
+
if (util.isDigit(c)) {
|
|
673
|
+
buffer += read();
|
|
674
|
+
lexState = "decimalExponentInteger";
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
throw invalidChar(read());
|
|
678
|
+
},
|
|
679
|
+
decimalExponentInteger: function decimalExponentInteger() {
|
|
680
|
+
if (util.isDigit(c)) {
|
|
681
|
+
buffer += read();
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
return newToken("numeric", sign * Number(buffer));
|
|
685
|
+
},
|
|
686
|
+
hexadecimal: function hexadecimal() {
|
|
687
|
+
if (util.isHexDigit(c)) {
|
|
688
|
+
buffer += read();
|
|
689
|
+
lexState = "hexadecimalInteger";
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
throw invalidChar(read());
|
|
693
|
+
},
|
|
694
|
+
hexadecimalInteger: function hexadecimalInteger() {
|
|
695
|
+
if (util.isHexDigit(c)) {
|
|
696
|
+
buffer += read();
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
return newToken("numeric", sign * Number(buffer));
|
|
700
|
+
},
|
|
701
|
+
string: function string() {
|
|
702
|
+
switch (c) {
|
|
703
|
+
case "\\":
|
|
704
|
+
read();
|
|
705
|
+
buffer += escape();
|
|
706
|
+
return;
|
|
707
|
+
case "\"":
|
|
708
|
+
if (doubleQuote) {
|
|
709
|
+
read();
|
|
710
|
+
return newToken("string", buffer);
|
|
711
|
+
}
|
|
712
|
+
buffer += read();
|
|
713
|
+
return;
|
|
714
|
+
case "'":
|
|
715
|
+
if (!doubleQuote) {
|
|
716
|
+
read();
|
|
717
|
+
return newToken("string", buffer);
|
|
718
|
+
}
|
|
719
|
+
buffer += read();
|
|
720
|
+
return;
|
|
721
|
+
case "\n":
|
|
722
|
+
case "\r": throw invalidChar(read());
|
|
723
|
+
case "\u2028":
|
|
724
|
+
case "\u2029":
|
|
725
|
+
separatorChar(c);
|
|
726
|
+
break;
|
|
727
|
+
case void 0: throw invalidChar(read());
|
|
728
|
+
}
|
|
729
|
+
buffer += read();
|
|
730
|
+
},
|
|
731
|
+
start: function start() {
|
|
732
|
+
switch (c) {
|
|
733
|
+
case "{":
|
|
734
|
+
case "[": return newToken("punctuator", read());
|
|
735
|
+
}
|
|
736
|
+
lexState = "value";
|
|
737
|
+
},
|
|
738
|
+
beforePropertyName: function beforePropertyName() {
|
|
739
|
+
switch (c) {
|
|
740
|
+
case "$":
|
|
741
|
+
case "_":
|
|
742
|
+
buffer = read();
|
|
743
|
+
lexState = "identifierName";
|
|
744
|
+
return;
|
|
745
|
+
case "\\":
|
|
746
|
+
read();
|
|
747
|
+
lexState = "identifierNameStartEscape";
|
|
748
|
+
return;
|
|
749
|
+
case "}": return newToken("punctuator", read());
|
|
750
|
+
case "\"":
|
|
751
|
+
case "'":
|
|
752
|
+
doubleQuote = read() === "\"";
|
|
753
|
+
lexState = "string";
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (util.isIdStartChar(c)) {
|
|
757
|
+
buffer += read();
|
|
758
|
+
lexState = "identifierName";
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
throw invalidChar(read());
|
|
762
|
+
},
|
|
763
|
+
afterPropertyName: function afterPropertyName() {
|
|
764
|
+
if (c === ":") return newToken("punctuator", read());
|
|
765
|
+
throw invalidChar(read());
|
|
766
|
+
},
|
|
767
|
+
beforePropertyValue: function beforePropertyValue() {
|
|
768
|
+
lexState = "value";
|
|
769
|
+
},
|
|
770
|
+
afterPropertyValue: function afterPropertyValue() {
|
|
771
|
+
switch (c) {
|
|
772
|
+
case ",":
|
|
773
|
+
case "}": return newToken("punctuator", read());
|
|
774
|
+
}
|
|
775
|
+
throw invalidChar(read());
|
|
776
|
+
},
|
|
777
|
+
beforeArrayValue: function beforeArrayValue() {
|
|
778
|
+
if (c === "]") return newToken("punctuator", read());
|
|
779
|
+
lexState = "value";
|
|
780
|
+
},
|
|
781
|
+
afterArrayValue: function afterArrayValue() {
|
|
782
|
+
switch (c) {
|
|
783
|
+
case ",":
|
|
784
|
+
case "]": return newToken("punctuator", read());
|
|
785
|
+
}
|
|
786
|
+
throw invalidChar(read());
|
|
787
|
+
},
|
|
788
|
+
end: function end() {
|
|
789
|
+
throw invalidChar(read());
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
function newToken(type, value) {
|
|
793
|
+
return {
|
|
794
|
+
type,
|
|
795
|
+
value,
|
|
796
|
+
line,
|
|
797
|
+
column
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function literal(s) {
|
|
801
|
+
for (var i = 0, list = s; i < list.length; i += 1) {
|
|
802
|
+
var c = list[i];
|
|
803
|
+
if (peek() !== c) throw invalidChar(read());
|
|
804
|
+
read();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
function escape() {
|
|
808
|
+
switch (peek()) {
|
|
809
|
+
case "b":
|
|
810
|
+
read();
|
|
811
|
+
return "\b";
|
|
812
|
+
case "f":
|
|
813
|
+
read();
|
|
814
|
+
return "\f";
|
|
815
|
+
case "n":
|
|
816
|
+
read();
|
|
817
|
+
return "\n";
|
|
818
|
+
case "r":
|
|
819
|
+
read();
|
|
820
|
+
return "\r";
|
|
821
|
+
case "t":
|
|
822
|
+
read();
|
|
823
|
+
return " ";
|
|
824
|
+
case "v":
|
|
825
|
+
read();
|
|
826
|
+
return "\v";
|
|
827
|
+
case "0":
|
|
828
|
+
read();
|
|
829
|
+
if (util.isDigit(peek())) throw invalidChar(read());
|
|
830
|
+
return "\0";
|
|
831
|
+
case "x":
|
|
832
|
+
read();
|
|
833
|
+
return hexEscape();
|
|
834
|
+
case "u":
|
|
835
|
+
read();
|
|
836
|
+
return unicodeEscape();
|
|
837
|
+
case "\n":
|
|
838
|
+
case "\u2028":
|
|
839
|
+
case "\u2029":
|
|
840
|
+
read();
|
|
841
|
+
return "";
|
|
842
|
+
case "\r":
|
|
843
|
+
read();
|
|
844
|
+
if (peek() === "\n") read();
|
|
845
|
+
return "";
|
|
846
|
+
case "1":
|
|
847
|
+
case "2":
|
|
848
|
+
case "3":
|
|
849
|
+
case "4":
|
|
850
|
+
case "5":
|
|
851
|
+
case "6":
|
|
852
|
+
case "7":
|
|
853
|
+
case "8":
|
|
854
|
+
case "9": throw invalidChar(read());
|
|
855
|
+
case void 0: throw invalidChar(read());
|
|
856
|
+
}
|
|
857
|
+
return read();
|
|
858
|
+
}
|
|
859
|
+
function hexEscape() {
|
|
860
|
+
var buffer = "";
|
|
861
|
+
var c = peek();
|
|
862
|
+
if (!util.isHexDigit(c)) throw invalidChar(read());
|
|
863
|
+
buffer += read();
|
|
864
|
+
c = peek();
|
|
865
|
+
if (!util.isHexDigit(c)) throw invalidChar(read());
|
|
866
|
+
buffer += read();
|
|
867
|
+
return String.fromCodePoint(parseInt(buffer, 16));
|
|
868
|
+
}
|
|
869
|
+
function unicodeEscape() {
|
|
870
|
+
var buffer = "";
|
|
871
|
+
var count = 4;
|
|
872
|
+
while (count-- > 0) {
|
|
873
|
+
var c = peek();
|
|
874
|
+
if (!util.isHexDigit(c)) throw invalidChar(read());
|
|
875
|
+
buffer += read();
|
|
876
|
+
}
|
|
877
|
+
return String.fromCodePoint(parseInt(buffer, 16));
|
|
878
|
+
}
|
|
879
|
+
var parseStates = {
|
|
880
|
+
start: function start() {
|
|
881
|
+
if (token.type === "eof") throw invalidEOF();
|
|
882
|
+
push();
|
|
883
|
+
},
|
|
884
|
+
beforePropertyName: function beforePropertyName() {
|
|
885
|
+
switch (token.type) {
|
|
886
|
+
case "identifier":
|
|
887
|
+
case "string":
|
|
888
|
+
key = token.value;
|
|
889
|
+
parseState = "afterPropertyName";
|
|
890
|
+
return;
|
|
891
|
+
case "punctuator":
|
|
892
|
+
pop();
|
|
893
|
+
return;
|
|
894
|
+
case "eof": throw invalidEOF();
|
|
895
|
+
}
|
|
896
|
+
},
|
|
897
|
+
afterPropertyName: function afterPropertyName() {
|
|
898
|
+
if (token.type === "eof") throw invalidEOF();
|
|
899
|
+
parseState = "beforePropertyValue";
|
|
900
|
+
},
|
|
901
|
+
beforePropertyValue: function beforePropertyValue() {
|
|
902
|
+
if (token.type === "eof") throw invalidEOF();
|
|
903
|
+
push();
|
|
904
|
+
},
|
|
905
|
+
beforeArrayValue: function beforeArrayValue() {
|
|
906
|
+
if (token.type === "eof") throw invalidEOF();
|
|
907
|
+
if (token.type === "punctuator" && token.value === "]") {
|
|
908
|
+
pop();
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
push();
|
|
912
|
+
},
|
|
913
|
+
afterPropertyValue: function afterPropertyValue() {
|
|
914
|
+
if (token.type === "eof") throw invalidEOF();
|
|
915
|
+
switch (token.value) {
|
|
916
|
+
case ",":
|
|
917
|
+
parseState = "beforePropertyName";
|
|
918
|
+
return;
|
|
919
|
+
case "}": pop();
|
|
920
|
+
}
|
|
921
|
+
},
|
|
922
|
+
afterArrayValue: function afterArrayValue() {
|
|
923
|
+
if (token.type === "eof") throw invalidEOF();
|
|
924
|
+
switch (token.value) {
|
|
925
|
+
case ",":
|
|
926
|
+
parseState = "beforeArrayValue";
|
|
927
|
+
return;
|
|
928
|
+
case "]": pop();
|
|
929
|
+
}
|
|
930
|
+
},
|
|
931
|
+
end: function end() {}
|
|
932
|
+
};
|
|
933
|
+
function push() {
|
|
934
|
+
var value;
|
|
935
|
+
switch (token.type) {
|
|
936
|
+
case "punctuator":
|
|
937
|
+
switch (token.value) {
|
|
938
|
+
case "{":
|
|
939
|
+
value = {};
|
|
940
|
+
break;
|
|
941
|
+
case "[": value = [];
|
|
942
|
+
}
|
|
943
|
+
break;
|
|
944
|
+
case "null":
|
|
945
|
+
case "boolean":
|
|
946
|
+
case "numeric":
|
|
947
|
+
case "string": value = token.value;
|
|
948
|
+
}
|
|
949
|
+
if (root === void 0) root = value;
|
|
950
|
+
else {
|
|
951
|
+
var parent = stack[stack.length - 1];
|
|
952
|
+
if (Array.isArray(parent)) parent.push(value);
|
|
953
|
+
else Object.defineProperty(parent, key, {
|
|
954
|
+
value,
|
|
955
|
+
writable: true,
|
|
956
|
+
enumerable: true,
|
|
957
|
+
configurable: true
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
if (value !== null && typeof value === "object") {
|
|
961
|
+
stack.push(value);
|
|
962
|
+
if (Array.isArray(value)) parseState = "beforeArrayValue";
|
|
963
|
+
else parseState = "beforePropertyName";
|
|
964
|
+
} else {
|
|
965
|
+
var current = stack[stack.length - 1];
|
|
966
|
+
if (current == null) parseState = "end";
|
|
967
|
+
else if (Array.isArray(current)) parseState = "afterArrayValue";
|
|
968
|
+
else parseState = "afterPropertyValue";
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function pop() {
|
|
972
|
+
stack.pop();
|
|
973
|
+
var current = stack[stack.length - 1];
|
|
974
|
+
if (current == null) parseState = "end";
|
|
975
|
+
else if (Array.isArray(current)) parseState = "afterArrayValue";
|
|
976
|
+
else parseState = "afterPropertyValue";
|
|
977
|
+
}
|
|
978
|
+
function invalidChar(c) {
|
|
979
|
+
if (c === void 0) return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
|
|
980
|
+
return syntaxError("JSON5: invalid character '" + formatChar(c) + "' at " + line + ":" + column);
|
|
981
|
+
}
|
|
982
|
+
function invalidEOF() {
|
|
983
|
+
return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
|
|
984
|
+
}
|
|
985
|
+
function invalidIdentifier() {
|
|
986
|
+
column -= 5;
|
|
987
|
+
return syntaxError("JSON5: invalid identifier character at " + line + ":" + column);
|
|
988
|
+
}
|
|
989
|
+
function separatorChar(c) {
|
|
990
|
+
console.warn("JSON5: '" + formatChar(c) + "' in strings is not valid ECMAScript; consider escaping");
|
|
991
|
+
}
|
|
992
|
+
function formatChar(c) {
|
|
993
|
+
var replacements = {
|
|
994
|
+
"'": "\\'",
|
|
995
|
+
"\"": "\\\"",
|
|
996
|
+
"\\": "\\\\",
|
|
997
|
+
"\b": "\\b",
|
|
998
|
+
"\f": "\\f",
|
|
999
|
+
"\n": "\\n",
|
|
1000
|
+
"\r": "\\r",
|
|
1001
|
+
" ": "\\t",
|
|
1002
|
+
"\v": "\\v",
|
|
1003
|
+
"\0": "\\0",
|
|
1004
|
+
"\u2028": "\\u2028",
|
|
1005
|
+
"\u2029": "\\u2029"
|
|
1006
|
+
};
|
|
1007
|
+
if (replacements[c]) return replacements[c];
|
|
1008
|
+
if (c < " ") {
|
|
1009
|
+
var hexString = c.charCodeAt(0).toString(16);
|
|
1010
|
+
return "\\x" + ("00" + hexString).substring(hexString.length);
|
|
1011
|
+
}
|
|
1012
|
+
return c;
|
|
1013
|
+
}
|
|
1014
|
+
function syntaxError(message) {
|
|
1015
|
+
var err = new SyntaxError(message);
|
|
1016
|
+
err.lineNumber = line;
|
|
1017
|
+
err.columnNumber = column;
|
|
1018
|
+
return err;
|
|
1019
|
+
}
|
|
1020
|
+
return {
|
|
1021
|
+
parse,
|
|
1022
|
+
stringify: function stringify(value, replacer, space) {
|
|
1023
|
+
var stack = [];
|
|
1024
|
+
var indent = "";
|
|
1025
|
+
var propertyList;
|
|
1026
|
+
var replacerFunc;
|
|
1027
|
+
var gap = "";
|
|
1028
|
+
var quote;
|
|
1029
|
+
if (replacer != null && typeof replacer === "object" && !Array.isArray(replacer)) {
|
|
1030
|
+
space = replacer.space;
|
|
1031
|
+
quote = replacer.quote;
|
|
1032
|
+
replacer = replacer.replacer;
|
|
1033
|
+
}
|
|
1034
|
+
if (typeof replacer === "function") replacerFunc = replacer;
|
|
1035
|
+
else if (Array.isArray(replacer)) {
|
|
1036
|
+
propertyList = [];
|
|
1037
|
+
for (var i = 0, list = replacer; i < list.length; i += 1) {
|
|
1038
|
+
var v = list[i];
|
|
1039
|
+
var item = void 0;
|
|
1040
|
+
if (typeof v === "string") item = v;
|
|
1041
|
+
else if (typeof v === "number" || v instanceof String || v instanceof Number) item = String(v);
|
|
1042
|
+
if (item !== void 0 && propertyList.indexOf(item) < 0) propertyList.push(item);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
if (space instanceof Number) space = Number(space);
|
|
1046
|
+
else if (space instanceof String) space = String(space);
|
|
1047
|
+
if (typeof space === "number") {
|
|
1048
|
+
if (space > 0) {
|
|
1049
|
+
space = Math.min(10, Math.floor(space));
|
|
1050
|
+
gap = " ".substr(0, space);
|
|
1051
|
+
}
|
|
1052
|
+
} else if (typeof space === "string") gap = space.substr(0, 10);
|
|
1053
|
+
return serializeProperty("", { "": value });
|
|
1054
|
+
function serializeProperty(key, holder) {
|
|
1055
|
+
var value = holder[key];
|
|
1056
|
+
if (value != null) {
|
|
1057
|
+
if (typeof value.toJSON5 === "function") value = value.toJSON5(key);
|
|
1058
|
+
else if (typeof value.toJSON === "function") value = value.toJSON(key);
|
|
1059
|
+
}
|
|
1060
|
+
if (replacerFunc) value = replacerFunc.call(holder, key, value);
|
|
1061
|
+
if (value instanceof Number) value = Number(value);
|
|
1062
|
+
else if (value instanceof String) value = String(value);
|
|
1063
|
+
else if (value instanceof Boolean) value = value.valueOf();
|
|
1064
|
+
switch (value) {
|
|
1065
|
+
case null: return "null";
|
|
1066
|
+
case true: return "true";
|
|
1067
|
+
case false: return "false";
|
|
1068
|
+
}
|
|
1069
|
+
if (typeof value === "string") return quoteString(value, false);
|
|
1070
|
+
if (typeof value === "number") return String(value);
|
|
1071
|
+
if (typeof value === "object") return Array.isArray(value) ? serializeArray(value) : serializeObject(value);
|
|
1072
|
+
}
|
|
1073
|
+
function quoteString(value) {
|
|
1074
|
+
var quotes = {
|
|
1075
|
+
"'": .1,
|
|
1076
|
+
"\"": .2
|
|
1077
|
+
};
|
|
1078
|
+
var replacements = {
|
|
1079
|
+
"'": "\\'",
|
|
1080
|
+
"\"": "\\\"",
|
|
1081
|
+
"\\": "\\\\",
|
|
1082
|
+
"\b": "\\b",
|
|
1083
|
+
"\f": "\\f",
|
|
1084
|
+
"\n": "\\n",
|
|
1085
|
+
"\r": "\\r",
|
|
1086
|
+
" ": "\\t",
|
|
1087
|
+
"\v": "\\v",
|
|
1088
|
+
"\0": "\\0",
|
|
1089
|
+
"\u2028": "\\u2028",
|
|
1090
|
+
"\u2029": "\\u2029"
|
|
1091
|
+
};
|
|
1092
|
+
var product = "";
|
|
1093
|
+
for (var i = 0; i < value.length; i++) {
|
|
1094
|
+
var c = value[i];
|
|
1095
|
+
switch (c) {
|
|
1096
|
+
case "'":
|
|
1097
|
+
case "\"":
|
|
1098
|
+
quotes[c]++;
|
|
1099
|
+
product += c;
|
|
1100
|
+
continue;
|
|
1101
|
+
case "\0": if (util.isDigit(value[i + 1])) {
|
|
1102
|
+
product += "\\x00";
|
|
1103
|
+
continue;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (replacements[c]) {
|
|
1107
|
+
product += replacements[c];
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
if (c < " ") {
|
|
1111
|
+
var hexString = c.charCodeAt(0).toString(16);
|
|
1112
|
+
product += "\\x" + ("00" + hexString).substring(hexString.length);
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
product += c;
|
|
1116
|
+
}
|
|
1117
|
+
var quoteChar = quote || Object.keys(quotes).reduce(function(a, b) {
|
|
1118
|
+
return quotes[a] < quotes[b] ? a : b;
|
|
1119
|
+
});
|
|
1120
|
+
product = product.replace(new RegExp(quoteChar, "g"), replacements[quoteChar]);
|
|
1121
|
+
return quoteChar + product + quoteChar;
|
|
1122
|
+
}
|
|
1123
|
+
function serializeObject(value) {
|
|
1124
|
+
if (stack.indexOf(value) >= 0) throw TypeError("Converting circular structure to JSON5");
|
|
1125
|
+
stack.push(value);
|
|
1126
|
+
var stepback = indent;
|
|
1127
|
+
indent = indent + gap;
|
|
1128
|
+
var keys = propertyList || Object.keys(value);
|
|
1129
|
+
var partial = [];
|
|
1130
|
+
for (var i = 0, list = keys; i < list.length; i += 1) {
|
|
1131
|
+
var key = list[i];
|
|
1132
|
+
var propertyString = serializeProperty(key, value);
|
|
1133
|
+
if (propertyString !== void 0) {
|
|
1134
|
+
var member = serializeKey(key) + ":";
|
|
1135
|
+
if (gap !== "") member += " ";
|
|
1136
|
+
member += propertyString;
|
|
1137
|
+
partial.push(member);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
var final;
|
|
1141
|
+
if (partial.length === 0) final = "{}";
|
|
1142
|
+
else {
|
|
1143
|
+
var properties;
|
|
1144
|
+
if (gap === "") {
|
|
1145
|
+
properties = partial.join(",");
|
|
1146
|
+
final = "{" + properties + "}";
|
|
1147
|
+
} else {
|
|
1148
|
+
var separator = ",\n" + indent;
|
|
1149
|
+
properties = partial.join(separator);
|
|
1150
|
+
final = "{\n" + indent + properties + ",\n" + stepback + "}";
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
stack.pop();
|
|
1154
|
+
indent = stepback;
|
|
1155
|
+
return final;
|
|
1156
|
+
}
|
|
1157
|
+
function serializeKey(key) {
|
|
1158
|
+
if (key.length === 0) return quoteString(key, true);
|
|
1159
|
+
var firstChar = String.fromCodePoint(key.codePointAt(0));
|
|
1160
|
+
if (!util.isIdStartChar(firstChar)) return quoteString(key, true);
|
|
1161
|
+
for (var i = firstChar.length; i < key.length; i++) if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) return quoteString(key, true);
|
|
1162
|
+
return key;
|
|
1163
|
+
}
|
|
1164
|
+
function serializeArray(value) {
|
|
1165
|
+
if (stack.indexOf(value) >= 0) throw TypeError("Converting circular structure to JSON5");
|
|
1166
|
+
stack.push(value);
|
|
1167
|
+
var stepback = indent;
|
|
1168
|
+
indent = indent + gap;
|
|
1169
|
+
var partial = [];
|
|
1170
|
+
for (var i = 0; i < value.length; i++) {
|
|
1171
|
+
var propertyString = serializeProperty(String(i), value);
|
|
1172
|
+
partial.push(propertyString !== void 0 ? propertyString : "null");
|
|
1173
|
+
}
|
|
1174
|
+
var final;
|
|
1175
|
+
if (partial.length === 0) final = "[]";
|
|
1176
|
+
else if (gap === "") final = "[" + partial.join(",") + "]";
|
|
1177
|
+
else {
|
|
1178
|
+
var separator = ",\n" + indent;
|
|
1179
|
+
var properties$1 = partial.join(separator);
|
|
1180
|
+
final = "[\n" + indent + properties$1 + ",\n" + stepback + "]";
|
|
1181
|
+
}
|
|
1182
|
+
stack.pop();
|
|
1183
|
+
indent = stepback;
|
|
1184
|
+
return final;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
}));
|
|
1189
|
+
})))(), 1);
|
|
84
1190
|
var ComponentRegistry = class {
|
|
85
1191
|
schemas = /* @__PURE__ */ new Map();
|
|
1192
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1193
|
+
version = 0;
|
|
86
1194
|
/**
|
|
87
1195
|
* 注册组件 schema
|
|
88
1196
|
*/
|
|
89
1197
|
register(name, schema) {
|
|
90
1198
|
this.schemas.set(name, schema);
|
|
1199
|
+
this.emit();
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* 移除组件注册
|
|
1203
|
+
*/
|
|
1204
|
+
unregister(name) {
|
|
1205
|
+
if (this.schemas.delete(name)) this.emit();
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* 当前版本号,任意注册变更都会自增
|
|
1209
|
+
*/
|
|
1210
|
+
getVersion() {
|
|
1211
|
+
return this.version;
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* 订阅注册变更,返回退订函数
|
|
1215
|
+
*/
|
|
1216
|
+
subscribe(listener) {
|
|
1217
|
+
this.listeners.add(listener);
|
|
1218
|
+
return () => {
|
|
1219
|
+
this.listeners.delete(listener);
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
emit() {
|
|
1223
|
+
this.version += 1;
|
|
1224
|
+
this.listeners.forEach((listener) => listener(this.version));
|
|
91
1225
|
}
|
|
92
1226
|
/**
|
|
93
1227
|
* 根据组件名获取已注册的 schema
|
|
@@ -113,47 +1247,164 @@ var ComponentRegistry = class {
|
|
|
113
1247
|
getAll() {
|
|
114
1248
|
return Array.from(this.schemas.values());
|
|
115
1249
|
}
|
|
116
|
-
/**
|
|
117
|
-
* 移除组件注册
|
|
118
|
-
*/
|
|
119
|
-
unregister(name) {
|
|
120
|
-
this.schemas.delete(name);
|
|
121
|
-
}
|
|
122
1250
|
};
|
|
123
1251
|
var componentRegistry = new ComponentRegistry();
|
|
124
1252
|
//#endregion
|
|
1253
|
+
//#region src/utils/parseContainer.ts
|
|
1254
|
+
/**
|
|
1255
|
+
* 解析容器属性行。
|
|
1256
|
+
* 优先按 JSON5 解析(兼容标准 JSON 与 { key: 'value' } 宽松写法),
|
|
1257
|
+
* 失败时返回空对象,保证往返编辑不丢数据。
|
|
1258
|
+
*/
|
|
1259
|
+
function parseContainerProps(line) {
|
|
1260
|
+
const trimmed = line.trim();
|
|
1261
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return {};
|
|
1262
|
+
try {
|
|
1263
|
+
const parsed = import_dist.default.parse(trimmed);
|
|
1264
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
1265
|
+
const props = {};
|
|
1266
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
1267
|
+
if (value === null || value === void 0) continue;
|
|
1268
|
+
if (typeof value === "object") continue;
|
|
1269
|
+
props[key] = value;
|
|
1270
|
+
}
|
|
1271
|
+
return props;
|
|
1272
|
+
} catch {
|
|
1273
|
+
return {};
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* 解析行首的引用(blockquote)嵌套前缀。
|
|
1278
|
+
* markdown-it 解析引用内部内容时会剥掉一层 "> ",因此 "> :::badge" 在渲染侧
|
|
1279
|
+
* 等同于 ":::badge";编辑器侧需同样识别,否则嵌套引用的容器匹配不到标签。
|
|
1280
|
+
* 返回 [前缀文本(含 "> " 及尾随空格), 去掉前缀后的内容],无前缀时返回 ['', 原文本]。
|
|
1281
|
+
*/
|
|
1282
|
+
function splitQuotePrefix(line) {
|
|
1283
|
+
const m = line.match(/^((?:>\s*)+)(\S.*)$/);
|
|
1284
|
+
if (!m) return ["", line];
|
|
1285
|
+
return [m[1], m[2]];
|
|
1286
|
+
}
|
|
1287
|
+
/** 引用嵌套深度("> > x" 为 2,无前缀为 0) */
|
|
1288
|
+
function quoteDepth(prefix) {
|
|
1289
|
+
return (prefix.match(/>/g) ?? []).length;
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* 在编辑器文档中查找容器块。
|
|
1293
|
+
* 单次遍历 + 预累计行偏移,复杂度 O(行数)。
|
|
1294
|
+
* 支持整体嵌套在引用中的容器:头行、属性行、闭合行需具有相同的 "> " 前缀深度,
|
|
1295
|
+
* 避免跨引用层级错误配对。闭合 ::: 改为按栈配对,嵌套容器不会被内层闭合误截断。
|
|
1296
|
+
*/
|
|
1297
|
+
function findContainers(docText) {
|
|
1298
|
+
const containers = [];
|
|
1299
|
+
const lines = docText.split("\n");
|
|
1300
|
+
const offsets = new Array(lines.length);
|
|
1301
|
+
let pos = 0;
|
|
1302
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1303
|
+
offsets[i] = pos;
|
|
1304
|
+
pos += lines[i].length + 1;
|
|
1305
|
+
}
|
|
1306
|
+
const stack = [];
|
|
1307
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1308
|
+
const [prefix, body] = splitQuotePrefix(lines[i]);
|
|
1309
|
+
const depth = quoteDepth(prefix);
|
|
1310
|
+
if (/^:::$/.test(body)) {
|
|
1311
|
+
let top = stack.length - 1;
|
|
1312
|
+
while (top >= 0 && stack[top].depth !== depth) top--;
|
|
1313
|
+
if (top >= 0) {
|
|
1314
|
+
stack[top].block.endPos = offsets[i];
|
|
1315
|
+
stack.length = top;
|
|
1316
|
+
}
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1319
|
+
const match = body.match(/^:::(\w+)$/);
|
|
1320
|
+
if (!match) continue;
|
|
1321
|
+
const typeName = match[1];
|
|
1322
|
+
const headerPos = offsets[i];
|
|
1323
|
+
let props = {};
|
|
1324
|
+
let propsLineFrom = 0;
|
|
1325
|
+
let propsLineTo = 0;
|
|
1326
|
+
let propsQuotePrefix = "";
|
|
1327
|
+
const nextLine = lines[i + 1];
|
|
1328
|
+
if (nextLine) {
|
|
1329
|
+
const [nextPrefix, nextBody] = splitQuotePrefix(nextLine);
|
|
1330
|
+
if ((quoteDepth(nextPrefix) === depth || nextPrefix === "") && nextBody.trimStart().startsWith("{") && nextBody.trimEnd().endsWith("}")) {
|
|
1331
|
+
props = parseContainerProps(nextBody);
|
|
1332
|
+
propsLineFrom = offsets[i + 1];
|
|
1333
|
+
propsLineTo = propsLineFrom + nextLine.length;
|
|
1334
|
+
propsQuotePrefix = nextPrefix;
|
|
1335
|
+
i += 1;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
const block = {
|
|
1339
|
+
startPos: headerPos,
|
|
1340
|
+
typeName,
|
|
1341
|
+
propsLineFrom,
|
|
1342
|
+
propsLineTo,
|
|
1343
|
+
props,
|
|
1344
|
+
endPos: 0,
|
|
1345
|
+
registered: componentRegistry.has(typeName),
|
|
1346
|
+
quotePrefix: prefix,
|
|
1347
|
+
propsQuotePrefix
|
|
1348
|
+
};
|
|
1349
|
+
containers.push(block);
|
|
1350
|
+
stack.push({
|
|
1351
|
+
block,
|
|
1352
|
+
depth
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
return containers;
|
|
1356
|
+
}
|
|
1357
|
+
//#endregion
|
|
125
1358
|
//#region src/components/Editor/containerWidget.ts
|
|
126
1359
|
/**
|
|
1360
|
+
* 唤醒容器装饰重建的状态 effect(不改变文档)。
|
|
1361
|
+
* 编辑按钮是否展示取决于容器类型是否已注册,而宿主常在编辑器挂载之后才
|
|
1362
|
+
* 通过 useRegisterToolbar 异步注册 schema;注册不是 CodeMirror 事务,默认不会触发
|
|
1363
|
+
* ViewPlugin.update,导致初始化时烘焙的 registered=false 无法刷新(需手动改一个字才出现)。
|
|
1364
|
+
* 宿主在注册中心版本变化时 dispatch 本 effect,驱动插件重新求值 registered。
|
|
1365
|
+
*/
|
|
1366
|
+
var refreshContainers = StateEffect.define();
|
|
1367
|
+
/**
|
|
127
1368
|
* 自定义 facet 用于传递编辑回调
|
|
128
1369
|
*/
|
|
129
|
-
var containerEditCallback = Facet.define({ combine: (values) => values[
|
|
1370
|
+
var containerEditCallback = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
130
1371
|
/**
|
|
131
1372
|
* 只读的容器头行 Widget(显示 :::typeName + 编辑按钮)
|
|
132
|
-
* 使用 Decoration.replace
|
|
1373
|
+
* 使用 Decoration.replace 替换原始文本,使其不可直接编辑。
|
|
1374
|
+
* widget 直接携带所属容器索引与类型,点击时无需再做位置猜测。
|
|
133
1375
|
*/
|
|
134
1376
|
var ContainerHeaderWidget = class extends WidgetType {
|
|
135
1377
|
typeName;
|
|
136
|
-
|
|
1378
|
+
containerIndex;
|
|
1379
|
+
registered;
|
|
1380
|
+
quotePrefix;
|
|
1381
|
+
constructor(typeName, containerIndex, registered, quotePrefix) {
|
|
137
1382
|
super();
|
|
138
1383
|
this.typeName = typeName;
|
|
1384
|
+
this.containerIndex = containerIndex;
|
|
1385
|
+
this.registered = registered;
|
|
1386
|
+
this.quotePrefix = quotePrefix;
|
|
139
1387
|
}
|
|
140
1388
|
toDOM() {
|
|
141
1389
|
const container = document.createElement("span");
|
|
142
1390
|
container.className = "container-widget-header";
|
|
143
1391
|
const text = document.createElement("span");
|
|
144
1392
|
text.className = "container-widget-text";
|
|
145
|
-
text.textContent =
|
|
146
|
-
const button = document.createElement("button");
|
|
147
|
-
button.className = "container-edit-btn";
|
|
148
|
-
button.title = `编辑 ${componentRegistry.get(this.typeName)?.label ?? this.typeName}`;
|
|
149
|
-
button.textContent = "✎";
|
|
150
|
-
button.__typeName = this.typeName;
|
|
1393
|
+
text.textContent = `${this.quotePrefix}:::${this.typeName}`;
|
|
151
1394
|
container.appendChild(text);
|
|
152
|
-
|
|
1395
|
+
if (this.registered) {
|
|
1396
|
+
const button = document.createElement("button");
|
|
1397
|
+
button.className = "container-edit-btn";
|
|
1398
|
+
button.title = `编辑 ${this.typeName}`;
|
|
1399
|
+
button.textContent = "✎";
|
|
1400
|
+
button.dataset.containerIndex = String(this.containerIndex);
|
|
1401
|
+
button.dataset.typeName = this.typeName;
|
|
1402
|
+
container.appendChild(button);
|
|
1403
|
+
}
|
|
153
1404
|
return container;
|
|
154
1405
|
}
|
|
155
1406
|
eq(other) {
|
|
156
|
-
return this.typeName === other.typeName;
|
|
1407
|
+
return this.typeName === other.typeName && this.containerIndex === other.containerIndex && this.registered === other.registered && this.quotePrefix === other.quotePrefix;
|
|
157
1408
|
}
|
|
158
1409
|
ignoreEvent() {
|
|
159
1410
|
return false;
|
|
@@ -161,40 +1412,46 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
161
1412
|
};
|
|
162
1413
|
/**
|
|
163
1414
|
* 只读的容器属性行 Widget(显示 { key: value, ... })
|
|
164
|
-
*
|
|
1415
|
+
* 嵌套在引用中时原始行带 "> " 前缀,展示时剔除,与头行 widget 风格一致
|
|
165
1416
|
*/
|
|
166
1417
|
var ContainerPropsWidget = class extends WidgetType {
|
|
167
1418
|
propsText;
|
|
168
|
-
|
|
1419
|
+
quotePrefix;
|
|
1420
|
+
constructor(propsText, quotePrefix) {
|
|
169
1421
|
super();
|
|
170
1422
|
this.propsText = propsText;
|
|
1423
|
+
this.quotePrefix = quotePrefix;
|
|
171
1424
|
}
|
|
172
1425
|
toDOM() {
|
|
173
1426
|
const span = document.createElement("span");
|
|
174
1427
|
span.className = "container-widget-props";
|
|
175
|
-
span.textContent = this.propsText;
|
|
1428
|
+
span.textContent = this.propsText.startsWith(this.quotePrefix) ? this.propsText.slice(this.quotePrefix.length) : this.propsText;
|
|
176
1429
|
return span;
|
|
177
1430
|
}
|
|
178
1431
|
eq(other) {
|
|
179
|
-
return this.propsText === other.propsText;
|
|
1432
|
+
return this.propsText === other.propsText && this.quotePrefix === other.quotePrefix;
|
|
180
1433
|
}
|
|
181
1434
|
ignoreEvent() {
|
|
182
1435
|
return false;
|
|
183
1436
|
}
|
|
184
1437
|
};
|
|
185
1438
|
/**
|
|
186
|
-
* 只读的容器结束行 Widget(显示
|
|
187
|
-
* 使用 Decoration.replace 替换原始文本,使其不可直接编辑
|
|
1439
|
+
* 只读的容器结束行 Widget(显示 :::,嵌套引用时保留 "> " 前缀)
|
|
188
1440
|
*/
|
|
189
1441
|
var ContainerCloseWidget = class extends WidgetType {
|
|
1442
|
+
text;
|
|
1443
|
+
constructor(text) {
|
|
1444
|
+
super();
|
|
1445
|
+
this.text = text;
|
|
1446
|
+
}
|
|
190
1447
|
toDOM() {
|
|
191
1448
|
const span = document.createElement("span");
|
|
192
1449
|
span.className = "container-widget-text";
|
|
193
|
-
span.textContent =
|
|
1450
|
+
span.textContent = this.text;
|
|
194
1451
|
return span;
|
|
195
1452
|
}
|
|
196
|
-
eq() {
|
|
197
|
-
return
|
|
1453
|
+
eq(other) {
|
|
1454
|
+
return this.text === other.text;
|
|
198
1455
|
}
|
|
199
1456
|
ignoreEvent() {
|
|
200
1457
|
return false;
|
|
@@ -207,20 +1464,19 @@ var ContainerCloseWidget = class extends WidgetType {
|
|
|
207
1464
|
function findContainerDecorations(state) {
|
|
208
1465
|
const containers = findContainers(state.doc.toString());
|
|
209
1466
|
const decorations = [];
|
|
210
|
-
|
|
1467
|
+
containers.forEach((container, index) => {
|
|
211
1468
|
const headerLine = state.doc.lineAt(container.startPos);
|
|
212
1469
|
decorations.push({
|
|
213
1470
|
from: headerLine.from,
|
|
214
1471
|
to: headerLine.to,
|
|
215
|
-
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName) })
|
|
1472
|
+
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName, index, container.registered, container.quotePrefix ?? "") })
|
|
216
1473
|
});
|
|
217
1474
|
if (container.propsLineFrom > 0 && container.propsLineTo > 0) {
|
|
218
1475
|
const propsLine = state.doc.lineAt(container.propsLineFrom);
|
|
219
|
-
const propsText = propsLine.text;
|
|
220
1476
|
decorations.push({
|
|
221
1477
|
from: propsLine.from,
|
|
222
1478
|
to: propsLine.to,
|
|
223
|
-
value: Decoration.replace({ widget: new ContainerPropsWidget(
|
|
1479
|
+
value: Decoration.replace({ widget: new ContainerPropsWidget(propsLine.text, container.quotePrefix ?? "") })
|
|
224
1480
|
});
|
|
225
1481
|
}
|
|
226
1482
|
if (container.endPos > 0) {
|
|
@@ -228,55 +1484,64 @@ function findContainerDecorations(state) {
|
|
|
228
1484
|
decorations.push({
|
|
229
1485
|
from: endLine.from,
|
|
230
1486
|
to: endLine.to,
|
|
231
|
-
value: Decoration.replace({ widget: new ContainerCloseWidget() })
|
|
1487
|
+
value: Decoration.replace({ widget: new ContainerCloseWidget(endLine.text) })
|
|
232
1488
|
});
|
|
233
1489
|
}
|
|
234
|
-
}
|
|
1490
|
+
});
|
|
1491
|
+
decorations.sort((a, b) => a.from - b.from || b.to - a.to);
|
|
235
1492
|
return decorations;
|
|
236
1493
|
}
|
|
237
1494
|
/**
|
|
1495
|
+
* 点击编辑按钮时,依据按钮携带的容器索引回查最新属性并触发回调
|
|
1496
|
+
*/
|
|
1497
|
+
function handleEditButtonClick(event, view) {
|
|
1498
|
+
const target = event.target;
|
|
1499
|
+
if (!target.classList.contains("container-edit-btn")) return false;
|
|
1500
|
+
event.preventDefault();
|
|
1501
|
+
event.stopPropagation();
|
|
1502
|
+
const indexAttr = target.dataset.containerIndex;
|
|
1503
|
+
if (indexAttr === void 0) return false;
|
|
1504
|
+
const container = findContainers(view.state.doc.toString())[Number(indexAttr)];
|
|
1505
|
+
if (!container || !container.registered) return false;
|
|
1506
|
+
const callback = view.state.facet(containerEditCallback);
|
|
1507
|
+
if (callback) callback(view, {
|
|
1508
|
+
...container,
|
|
1509
|
+
props: { ...container.props }
|
|
1510
|
+
});
|
|
1511
|
+
return true;
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
238
1514
|
* 容器编辑 ViewPlugin
|
|
239
|
-
* 将容器的 ::: 头行和 {} 属性行替换为只读 widget
|
|
1515
|
+
* 将容器的 ::: 头行和 {} 属性行替换为只读 widget,使其无法在编辑器中直接编辑。
|
|
1516
|
+
* 仅在文档内容变化时重建装饰,光标移动不触发全文扫描。
|
|
240
1517
|
*/
|
|
241
1518
|
var containerWidgetPlugin = ViewPlugin.fromClass(class {
|
|
242
1519
|
decorations;
|
|
1520
|
+
/** 上次构建装饰时的注册中心版本,用于感知异步注册(不能标 private,否则导出匿名类的 dts 报 TS4094) */
|
|
1521
|
+
registryVersion;
|
|
243
1522
|
constructor(view) {
|
|
1523
|
+
this.registryVersion = componentRegistry.getVersion();
|
|
244
1524
|
this.decorations = Decoration.set(findContainerDecorations(view.state), true);
|
|
245
1525
|
}
|
|
246
1526
|
update(update) {
|
|
247
|
-
|
|
1527
|
+
const registryChanged = componentRegistry.getVersion() !== this.registryVersion;
|
|
1528
|
+
const woken = update.transactions.some((tr) => tr.effects.some((e) => e.is(refreshContainers)));
|
|
1529
|
+
if (update.docChanged || registryChanged || woken) {
|
|
1530
|
+
this.registryVersion = componentRegistry.getVersion();
|
|
1531
|
+
this.decorations = Decoration.set(findContainerDecorations(update.state), true);
|
|
1532
|
+
}
|
|
248
1533
|
}
|
|
249
1534
|
}, {
|
|
250
1535
|
decorations: (value) => value.decorations,
|
|
251
1536
|
eventHandlers: {
|
|
252
|
-
mousedown: (event,
|
|
1537
|
+
mousedown: (event, _view) => {
|
|
253
1538
|
if (event.target.classList.contains("container-edit-btn")) {
|
|
254
1539
|
event.preventDefault();
|
|
255
1540
|
return true;
|
|
256
1541
|
}
|
|
257
1542
|
return false;
|
|
258
1543
|
},
|
|
259
|
-
click:
|
|
260
|
-
const target = event.target;
|
|
261
|
-
if (target.classList.contains("container-edit-btn")) {
|
|
262
|
-
event.preventDefault();
|
|
263
|
-
event.stopPropagation();
|
|
264
|
-
if (target.__typeName) {
|
|
265
|
-
const containers = findContainers(view.state.doc.toString());
|
|
266
|
-
const buttonPos = view.posAtDOM(target);
|
|
267
|
-
for (const container of containers) {
|
|
268
|
-
const headerLine = view.state.doc.lineAt(container.startPos);
|
|
269
|
-
if (buttonPos >= headerLine.from - 5 && buttonPos <= headerLine.to + 5) {
|
|
270
|
-
const callback = view.state.facet(containerEditCallback);
|
|
271
|
-
if (callback) callback(view, container.typeName, container.propsLineFrom, container.propsLineTo, { ...container.props });
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
1544
|
+
click: handleEditButtonClick
|
|
280
1545
|
}
|
|
281
1546
|
});
|
|
282
1547
|
//#endregion
|
|
@@ -374,7 +1639,11 @@ function toggleTaskList(view) {
|
|
|
374
1639
|
});
|
|
375
1640
|
}
|
|
376
1641
|
}
|
|
377
|
-
view.
|
|
1642
|
+
const anchor = view.state.changes(changes).mapPos(from, 1);
|
|
1643
|
+
view.dispatch({
|
|
1644
|
+
changes,
|
|
1645
|
+
selection: { anchor }
|
|
1646
|
+
});
|
|
378
1647
|
}
|
|
379
1648
|
/**
|
|
380
1649
|
* 切换行首前缀(支持多行选区)
|
|
@@ -404,7 +1673,11 @@ function toggleLinePrefix(view, pattern, insertText) {
|
|
|
404
1673
|
insert: insertText
|
|
405
1674
|
});
|
|
406
1675
|
}
|
|
407
|
-
view.
|
|
1676
|
+
const anchor = view.state.changes(changes).mapPos(from, 1);
|
|
1677
|
+
view.dispatch({
|
|
1678
|
+
changes,
|
|
1679
|
+
selection: { anchor }
|
|
1680
|
+
});
|
|
408
1681
|
}
|
|
409
1682
|
/** Markdown 列表行:缩进 + 列表标记(无序/有序)+ 空白 */
|
|
410
1683
|
var LIST_LINE_RE = /^(\s*)([-*+]|\d+\.)([ \t]+)/;
|
|
@@ -517,28 +1790,32 @@ function dedentMarkdownList(view) {
|
|
|
517
1790
|
return true;
|
|
518
1791
|
}
|
|
519
1792
|
/**
|
|
520
|
-
*
|
|
1793
|
+
* 上传图片:失败(含网络异常)统一返回 null,不抛错
|
|
521
1794
|
* @param file - 要上传的文件
|
|
522
1795
|
* @param uploadConfig - 上传配置
|
|
523
1796
|
*/
|
|
524
1797
|
async function uploadFileToServer(file, uploadConfig) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
1798
|
+
try {
|
|
1799
|
+
if (uploadConfig.onUploadImage) return await uploadConfig.onUploadImage(file);
|
|
1800
|
+
if (uploadConfig.uploadUrl) {
|
|
1801
|
+
const formData = new FormData();
|
|
1802
|
+
formData.append("file", file);
|
|
1803
|
+
const response = await fetch(uploadConfig.uploadUrl, {
|
|
1804
|
+
method: "POST",
|
|
1805
|
+
body: formData
|
|
1806
|
+
});
|
|
1807
|
+
if (!response.ok) return null;
|
|
1808
|
+
const result = await response.json();
|
|
1809
|
+
if (uploadConfig.onGetUploadUrl) return uploadConfig.onGetUploadUrl(result);
|
|
1810
|
+
return result?.data?.path ?? null;
|
|
1811
|
+
}
|
|
1812
|
+
return null;
|
|
1813
|
+
} catch {
|
|
1814
|
+
return null;
|
|
537
1815
|
}
|
|
538
|
-
return null;
|
|
539
1816
|
}
|
|
540
1817
|
/**
|
|
541
|
-
*
|
|
1818
|
+
* 判断是否配置了图片上传(类型谓词,守卫后可安全访问配置)
|
|
542
1819
|
*/
|
|
543
1820
|
function isUploadConfigured(uploadConfig) {
|
|
544
1821
|
return !!(uploadConfig?.uploadUrl || uploadConfig?.onUploadImage);
|
|
@@ -552,7 +1829,6 @@ function uploadImage(view, uploadConfig) {
|
|
|
552
1829
|
const input = document.createElement("input");
|
|
553
1830
|
input.type = "file";
|
|
554
1831
|
input.accept = "image/*";
|
|
555
|
-
input.style.display = "none";
|
|
556
1832
|
input.addEventListener("change", async () => {
|
|
557
1833
|
if (!input.files || input.files.length === 0) return;
|
|
558
1834
|
const file = input.files[0];
|
|
@@ -569,7 +1845,6 @@ function uploadImage(view, uploadConfig) {
|
|
|
569
1845
|
}
|
|
570
1846
|
input.remove();
|
|
571
1847
|
});
|
|
572
|
-
document.body.appendChild(input);
|
|
573
1848
|
input.click();
|
|
574
1849
|
}
|
|
575
1850
|
/**
|
|
@@ -627,10 +1902,14 @@ function toggleWrap(view, openTag, closeTag) {
|
|
|
627
1902
|
}
|
|
628
1903
|
//#endregion
|
|
629
1904
|
//#region src/components/Editor/codemirrorExtensions.ts
|
|
630
|
-
/**
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
1905
|
+
/**
|
|
1906
|
+
* 图片上传配置 facet。
|
|
1907
|
+
* 传入 getter 而非配置本身:扩展只在 mount 时创建一次,
|
|
1908
|
+
* 运行期通过 getter 读取最新配置,避免闭包过期。
|
|
1909
|
+
*/
|
|
1910
|
+
var uploadConfigFacet = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
1911
|
+
/** 未配置上传时的提示回调 facet(同为 getter 形式) */
|
|
1912
|
+
var messageFacet = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
634
1913
|
/** 粘贴事件处理:拦截图片并上传 */
|
|
635
1914
|
var pasteHandler = EditorView$1.domEventHandlers({ paste: (event, view) => {
|
|
636
1915
|
const files = event.clipboardData?.files;
|
|
@@ -638,23 +1917,38 @@ var pasteHandler = EditorView$1.domEventHandlers({ paste: (event, view) => {
|
|
|
638
1917
|
const imageFiles = Array.from(files).filter((f) => f.type.startsWith("image/"));
|
|
639
1918
|
if (imageFiles.length === 0) return false;
|
|
640
1919
|
event.preventDefault();
|
|
641
|
-
const uploadConfig = view.state.facet(uploadConfigFacet);
|
|
642
|
-
const showMessage = view.state.facet(messageFacet);
|
|
1920
|
+
const uploadConfig = view.state.facet(uploadConfigFacet)?.();
|
|
1921
|
+
const showMessage = view.state.facet(messageFacet)?.();
|
|
643
1922
|
if (!isUploadConfigured(uploadConfig)) {
|
|
644
1923
|
showMessage?.();
|
|
645
1924
|
return true;
|
|
646
1925
|
}
|
|
647
|
-
const
|
|
648
|
-
let
|
|
649
|
-
for (const file of imageFiles) uploadFileToServer(file,
|
|
650
|
-
if (url)
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
1926
|
+
const config = uploadConfig;
|
|
1927
|
+
let isFirst = true;
|
|
1928
|
+
for (const file of imageFiles) uploadFileToServer(file, config).then((url) => {
|
|
1929
|
+
if (!url) return;
|
|
1930
|
+
const insert = `![${file.name.replace(/\.[^.]+$/, "")}](${url})`;
|
|
1931
|
+
const { state } = view;
|
|
1932
|
+
if (isFirst) {
|
|
1933
|
+
isFirst = false;
|
|
1934
|
+
const { from, to } = state.selection.main;
|
|
1935
|
+
view.dispatch({
|
|
1936
|
+
changes: {
|
|
1937
|
+
from,
|
|
1938
|
+
to,
|
|
1939
|
+
insert
|
|
1940
|
+
},
|
|
1941
|
+
selection: { anchor: from + insert.length }
|
|
1942
|
+
});
|
|
1943
|
+
} else {
|
|
1944
|
+
const end = state.doc.length;
|
|
1945
|
+
view.dispatch({
|
|
1946
|
+
changes: {
|
|
1947
|
+
from: end,
|
|
1948
|
+
insert: `\n${insert}`
|
|
1949
|
+
},
|
|
1950
|
+
selection: { anchor: end + insert.length + 1 }
|
|
1951
|
+
});
|
|
658
1952
|
}
|
|
659
1953
|
});
|
|
660
1954
|
return true;
|
|
@@ -714,8 +2008,8 @@ var getCodeMirrorExtensions = (opts) => {
|
|
|
714
2008
|
];
|
|
715
2009
|
extensions.push(containerWidgetPlugin);
|
|
716
2010
|
if (opts?.onEditContainer) extensions.push(containerEditCallback.of(opts.onEditContainer));
|
|
717
|
-
if (opts?.
|
|
718
|
-
if (opts?.
|
|
2011
|
+
if (opts?.getUploadConfig) extensions.push(uploadConfigFacet.of(opts.getUploadConfig));
|
|
2012
|
+
if (opts?.getOnMessageNoUploadConfig) extensions.push(messageFacet.of(opts.getOnMessageNoUploadConfig));
|
|
719
2013
|
return extensions;
|
|
720
2014
|
};
|
|
721
2015
|
//#endregion
|
|
@@ -723,17 +2017,29 @@ var getCodeMirrorExtensions = (opts) => {
|
|
|
723
2017
|
function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer, uploadConfig, onMessageNoUploadConfig }) {
|
|
724
2018
|
const editorRef = useRef(null);
|
|
725
2019
|
const viewRef = useRef(null);
|
|
2020
|
+
const latestRef = useRef({
|
|
2021
|
+
onChange,
|
|
2022
|
+
onEditContainer,
|
|
2023
|
+
uploadConfig,
|
|
2024
|
+
onMessageNoUploadConfig
|
|
2025
|
+
});
|
|
2026
|
+
latestRef.current = {
|
|
2027
|
+
onChange,
|
|
2028
|
+
onEditContainer,
|
|
2029
|
+
uploadConfig,
|
|
2030
|
+
onMessageNoUploadConfig
|
|
2031
|
+
};
|
|
726
2032
|
useEffect(() => {
|
|
727
2033
|
if (!editorRef.current) return;
|
|
728
2034
|
const extensions = [
|
|
729
2035
|
basicSetup,
|
|
730
2036
|
...getCodeMirrorExtensions({
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
2037
|
+
getUploadConfig: () => latestRef.current.uploadConfig,
|
|
2038
|
+
getOnMessageNoUploadConfig: () => latestRef.current.onMessageNoUploadConfig,
|
|
2039
|
+
onEditContainer: (view, container) => latestRef.current.onEditContainer?.(view, container)
|
|
734
2040
|
}),
|
|
735
2041
|
EditorView.updateListener.of((update) => {
|
|
736
|
-
if (update.docChanged) onChange(update.state.doc.toString());
|
|
2042
|
+
if (update.docChanged) latestRef.current.onChange(update.state.doc.toString());
|
|
737
2043
|
})
|
|
738
2044
|
];
|
|
739
2045
|
const state = EditorState.create({
|
|
@@ -744,18 +2050,26 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
|
|
|
744
2050
|
state,
|
|
745
2051
|
parent: editorRef.current
|
|
746
2052
|
});
|
|
747
|
-
if (
|
|
748
|
-
|
|
2053
|
+
if (viewRef.current) {
|
|
2054
|
+
onScrollReady?.(viewRef.current.scrollDOM);
|
|
2055
|
+
onViewReady?.(viewRef.current);
|
|
2056
|
+
}
|
|
749
2057
|
return () => {
|
|
750
2058
|
viewRef.current?.destroy();
|
|
2059
|
+
viewRef.current = null;
|
|
751
2060
|
};
|
|
752
2061
|
}, []);
|
|
753
2062
|
useEffect(() => {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
2063
|
+
const view = viewRef.current;
|
|
2064
|
+
if (view && view.state.doc.toString() !== value) view.dispatch({
|
|
2065
|
+
changes: {
|
|
2066
|
+
from: 0,
|
|
2067
|
+
to: view.state.doc.length,
|
|
2068
|
+
insert: value
|
|
2069
|
+
},
|
|
2070
|
+
effects: view.scrollSnapshot(),
|
|
2071
|
+
scrollIntoView: false
|
|
2072
|
+
});
|
|
759
2073
|
}, [value]);
|
|
760
2074
|
return /* @__PURE__ */ jsx("div", {
|
|
761
2075
|
ref: editorRef,
|
|
@@ -764,23 +2078,25 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
|
|
|
764
2078
|
}
|
|
765
2079
|
//#endregion
|
|
766
2080
|
//#region src/components/Preview/index.tsx
|
|
767
|
-
var Preview = forwardRef(({ content, previewOptions }, ref) => {
|
|
2081
|
+
var Preview = forwardRef(({ content, previewOptions, languages }, ref) => {
|
|
768
2082
|
useEffect(() => {
|
|
769
2083
|
initHighlighter({
|
|
770
2084
|
...languagesCommon,
|
|
771
|
-
...
|
|
2085
|
+
...languages ?? {}
|
|
772
2086
|
});
|
|
773
|
-
}, [
|
|
2087
|
+
}, [languages]);
|
|
2088
|
+
const { languages: _ignored, ...restOptions } = previewOptions ?? {};
|
|
774
2089
|
return /* @__PURE__ */ jsx("div", {
|
|
775
2090
|
ref,
|
|
776
2091
|
className: "preview",
|
|
777
2092
|
children: /* @__PURE__ */ jsx(RenderMarkdown, {
|
|
778
2093
|
content,
|
|
779
|
-
...
|
|
2094
|
+
...restOptions
|
|
780
2095
|
})
|
|
781
2096
|
});
|
|
782
2097
|
});
|
|
783
2098
|
Preview.displayName = "Preview";
|
|
2099
|
+
var Preview_default = memo(Preview);
|
|
784
2100
|
//#endregion
|
|
785
2101
|
//#region src/components/Panel/SplitPanels.tsx
|
|
786
2102
|
var { Panel } = Splitter;
|
|
@@ -796,9 +2112,31 @@ function SplitPanels({ leftPanel, rightPanel }) {
|
|
|
796
2112
|
});
|
|
797
2113
|
}
|
|
798
2114
|
//#endregion
|
|
2115
|
+
//#region src/components/Icon/config.ts
|
|
2116
|
+
var scriptUrl = "https://at.alicdn.com/t/c/font_5241307_xoojyr52dqn.js";
|
|
2117
|
+
var IconComp = null;
|
|
2118
|
+
/**
|
|
2119
|
+
* 配置 iconfont 脚本地址(宿主在应用入口调用),需在首次渲染前设置;
|
|
2120
|
+
* 变更后重置内部缓存,下次渲染时以新地址重建图标组件。
|
|
2121
|
+
*/
|
|
2122
|
+
function setIconfontScriptUrl(url) {
|
|
2123
|
+
if (url === scriptUrl) return;
|
|
2124
|
+
scriptUrl = url;
|
|
2125
|
+
IconComp = null;
|
|
2126
|
+
}
|
|
2127
|
+
/** 读取当前 iconfont 脚本地址 */
|
|
2128
|
+
function getIconfontScriptUrl() {
|
|
2129
|
+
return scriptUrl;
|
|
2130
|
+
}
|
|
2131
|
+
/** 懒创建图标组件:首次渲染时才注入 iconfont 脚本,避免模块层副作用 */
|
|
2132
|
+
function getIconComponent() {
|
|
2133
|
+
if (!IconComp) IconComp = createFromIconfontCN({ scriptUrl });
|
|
2134
|
+
return IconComp;
|
|
2135
|
+
}
|
|
2136
|
+
//#endregion
|
|
799
2137
|
//#region src/components/Icon/index.tsx
|
|
800
|
-
var Icon = createFromIconfontCN({ scriptUrl: "https://at.alicdn.com/t/c/font_5241307_xoojyr52dqn.js" });
|
|
801
2138
|
function IconComponent(type, className) {
|
|
2139
|
+
const Icon = getIconComponent();
|
|
802
2140
|
return /* @__PURE__ */ jsx(Icon, {
|
|
803
2141
|
type: `icon-${type}`,
|
|
804
2142
|
className
|
|
@@ -819,7 +2157,8 @@ var UPLOAD_CONFIG_MISSING_MESSAGE = "请先配置图片上传功能";
|
|
|
819
2157
|
* @param options - 配置选项
|
|
820
2158
|
*/
|
|
821
2159
|
function createToolbarConfig(options) {
|
|
822
|
-
const hasUploadConfig = isUploadConfigured(options);
|
|
2160
|
+
const hasUploadConfig = isUploadConfigured(options?.upload);
|
|
2161
|
+
const notify = options?.notify;
|
|
823
2162
|
return [
|
|
824
2163
|
{
|
|
825
2164
|
id: "heading",
|
|
@@ -913,7 +2252,7 @@ function createToolbarConfig(options) {
|
|
|
913
2252
|
id: "image",
|
|
914
2253
|
label: "图片",
|
|
915
2254
|
icon: PictureOutlined,
|
|
916
|
-
handler: hasUploadConfig && options ? (v) => uploadImage(v, options) : () =>
|
|
2255
|
+
handler: hasUploadConfig && options?.upload ? (v) => uploadImage(v, options.upload) : () => notify?.("warning", UPLOAD_CONFIG_MISSING_MESSAGE)
|
|
917
2256
|
},
|
|
918
2257
|
{ separatorBefore: true },
|
|
919
2258
|
{
|
|
@@ -960,11 +2299,14 @@ function createToolbarConfig(options) {
|
|
|
960
2299
|
//#endregion
|
|
961
2300
|
//#region src/components/Toolbar/hooks/useToolbar.ts
|
|
962
2301
|
function useToolbar(editorView, options) {
|
|
963
|
-
const { extraItems, uploadConfig } = options || {};
|
|
2302
|
+
const { extraItems, uploadConfig, notify } = options || {};
|
|
964
2303
|
return {
|
|
965
2304
|
config: useMemo(() => {
|
|
966
|
-
return createToolbarConfig(
|
|
967
|
-
|
|
2305
|
+
return createToolbarConfig({
|
|
2306
|
+
upload: uploadConfig,
|
|
2307
|
+
notify
|
|
2308
|
+
});
|
|
2309
|
+
}, [uploadConfig, notify]),
|
|
968
2310
|
extraItemsConfig: useMemo(() => {
|
|
969
2311
|
return extraItems || [];
|
|
970
2312
|
}, [extraItems]),
|
|
@@ -984,34 +2326,52 @@ function useToolbar(editorView, options) {
|
|
|
984
2326
|
}
|
|
985
2327
|
//#endregion
|
|
986
2328
|
//#region src/components/Toolbar/renderers/ToolbarItemRenderer.tsx
|
|
2329
|
+
/**
|
|
2330
|
+
* 渲染图标:统一接受组件类型;兼容传入 ReactNode 的旧用法。
|
|
2331
|
+
* 组件类型不仅指函数/class,也包括 forwardRef、memo 包装出的对象
|
|
2332
|
+
* (@ant-design/icons 即为 forwardRef,不能当作普通 child 直接渲染)。
|
|
2333
|
+
*/
|
|
2334
|
+
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
2335
|
+
var REACT_MEMO = Symbol.for("react.memo");
|
|
2336
|
+
function isComponentType(icon) {
|
|
2337
|
+
if (typeof icon === "function") return true;
|
|
2338
|
+
if (typeof icon === "object" && icon !== null) {
|
|
2339
|
+
const t = icon.$$typeof;
|
|
2340
|
+
return t === REACT_FORWARD_REF || t === REACT_MEMO;
|
|
2341
|
+
}
|
|
2342
|
+
return false;
|
|
2343
|
+
}
|
|
2344
|
+
function renderIcon(icon) {
|
|
2345
|
+
if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, {});
|
|
2346
|
+
return icon;
|
|
2347
|
+
}
|
|
987
2348
|
function ToolbarItemRenderer({ item, onClick }) {
|
|
988
|
-
const Icon = item.icon;
|
|
989
2349
|
if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Fragment, { children: [item.separatorBefore && /* @__PURE__ */ jsx("div", { className: "toolbar-separator" }), /* @__PURE__ */ jsx("div", {
|
|
990
2350
|
className: "toolbar-group",
|
|
991
2351
|
children: /* @__PURE__ */ jsx(Tooltip, {
|
|
992
2352
|
title: item.label,
|
|
993
2353
|
children: /* @__PURE__ */ jsx(Dropdown, {
|
|
994
|
-
menu: {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
children: [
|
|
1000
|
-
child.icon && (() => {
|
|
1001
|
-
const ChildIcon = child.icon;
|
|
1002
|
-
return /* @__PURE__ */ jsx(ChildIcon, {});
|
|
1003
|
-
})(),
|
|
2354
|
+
menu: {
|
|
2355
|
+
items: item.children.map((child) => ({
|
|
2356
|
+
key: child.id ?? "",
|
|
2357
|
+
label: /* @__PURE__ */ jsxs("span", { children: [
|
|
2358
|
+
child.icon && renderIcon(child.icon),
|
|
1004
2359
|
" ",
|
|
1005
2360
|
child.label
|
|
1006
|
-
]
|
|
1007
|
-
|
|
1008
|
-
|
|
2361
|
+
] }),
|
|
2362
|
+
disabled: child.disabled
|
|
2363
|
+
})),
|
|
2364
|
+
onClick: ({ key }) => {
|
|
2365
|
+
const child = item.children?.find((c) => c.id === key);
|
|
2366
|
+
if (child && !child.disabled) onClick(child);
|
|
2367
|
+
}
|
|
2368
|
+
},
|
|
1009
2369
|
placement: "bottomLeft",
|
|
1010
2370
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
1011
2371
|
className: "toolbar-button",
|
|
1012
2372
|
type: "text",
|
|
1013
2373
|
size: "small",
|
|
1014
|
-
children: [
|
|
2374
|
+
children: [item.icon && renderIcon(item.icon), /* @__PURE__ */ jsx(DownOutlined, { style: { fontSize: 10 } })]
|
|
1015
2375
|
})
|
|
1016
2376
|
})
|
|
1017
2377
|
})
|
|
@@ -1028,7 +2388,7 @@ function ToolbarItemRenderer({ item, onClick }) {
|
|
|
1028
2388
|
size: "small",
|
|
1029
2389
|
disabled: isDisabled,
|
|
1030
2390
|
onClick: () => !isDisabled && onClick(item),
|
|
1031
|
-
children:
|
|
2391
|
+
children: item.icon && renderIcon(item.icon)
|
|
1032
2392
|
})
|
|
1033
2393
|
})
|
|
1034
2394
|
})] });
|
|
@@ -1046,125 +2406,81 @@ var index_module_default = {
|
|
|
1046
2406
|
var MAX_ROW = 8;
|
|
1047
2407
|
var MAX_COL = 8;
|
|
1048
2408
|
function TablePicker({ onSelect }) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
const [confirmedSize, setConfirmedSize] = useState({
|
|
1054
|
-
row: 0,
|
|
1055
|
-
col: 0
|
|
2409
|
+
/** 当前高亮区域(rows x cols),渲染唯一依赖此状态 */
|
|
2410
|
+
const [size, setSize] = useState({
|
|
2411
|
+
rows: 0,
|
|
2412
|
+
cols: 0
|
|
1056
2413
|
});
|
|
1057
|
-
|
|
2414
|
+
/** 鼠标回撤(向上/向左)后需要重置列跟踪,prevRow 与 pending 成对出现,仅事件处理内使用 */
|
|
1058
2415
|
const prevRowRef = useRef(0);
|
|
1059
|
-
const
|
|
1060
|
-
const
|
|
1061
|
-
const commitRef = useRef(null);
|
|
1062
|
-
const clearTimer = useCallback(() => {
|
|
1063
|
-
if (timerIdRef.current) {
|
|
1064
|
-
clearTimeout(timerIdRef.current);
|
|
1065
|
-
timerIdRef.current = null;
|
|
1066
|
-
}
|
|
1067
|
-
}, []);
|
|
2416
|
+
const pendingColsRef = useRef(0);
|
|
2417
|
+
const flashTimerRef = useRef(null);
|
|
1068
2418
|
const clearFlash = useCallback(() => {
|
|
1069
|
-
if (
|
|
1070
|
-
clearInterval(
|
|
1071
|
-
|
|
2419
|
+
if (flashTimerRef.current) {
|
|
2420
|
+
clearInterval(flashTimerRef.current);
|
|
2421
|
+
flashTimerRef.current = null;
|
|
1072
2422
|
}
|
|
1073
2423
|
}, []);
|
|
1074
2424
|
useEffect(() => () => {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
}, []);
|
|
2425
|
+
clearFlash();
|
|
2426
|
+
}, [clearFlash]);
|
|
1078
2427
|
/**
|
|
1079
2428
|
* 扩展选中区域至 (col, row)
|
|
1080
2429
|
*/
|
|
1081
2430
|
function extend(col, row) {
|
|
1082
|
-
if (row < prevRowRef.current || col <
|
|
1083
|
-
if (col >
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
setConfirmedSize({
|
|
1089
|
-
row,
|
|
1090
|
-
col: maxColRef.current
|
|
2431
|
+
if (row < prevRowRef.current || col < pendingColsRef.current) pendingColsRef.current = 0;
|
|
2432
|
+
if (col > pendingColsRef.current) pendingColsRef.current = col;
|
|
2433
|
+
const cols = pendingColsRef.current;
|
|
2434
|
+
setSize({
|
|
2435
|
+
rows: row,
|
|
2436
|
+
cols
|
|
1091
2437
|
});
|
|
1092
|
-
|
|
1093
|
-
cols: maxColRef.current,
|
|
1094
|
-
rows: 1
|
|
1095
|
-
};
|
|
2438
|
+
prevRowRef.current = row;
|
|
1096
2439
|
}
|
|
1097
2440
|
/**
|
|
1098
|
-
*
|
|
2441
|
+
* 跳跃动画效果:逐行推进高亮,结束后落到 (col, limit)
|
|
1099
2442
|
*/
|
|
1100
|
-
function flash(col, dir, limit
|
|
2443
|
+
function flash(col, dir, limit) {
|
|
2444
|
+
clearFlash();
|
|
1101
2445
|
let current = dir === 1 ? 1 : limit;
|
|
1102
2446
|
const step = dir === 1 ? 1 : -1;
|
|
1103
|
-
|
|
1104
|
-
setHoverSize({
|
|
1105
|
-
row: current,
|
|
1106
|
-
col
|
|
1107
|
-
});
|
|
1108
|
-
if (current > confirmedSize.row || dir === -1) maxColRef.current = Math.min(MAX_COL, col);
|
|
1109
|
-
current += step;
|
|
2447
|
+
flashTimerRef.current = setInterval(() => {
|
|
1110
2448
|
if (dir === 1 && current > limit || dir === -1 && current < 1) {
|
|
1111
|
-
|
|
1112
|
-
refreshTimerRef.current = null;
|
|
2449
|
+
clearFlash();
|
|
1113
2450
|
const finalRow = current - step;
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
col
|
|
2451
|
+
setSize({
|
|
2452
|
+
rows: finalRow,
|
|
2453
|
+
cols: col
|
|
1117
2454
|
});
|
|
1118
|
-
|
|
2455
|
+
return;
|
|
1119
2456
|
}
|
|
2457
|
+
setSize({
|
|
2458
|
+
rows: current,
|
|
2459
|
+
cols: col
|
|
2460
|
+
});
|
|
2461
|
+
current += step;
|
|
1120
2462
|
}, 50);
|
|
1121
2463
|
}
|
|
1122
2464
|
/**
|
|
1123
2465
|
* 核心逻辑:鼠标进入格子
|
|
1124
2466
|
*/
|
|
1125
|
-
function
|
|
1126
|
-
clearTimer();
|
|
2467
|
+
function onCellEnter(index) {
|
|
1127
2468
|
clearFlash();
|
|
1128
2469
|
const row = Math.floor(index / MAX_COL) + 1;
|
|
1129
2470
|
const col = index % MAX_COL + 1;
|
|
1130
|
-
const
|
|
1131
|
-
const isJump = Math.abs(row -
|
|
1132
|
-
const isDown = row > prevRow;
|
|
2471
|
+
const maxCol = pendingColsRef.current;
|
|
2472
|
+
const isJump = Math.abs(row - prevRowRef.current) > 1;
|
|
1133
2473
|
prevRowRef.current = row;
|
|
1134
2474
|
if (!isJump) extend(col, row);
|
|
1135
|
-
else if (
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
row: r,
|
|
1139
|
-
col: c
|
|
1140
|
-
});
|
|
1141
|
-
});
|
|
1142
|
-
else extend(col, row);
|
|
2475
|
+
else if (row > 0 && (col > maxCol || maxCol >= MAX_COL)) {
|
|
2476
|
+
pendingColsRef.current = Math.min(MAX_COL, col);
|
|
2477
|
+
flash(Math.min(MAX_COL, col), 1, Math.min(row, MAX_ROW));
|
|
1143
2478
|
} else {
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
setConfirmedSize({
|
|
1147
|
-
row: r,
|
|
1148
|
-
col: c
|
|
1149
|
-
});
|
|
1150
|
-
if (r === 1) {
|
|
1151
|
-
commitRef.current = {
|
|
1152
|
-
cols: Math.min(MAX_COL, col),
|
|
1153
|
-
rows: 1
|
|
1154
|
-
};
|
|
1155
|
-
setConfirmedSize({
|
|
1156
|
-
row: 1,
|
|
1157
|
-
col: Math.min(MAX_COL, col)
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
});
|
|
2479
|
+
pendingColsRef.current = 0;
|
|
2480
|
+
extend(col, row);
|
|
1161
2481
|
}
|
|
1162
2482
|
}
|
|
1163
2483
|
function onMouseDown() {
|
|
1164
|
-
const size = commitRef.current || {
|
|
1165
|
-
cols: maxColRef.current,
|
|
1166
|
-
rows: confirmedSize.row
|
|
1167
|
-
};
|
|
1168
2484
|
if (size.rows > 0 && size.cols > 0) onSelect(size);
|
|
1169
2485
|
}
|
|
1170
2486
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1176,18 +2492,18 @@ function TablePicker({ onSelect }) {
|
|
|
1176
2492
|
children: Array.from({ length: 64 }).map((_, i) => {
|
|
1177
2493
|
const row = Math.floor(i / MAX_COL) + 1;
|
|
1178
2494
|
const col = i % MAX_COL + 1;
|
|
1179
|
-
const isSelected = row <=
|
|
2495
|
+
const isSelected = row <= size.rows && col <= size.cols;
|
|
1180
2496
|
return /* @__PURE__ */ jsx("div", {
|
|
1181
2497
|
className: `${index_module_default.cell} ${isSelected ? index_module_default.cellActive : ""}`,
|
|
1182
|
-
onMouseEnter: () =>
|
|
2498
|
+
onMouseEnter: () => onCellEnter(i)
|
|
1183
2499
|
}, i);
|
|
1184
2500
|
})
|
|
1185
2501
|
}), /* @__PURE__ */ jsxs("div", {
|
|
1186
2502
|
className: index_module_default.label,
|
|
1187
2503
|
children: [
|
|
1188
|
-
|
|
2504
|
+
size.rows,
|
|
1189
2505
|
" x ",
|
|
1190
|
-
|
|
2506
|
+
size.cols || 1
|
|
1191
2507
|
]
|
|
1192
2508
|
})]
|
|
1193
2509
|
});
|
|
@@ -1195,8 +2511,10 @@ function TablePicker({ onSelect }) {
|
|
|
1195
2511
|
//#endregion
|
|
1196
2512
|
//#region src/components/Toolbar/renderers/TablePicker/TableDropdown.tsx
|
|
1197
2513
|
function TableDropdown({ editorView }) {
|
|
1198
|
-
const [open, setOpen] =
|
|
1199
|
-
const
|
|
2514
|
+
const [open, setOpen] = useState(false);
|
|
2515
|
+
const handleOpenChange = useCallback((next) => {
|
|
2516
|
+
setOpen(next);
|
|
2517
|
+
}, []);
|
|
1200
2518
|
const handleTableSelect = useCallback((rows, cols) => {
|
|
1201
2519
|
if (!editorView || rows <= 0 || cols <= 0) return;
|
|
1202
2520
|
editorView.focus();
|
|
@@ -1213,18 +2531,15 @@ function TableDropdown({ editorView }) {
|
|
|
1213
2531
|
return /* @__PURE__ */ jsx(Dropdown, {
|
|
1214
2532
|
trigger: ["click"],
|
|
1215
2533
|
open,
|
|
1216
|
-
onOpenChange:
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
} }, openCountRef.current)
|
|
1226
|
-
});
|
|
1227
|
-
},
|
|
2534
|
+
onOpenChange: handleOpenChange,
|
|
2535
|
+
destroyOnHidden: true,
|
|
2536
|
+
popupRender: () => /* @__PURE__ */ jsx("div", {
|
|
2537
|
+
style: { padding: 4 },
|
|
2538
|
+
children: /* @__PURE__ */ jsx(TablePicker, { onSelect: (size) => {
|
|
2539
|
+
handleTableSelect(size.rows, size.cols);
|
|
2540
|
+
setOpen(false);
|
|
2541
|
+
} })
|
|
2542
|
+
}),
|
|
1228
2543
|
placement: "bottomLeft",
|
|
1229
2544
|
children: /* @__PURE__ */ jsx(Button, {
|
|
1230
2545
|
className: "toolbar-button",
|
|
@@ -1237,10 +2552,11 @@ function TableDropdown({ editorView }) {
|
|
|
1237
2552
|
}
|
|
1238
2553
|
//#endregion
|
|
1239
2554
|
//#region src/components/Toolbar/index.tsx
|
|
1240
|
-
function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig }) {
|
|
2555
|
+
function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig, notify }) {
|
|
1241
2556
|
const { config, extraItemsConfig, handleClick } = useToolbar(editorView, {
|
|
1242
2557
|
extraItems,
|
|
1243
|
-
uploadConfig
|
|
2558
|
+
uploadConfig,
|
|
2559
|
+
notify
|
|
1244
2560
|
});
|
|
1245
2561
|
const renderFullscreen = useCallback(() => {
|
|
1246
2562
|
if (!onToggleFullscreen) return null;
|
|
@@ -1280,8 +2596,305 @@ function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems
|
|
|
1280
2596
|
]
|
|
1281
2597
|
});
|
|
1282
2598
|
}
|
|
2599
|
+
var Toolbar_default = memo(Toolbar);
|
|
1283
2600
|
//#endregion
|
|
1284
2601
|
//#region src/components/Dialog/EditDialog.tsx
|
|
2602
|
+
var import_dayjs_min = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2603
|
+
(function(t, e) {
|
|
2604
|
+
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
|
|
2605
|
+
})(exports, (function() {
|
|
2606
|
+
"use strict";
|
|
2607
|
+
var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = {
|
|
2608
|
+
name: "en",
|
|
2609
|
+
weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
|
|
2610
|
+
months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
|
|
2611
|
+
ordinal: function(t) {
|
|
2612
|
+
var e = [
|
|
2613
|
+
"th",
|
|
2614
|
+
"st",
|
|
2615
|
+
"nd",
|
|
2616
|
+
"rd"
|
|
2617
|
+
], n = t % 100;
|
|
2618
|
+
return "[" + t + (e[(n - 20) % 10] || e[n] || e[0]) + "]";
|
|
2619
|
+
}
|
|
2620
|
+
}, m = function(t, e, n) {
|
|
2621
|
+
var r = String(t);
|
|
2622
|
+
return !r || r.length >= e ? t : "" + Array(e + 1 - r.length).join(n) + t;
|
|
2623
|
+
}, v = {
|
|
2624
|
+
s: m,
|
|
2625
|
+
z: function(t) {
|
|
2626
|
+
var e = -t.utcOffset(), n = Math.abs(e), r = Math.floor(n / 60), i = n % 60;
|
|
2627
|
+
return (e <= 0 ? "+" : "-") + m(r, 2, "0") + ":" + m(i, 2, "0");
|
|
2628
|
+
},
|
|
2629
|
+
m: function t(e, n) {
|
|
2630
|
+
if (e.date() < n.date()) return -t(n, e);
|
|
2631
|
+
var r = 12 * (n.year() - e.year()) + (n.month() - e.month()), i = e.clone().add(r, c), s = n - i < 0, u = e.clone().add(r + (s ? -1 : 1), c);
|
|
2632
|
+
return +(-(r + (n - i) / (s ? i - u : u - i)) || 0);
|
|
2633
|
+
},
|
|
2634
|
+
a: function(t) {
|
|
2635
|
+
return t < 0 ? Math.ceil(t) || 0 : Math.floor(t);
|
|
2636
|
+
},
|
|
2637
|
+
p: function(t) {
|
|
2638
|
+
return {
|
|
2639
|
+
M: c,
|
|
2640
|
+
y: h,
|
|
2641
|
+
w: o,
|
|
2642
|
+
d: a,
|
|
2643
|
+
D: d,
|
|
2644
|
+
h: u,
|
|
2645
|
+
m: s,
|
|
2646
|
+
s: i,
|
|
2647
|
+
ms: r,
|
|
2648
|
+
Q: f
|
|
2649
|
+
}[t] || String(t || "").toLowerCase().replace(/s$/, "");
|
|
2650
|
+
},
|
|
2651
|
+
u: function(t) {
|
|
2652
|
+
return void 0 === t;
|
|
2653
|
+
}
|
|
2654
|
+
}, g = "en", D = {};
|
|
2655
|
+
D[g] = M;
|
|
2656
|
+
var p = "$isDayjsObject", S = function(t) {
|
|
2657
|
+
return t instanceof _ || !(!t || !t[p]);
|
|
2658
|
+
}, w = function t(e, n, r) {
|
|
2659
|
+
var i;
|
|
2660
|
+
if (!e) return g;
|
|
2661
|
+
if ("string" == typeof e) {
|
|
2662
|
+
var s = e.toLowerCase();
|
|
2663
|
+
D[s] && (i = s), n && (D[s] = n, i = s);
|
|
2664
|
+
var u = e.split("-");
|
|
2665
|
+
if (!i && u.length > 1) return t(u[0]);
|
|
2666
|
+
} else {
|
|
2667
|
+
var a = e.name;
|
|
2668
|
+
D[a] = e, i = a;
|
|
2669
|
+
}
|
|
2670
|
+
return !r && i && (g = i), i || !r && g;
|
|
2671
|
+
}, O = function(t, e) {
|
|
2672
|
+
if (S(t)) return t.clone();
|
|
2673
|
+
var n = "object" == typeof e ? e : {};
|
|
2674
|
+
return n.date = t, n.args = arguments, new _(n);
|
|
2675
|
+
}, b = v;
|
|
2676
|
+
b.l = w, b.i = S, b.w = function(t, e) {
|
|
2677
|
+
return O(t, {
|
|
2678
|
+
locale: e.$L,
|
|
2679
|
+
utc: e.$u,
|
|
2680
|
+
x: e.$x,
|
|
2681
|
+
$offset: e.$offset
|
|
2682
|
+
});
|
|
2683
|
+
};
|
|
2684
|
+
var _ = function() {
|
|
2685
|
+
function M(t) {
|
|
2686
|
+
this.$L = w(t.locale, null, !0), this.parse(t), this.$x = this.$x || t.x || {}, this[p] = !0;
|
|
2687
|
+
}
|
|
2688
|
+
var m = M.prototype;
|
|
2689
|
+
return m.parse = function(t) {
|
|
2690
|
+
this.$d = function(t) {
|
|
2691
|
+
var e = t.date, n = t.utc;
|
|
2692
|
+
if (null === e) return /* @__PURE__ */ new Date(NaN);
|
|
2693
|
+
if (b.u(e)) return /* @__PURE__ */ new Date();
|
|
2694
|
+
if (e instanceof Date) return new Date(e);
|
|
2695
|
+
if ("string" == typeof e && !/Z$/i.test(e)) {
|
|
2696
|
+
var r = e.match($);
|
|
2697
|
+
if (r) {
|
|
2698
|
+
var i = r[2] - 1 || 0, s = (r[7] || "0").substring(0, 3);
|
|
2699
|
+
return n ? new Date(Date.UTC(r[1], i, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, s)) : new Date(r[1], i, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, s);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
return new Date(e);
|
|
2703
|
+
}(t), this.init();
|
|
2704
|
+
}, m.init = function() {
|
|
2705
|
+
var t = this.$d;
|
|
2706
|
+
this.$y = t.getFullYear(), this.$M = t.getMonth(), this.$D = t.getDate(), this.$W = t.getDay(), this.$H = t.getHours(), this.$m = t.getMinutes(), this.$s = t.getSeconds(), this.$ms = t.getMilliseconds();
|
|
2707
|
+
}, m.$utils = function() {
|
|
2708
|
+
return b;
|
|
2709
|
+
}, m.isValid = function() {
|
|
2710
|
+
return !(this.$d.toString() === l);
|
|
2711
|
+
}, m.isSame = function(t, e) {
|
|
2712
|
+
var n = O(t);
|
|
2713
|
+
return this.startOf(e) <= n && n <= this.endOf(e);
|
|
2714
|
+
}, m.isAfter = function(t, e) {
|
|
2715
|
+
return O(t) < this.startOf(e);
|
|
2716
|
+
}, m.isBefore = function(t, e) {
|
|
2717
|
+
return this.endOf(e) < O(t);
|
|
2718
|
+
}, m.$g = function(t, e, n) {
|
|
2719
|
+
return b.u(t) ? this[e] : this.set(n, t);
|
|
2720
|
+
}, m.unix = function() {
|
|
2721
|
+
return Math.floor(this.valueOf() / 1e3);
|
|
2722
|
+
}, m.valueOf = function() {
|
|
2723
|
+
return this.$d.getTime();
|
|
2724
|
+
}, m.startOf = function(t, e) {
|
|
2725
|
+
var n = this, r = !!b.u(e) || e, f = b.p(t), l = function(t, e) {
|
|
2726
|
+
var i = b.w(n.$u ? Date.UTC(n.$y, e, t) : new Date(n.$y, e, t), n);
|
|
2727
|
+
return r ? i : i.endOf(a);
|
|
2728
|
+
}, $ = function(t, e) {
|
|
2729
|
+
return b.w(n.toDate()[t].apply(n.toDate("s"), (r ? [
|
|
2730
|
+
0,
|
|
2731
|
+
0,
|
|
2732
|
+
0,
|
|
2733
|
+
0
|
|
2734
|
+
] : [
|
|
2735
|
+
23,
|
|
2736
|
+
59,
|
|
2737
|
+
59,
|
|
2738
|
+
999
|
|
2739
|
+
]).slice(e)), n);
|
|
2740
|
+
}, y = this.$W, M = this.$M, m = this.$D, v = "set" + (this.$u ? "UTC" : "");
|
|
2741
|
+
switch (f) {
|
|
2742
|
+
case h: return r ? l(1, 0) : l(31, 11);
|
|
2743
|
+
case c: return r ? l(1, M) : l(0, M + 1);
|
|
2744
|
+
case o:
|
|
2745
|
+
var g = this.$locale().weekStart || 0, D = (y < g ? y + 7 : y) - g;
|
|
2746
|
+
return l(r ? m - D : m + (6 - D), M);
|
|
2747
|
+
case a:
|
|
2748
|
+
case d: return $(v + "Hours", 0);
|
|
2749
|
+
case u: return $(v + "Minutes", 1);
|
|
2750
|
+
case s: return $(v + "Seconds", 2);
|
|
2751
|
+
case i: return $(v + "Milliseconds", 3);
|
|
2752
|
+
default: return this.clone();
|
|
2753
|
+
}
|
|
2754
|
+
}, m.endOf = function(t) {
|
|
2755
|
+
return this.startOf(t, !1);
|
|
2756
|
+
}, m.$set = function(t, e) {
|
|
2757
|
+
var n, o = b.p(t), f = "set" + (this.$u ? "UTC" : ""), l = (n = {}, n[a] = f + "Date", n[d] = f + "Date", n[c] = f + "Month", n[h] = f + "FullYear", n[u] = f + "Hours", n[s] = f + "Minutes", n[i] = f + "Seconds", n[r] = f + "Milliseconds", n)[o], $ = o === a ? this.$D + (e - this.$W) : e;
|
|
2758
|
+
if (o === c || o === h) {
|
|
2759
|
+
var y = this.clone().set(d, 1);
|
|
2760
|
+
y.$d[l]($), y.init(), this.$d = y.set(d, Math.min(this.$D, y.daysInMonth())).$d;
|
|
2761
|
+
} else l && this.$d[l]($);
|
|
2762
|
+
return this.init(), this;
|
|
2763
|
+
}, m.set = function(t, e) {
|
|
2764
|
+
return this.clone().$set(t, e);
|
|
2765
|
+
}, m.get = function(t) {
|
|
2766
|
+
return this[b.p(t)]();
|
|
2767
|
+
}, m.add = function(r, f) {
|
|
2768
|
+
var d, l = this;
|
|
2769
|
+
r = Number(r);
|
|
2770
|
+
var $ = b.p(f), y = function(t) {
|
|
2771
|
+
var e = O(l);
|
|
2772
|
+
return b.w(e.date(e.date() + Math.round(t * r)), l);
|
|
2773
|
+
};
|
|
2774
|
+
if ($ === c) return this.set(c, this.$M + r);
|
|
2775
|
+
if ($ === h) return this.set(h, this.$y + r);
|
|
2776
|
+
if ($ === a) return y(1);
|
|
2777
|
+
if ($ === o) return y(7);
|
|
2778
|
+
var M = (d = {}, d[s] = e, d[u] = n, d[i] = t, d)[$] || 1, m = this.$d.getTime() + r * M;
|
|
2779
|
+
return b.w(m, this);
|
|
2780
|
+
}, m.subtract = function(t, e) {
|
|
2781
|
+
return this.add(-1 * t, e);
|
|
2782
|
+
}, m.format = function(t) {
|
|
2783
|
+
var e = this, n = this.$locale();
|
|
2784
|
+
if (!this.isValid()) return n.invalidDate || l;
|
|
2785
|
+
var r = t || "YYYY-MM-DDTHH:mm:ssZ", i = b.z(this), s = this.$H, u = this.$m, a = this.$M, o = n.weekdays, c = n.months, f = n.meridiem, h = function(t, n, i, s) {
|
|
2786
|
+
return t && (t[n] || t(e, r)) || i[n].slice(0, s);
|
|
2787
|
+
}, d = function(t) {
|
|
2788
|
+
return b.s(s % 12 || 12, t, "0");
|
|
2789
|
+
}, $ = f || function(t, e, n) {
|
|
2790
|
+
var r = t < 12 ? "AM" : "PM";
|
|
2791
|
+
return n ? r.toLowerCase() : r;
|
|
2792
|
+
};
|
|
2793
|
+
return r.replace(y, (function(t, r) {
|
|
2794
|
+
return r || function(t) {
|
|
2795
|
+
switch (t) {
|
|
2796
|
+
case "YY": return String(e.$y).slice(-2);
|
|
2797
|
+
case "YYYY": return b.s(e.$y, 4, "0");
|
|
2798
|
+
case "M": return a + 1;
|
|
2799
|
+
case "MM": return b.s(a + 1, 2, "0");
|
|
2800
|
+
case "MMM": return h(n.monthsShort, a, c, 3);
|
|
2801
|
+
case "MMMM": return h(c, a);
|
|
2802
|
+
case "D": return e.$D;
|
|
2803
|
+
case "DD": return b.s(e.$D, 2, "0");
|
|
2804
|
+
case "d": return String(e.$W);
|
|
2805
|
+
case "dd": return h(n.weekdaysMin, e.$W, o, 2);
|
|
2806
|
+
case "ddd": return h(n.weekdaysShort, e.$W, o, 3);
|
|
2807
|
+
case "dddd": return o[e.$W];
|
|
2808
|
+
case "H": return String(s);
|
|
2809
|
+
case "HH": return b.s(s, 2, "0");
|
|
2810
|
+
case "h": return d(1);
|
|
2811
|
+
case "hh": return d(2);
|
|
2812
|
+
case "a": return $(s, u, !0);
|
|
2813
|
+
case "A": return $(s, u, !1);
|
|
2814
|
+
case "m": return String(u);
|
|
2815
|
+
case "mm": return b.s(u, 2, "0");
|
|
2816
|
+
case "s": return String(e.$s);
|
|
2817
|
+
case "ss": return b.s(e.$s, 2, "0");
|
|
2818
|
+
case "SSS": return b.s(e.$ms, 3, "0");
|
|
2819
|
+
case "Z": return i;
|
|
2820
|
+
}
|
|
2821
|
+
return null;
|
|
2822
|
+
}(t) || i.replace(":", "");
|
|
2823
|
+
}));
|
|
2824
|
+
}, m.utcOffset = function() {
|
|
2825
|
+
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
|
|
2826
|
+
}, m.diff = function(r, d, l) {
|
|
2827
|
+
var $, y = this, M = b.p(d), m = O(r), v = (m.utcOffset() - this.utcOffset()) * e, g = this - m, D = function() {
|
|
2828
|
+
return b.m(y, m);
|
|
2829
|
+
};
|
|
2830
|
+
switch (M) {
|
|
2831
|
+
case h:
|
|
2832
|
+
$ = D() / 12;
|
|
2833
|
+
break;
|
|
2834
|
+
case c:
|
|
2835
|
+
$ = D();
|
|
2836
|
+
break;
|
|
2837
|
+
case f:
|
|
2838
|
+
$ = D() / 3;
|
|
2839
|
+
break;
|
|
2840
|
+
case o:
|
|
2841
|
+
$ = (g - v) / 6048e5;
|
|
2842
|
+
break;
|
|
2843
|
+
case a:
|
|
2844
|
+
$ = (g - v) / 864e5;
|
|
2845
|
+
break;
|
|
2846
|
+
case u:
|
|
2847
|
+
$ = g / n;
|
|
2848
|
+
break;
|
|
2849
|
+
case s:
|
|
2850
|
+
$ = g / e;
|
|
2851
|
+
break;
|
|
2852
|
+
case i:
|
|
2853
|
+
$ = g / t;
|
|
2854
|
+
break;
|
|
2855
|
+
default: $ = g;
|
|
2856
|
+
}
|
|
2857
|
+
return l ? $ : b.a($);
|
|
2858
|
+
}, m.daysInMonth = function() {
|
|
2859
|
+
return this.endOf(c).$D;
|
|
2860
|
+
}, m.$locale = function() {
|
|
2861
|
+
return D[this.$L];
|
|
2862
|
+
}, m.locale = function(t, e) {
|
|
2863
|
+
if (!t) return this.$L;
|
|
2864
|
+
var n = this.clone(), r = w(t, e, !0);
|
|
2865
|
+
return r && (n.$L = r), n;
|
|
2866
|
+
}, m.clone = function() {
|
|
2867
|
+
return b.w(this.$d, this);
|
|
2868
|
+
}, m.toDate = function() {
|
|
2869
|
+
return new Date(this.valueOf());
|
|
2870
|
+
}, m.toJSON = function() {
|
|
2871
|
+
return this.isValid() ? this.toISOString() : null;
|
|
2872
|
+
}, m.toISOString = function() {
|
|
2873
|
+
return this.$d.toISOString();
|
|
2874
|
+
}, m.toString = function() {
|
|
2875
|
+
return this.$d.toUTCString();
|
|
2876
|
+
}, M;
|
|
2877
|
+
}(), Y = _.prototype;
|
|
2878
|
+
return O.prototype = Y, [
|
|
2879
|
+
["$ms", r],
|
|
2880
|
+
["$s", i],
|
|
2881
|
+
["$m", s],
|
|
2882
|
+
["$H", u],
|
|
2883
|
+
["$W", a],
|
|
2884
|
+
["$M", c],
|
|
2885
|
+
["$y", h],
|
|
2886
|
+
["$D", d]
|
|
2887
|
+
].forEach((function(t) {
|
|
2888
|
+
Y[t[1]] = function(e) {
|
|
2889
|
+
return this.$g(e, t[0], t[1]);
|
|
2890
|
+
};
|
|
2891
|
+
})), O.extend = function(t, e) {
|
|
2892
|
+
return t.$i || (t(e, _, O), t.$i = !0), O;
|
|
2893
|
+
}, O.locale = w, O.isDayjs = S, O.unix = function(t) {
|
|
2894
|
+
return O(1e3 * t);
|
|
2895
|
+
}, O.en = D[g], O.Ls = D, O.p = {}, O;
|
|
2896
|
+
}));
|
|
2897
|
+
})))(), 1);
|
|
1285
2898
|
/**
|
|
1286
2899
|
* 组件类型到 antd 表单组件的映射
|
|
1287
2900
|
*/
|
|
@@ -1298,7 +2911,7 @@ var FormComponents = {
|
|
|
1298
2911
|
dateRange: DatePicker.RangePicker
|
|
1299
2912
|
};
|
|
1300
2913
|
/**
|
|
1301
|
-
* 渲染对应类型的 antd
|
|
2914
|
+
* 渲染对应类型的 antd 表单组件(仅接收 componentProps,不再与 Form.Item props 混用)
|
|
1302
2915
|
*/
|
|
1303
2916
|
function renderFormItemComponent(field) {
|
|
1304
2917
|
const props = field.componentProps || {};
|
|
@@ -1307,32 +2920,70 @@ function renderFormItemComponent(field) {
|
|
|
1307
2920
|
}
|
|
1308
2921
|
/**
|
|
1309
2922
|
* 根据 fields 自动生成 Form.Item 列表
|
|
2923
|
+
* 初始值走 <Form initialValues> + 按次打开的 key:
|
|
2924
|
+
* initialValues 在字段实体注册时消费,天然避开“Modal 首次挂载前 setFieldsValue 落空”的时序竞态;
|
|
2925
|
+
* key 每次打开变化触发 Form 重挂载,确保切换到不同容器时重新取值。
|
|
1310
2926
|
*/
|
|
1311
|
-
function renderAutoForm(form, fields) {
|
|
2927
|
+
function renderAutoForm(form, fields, initialValues, initKey) {
|
|
1312
2928
|
if (!fields || fields.length === 0) return null;
|
|
1313
2929
|
return /* @__PURE__ */ jsx(Form, {
|
|
1314
2930
|
form,
|
|
1315
2931
|
layout: "vertical",
|
|
2932
|
+
preserve: false,
|
|
2933
|
+
initialValues,
|
|
1316
2934
|
children: fields.map((field) => {
|
|
1317
2935
|
if (!field.componentType) return null;
|
|
1318
2936
|
const formItemProps = {
|
|
1319
2937
|
name: field.key,
|
|
1320
2938
|
label: field.name || field.key,
|
|
1321
2939
|
valuePropName: field.componentType === "switch" ? "checked" : void 0,
|
|
1322
|
-
...field.
|
|
2940
|
+
...field.formItemProps
|
|
1323
2941
|
};
|
|
1324
2942
|
return /* @__PURE__ */ jsx(Form.Item, {
|
|
1325
2943
|
...formItemProps,
|
|
1326
2944
|
children: renderFormItemComponent(field)
|
|
1327
2945
|
}, field.key);
|
|
1328
2946
|
})
|
|
1329
|
-
});
|
|
2947
|
+
}, initKey);
|
|
2948
|
+
}
|
|
2949
|
+
/** 字符串形式的历史属性值('true'/'false')还原为布尔,供 Switch 初始化 */
|
|
2950
|
+
function toFormInitialValue(field, value) {
|
|
2951
|
+
if (value === void 0) return field.defaultValue ?? (field.componentType === "switch" ? false : void 0);
|
|
2952
|
+
if (field.componentType === "switch") {
|
|
2953
|
+
if (typeof value === "boolean") return value;
|
|
2954
|
+
return value === "true" || value === 1 || value === "1";
|
|
2955
|
+
}
|
|
2956
|
+
if (field.componentType === "number" || field.componentType === "slider" || field.componentType === "rate") {
|
|
2957
|
+
const num = Number(value);
|
|
2958
|
+
return Number.isNaN(num) ? void 0 : num;
|
|
2959
|
+
}
|
|
2960
|
+
if (field.componentType === "date") {
|
|
2961
|
+
const d = (0, import_dayjs_min.default)(typeof value === "boolean" ? String(value) : value);
|
|
2962
|
+
return d.isValid() ? d : void 0;
|
|
2963
|
+
}
|
|
2964
|
+
if (field.componentType === "dateRange") {
|
|
2965
|
+
const parts = String(value).split(",").map((s) => s.trim()).filter(Boolean);
|
|
2966
|
+
if (parts.length !== 2) return void 0;
|
|
2967
|
+
const [start, end] = parts.map((p) => (0, import_dayjs_min.default)(p));
|
|
2968
|
+
return start.isValid() && end.isValid() ? [start, end] : void 0;
|
|
2969
|
+
}
|
|
2970
|
+
return value;
|
|
2971
|
+
}
|
|
2972
|
+
/** 表单控件值归一化为容器属性可存储的字符串(容器语法仅支持扁平原始值) */
|
|
2973
|
+
function normalizeValue(field, value) {
|
|
2974
|
+
if (value === null || value === void 0) return "";
|
|
2975
|
+
if (field?.componentType === "date" && import_dayjs_min.default.isDayjs(value)) return value.format("YYYY-MM-DD");
|
|
2976
|
+
if (field?.componentType === "dateRange" && Array.isArray(value)) return value.filter((v) => import_dayjs_min.default.isDayjs(v)).map((v) => v.format("YYYY-MM-DD")).join(", ");
|
|
2977
|
+
const colorLike = value;
|
|
2978
|
+
if (colorLike && typeof colorLike === "object" && typeof colorLike.toHexString === "function") return colorLike.toHexString();
|
|
2979
|
+
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
2980
|
+
return String(value);
|
|
1330
2981
|
}
|
|
1331
2982
|
/**
|
|
1332
2983
|
* 属性编辑弹窗组件
|
|
1333
2984
|
* 根据组件 schema 的 renderDialog 函数渲染弹窗内容
|
|
1334
2985
|
*/
|
|
1335
|
-
function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
2986
|
+
function EditDialog({ visible, typeName, currentProps, initKey, onSave, onClose }) {
|
|
1336
2987
|
const schema = componentRegistry.get(typeName);
|
|
1337
2988
|
const [formProps, setFormProps] = useState({});
|
|
1338
2989
|
const [form] = Form.useForm();
|
|
@@ -1341,46 +2992,57 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
1341
2992
|
const dirtyRef = useRef(false);
|
|
1342
2993
|
const mergedProps = useMemo(() => {
|
|
1343
2994
|
if (!schema) return currentProps;
|
|
1344
|
-
const
|
|
1345
|
-
for (const field of schema.fields || [])
|
|
2995
|
+
const merged = {};
|
|
2996
|
+
for (const field of schema.fields || []) if (field.defaultValue !== void 0) merged[field.key] = field.defaultValue;
|
|
1346
2997
|
return {
|
|
1347
|
-
...
|
|
2998
|
+
...merged,
|
|
1348
2999
|
...currentProps
|
|
1349
3000
|
};
|
|
1350
3001
|
}, [schema, currentProps]);
|
|
3002
|
+
const initialValues = useMemo(() => {
|
|
3003
|
+
const initial = {};
|
|
3004
|
+
for (const [key, value] of Object.entries(mergedProps)) {
|
|
3005
|
+
const field = schema?.fields?.find((f) => f.key === key);
|
|
3006
|
+
const formValue = toFormInitialValue(field ?? { key }, value);
|
|
3007
|
+
if (formValue !== void 0) initial[key] = formValue;
|
|
3008
|
+
}
|
|
3009
|
+
return initial;
|
|
3010
|
+
}, [mergedProps, schema]);
|
|
1351
3011
|
useEffect(() => {
|
|
1352
3012
|
if (visible) {
|
|
1353
|
-
form.setFieldsValue(mergedProps);
|
|
1354
3013
|
setFormProps({});
|
|
3014
|
+
form.setFieldsValue(initialValues);
|
|
3015
|
+
dirtyRef.current = false;
|
|
1355
3016
|
}
|
|
1356
|
-
}, [
|
|
1357
|
-
visible,
|
|
1358
|
-
mergedProps,
|
|
1359
|
-
form
|
|
1360
|
-
]);
|
|
3017
|
+
}, [visible, form]);
|
|
1361
3018
|
const handleDialogChange = (key, value) => {
|
|
1362
3019
|
setFormProps((prev) => ({
|
|
1363
3020
|
...prev,
|
|
1364
3021
|
[key]: value
|
|
1365
3022
|
}));
|
|
3023
|
+
dirtyRef.current = true;
|
|
1366
3024
|
};
|
|
1367
3025
|
const handleOk = async () => {
|
|
1368
|
-
let finalProps = visible ? {
|
|
1369
|
-
...mergedProps,
|
|
1370
|
-
...formProps
|
|
1371
|
-
} : mergedProps;
|
|
1372
3026
|
try {
|
|
1373
3027
|
const formValues = await form.validateFields();
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
3028
|
+
for (const [key, value] of Object.entries(formValues)) formProps[key] = value;
|
|
3029
|
+
} catch {
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
3032
|
+
const finalProps = {};
|
|
3033
|
+
for (const [key, value] of Object.entries({
|
|
3034
|
+
...mergedProps,
|
|
3035
|
+
...formProps
|
|
3036
|
+
})) {
|
|
3037
|
+
const field = schema?.fields?.find((f) => f.key === key);
|
|
3038
|
+
finalProps[key] = normalizeValue(field, value);
|
|
3039
|
+
}
|
|
1379
3040
|
onSaveRef.current(finalProps);
|
|
1380
3041
|
dirtyRef.current = false;
|
|
1381
3042
|
onClose();
|
|
1382
3043
|
};
|
|
1383
3044
|
const handleClose = () => {
|
|
3045
|
+
if (dirtyRef.current && !window.confirm("属性修改尚未保存,确定关闭吗?")) return;
|
|
1384
3046
|
setFormProps({});
|
|
1385
3047
|
dirtyRef.current = false;
|
|
1386
3048
|
onClose();
|
|
@@ -1394,14 +3056,17 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
1394
3056
|
dirtyRef.current = true;
|
|
1395
3057
|
};
|
|
1396
3058
|
const context = {
|
|
1397
|
-
props:
|
|
3059
|
+
props: {
|
|
3060
|
+
...mergedProps,
|
|
3061
|
+
...formProps
|
|
3062
|
+
},
|
|
1398
3063
|
form,
|
|
1399
3064
|
onChange: handleDialogChange,
|
|
1400
3065
|
onSave: contextSave
|
|
1401
3066
|
};
|
|
1402
3067
|
const renderDialogContent = () => {
|
|
1403
3068
|
if (schema.renderDialog) return schema.renderDialog(context);
|
|
1404
|
-
if (schema.fields?.some((f) => f.componentType) && schema.fields) return renderAutoForm(form, schema.fields);
|
|
3069
|
+
if (schema.fields?.some((f) => f.componentType) && schema.fields) return renderAutoForm(form, schema.fields, initialValues, initKey);
|
|
1405
3070
|
return null;
|
|
1406
3071
|
};
|
|
1407
3072
|
return /* @__PURE__ */ jsx(Modal, {
|
|
@@ -1417,36 +3082,47 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
1417
3082
|
//#endregion
|
|
1418
3083
|
//#region src/utils/writeContainer.ts
|
|
1419
3084
|
/**
|
|
1420
|
-
*
|
|
1421
|
-
*
|
|
3085
|
+
* 从属性对象生成属性行。
|
|
3086
|
+
* 使用 JSON5 序列化:单引号风格与旧格式兼容,特殊字符会被正确转义,
|
|
3087
|
+
* 配合 parseContainerProps 保证读写往返无损。
|
|
1422
3088
|
*/
|
|
1423
3089
|
function writeContainerProps(props) {
|
|
1424
|
-
|
|
1425
|
-
return entries ? `{ ${entries} }` : "{}";
|
|
3090
|
+
return import_dist.default.stringify(props) ?? "{}";
|
|
1426
3091
|
}
|
|
1427
3092
|
/**
|
|
1428
3093
|
* 更新编辑器文档中的容器属性。
|
|
1429
|
-
*
|
|
3094
|
+
* 已有属性行则整行替换;没有属性行则在容器头行后插入一行。
|
|
3095
|
+
* @param headerPos 容器头行(:::type)任意位置,用于无属性行时定位插入点
|
|
3096
|
+
* @param quotePrefix 容器所处的引用前缀(如 "> "),嵌套在引用中时插入的属性行需保持一致
|
|
1430
3097
|
*/
|
|
1431
|
-
function updateContainerProps(view, propsLineFrom, propsLineTo, newProps) {
|
|
3098
|
+
function updateContainerProps(view, headerPos, propsLineFrom, propsLineTo, newProps, quotePrefix = "") {
|
|
1432
3099
|
const newPropsLine = writeContainerProps(newProps);
|
|
1433
|
-
view.dispatch({ changes: {
|
|
3100
|
+
if (propsLineTo > propsLineFrom) view.dispatch({ changes: {
|
|
1434
3101
|
from: propsLineFrom,
|
|
1435
3102
|
to: propsLineTo,
|
|
1436
|
-
insert: newPropsLine
|
|
3103
|
+
insert: `${quotePrefix}${newPropsLine}`
|
|
1437
3104
|
} });
|
|
3105
|
+
else {
|
|
3106
|
+
const headerLine = view.state.doc.lineAt(headerPos);
|
|
3107
|
+
view.dispatch({ changes: {
|
|
3108
|
+
from: headerLine.to,
|
|
3109
|
+
insert: `\n${quotePrefix}${newPropsLine}`
|
|
3110
|
+
} });
|
|
3111
|
+
}
|
|
1438
3112
|
}
|
|
1439
3113
|
/**
|
|
1440
3114
|
* 在当前光标位置插入新容器。
|
|
1441
|
-
* 创建 :::type 打开行 +
|
|
3115
|
+
* 创建 :::type 打开行 + 属性行 + ::: 关闭行的结构。
|
|
1442
3116
|
*/
|
|
1443
3117
|
function insertContainer(view, typeName, defaultProps) {
|
|
1444
3118
|
const { from } = view.state.selection.main;
|
|
1445
|
-
const
|
|
3119
|
+
const propsLine = writeContainerProps(defaultProps);
|
|
3120
|
+
const container = `\n:::${typeName}\n${propsLine}\n:::\n`;
|
|
1446
3121
|
view.dispatch({ changes: {
|
|
1447
3122
|
from,
|
|
1448
3123
|
insert: container
|
|
1449
3124
|
} });
|
|
3125
|
+
view.dispatch({ selection: { anchor: from + `\n:::${typeName}\n${propsLine}\n`.length } });
|
|
1450
3126
|
}
|
|
1451
3127
|
//#endregion
|
|
1452
3128
|
//#region src/hooks/useFullscreen.ts
|
|
@@ -1485,9 +3161,12 @@ function useFullscreen() {
|
|
|
1485
3161
|
/**
|
|
1486
3162
|
* 双向滚动同步 Hook
|
|
1487
3163
|
* 编辑器与预览区互相同步滚动位置(基于比例)
|
|
1488
|
-
* 使用
|
|
3164
|
+
* 使用 syncing 锁防止双向循环触发
|
|
3165
|
+
*
|
|
3166
|
+
* 直接接收滚动容器元素(而非 ref):元素变化时 effect 重新执行并重新绑定监听,
|
|
3167
|
+
* 避免"挂载时容器尚未就绪 / 编辑器 view 被重建"导致监听永久失效或绑到旧节点。
|
|
1489
3168
|
*/
|
|
1490
|
-
function useScrollSync(
|
|
3169
|
+
function useScrollSync(source, target) {
|
|
1491
3170
|
const rafIdRef = useRef(null);
|
|
1492
3171
|
const syncingRef = useRef(null);
|
|
1493
3172
|
const syncScroll = (from, fromEl, toEl) => {
|
|
@@ -1512,132 +3191,164 @@ function useScrollSync(sourceRef, targetRef) {
|
|
|
1512
3191
|
});
|
|
1513
3192
|
};
|
|
1514
3193
|
useEffect(() => {
|
|
1515
|
-
const source = sourceRef.current;
|
|
1516
|
-
const target = targetRef.current;
|
|
1517
3194
|
if (!source || !target) return;
|
|
1518
3195
|
const onSourceScroll = () => {
|
|
1519
3196
|
if (syncingRef.current !== null) return;
|
|
1520
|
-
|
|
1521
|
-
const t = targetRef.current;
|
|
1522
|
-
syncScroll("source", s, t);
|
|
3197
|
+
syncScroll("source", source, target);
|
|
1523
3198
|
};
|
|
1524
3199
|
const onTargetScroll = () => {
|
|
1525
3200
|
if (syncingRef.current !== null) return;
|
|
1526
|
-
|
|
1527
|
-
const t = targetRef.current;
|
|
1528
|
-
syncScroll("target", t, s);
|
|
3201
|
+
syncScroll("target", target, source);
|
|
1529
3202
|
};
|
|
1530
3203
|
source.addEventListener("scroll", onSourceScroll, { passive: true });
|
|
1531
3204
|
target.addEventListener("scroll", onTargetScroll, { passive: true });
|
|
1532
3205
|
return () => {
|
|
1533
3206
|
source.removeEventListener("scroll", onSourceScroll);
|
|
1534
3207
|
target.removeEventListener("scroll", onTargetScroll);
|
|
1535
|
-
if (rafIdRef.current)
|
|
3208
|
+
if (rafIdRef.current) {
|
|
3209
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
3210
|
+
rafIdRef.current = null;
|
|
3211
|
+
}
|
|
3212
|
+
syncingRef.current = null;
|
|
1536
3213
|
};
|
|
1537
|
-
}, [
|
|
3214
|
+
}, [source, target]);
|
|
1538
3215
|
}
|
|
1539
3216
|
//#endregion
|
|
1540
3217
|
//#region src/MarkdownEditor.tsx
|
|
1541
|
-
|
|
3218
|
+
/** 订阅注册中心版本,注册变化时触发重渲染 */
|
|
3219
|
+
function useRegistryVersion() {
|
|
3220
|
+
const subscribe = useCallback((onChange) => componentRegistry.subscribe(onChange), []);
|
|
3221
|
+
const getSnapshot = useCallback(() => componentRegistry.getVersion(), []);
|
|
3222
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
3223
|
+
}
|
|
3224
|
+
var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = true, fullscreen: fullscreenProp = true, previewOptions, uploadConfig, schemas, onNotify }, ref) => {
|
|
1542
3225
|
const [content, setContent] = useState(value ?? defaultValue);
|
|
1543
3226
|
const [editorView, setEditorView] = useState(null);
|
|
1544
|
-
const
|
|
1545
|
-
const
|
|
3227
|
+
const [scrollDOM, setScrollDOM] = useState(null);
|
|
3228
|
+
const [previewEl, setPreviewEl] = useState(null);
|
|
1546
3229
|
const { fullscreen, toggleFullscreen } = useFullscreen();
|
|
1547
|
-
useScrollSync(
|
|
3230
|
+
useScrollSync(scrollDOM, previewEl);
|
|
1548
3231
|
const [dialogVisible, setDialogVisible] = useState(false);
|
|
1549
3232
|
const [dialogTypeName, setDialogTypeName] = useState("");
|
|
1550
|
-
const [
|
|
1551
|
-
const [
|
|
3233
|
+
const [dialogContainer, setDialogContainer] = useState(null);
|
|
3234
|
+
const [dialogSeq, setDialogSeq] = useState(0);
|
|
3235
|
+
const app = App.useApp();
|
|
3236
|
+
const notify = useCallback((type, text) => {
|
|
3237
|
+
if (onNotify) {
|
|
3238
|
+
onNotify(type, text);
|
|
3239
|
+
return;
|
|
3240
|
+
}
|
|
3241
|
+
(app?.message ?? message)[type](text);
|
|
3242
|
+
}, [onNotify, app]);
|
|
3243
|
+
const lastEmittedRef = useRef(void 0);
|
|
1552
3244
|
useEffect(() => {
|
|
1553
|
-
if (value !== void 0) setContent(value);
|
|
3245
|
+
if (value !== void 0 && value !== lastEmittedRef.current) setContent(value);
|
|
1554
3246
|
}, [value]);
|
|
1555
3247
|
const internalSetContent = useCallback((newContent) => {
|
|
1556
3248
|
setContent(newContent);
|
|
3249
|
+
lastEmittedRef.current = newContent;
|
|
1557
3250
|
onChange?.(newContent);
|
|
1558
3251
|
}, [onChange]);
|
|
1559
3252
|
useImperativeHandle(ref, () => ({ getContent: () => content }), [content]);
|
|
1560
|
-
const
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
const
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
3253
|
+
const registryVersion = useRegistryVersion();
|
|
3254
|
+
useEffect(() => {
|
|
3255
|
+
editorView?.dispatch({ effects: refreshContainers.of(null) });
|
|
3256
|
+
}, [registryVersion, editorView]);
|
|
3257
|
+
const extraToolbarItems = useMemo(() => {
|
|
3258
|
+
const merged = /* @__PURE__ */ new Map();
|
|
3259
|
+
for (const schema of componentRegistry.getAll()) merged.set(schema.name, schema);
|
|
3260
|
+
for (const schema of schemas ?? []) merged.set(schema.name, schema);
|
|
3261
|
+
return [...merged.values()].flatMap((schema) => {
|
|
3262
|
+
if (schema.wrapTags) return {
|
|
3263
|
+
id: `wrap-${schema.name}`,
|
|
3264
|
+
label: schema.label,
|
|
3265
|
+
icon: schema.icon ?? ReadOutlined,
|
|
3266
|
+
wrapTags: schema.wrapTags
|
|
3267
|
+
};
|
|
3268
|
+
const defaultProps = {};
|
|
3269
|
+
for (const field of schema.fields ?? []) if (field.defaultValue !== void 0) defaultProps[field.key] = field.defaultValue;
|
|
3270
|
+
return {
|
|
3271
|
+
id: `container-${schema.name}`,
|
|
3272
|
+
label: schema.label,
|
|
3273
|
+
icon: schema.icon ?? ReadOutlined,
|
|
3274
|
+
handler: (view) => insertContainer(view, schema.name, defaultProps)
|
|
3275
|
+
};
|
|
3276
|
+
});
|
|
3277
|
+
}, [registryVersion, schemas]);
|
|
3278
|
+
const handleScrollReady = useCallback((dom) => {
|
|
3279
|
+
setScrollDOM(dom);
|
|
1578
3280
|
}, []);
|
|
1579
3281
|
const handlePreviewRef = useCallback((node) => {
|
|
1580
|
-
|
|
3282
|
+
setPreviewEl(node);
|
|
1581
3283
|
}, []);
|
|
1582
3284
|
const handleViewReady = useCallback((view) => {
|
|
1583
3285
|
setEditorView(view);
|
|
1584
3286
|
}, []);
|
|
1585
|
-
const handleEditContainer = useCallback((_view,
|
|
1586
|
-
setDialogTypeName(typeName);
|
|
1587
|
-
|
|
1588
|
-
|
|
3287
|
+
const handleEditContainer = useCallback((_view, container) => {
|
|
3288
|
+
setDialogTypeName(container.typeName);
|
|
3289
|
+
setDialogContainer(container);
|
|
3290
|
+
setDialogSeq((seq) => seq + 1);
|
|
1589
3291
|
setDialogVisible(true);
|
|
1590
3292
|
}, []);
|
|
1591
3293
|
const handleDialogSave = useCallback((newProps) => {
|
|
1592
|
-
if (editorView) updateContainerProps(editorView,
|
|
1593
|
-
}, [editorView,
|
|
3294
|
+
if (editorView && dialogContainer) updateContainerProps(editorView, dialogContainer.startPos, dialogContainer.propsLineFrom, dialogContainer.propsLineTo, newProps, dialogContainer.quotePrefix);
|
|
3295
|
+
}, [editorView, dialogContainer]);
|
|
1594
3296
|
const handleDialogClose = useCallback(() => {
|
|
1595
3297
|
setDialogVisible(false);
|
|
1596
3298
|
}, []);
|
|
3299
|
+
const editorNode = /* @__PURE__ */ jsx(Editor, {
|
|
3300
|
+
value: content,
|
|
3301
|
+
onChange: internalSetContent,
|
|
3302
|
+
onScrollReady: handleScrollReady,
|
|
3303
|
+
onViewReady: handleViewReady,
|
|
3304
|
+
onEditContainer: handleEditContainer,
|
|
3305
|
+
uploadConfig,
|
|
3306
|
+
onMessageNoUploadConfig: () => notify("warning", "请先配置图片上传功能")
|
|
3307
|
+
});
|
|
1597
3308
|
return /* @__PURE__ */ jsxs("div", {
|
|
1598
3309
|
className: fullscreen ? "markdown-editor-app fullscreen" : "markdown-editor-app",
|
|
1599
3310
|
children: [
|
|
1600
|
-
/* @__PURE__ */ jsx(
|
|
3311
|
+
/* @__PURE__ */ jsx(Toolbar_default, {
|
|
1601
3312
|
editorView,
|
|
1602
3313
|
fullscreen,
|
|
1603
3314
|
onToggleFullscreen: fullscreenProp ? toggleFullscreen : void 0,
|
|
1604
3315
|
extraItems: extraToolbarItems,
|
|
1605
|
-
uploadConfig
|
|
3316
|
+
uploadConfig,
|
|
3317
|
+
notify
|
|
1606
3318
|
}),
|
|
1607
3319
|
showPreview ? /* @__PURE__ */ jsx(SplitPanels, {
|
|
1608
|
-
leftPanel:
|
|
1609
|
-
|
|
1610
|
-
onChange: internalSetContent,
|
|
1611
|
-
onScrollReady: handleScrollReady,
|
|
1612
|
-
onViewReady: handleViewReady,
|
|
1613
|
-
onEditContainer: handleEditContainer,
|
|
1614
|
-
uploadConfig,
|
|
1615
|
-
onMessageNoUploadConfig: () => message.warning("请先配置图片上传功能")
|
|
1616
|
-
}),
|
|
1617
|
-
rightPanel: /* @__PURE__ */ jsx(Preview, {
|
|
3320
|
+
leftPanel: editorNode,
|
|
3321
|
+
rightPanel: /* @__PURE__ */ jsx(Preview_default, {
|
|
1618
3322
|
content,
|
|
1619
3323
|
ref: handlePreviewRef,
|
|
1620
3324
|
previewOptions
|
|
1621
3325
|
})
|
|
1622
|
-
}) :
|
|
1623
|
-
value: content,
|
|
1624
|
-
onChange: internalSetContent,
|
|
1625
|
-
onScrollReady: handleScrollReady,
|
|
1626
|
-
onViewReady: handleViewReady,
|
|
1627
|
-
onEditContainer: handleEditContainer,
|
|
1628
|
-
uploadConfig,
|
|
1629
|
-
onMessageNoUploadConfig: () => message.warning("请先配置图片上传功能")
|
|
1630
|
-
}),
|
|
3326
|
+
}) : editorNode,
|
|
1631
3327
|
/* @__PURE__ */ jsx(EditDialog, {
|
|
1632
3328
|
visible: dialogVisible,
|
|
1633
3329
|
typeName: dialogTypeName,
|
|
1634
|
-
currentProps:
|
|
3330
|
+
currentProps: dialogContainer?.props ?? {},
|
|
3331
|
+
initKey: dialogSeq,
|
|
1635
3332
|
onSave: handleDialogSave,
|
|
1636
3333
|
onClose: handleDialogClose
|
|
1637
3334
|
})
|
|
1638
3335
|
]
|
|
1639
3336
|
});
|
|
1640
|
-
}
|
|
3337
|
+
};
|
|
3338
|
+
var MarkdownEditor = forwardRef(MarkdownEditorInner);
|
|
3339
|
+
/**
|
|
3340
|
+
* 包一层 antd App:为库内部的 message 等反馈组件提供上下文;
|
|
3341
|
+
* 宿主已有 App 包裹时内层仅作兜底(component={false} 不额外渲染 DOM)。
|
|
3342
|
+
*/
|
|
3343
|
+
function MarkdownEditorWithApp({ ref, ...props }) {
|
|
3344
|
+
return /* @__PURE__ */ jsx(App, {
|
|
3345
|
+
component: false,
|
|
3346
|
+
children: /* @__PURE__ */ jsx(MarkdownEditor, {
|
|
3347
|
+
...props,
|
|
3348
|
+
ref
|
|
3349
|
+
})
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
1641
3352
|
//#endregion
|
|
1642
3353
|
//#region src/hooks/useRegisterToolbar.ts
|
|
1643
3354
|
/**
|
|
@@ -1734,14 +3445,17 @@ var MarkdownEditor_default = forwardRef(function MarkdownEditor({ defaultValue =
|
|
|
1734
3445
|
* @example 批量注册
|
|
1735
3446
|
* ```tsx
|
|
1736
3447
|
* function MyPage() {
|
|
3448
|
+
* // 注意:schema 需声明为稳定引用(组件外常量或 useMemo),
|
|
3449
|
+
* // 否则每次渲染都会重新注册;多实例互不干扰的场景请改用
|
|
3450
|
+
* // <MarkdownEditor schemas={[...]} /> 局部注册
|
|
1737
3451
|
* useRegisterToolbar([schema1, schema2, schema3])
|
|
1738
3452
|
* return <MarkdownEditor />
|
|
1739
3453
|
* }
|
|
1740
3454
|
* ```
|
|
1741
3455
|
*/
|
|
1742
3456
|
function useRegisterToolbar(schemas) {
|
|
1743
|
-
const schemaList = Array.isArray(schemas) ? schemas : [schemas];
|
|
1744
3457
|
useEffect(() => {
|
|
3458
|
+
const schemaList = Array.isArray(schemas) ? schemas : [schemas];
|
|
1745
3459
|
schemaList.forEach((schema) => {
|
|
1746
3460
|
componentRegistry.register(schema.name, schema);
|
|
1747
3461
|
});
|
|
@@ -1750,9 +3464,9 @@ function useRegisterToolbar(schemas) {
|
|
|
1750
3464
|
componentRegistry.unregister(schema.name);
|
|
1751
3465
|
});
|
|
1752
3466
|
};
|
|
1753
|
-
}, [
|
|
3467
|
+
}, [schemas]);
|
|
1754
3468
|
}
|
|
1755
3469
|
//#endregion
|
|
1756
|
-
export {
|
|
3470
|
+
export { MarkdownEditorWithApp as MarkdownEditor, getIconfontScriptUrl, setIconfontScriptUrl, useRegisterToolbar };
|
|
1757
3471
|
|
|
1758
3472
|
//# sourceMappingURL=index.js.map
|