remons-markdown-editor 1.0.0-beta.9 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MarkdownEditor.d.ts +24 -5
- package/dist/components/Dialog/EditDialog.d.ts +4 -3
- package/dist/components/Editor/codemirrorExtensions.d.ts +4 -4
- package/dist/components/Editor/containerWidget.d.ts +13 -8
- package/dist/components/Editor/index.d.ts +3 -2
- package/dist/components/Icon/config.d.ts +9 -0
- package/dist/components/Icon/index.d.ts +2 -0
- package/dist/components/Preview/index.d.ts +6 -5
- package/dist/components/Toolbar/buttons.d.ts +40 -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/components/Toolbar/renderers/TablePicker/index.d.ts +1 -1
- package/dist/components/Toolbar/renderers/ToolbarItemRenderer.d.ts +1 -1
- package/dist/hooks/useRegisterToolbar.d.ts +3 -0
- package/dist/hooks/useScrollSync.d.ts +7 -3
- package/dist/index.cjs +2326 -438
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +86 -63
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2348 -441
- package/dist/index.js.map +1 -1
- package/dist/registry/componentRegistry.d.ts +17 -4
- package/dist/types/index.d.ts +18 -9
- package/dist/utils/parseContainer.d.ts +20 -6
- package/dist/utils/writeContainer.d.ts +10 -7
- package/package.json +12 -17
- package/readme.md +29 -26
- package/dist/App.d.ts +0 -2
- package/dist/main.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,92 +1,1227 @@
|
|
|
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
4
|
import { EditorState, Facet } 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";
|
|
8
8
|
import { oneDark } from "@codemirror/theme-one-dark";
|
|
9
|
+
import { syntaxTree } from "@codemirror/language";
|
|
9
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
import RenderMarkdown, { initHighlighter, languagesCommon } from "remons-render-markdown";
|
|
11
12
|
import "remons-render-markdown/dist/index.css";
|
|
12
|
-
import {
|
|
13
|
-
//#region
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
return props;
|
|
29
|
-
} catch {
|
|
30
|
-
return {};
|
|
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 \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
|
+
});
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
});
|
|
54
332
|
}
|
|
55
333
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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;
|
|
63
350
|
}
|
|
64
|
-
containers.push({
|
|
65
|
-
startPos: charPos,
|
|
66
|
-
typeName,
|
|
67
|
-
propsLineFrom,
|
|
68
|
-
propsLineTo,
|
|
69
|
-
props,
|
|
70
|
-
endPos
|
|
71
|
-
});
|
|
72
351
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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);
|
|
83
1190
|
var ComponentRegistry = class {
|
|
84
1191
|
schemas = /* @__PURE__ */ new Map();
|
|
1192
|
+
listeners = /* @__PURE__ */ new Set();
|
|
1193
|
+
version = 0;
|
|
85
1194
|
/**
|
|
86
1195
|
* 注册组件 schema
|
|
87
1196
|
*/
|
|
88
1197
|
register(name, schema) {
|
|
89
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));
|
|
90
1225
|
}
|
|
91
1226
|
/**
|
|
92
1227
|
* 根据组件名获取已注册的 schema
|
|
@@ -112,29 +1247,97 @@ var ComponentRegistry = class {
|
|
|
112
1247
|
getAll() {
|
|
113
1248
|
return Array.from(this.schemas.values());
|
|
114
1249
|
}
|
|
115
|
-
/**
|
|
116
|
-
* 移除组件注册
|
|
117
|
-
*/
|
|
118
|
-
unregister(name) {
|
|
119
|
-
this.schemas.delete(name);
|
|
120
|
-
}
|
|
121
1250
|
};
|
|
122
1251
|
var componentRegistry = new ComponentRegistry();
|
|
123
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
|
+
* 在编辑器文档中查找容器块。
|
|
1278
|
+
* 单次遍历 + 预累计行偏移,复杂度 O(行数)。
|
|
1279
|
+
*/
|
|
1280
|
+
function findContainers(docText) {
|
|
1281
|
+
const containers = [];
|
|
1282
|
+
const lines = docText.split("\n");
|
|
1283
|
+
const offsets = new Array(lines.length);
|
|
1284
|
+
let pos = 0;
|
|
1285
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1286
|
+
offsets[i] = pos;
|
|
1287
|
+
pos += lines[i].length + 1;
|
|
1288
|
+
}
|
|
1289
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1290
|
+
const match = lines[i].match(/^:::(\w+)$/);
|
|
1291
|
+
if (!match) continue;
|
|
1292
|
+
const typeName = match[1];
|
|
1293
|
+
const headerPos = offsets[i];
|
|
1294
|
+
let props = {};
|
|
1295
|
+
let propsLineFrom = 0;
|
|
1296
|
+
let propsLineTo = 0;
|
|
1297
|
+
const propsLine = lines[i + 1];
|
|
1298
|
+
if (propsLine && propsLine.trim().startsWith("{") && propsLine.trim().endsWith("}")) {
|
|
1299
|
+
props = parseContainerProps(propsLine);
|
|
1300
|
+
propsLineFrom = offsets[i + 1];
|
|
1301
|
+
propsLineTo = propsLineFrom + propsLine.length;
|
|
1302
|
+
}
|
|
1303
|
+
let endPos = 0;
|
|
1304
|
+
for (let j = i + 1; j < lines.length; j++) if (lines[j].trim() === ":::") {
|
|
1305
|
+
endPos = offsets[j];
|
|
1306
|
+
i = j;
|
|
1307
|
+
break;
|
|
1308
|
+
}
|
|
1309
|
+
containers.push({
|
|
1310
|
+
startPos: headerPos,
|
|
1311
|
+
typeName,
|
|
1312
|
+
propsLineFrom,
|
|
1313
|
+
propsLineTo,
|
|
1314
|
+
props,
|
|
1315
|
+
endPos,
|
|
1316
|
+
registered: componentRegistry.has(typeName)
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
return containers;
|
|
1320
|
+
}
|
|
1321
|
+
//#endregion
|
|
124
1322
|
//#region src/components/Editor/containerWidget.ts
|
|
125
1323
|
/**
|
|
126
1324
|
* 自定义 facet 用于传递编辑回调
|
|
127
1325
|
*/
|
|
128
|
-
var containerEditCallback = Facet.define({ combine: (values) => values[
|
|
1326
|
+
var containerEditCallback = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
129
1327
|
/**
|
|
130
1328
|
* 只读的容器头行 Widget(显示 :::typeName + 编辑按钮)
|
|
131
|
-
* 使用 Decoration.replace
|
|
1329
|
+
* 使用 Decoration.replace 替换原始文本,使其不可直接编辑。
|
|
1330
|
+
* widget 直接携带所属容器索引与类型,点击时无需再做位置猜测。
|
|
132
1331
|
*/
|
|
133
1332
|
var ContainerHeaderWidget = class extends WidgetType {
|
|
134
1333
|
typeName;
|
|
135
|
-
|
|
1334
|
+
containerIndex;
|
|
1335
|
+
registered;
|
|
1336
|
+
constructor(typeName, containerIndex, registered) {
|
|
136
1337
|
super();
|
|
137
1338
|
this.typeName = typeName;
|
|
1339
|
+
this.containerIndex = containerIndex;
|
|
1340
|
+
this.registered = registered;
|
|
138
1341
|
}
|
|
139
1342
|
toDOM() {
|
|
140
1343
|
const container = document.createElement("span");
|
|
@@ -142,17 +1345,20 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
142
1345
|
const text = document.createElement("span");
|
|
143
1346
|
text.className = "container-widget-text";
|
|
144
1347
|
text.textContent = `:::${this.typeName}`;
|
|
145
|
-
const button = document.createElement("button");
|
|
146
|
-
button.className = "container-edit-btn";
|
|
147
|
-
button.title = `编辑 ${componentRegistry.get(this.typeName)?.label ?? this.typeName}`;
|
|
148
|
-
button.textContent = "✎";
|
|
149
|
-
button.__typeName = this.typeName;
|
|
150
1348
|
container.appendChild(text);
|
|
151
|
-
|
|
1349
|
+
if (this.registered) {
|
|
1350
|
+
const button = document.createElement("button");
|
|
1351
|
+
button.className = "container-edit-btn";
|
|
1352
|
+
button.title = `编辑 ${this.typeName}`;
|
|
1353
|
+
button.textContent = "✎";
|
|
1354
|
+
button.dataset.containerIndex = String(this.containerIndex);
|
|
1355
|
+
button.dataset.typeName = this.typeName;
|
|
1356
|
+
container.appendChild(button);
|
|
1357
|
+
}
|
|
152
1358
|
return container;
|
|
153
1359
|
}
|
|
154
1360
|
eq(other) {
|
|
155
|
-
return this.typeName === other.typeName;
|
|
1361
|
+
return this.typeName === other.typeName && this.containerIndex === other.containerIndex && this.registered === other.registered;
|
|
156
1362
|
}
|
|
157
1363
|
ignoreEvent() {
|
|
158
1364
|
return false;
|
|
@@ -160,7 +1366,6 @@ var ContainerHeaderWidget = class extends WidgetType {
|
|
|
160
1366
|
};
|
|
161
1367
|
/**
|
|
162
1368
|
* 只读的容器属性行 Widget(显示 { key: value, ... })
|
|
163
|
-
* 使用 Decoration.replace 替换原始文本,使其不可直接编辑
|
|
164
1369
|
*/
|
|
165
1370
|
var ContainerPropsWidget = class extends WidgetType {
|
|
166
1371
|
propsText;
|
|
@@ -183,7 +1388,6 @@ var ContainerPropsWidget = class extends WidgetType {
|
|
|
183
1388
|
};
|
|
184
1389
|
/**
|
|
185
1390
|
* 只读的容器结束行 Widget(显示 :::)
|
|
186
|
-
* 使用 Decoration.replace 替换原始文本,使其不可直接编辑
|
|
187
1391
|
*/
|
|
188
1392
|
var ContainerCloseWidget = class extends WidgetType {
|
|
189
1393
|
toDOM() {
|
|
@@ -206,20 +1410,19 @@ var ContainerCloseWidget = class extends WidgetType {
|
|
|
206
1410
|
function findContainerDecorations(state) {
|
|
207
1411
|
const containers = findContainers(state.doc.toString());
|
|
208
1412
|
const decorations = [];
|
|
209
|
-
|
|
1413
|
+
containers.forEach((container, index) => {
|
|
210
1414
|
const headerLine = state.doc.lineAt(container.startPos);
|
|
211
1415
|
decorations.push({
|
|
212
1416
|
from: headerLine.from,
|
|
213
1417
|
to: headerLine.to,
|
|
214
|
-
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName) })
|
|
1418
|
+
value: Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName, index, container.registered) })
|
|
215
1419
|
});
|
|
216
1420
|
if (container.propsLineFrom > 0 && container.propsLineTo > 0) {
|
|
217
1421
|
const propsLine = state.doc.lineAt(container.propsLineFrom);
|
|
218
|
-
const propsText = propsLine.text;
|
|
219
1422
|
decorations.push({
|
|
220
1423
|
from: propsLine.from,
|
|
221
1424
|
to: propsLine.to,
|
|
222
|
-
value: Decoration.replace({ widget: new ContainerPropsWidget(
|
|
1425
|
+
value: Decoration.replace({ widget: new ContainerPropsWidget(propsLine.text) })
|
|
223
1426
|
});
|
|
224
1427
|
}
|
|
225
1428
|
if (container.endPos > 0) {
|
|
@@ -230,12 +1433,32 @@ function findContainerDecorations(state) {
|
|
|
230
1433
|
value: Decoration.replace({ widget: new ContainerCloseWidget() })
|
|
231
1434
|
});
|
|
232
1435
|
}
|
|
233
|
-
}
|
|
1436
|
+
});
|
|
234
1437
|
return decorations;
|
|
235
1438
|
}
|
|
236
1439
|
/**
|
|
1440
|
+
* 点击编辑按钮时,依据按钮携带的容器索引回查最新属性并触发回调
|
|
1441
|
+
*/
|
|
1442
|
+
function handleEditButtonClick(event, view) {
|
|
1443
|
+
const target = event.target;
|
|
1444
|
+
if (!target.classList.contains("container-edit-btn")) return false;
|
|
1445
|
+
event.preventDefault();
|
|
1446
|
+
event.stopPropagation();
|
|
1447
|
+
const indexAttr = target.dataset.containerIndex;
|
|
1448
|
+
if (indexAttr === void 0) return false;
|
|
1449
|
+
const container = findContainers(view.state.doc.toString())[Number(indexAttr)];
|
|
1450
|
+
if (!container || !container.registered) return false;
|
|
1451
|
+
const callback = view.state.facet(containerEditCallback);
|
|
1452
|
+
if (callback) callback(view, {
|
|
1453
|
+
...container,
|
|
1454
|
+
props: { ...container.props }
|
|
1455
|
+
});
|
|
1456
|
+
return true;
|
|
1457
|
+
}
|
|
1458
|
+
/**
|
|
237
1459
|
* 容器编辑 ViewPlugin
|
|
238
|
-
* 将容器的 ::: 头行和 {} 属性行替换为只读 widget
|
|
1460
|
+
* 将容器的 ::: 头行和 {} 属性行替换为只读 widget,使其无法在编辑器中直接编辑。
|
|
1461
|
+
* 仅在文档内容变化时重建装饰,光标移动不触发全文扫描。
|
|
239
1462
|
*/
|
|
240
1463
|
var containerWidgetPlugin = ViewPlugin.fromClass(class {
|
|
241
1464
|
decorations;
|
|
@@ -243,29 +1466,20 @@ var containerWidgetPlugin = ViewPlugin.fromClass(class {
|
|
|
243
1466
|
this.decorations = Decoration.set(findContainerDecorations(view.state), true);
|
|
244
1467
|
}
|
|
245
1468
|
update(update) {
|
|
246
|
-
if (update.docChanged
|
|
1469
|
+
if (update.docChanged) this.decorations = Decoration.set(findContainerDecorations(update.state), true);
|
|
247
1470
|
}
|
|
248
1471
|
}, {
|
|
249
1472
|
decorations: (value) => value.decorations,
|
|
250
|
-
eventHandlers: {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const buttonPos = view.posAtDOM(target);
|
|
256
|
-
for (const container of containers) {
|
|
257
|
-
const headerLine = view.state.doc.lineAt(container.startPos);
|
|
258
|
-
if (buttonPos >= headerLine.from - 5 && buttonPos <= headerLine.to + 5) {
|
|
259
|
-
const callback = view.state.facet(containerEditCallback);
|
|
260
|
-
if (callback) callback(view, container.typeName, container.propsLineFrom, container.propsLineTo, { ...container.props });
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
1473
|
+
eventHandlers: {
|
|
1474
|
+
mousedown: (event, _view) => {
|
|
1475
|
+
if (event.target.classList.contains("container-edit-btn")) {
|
|
1476
|
+
event.preventDefault();
|
|
1477
|
+
return true;
|
|
264
1478
|
}
|
|
265
1479
|
return false;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
}
|
|
1480
|
+
},
|
|
1481
|
+
click: handleEditButtonClick
|
|
1482
|
+
}
|
|
269
1483
|
});
|
|
270
1484
|
//#endregion
|
|
271
1485
|
//#region src/components/Toolbar/buttons.tsx
|
|
@@ -297,28 +1511,248 @@ function insertAtLineStart(view, text) {
|
|
|
297
1511
|
view.dispatch({ selection: { anchor: line.from + text.length } });
|
|
298
1512
|
}
|
|
299
1513
|
/**
|
|
300
|
-
*
|
|
1514
|
+
* 切换标题:
|
|
1515
|
+
* - 当前行已是目标级别标题 → 移除行首 # 前缀(变回普通文本)
|
|
1516
|
+
* - 当前行是其他级别标题 → 替换为目标级别
|
|
1517
|
+
* - 当前行是普通文本 → 插入目标级别前缀
|
|
1518
|
+
* @param view - CodeMirror 编辑器实例
|
|
1519
|
+
* @param level - 标题级别(1-6)
|
|
1520
|
+
*/
|
|
1521
|
+
function toggleHeading(view, level) {
|
|
1522
|
+
const line = view.state.doc.lineAt(view.state.selection.main.from);
|
|
1523
|
+
const m = line.text.match(/^(\s*)(#{1,6})(\s+|\s*$)/);
|
|
1524
|
+
const indent = m ? m[1] : "";
|
|
1525
|
+
const text = "#".repeat(level) + " ";
|
|
1526
|
+
if (m && m[2].length === level) view.dispatch({ changes: {
|
|
1527
|
+
from: line.from,
|
|
1528
|
+
to: line.from + m[0].length,
|
|
1529
|
+
insert: indent
|
|
1530
|
+
} });
|
|
1531
|
+
else {
|
|
1532
|
+
view.dispatch({ changes: {
|
|
1533
|
+
from: line.from,
|
|
1534
|
+
to: m ? line.from + m[0].length : line.from,
|
|
1535
|
+
insert: indent + text
|
|
1536
|
+
} });
|
|
1537
|
+
view.dispatch({ selection: { anchor: line.from + indent.length + text.length } });
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* 切换任务列表(checkbox 待办)
|
|
1542
|
+
* - 支持多行:对选区内每一行应用 `- [ ] `
|
|
1543
|
+
* - 普通列表项(如 `- 内容`)直接转换为 `- [ ] 内容`
|
|
1544
|
+
* - 切换:若所有目标行都已是任务项,则移除行首前缀
|
|
1545
|
+
*/
|
|
1546
|
+
function toggleTaskList(view) {
|
|
1547
|
+
const doc = view.state.doc;
|
|
1548
|
+
const { from, to } = view.state.selection.main;
|
|
1549
|
+
const first = doc.lineAt(from);
|
|
1550
|
+
const last = doc.lineAt(to);
|
|
1551
|
+
const lines = [];
|
|
1552
|
+
for (let n = first.number; n <= last.number; n++) lines.push(doc.line(n));
|
|
1553
|
+
const taskRe = /^(\s*)([-*+])\s\[( |x)\]\s?/;
|
|
1554
|
+
const allTask = lines.every((line) => taskRe.test(line.text));
|
|
1555
|
+
const changes = [];
|
|
1556
|
+
for (const line of lines) {
|
|
1557
|
+
const taskMatch = line.text.match(taskRe);
|
|
1558
|
+
if (taskMatch) changes.push({
|
|
1559
|
+
from: line.from,
|
|
1560
|
+
to: line.from + taskMatch[0].length,
|
|
1561
|
+
insert: allTask ? "" : `${taskMatch[1]}${taskMatch[2]} [ ] `
|
|
1562
|
+
});
|
|
1563
|
+
else {
|
|
1564
|
+
const bulletMatch = line.text.match(/^(\s*)([-*+])\s/);
|
|
1565
|
+
if (bulletMatch) {
|
|
1566
|
+
const idx = line.from + bulletMatch[1].length + bulletMatch[2].length;
|
|
1567
|
+
changes.push({
|
|
1568
|
+
from: idx,
|
|
1569
|
+
to: idx + 1,
|
|
1570
|
+
insert: " [ ] "
|
|
1571
|
+
});
|
|
1572
|
+
} else changes.push({
|
|
1573
|
+
from: line.from,
|
|
1574
|
+
to: line.from,
|
|
1575
|
+
insert: "- [ ] "
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
const anchor = view.state.changes(changes).mapPos(from, 1);
|
|
1580
|
+
view.dispatch({
|
|
1581
|
+
changes,
|
|
1582
|
+
selection: { anchor }
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* 切换行首前缀(支持多行选区)
|
|
1587
|
+
* - 已是对应前缀的行 → 移除前缀(变回普通文本)
|
|
1588
|
+
* - 未加前缀的行 → 在行首插入前缀
|
|
1589
|
+
* @param view - CodeMirror 编辑器实例
|
|
1590
|
+
* @param pattern - 匹配行首前缀的正则
|
|
1591
|
+
* @param insertText - 未匹配时插入的前缀文本
|
|
1592
|
+
*/
|
|
1593
|
+
function toggleLinePrefix(view, pattern, insertText) {
|
|
1594
|
+
const doc = view.state.doc;
|
|
1595
|
+
const { from, to } = view.state.selection.main;
|
|
1596
|
+
const first = doc.lineAt(from);
|
|
1597
|
+
const last = doc.lineAt(Math.max(to, from));
|
|
1598
|
+
const changes = [];
|
|
1599
|
+
for (let n = first.number; n <= last.number; n++) {
|
|
1600
|
+
const line = doc.line(n);
|
|
1601
|
+
const m = line.text.match(pattern);
|
|
1602
|
+
if (m) changes.push({
|
|
1603
|
+
from: line.from,
|
|
1604
|
+
to: line.from + m[0].length,
|
|
1605
|
+
insert: ""
|
|
1606
|
+
});
|
|
1607
|
+
else changes.push({
|
|
1608
|
+
from: line.from,
|
|
1609
|
+
to: line.from,
|
|
1610
|
+
insert: insertText
|
|
1611
|
+
});
|
|
1612
|
+
}
|
|
1613
|
+
const anchor = view.state.changes(changes).mapPos(from, 1);
|
|
1614
|
+
view.dispatch({
|
|
1615
|
+
changes,
|
|
1616
|
+
selection: { anchor }
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
/** Markdown 列表行:缩进 + 列表标记(无序/有序)+ 空白 */
|
|
1620
|
+
var LIST_LINE_RE = /^(\s*)([-*+]|\d+\.)([ \t]+)/;
|
|
1621
|
+
/** 列表缩进台阶:4 个空格,确保缩进后能被解析为子列表 */
|
|
1622
|
+
var LIST_INDENT_WIDTH = 4;
|
|
1623
|
+
/** 判断位置是否位于代码块内(代码块内不参与列表缩进逻辑) */
|
|
1624
|
+
function isInCodeBlock(state, pos) {
|
|
1625
|
+
let node = syntaxTree(state).resolveInner(pos, 1);
|
|
1626
|
+
while (node) {
|
|
1627
|
+
if (node.name === "FencedCode" || node.name === "CodeBlock") return true;
|
|
1628
|
+
node = node.parent;
|
|
1629
|
+
}
|
|
1630
|
+
return false;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* 向上查找同缩进的前一个列表项,返回其序号
|
|
1634
|
+
* - 跳过更深的子列表行和空行
|
|
1635
|
+
* - 遇到非列表内容或更浅层列表时结束
|
|
1636
|
+
*/
|
|
1637
|
+
function findPrevSiblingOrder(state, plans, lineNo, indent) {
|
|
1638
|
+
const doc = state.doc;
|
|
1639
|
+
for (let n = lineNo - 1; n >= 1; n--) {
|
|
1640
|
+
const plan = plans.get(n);
|
|
1641
|
+
if (plan) {
|
|
1642
|
+
if (plan.nextIndent === indent) return plan.nextOrder;
|
|
1643
|
+
if (plan.nextIndent < indent) return null;
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1646
|
+
const text = doc.line(n).text;
|
|
1647
|
+
if (!text.trim()) continue;
|
|
1648
|
+
const m = text.match(LIST_LINE_RE);
|
|
1649
|
+
if (!m) return null;
|
|
1650
|
+
const lineIndent = m[1].length;
|
|
1651
|
+
if (lineIndent === indent) return /^\d+\.$/.test(m[2]) ? parseInt(m[2], 10) : null;
|
|
1652
|
+
if (lineIndent < indent) return null;
|
|
1653
|
+
}
|
|
1654
|
+
return null;
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* 计算列表行缩进/反缩进的变更
|
|
1658
|
+
* - 仅当所有选区行都是列表行时生效,否则返回 null 交给默认缩进行为
|
|
1659
|
+
* - 有序列表缩进后重新编号,保证新一级子列表从 1 开始
|
|
1660
|
+
*/
|
|
1661
|
+
function planListIndent(view, direction) {
|
|
1662
|
+
const { state } = view;
|
|
1663
|
+
const doc = state.doc;
|
|
1664
|
+
const plans = /* @__PURE__ */ new Map();
|
|
1665
|
+
for (const range of state.selection.ranges) {
|
|
1666
|
+
const first = doc.lineAt(range.from).number;
|
|
1667
|
+
const last = doc.lineAt(range.to).number;
|
|
1668
|
+
for (let n = first; n <= last; n++) {
|
|
1669
|
+
if (plans.has(n)) continue;
|
|
1670
|
+
const line = doc.line(n);
|
|
1671
|
+
if (isInCodeBlock(state, line.from)) return null;
|
|
1672
|
+
const m = line.text.match(LIST_LINE_RE);
|
|
1673
|
+
if (!m) return null;
|
|
1674
|
+
const indent = m[1].length;
|
|
1675
|
+
plans.set(n, {
|
|
1676
|
+
indent,
|
|
1677
|
+
nextIndent: direction === 1 ? indent + LIST_INDENT_WIDTH : Math.max(0, indent - LIST_INDENT_WIDTH),
|
|
1678
|
+
order: /^\d+\.$/.test(m[2]) ? parseInt(m[2], 10) : null,
|
|
1679
|
+
nextOrder: null
|
|
1680
|
+
});
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
if (plans.size === 0) return null;
|
|
1684
|
+
const ordered = [...plans.entries()].sort((a, b) => a[0] - b[0]);
|
|
1685
|
+
for (const [lineNo, info] of ordered) {
|
|
1686
|
+
if (info.order === null) continue;
|
|
1687
|
+
const prevOrder = findPrevSiblingOrder(state, plans, lineNo, info.nextIndent);
|
|
1688
|
+
info.nextOrder = prevOrder === null ? 1 : prevOrder + 1;
|
|
1689
|
+
}
|
|
1690
|
+
return ordered.map(([lineNo, info]) => {
|
|
1691
|
+
const line = doc.line(lineNo);
|
|
1692
|
+
const m = line.text.match(LIST_LINE_RE);
|
|
1693
|
+
const useNextOrder = (direction === 1 || info.indent > 0) && info.order !== null && info.nextOrder !== null && info.order !== info.nextOrder;
|
|
1694
|
+
return {
|
|
1695
|
+
from: line.from,
|
|
1696
|
+
to: line.from + m[0].length,
|
|
1697
|
+
insert: " ".repeat(info.nextIndent) + (useNextOrder ? `${info.nextOrder}.` : m[2]) + m[3]
|
|
1698
|
+
};
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Tab:列表行缩进一级(4 空格)
|
|
1703
|
+
* - 普通行返回 false,继续走默认缩进
|
|
1704
|
+
* - 有序列表缩进后重排序号,子列表从 1 开始
|
|
1705
|
+
*/
|
|
1706
|
+
function indentMarkdownList(view) {
|
|
1707
|
+
const changes = planListIndent(view, 1);
|
|
1708
|
+
if (!changes) return false;
|
|
1709
|
+
view.dispatch({
|
|
1710
|
+
changes,
|
|
1711
|
+
userEvent: "input.indent"
|
|
1712
|
+
});
|
|
1713
|
+
return true;
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Shift-Tab:列表行反缩进一级
|
|
1717
|
+
* - 普通行返回 false,继续走默认缩进
|
|
1718
|
+
* - 有序列表反缩进后并入上一层并重排序号
|
|
1719
|
+
*/
|
|
1720
|
+
function dedentMarkdownList(view) {
|
|
1721
|
+
const changes = planListIndent(view, -1);
|
|
1722
|
+
if (!changes) return false;
|
|
1723
|
+
view.dispatch({
|
|
1724
|
+
changes,
|
|
1725
|
+
userEvent: "delete.dedent"
|
|
1726
|
+
});
|
|
1727
|
+
return true;
|
|
1728
|
+
}
|
|
1729
|
+
/**
|
|
1730
|
+
* 上传图片:失败(含网络异常)统一返回 null,不抛错
|
|
301
1731
|
* @param file - 要上传的文件
|
|
302
1732
|
* @param uploadConfig - 上传配置
|
|
303
1733
|
*/
|
|
304
1734
|
async function uploadFileToServer(file, uploadConfig) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
1735
|
+
try {
|
|
1736
|
+
if (uploadConfig.onUploadImage) return await uploadConfig.onUploadImage(file);
|
|
1737
|
+
if (uploadConfig.uploadUrl) {
|
|
1738
|
+
const formData = new FormData();
|
|
1739
|
+
formData.append("file", file);
|
|
1740
|
+
const response = await fetch(uploadConfig.uploadUrl, {
|
|
1741
|
+
method: "POST",
|
|
1742
|
+
body: formData
|
|
1743
|
+
});
|
|
1744
|
+
if (!response.ok) return null;
|
|
1745
|
+
const result = await response.json();
|
|
1746
|
+
if (uploadConfig.onGetUploadUrl) return uploadConfig.onGetUploadUrl(result);
|
|
1747
|
+
return result?.data?.path ?? null;
|
|
1748
|
+
}
|
|
1749
|
+
return null;
|
|
1750
|
+
} catch {
|
|
1751
|
+
return null;
|
|
317
1752
|
}
|
|
318
|
-
return null;
|
|
319
1753
|
}
|
|
320
1754
|
/**
|
|
321
|
-
*
|
|
1755
|
+
* 判断是否配置了图片上传(类型谓词,守卫后可安全访问配置)
|
|
322
1756
|
*/
|
|
323
1757
|
function isUploadConfigured(uploadConfig) {
|
|
324
1758
|
return !!(uploadConfig?.uploadUrl || uploadConfig?.onUploadImage);
|
|
@@ -332,7 +1766,6 @@ function uploadImage(view, uploadConfig) {
|
|
|
332
1766
|
const input = document.createElement("input");
|
|
333
1767
|
input.type = "file";
|
|
334
1768
|
input.accept = "image/*";
|
|
335
|
-
input.style.display = "none";
|
|
336
1769
|
input.addEventListener("change", async () => {
|
|
337
1770
|
if (!input.files || input.files.length === 0) return;
|
|
338
1771
|
const file = input.files[0];
|
|
@@ -349,7 +1782,6 @@ function uploadImage(view, uploadConfig) {
|
|
|
349
1782
|
}
|
|
350
1783
|
input.remove();
|
|
351
1784
|
});
|
|
352
|
-
document.body.appendChild(input);
|
|
353
1785
|
input.click();
|
|
354
1786
|
}
|
|
355
1787
|
/**
|
|
@@ -407,10 +1839,14 @@ function toggleWrap(view, openTag, closeTag) {
|
|
|
407
1839
|
}
|
|
408
1840
|
//#endregion
|
|
409
1841
|
//#region src/components/Editor/codemirrorExtensions.ts
|
|
410
|
-
/**
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
1842
|
+
/**
|
|
1843
|
+
* 图片上传配置 facet。
|
|
1844
|
+
* 传入 getter 而非配置本身:扩展只在 mount 时创建一次,
|
|
1845
|
+
* 运行期通过 getter 读取最新配置,避免闭包过期。
|
|
1846
|
+
*/
|
|
1847
|
+
var uploadConfigFacet = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
1848
|
+
/** 未配置上传时的提示回调 facet(同为 getter 形式) */
|
|
1849
|
+
var messageFacet = Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
|
|
414
1850
|
/** 粘贴事件处理:拦截图片并上传 */
|
|
415
1851
|
var pasteHandler = EditorView$1.domEventHandlers({ paste: (event, view) => {
|
|
416
1852
|
const files = event.clipboardData?.files;
|
|
@@ -418,23 +1854,38 @@ var pasteHandler = EditorView$1.domEventHandlers({ paste: (event, view) => {
|
|
|
418
1854
|
const imageFiles = Array.from(files).filter((f) => f.type.startsWith("image/"));
|
|
419
1855
|
if (imageFiles.length === 0) return false;
|
|
420
1856
|
event.preventDefault();
|
|
421
|
-
const uploadConfig = view.state.facet(uploadConfigFacet);
|
|
422
|
-
const showMessage = view.state.facet(messageFacet);
|
|
1857
|
+
const uploadConfig = view.state.facet(uploadConfigFacet)?.();
|
|
1858
|
+
const showMessage = view.state.facet(messageFacet)?.();
|
|
423
1859
|
if (!isUploadConfigured(uploadConfig)) {
|
|
424
1860
|
showMessage?.();
|
|
425
1861
|
return true;
|
|
426
1862
|
}
|
|
427
|
-
const
|
|
428
|
-
let
|
|
429
|
-
for (const file of imageFiles) uploadFileToServer(file,
|
|
430
|
-
if (url)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
1863
|
+
const config = uploadConfig;
|
|
1864
|
+
let isFirst = true;
|
|
1865
|
+
for (const file of imageFiles) uploadFileToServer(file, config).then((url) => {
|
|
1866
|
+
if (!url) return;
|
|
1867
|
+
const insert = `![${file.name.replace(/\.[^.]+$/, "")}](${url})`;
|
|
1868
|
+
const { state } = view;
|
|
1869
|
+
if (isFirst) {
|
|
1870
|
+
isFirst = false;
|
|
1871
|
+
const { from, to } = state.selection.main;
|
|
1872
|
+
view.dispatch({
|
|
1873
|
+
changes: {
|
|
1874
|
+
from,
|
|
1875
|
+
to,
|
|
1876
|
+
insert
|
|
1877
|
+
},
|
|
1878
|
+
selection: { anchor: from + insert.length }
|
|
1879
|
+
});
|
|
1880
|
+
} else {
|
|
1881
|
+
const end = state.doc.length;
|
|
1882
|
+
view.dispatch({
|
|
1883
|
+
changes: {
|
|
1884
|
+
from: end,
|
|
1885
|
+
insert: `\n${insert}`
|
|
1886
|
+
},
|
|
1887
|
+
selection: { anchor: end + insert.length + 1 }
|
|
1888
|
+
});
|
|
438
1889
|
}
|
|
439
1890
|
});
|
|
440
1891
|
return true;
|
|
@@ -443,7 +1894,18 @@ var getCodeMirrorExtensions = (opts) => {
|
|
|
443
1894
|
const extensions = [
|
|
444
1895
|
markdown(),
|
|
445
1896
|
oneDark,
|
|
446
|
-
keymap.of([
|
|
1897
|
+
keymap.of([
|
|
1898
|
+
{
|
|
1899
|
+
key: "Tab",
|
|
1900
|
+
run: indentMarkdownList
|
|
1901
|
+
},
|
|
1902
|
+
{
|
|
1903
|
+
key: "Shift-Tab",
|
|
1904
|
+
run: dedentMarkdownList
|
|
1905
|
+
},
|
|
1906
|
+
...defaultKeymap,
|
|
1907
|
+
indentWithTab
|
|
1908
|
+
]),
|
|
447
1909
|
EditorView$1.lineWrapping,
|
|
448
1910
|
pasteHandler,
|
|
449
1911
|
EditorView$1.baseTheme({
|
|
@@ -483,8 +1945,8 @@ var getCodeMirrorExtensions = (opts) => {
|
|
|
483
1945
|
];
|
|
484
1946
|
extensions.push(containerWidgetPlugin);
|
|
485
1947
|
if (opts?.onEditContainer) extensions.push(containerEditCallback.of(opts.onEditContainer));
|
|
486
|
-
if (opts?.
|
|
487
|
-
if (opts?.
|
|
1948
|
+
if (opts?.getUploadConfig) extensions.push(uploadConfigFacet.of(opts.getUploadConfig));
|
|
1949
|
+
if (opts?.getOnMessageNoUploadConfig) extensions.push(messageFacet.of(opts.getOnMessageNoUploadConfig));
|
|
488
1950
|
return extensions;
|
|
489
1951
|
};
|
|
490
1952
|
//#endregion
|
|
@@ -492,17 +1954,29 @@ var getCodeMirrorExtensions = (opts) => {
|
|
|
492
1954
|
function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer, uploadConfig, onMessageNoUploadConfig }) {
|
|
493
1955
|
const editorRef = useRef(null);
|
|
494
1956
|
const viewRef = useRef(null);
|
|
1957
|
+
const latestRef = useRef({
|
|
1958
|
+
onChange,
|
|
1959
|
+
onEditContainer,
|
|
1960
|
+
uploadConfig,
|
|
1961
|
+
onMessageNoUploadConfig
|
|
1962
|
+
});
|
|
1963
|
+
latestRef.current = {
|
|
1964
|
+
onChange,
|
|
1965
|
+
onEditContainer,
|
|
1966
|
+
uploadConfig,
|
|
1967
|
+
onMessageNoUploadConfig
|
|
1968
|
+
};
|
|
495
1969
|
useEffect(() => {
|
|
496
1970
|
if (!editorRef.current) return;
|
|
497
1971
|
const extensions = [
|
|
498
1972
|
basicSetup,
|
|
499
1973
|
...getCodeMirrorExtensions({
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
1974
|
+
getUploadConfig: () => latestRef.current.uploadConfig,
|
|
1975
|
+
getOnMessageNoUploadConfig: () => latestRef.current.onMessageNoUploadConfig,
|
|
1976
|
+
onEditContainer: (view, container) => latestRef.current.onEditContainer?.(view, container)
|
|
503
1977
|
}),
|
|
504
1978
|
EditorView.updateListener.of((update) => {
|
|
505
|
-
if (update.docChanged) onChange(update.state.doc.toString());
|
|
1979
|
+
if (update.docChanged) latestRef.current.onChange(update.state.doc.toString());
|
|
506
1980
|
})
|
|
507
1981
|
];
|
|
508
1982
|
const state = EditorState.create({
|
|
@@ -513,18 +1987,26 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
|
|
|
513
1987
|
state,
|
|
514
1988
|
parent: editorRef.current
|
|
515
1989
|
});
|
|
516
|
-
if (
|
|
517
|
-
|
|
1990
|
+
if (viewRef.current) {
|
|
1991
|
+
onScrollReady?.(viewRef.current.scrollDOM);
|
|
1992
|
+
onViewReady?.(viewRef.current);
|
|
1993
|
+
}
|
|
518
1994
|
return () => {
|
|
519
1995
|
viewRef.current?.destroy();
|
|
1996
|
+
viewRef.current = null;
|
|
520
1997
|
};
|
|
521
1998
|
}, []);
|
|
522
1999
|
useEffect(() => {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
2000
|
+
const view = viewRef.current;
|
|
2001
|
+
if (view && view.state.doc.toString() !== value) view.dispatch({
|
|
2002
|
+
changes: {
|
|
2003
|
+
from: 0,
|
|
2004
|
+
to: view.state.doc.length,
|
|
2005
|
+
insert: value
|
|
2006
|
+
},
|
|
2007
|
+
effects: view.scrollSnapshot(),
|
|
2008
|
+
scrollIntoView: false
|
|
2009
|
+
});
|
|
528
2010
|
}, [value]);
|
|
529
2011
|
return /* @__PURE__ */ jsx("div", {
|
|
530
2012
|
ref: editorRef,
|
|
@@ -533,23 +2015,25 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
|
|
|
533
2015
|
}
|
|
534
2016
|
//#endregion
|
|
535
2017
|
//#region src/components/Preview/index.tsx
|
|
536
|
-
var Preview = forwardRef(({ content, previewOptions }, ref) => {
|
|
2018
|
+
var Preview = forwardRef(({ content, previewOptions, languages }, ref) => {
|
|
537
2019
|
useEffect(() => {
|
|
538
2020
|
initHighlighter({
|
|
539
2021
|
...languagesCommon,
|
|
540
|
-
...
|
|
2022
|
+
...languages ?? {}
|
|
541
2023
|
});
|
|
542
|
-
}, [
|
|
2024
|
+
}, [languages]);
|
|
2025
|
+
const { languages: _ignored, ...restOptions } = previewOptions ?? {};
|
|
543
2026
|
return /* @__PURE__ */ jsx("div", {
|
|
544
2027
|
ref,
|
|
545
2028
|
className: "preview",
|
|
546
2029
|
children: /* @__PURE__ */ jsx(RenderMarkdown, {
|
|
547
2030
|
content,
|
|
548
|
-
...
|
|
2031
|
+
...restOptions
|
|
549
2032
|
})
|
|
550
2033
|
});
|
|
551
2034
|
});
|
|
552
2035
|
Preview.displayName = "Preview";
|
|
2036
|
+
var Preview_default = memo(Preview);
|
|
553
2037
|
//#endregion
|
|
554
2038
|
//#region src/components/Panel/SplitPanels.tsx
|
|
555
2039
|
var { Panel } = Splitter;
|
|
@@ -565,13 +2049,53 @@ function SplitPanels({ leftPanel, rightPanel }) {
|
|
|
565
2049
|
});
|
|
566
2050
|
}
|
|
567
2051
|
//#endregion
|
|
2052
|
+
//#region src/components/Icon/config.ts
|
|
2053
|
+
var scriptUrl = "https://at.alicdn.com/t/c/font_5241307_xoojyr52dqn.js";
|
|
2054
|
+
var IconComp = null;
|
|
2055
|
+
/**
|
|
2056
|
+
* 配置 iconfont 脚本地址(宿主在应用入口调用),需在首次渲染前设置;
|
|
2057
|
+
* 变更后重置内部缓存,下次渲染时以新地址重建图标组件。
|
|
2058
|
+
*/
|
|
2059
|
+
function setIconfontScriptUrl(url) {
|
|
2060
|
+
if (url === scriptUrl) return;
|
|
2061
|
+
scriptUrl = url;
|
|
2062
|
+
IconComp = null;
|
|
2063
|
+
}
|
|
2064
|
+
/** 读取当前 iconfont 脚本地址 */
|
|
2065
|
+
function getIconfontScriptUrl() {
|
|
2066
|
+
return scriptUrl;
|
|
2067
|
+
}
|
|
2068
|
+
/** 懒创建图标组件:首次渲染时才注入 iconfont 脚本,避免模块层副作用 */
|
|
2069
|
+
function getIconComponent() {
|
|
2070
|
+
if (!IconComp) IconComp = createFromIconfontCN({ scriptUrl });
|
|
2071
|
+
return IconComp;
|
|
2072
|
+
}
|
|
2073
|
+
//#endregion
|
|
2074
|
+
//#region src/components/Icon/index.tsx
|
|
2075
|
+
function IconComponent(type, className) {
|
|
2076
|
+
const Icon = getIconComponent();
|
|
2077
|
+
return /* @__PURE__ */ jsx(Icon, {
|
|
2078
|
+
type: `icon-${type}`,
|
|
2079
|
+
className
|
|
2080
|
+
});
|
|
2081
|
+
}
|
|
2082
|
+
//#endregion
|
|
568
2083
|
//#region src/components/Toolbar/config.ts
|
|
2084
|
+
function Quote() {
|
|
2085
|
+
return IconComponent("quote");
|
|
2086
|
+
}
|
|
2087
|
+
function InlineCode() {
|
|
2088
|
+
return IconComponent("inlinecode");
|
|
2089
|
+
}
|
|
2090
|
+
/** 未配置图片上传时的提示文案 */
|
|
2091
|
+
var UPLOAD_CONFIG_MISSING_MESSAGE = "请先配置图片上传功能";
|
|
569
2092
|
/**
|
|
570
2093
|
* 创建工具栏配置
|
|
571
2094
|
* @param options - 配置选项
|
|
572
2095
|
*/
|
|
573
2096
|
function createToolbarConfig(options) {
|
|
574
|
-
const hasUploadConfig = isUploadConfigured(options);
|
|
2097
|
+
const hasUploadConfig = isUploadConfigured(options?.upload);
|
|
2098
|
+
const notify = options?.notify;
|
|
575
2099
|
return [
|
|
576
2100
|
{
|
|
577
2101
|
id: "heading",
|
|
@@ -580,39 +2104,33 @@ function createToolbarConfig(options) {
|
|
|
580
2104
|
children: [
|
|
581
2105
|
{
|
|
582
2106
|
id: "heading1",
|
|
583
|
-
label: "
|
|
584
|
-
|
|
585
|
-
handler: (v) => insertAtLineStart(v, "# ")
|
|
2107
|
+
label: "H1",
|
|
2108
|
+
handler: (v) => toggleHeading(v, 1)
|
|
586
2109
|
},
|
|
587
2110
|
{
|
|
588
2111
|
id: "heading2",
|
|
589
|
-
label: "
|
|
590
|
-
|
|
591
|
-
handler: (v) => insertAtLineStart(v, "## ")
|
|
2112
|
+
label: "H2",
|
|
2113
|
+
handler: (v) => toggleHeading(v, 2)
|
|
592
2114
|
},
|
|
593
2115
|
{
|
|
594
2116
|
id: "heading3",
|
|
595
|
-
label: "
|
|
596
|
-
|
|
597
|
-
handler: (v) => insertAtLineStart(v, "### ")
|
|
2117
|
+
label: "H3",
|
|
2118
|
+
handler: (v) => toggleHeading(v, 3)
|
|
598
2119
|
},
|
|
599
2120
|
{
|
|
600
2121
|
id: "heading4",
|
|
601
|
-
label: "
|
|
602
|
-
|
|
603
|
-
handler: (v) => insertAtLineStart(v, "#### ")
|
|
2122
|
+
label: "H4",
|
|
2123
|
+
handler: (v) => toggleHeading(v, 4)
|
|
604
2124
|
},
|
|
605
2125
|
{
|
|
606
2126
|
id: "heading5",
|
|
607
|
-
label: "
|
|
608
|
-
|
|
609
|
-
handler: (v) => insertAtLineStart(v, "##### ")
|
|
2127
|
+
label: "H5",
|
|
2128
|
+
handler: (v) => toggleHeading(v, 5)
|
|
610
2129
|
},
|
|
611
2130
|
{
|
|
612
2131
|
id: "heading6",
|
|
613
|
-
label: "
|
|
614
|
-
|
|
615
|
-
handler: (v) => insertAtLineStart(v, "###### ")
|
|
2132
|
+
label: "H6",
|
|
2133
|
+
handler: (v) => toggleHeading(v, 6)
|
|
616
2134
|
}
|
|
617
2135
|
]
|
|
618
2136
|
},
|
|
@@ -621,38 +2139,44 @@ function createToolbarConfig(options) {
|
|
|
621
2139
|
id: "bold",
|
|
622
2140
|
label: "加粗",
|
|
623
2141
|
icon: BoldOutlined,
|
|
624
|
-
handler: (v) =>
|
|
2142
|
+
handler: (v) => toggleWrap(v, "**", "**")
|
|
625
2143
|
},
|
|
626
2144
|
{
|
|
627
2145
|
id: "italic",
|
|
628
2146
|
label: "斜体",
|
|
629
2147
|
icon: ItalicOutlined,
|
|
630
|
-
handler: (v) =>
|
|
2148
|
+
handler: (v) => toggleWrap(v, "*", "*")
|
|
631
2149
|
},
|
|
632
2150
|
{
|
|
633
2151
|
id: "strikethrough",
|
|
634
2152
|
label: "删除线",
|
|
635
2153
|
icon: StrikethroughOutlined,
|
|
636
|
-
handler: (v) =>
|
|
2154
|
+
handler: (v) => toggleWrap(v, "~~", "~~")
|
|
637
2155
|
},
|
|
638
2156
|
{
|
|
639
2157
|
id: "underline",
|
|
640
2158
|
label: "下划线",
|
|
641
2159
|
icon: UnderlineOutlined,
|
|
642
|
-
handler: (v) =>
|
|
2160
|
+
handler: (v) => toggleWrap(v, "<u>", "</u>")
|
|
643
2161
|
},
|
|
644
2162
|
{ separatorBefore: true },
|
|
645
2163
|
{
|
|
646
2164
|
id: "ul",
|
|
647
2165
|
label: "无序列表",
|
|
648
2166
|
icon: UnorderedListOutlined,
|
|
649
|
-
handler: (v) =>
|
|
2167
|
+
handler: (v) => toggleLinePrefix(v, /^(\s*)-(?!\s*\[)\s/, "- ")
|
|
650
2168
|
},
|
|
651
2169
|
{
|
|
652
2170
|
id: "ol",
|
|
653
2171
|
label: "有序列表",
|
|
654
2172
|
icon: OrderedListOutlined,
|
|
655
|
-
handler: (v) =>
|
|
2173
|
+
handler: (v) => toggleLinePrefix(v, /^(\s*)\d+\.\s/, "1. ")
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
id: "checkbox",
|
|
2177
|
+
label: "待办",
|
|
2178
|
+
icon: CheckSquareOutlined,
|
|
2179
|
+
handler: (v) => toggleTaskList(v)
|
|
656
2180
|
},
|
|
657
2181
|
{ separatorBefore: true },
|
|
658
2182
|
{
|
|
@@ -663,19 +2187,15 @@ function createToolbarConfig(options) {
|
|
|
663
2187
|
},
|
|
664
2188
|
{
|
|
665
2189
|
id: "image",
|
|
666
|
-
label:
|
|
2190
|
+
label: "图片",
|
|
667
2191
|
icon: PictureOutlined,
|
|
668
|
-
|
|
669
|
-
handler: hasUploadConfig ? (v) => uploadImage(v, {
|
|
670
|
-
uploadUrl: options?.uploadUrl,
|
|
671
|
-
onUploadImage: options?.onUploadImage
|
|
672
|
-
}) : void 0
|
|
2192
|
+
handler: hasUploadConfig && options?.upload ? (v) => uploadImage(v, options.upload) : () => notify?.("warning", UPLOAD_CONFIG_MISSING_MESSAGE)
|
|
673
2193
|
},
|
|
674
2194
|
{ separatorBefore: true },
|
|
675
2195
|
{
|
|
676
2196
|
id: "code",
|
|
677
2197
|
label: "行内代码",
|
|
678
|
-
icon:
|
|
2198
|
+
icon: InlineCode,
|
|
679
2199
|
handler: (v) => wrapSelection(v, "`", "`")
|
|
680
2200
|
},
|
|
681
2201
|
{
|
|
@@ -696,7 +2216,7 @@ function createToolbarConfig(options) {
|
|
|
696
2216
|
{
|
|
697
2217
|
id: "quote",
|
|
698
2218
|
label: "引用",
|
|
699
|
-
icon:
|
|
2219
|
+
icon: Quote,
|
|
700
2220
|
handler: (v) => insertAtLineStart(v, "> ")
|
|
701
2221
|
},
|
|
702
2222
|
{
|
|
@@ -716,11 +2236,14 @@ function createToolbarConfig(options) {
|
|
|
716
2236
|
//#endregion
|
|
717
2237
|
//#region src/components/Toolbar/hooks/useToolbar.ts
|
|
718
2238
|
function useToolbar(editorView, options) {
|
|
719
|
-
const { extraItems, uploadConfig } = options || {};
|
|
2239
|
+
const { extraItems, uploadConfig, notify } = options || {};
|
|
720
2240
|
return {
|
|
721
2241
|
config: useMemo(() => {
|
|
722
|
-
return createToolbarConfig(
|
|
723
|
-
|
|
2242
|
+
return createToolbarConfig({
|
|
2243
|
+
upload: uploadConfig,
|
|
2244
|
+
notify
|
|
2245
|
+
});
|
|
2246
|
+
}, [uploadConfig, notify]),
|
|
724
2247
|
extraItemsConfig: useMemo(() => {
|
|
725
2248
|
return extraItems || [];
|
|
726
2249
|
}, [extraItems]),
|
|
@@ -740,37 +2263,52 @@ function useToolbar(editorView, options) {
|
|
|
740
2263
|
}
|
|
741
2264
|
//#endregion
|
|
742
2265
|
//#region src/components/Toolbar/renderers/ToolbarItemRenderer.tsx
|
|
2266
|
+
/**
|
|
2267
|
+
* 渲染图标:统一接受组件类型;兼容传入 ReactNode 的旧用法。
|
|
2268
|
+
* 组件类型不仅指函数/class,也包括 forwardRef、memo 包装出的对象
|
|
2269
|
+
* (@ant-design/icons 即为 forwardRef,不能当作普通 child 直接渲染)。
|
|
2270
|
+
*/
|
|
2271
|
+
var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
|
|
2272
|
+
var REACT_MEMO = Symbol.for("react.memo");
|
|
2273
|
+
function isComponentType(icon) {
|
|
2274
|
+
if (typeof icon === "function") return true;
|
|
2275
|
+
if (typeof icon === "object" && icon !== null) {
|
|
2276
|
+
const t = icon.$$typeof;
|
|
2277
|
+
return t === REACT_FORWARD_REF || t === REACT_MEMO;
|
|
2278
|
+
}
|
|
2279
|
+
return false;
|
|
2280
|
+
}
|
|
2281
|
+
function renderIcon(icon) {
|
|
2282
|
+
if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, {});
|
|
2283
|
+
return icon;
|
|
2284
|
+
}
|
|
743
2285
|
function ToolbarItemRenderer({ item, onClick }) {
|
|
744
|
-
const Icon = item.icon;
|
|
745
2286
|
if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Fragment, { children: [item.separatorBefore && /* @__PURE__ */ jsx("div", { className: "toolbar-separator" }), /* @__PURE__ */ jsx("div", {
|
|
746
2287
|
className: "toolbar-group",
|
|
747
2288
|
children: /* @__PURE__ */ jsx(Tooltip, {
|
|
748
2289
|
title: item.label,
|
|
749
2290
|
children: /* @__PURE__ */ jsx(Dropdown, {
|
|
750
|
-
menu: {
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
children: [
|
|
756
|
-
child.icon && (() => {
|
|
757
|
-
const ChildIcon = child.icon;
|
|
758
|
-
return /* @__PURE__ */ jsx(ChildIcon, {});
|
|
759
|
-
})(),
|
|
2291
|
+
menu: {
|
|
2292
|
+
items: item.children.map((child) => ({
|
|
2293
|
+
key: child.id ?? "",
|
|
2294
|
+
label: /* @__PURE__ */ jsxs("span", { children: [
|
|
2295
|
+
child.icon && renderIcon(child.icon),
|
|
760
2296
|
" ",
|
|
761
2297
|
child.label
|
|
762
|
-
]
|
|
763
|
-
|
|
764
|
-
|
|
2298
|
+
] }),
|
|
2299
|
+
disabled: child.disabled
|
|
2300
|
+
})),
|
|
2301
|
+
onClick: ({ key }) => {
|
|
2302
|
+
const child = item.children?.find((c) => c.id === key);
|
|
2303
|
+
if (child && !child.disabled) onClick(child);
|
|
2304
|
+
}
|
|
2305
|
+
},
|
|
765
2306
|
placement: "bottomLeft",
|
|
766
2307
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
767
2308
|
className: "toolbar-button",
|
|
768
2309
|
type: "text",
|
|
769
2310
|
size: "small",
|
|
770
|
-
children: [
|
|
771
|
-
marginLeft: 2,
|
|
772
|
-
fontSize: 10
|
|
773
|
-
} })]
|
|
2311
|
+
children: [item.icon && renderIcon(item.icon), /* @__PURE__ */ jsx(DownOutlined, { style: { fontSize: 10 } })]
|
|
774
2312
|
})
|
|
775
2313
|
})
|
|
776
2314
|
})
|
|
@@ -787,7 +2325,7 @@ function ToolbarItemRenderer({ item, onClick }) {
|
|
|
787
2325
|
size: "small",
|
|
788
2326
|
disabled: isDisabled,
|
|
789
2327
|
onClick: () => !isDisabled && onClick(item),
|
|
790
|
-
children:
|
|
2328
|
+
children: item.icon && renderIcon(item.icon)
|
|
791
2329
|
})
|
|
792
2330
|
})
|
|
793
2331
|
})] });
|
|
@@ -805,125 +2343,81 @@ var index_module_default = {
|
|
|
805
2343
|
var MAX_ROW = 8;
|
|
806
2344
|
var MAX_COL = 8;
|
|
807
2345
|
function TablePicker({ onSelect }) {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
const [confirmedSize, setConfirmedSize] = useState({
|
|
813
|
-
row: 0,
|
|
814
|
-
col: 0
|
|
2346
|
+
/** 当前高亮区域(rows x cols),渲染唯一依赖此状态 */
|
|
2347
|
+
const [size, setSize] = useState({
|
|
2348
|
+
rows: 0,
|
|
2349
|
+
cols: 0
|
|
815
2350
|
});
|
|
816
|
-
|
|
2351
|
+
/** 鼠标回撤(向上/向左)后需要重置列跟踪,prevRow 与 pending 成对出现,仅事件处理内使用 */
|
|
817
2352
|
const prevRowRef = useRef(0);
|
|
818
|
-
const
|
|
819
|
-
const
|
|
820
|
-
const commitRef = useRef(null);
|
|
821
|
-
const clearTimer = useCallback(() => {
|
|
822
|
-
if (timerIdRef.current) {
|
|
823
|
-
clearTimeout(timerIdRef.current);
|
|
824
|
-
timerIdRef.current = null;
|
|
825
|
-
}
|
|
826
|
-
}, []);
|
|
2353
|
+
const pendingColsRef = useRef(0);
|
|
2354
|
+
const flashTimerRef = useRef(null);
|
|
827
2355
|
const clearFlash = useCallback(() => {
|
|
828
|
-
if (
|
|
829
|
-
clearInterval(
|
|
830
|
-
|
|
2356
|
+
if (flashTimerRef.current) {
|
|
2357
|
+
clearInterval(flashTimerRef.current);
|
|
2358
|
+
flashTimerRef.current = null;
|
|
831
2359
|
}
|
|
832
2360
|
}, []);
|
|
833
2361
|
useEffect(() => () => {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
}, []);
|
|
2362
|
+
clearFlash();
|
|
2363
|
+
}, [clearFlash]);
|
|
837
2364
|
/**
|
|
838
2365
|
* 扩展选中区域至 (col, row)
|
|
839
2366
|
*/
|
|
840
2367
|
function extend(col, row) {
|
|
841
|
-
if (row < prevRowRef.current || col <
|
|
842
|
-
if (col >
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
2368
|
+
if (row < prevRowRef.current || col < pendingColsRef.current) pendingColsRef.current = 0;
|
|
2369
|
+
if (col > pendingColsRef.current) pendingColsRef.current = col;
|
|
2370
|
+
const cols = pendingColsRef.current;
|
|
2371
|
+
setSize({
|
|
2372
|
+
rows: row,
|
|
2373
|
+
cols
|
|
846
2374
|
});
|
|
847
|
-
|
|
848
|
-
row,
|
|
849
|
-
col: maxColRef.current
|
|
850
|
-
});
|
|
851
|
-
if (row === 1) commitRef.current = {
|
|
852
|
-
cols: maxColRef.current,
|
|
853
|
-
rows: 1
|
|
854
|
-
};
|
|
2375
|
+
prevRowRef.current = row;
|
|
855
2376
|
}
|
|
856
2377
|
/**
|
|
857
|
-
*
|
|
2378
|
+
* 跳跃动画效果:逐行推进高亮,结束后落到 (col, limit)
|
|
858
2379
|
*/
|
|
859
|
-
function flash(col, dir, limit
|
|
2380
|
+
function flash(col, dir, limit) {
|
|
2381
|
+
clearFlash();
|
|
860
2382
|
let current = dir === 1 ? 1 : limit;
|
|
861
2383
|
const step = dir === 1 ? 1 : -1;
|
|
862
|
-
|
|
863
|
-
setHoverSize({
|
|
864
|
-
row: current,
|
|
865
|
-
col
|
|
866
|
-
});
|
|
867
|
-
if (current > confirmedSize.row || dir === -1) maxColRef.current = Math.min(MAX_COL, col);
|
|
868
|
-
current += step;
|
|
2384
|
+
flashTimerRef.current = setInterval(() => {
|
|
869
2385
|
if (dir === 1 && current > limit || dir === -1 && current < 1) {
|
|
870
|
-
|
|
871
|
-
refreshTimerRef.current = null;
|
|
2386
|
+
clearFlash();
|
|
872
2387
|
const finalRow = current - step;
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
col
|
|
2388
|
+
setSize({
|
|
2389
|
+
rows: finalRow,
|
|
2390
|
+
cols: col
|
|
876
2391
|
});
|
|
877
|
-
|
|
2392
|
+
return;
|
|
878
2393
|
}
|
|
2394
|
+
setSize({
|
|
2395
|
+
rows: current,
|
|
2396
|
+
cols: col
|
|
2397
|
+
});
|
|
2398
|
+
current += step;
|
|
879
2399
|
}, 50);
|
|
880
2400
|
}
|
|
881
2401
|
/**
|
|
882
2402
|
* 核心逻辑:鼠标进入格子
|
|
883
2403
|
*/
|
|
884
|
-
function
|
|
885
|
-
clearTimer();
|
|
2404
|
+
function onCellEnter(index) {
|
|
886
2405
|
clearFlash();
|
|
887
2406
|
const row = Math.floor(index / MAX_COL) + 1;
|
|
888
2407
|
const col = index % MAX_COL + 1;
|
|
889
|
-
const
|
|
890
|
-
const isJump = Math.abs(row -
|
|
891
|
-
const isDown = row > prevRow;
|
|
2408
|
+
const maxCol = pendingColsRef.current;
|
|
2409
|
+
const isJump = Math.abs(row - prevRowRef.current) > 1;
|
|
892
2410
|
prevRowRef.current = row;
|
|
893
2411
|
if (!isJump) extend(col, row);
|
|
894
|
-
else if (
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
row: r,
|
|
898
|
-
col: c
|
|
899
|
-
});
|
|
900
|
-
});
|
|
901
|
-
else extend(col, row);
|
|
2412
|
+
else if (row > 0 && (col > maxCol || maxCol >= MAX_COL)) {
|
|
2413
|
+
pendingColsRef.current = Math.min(MAX_COL, col);
|
|
2414
|
+
flash(Math.min(MAX_COL, col), 1, Math.min(row, MAX_ROW));
|
|
902
2415
|
} else {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
setConfirmedSize({
|
|
906
|
-
row: r,
|
|
907
|
-
col: c
|
|
908
|
-
});
|
|
909
|
-
if (r === 1) {
|
|
910
|
-
commitRef.current = {
|
|
911
|
-
cols: Math.min(MAX_COL, col),
|
|
912
|
-
rows: 1
|
|
913
|
-
};
|
|
914
|
-
setConfirmedSize({
|
|
915
|
-
row: 1,
|
|
916
|
-
col: Math.min(MAX_COL, col)
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
});
|
|
2416
|
+
pendingColsRef.current = 0;
|
|
2417
|
+
extend(col, row);
|
|
920
2418
|
}
|
|
921
2419
|
}
|
|
922
2420
|
function onMouseDown() {
|
|
923
|
-
const size = commitRef.current || {
|
|
924
|
-
cols: maxColRef.current,
|
|
925
|
-
rows: confirmedSize.row
|
|
926
|
-
};
|
|
927
2421
|
if (size.rows > 0 && size.cols > 0) onSelect(size);
|
|
928
2422
|
}
|
|
929
2423
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -935,18 +2429,18 @@ function TablePicker({ onSelect }) {
|
|
|
935
2429
|
children: Array.from({ length: 64 }).map((_, i) => {
|
|
936
2430
|
const row = Math.floor(i / MAX_COL) + 1;
|
|
937
2431
|
const col = i % MAX_COL + 1;
|
|
938
|
-
const isSelected = row <=
|
|
2432
|
+
const isSelected = row <= size.rows && col <= size.cols;
|
|
939
2433
|
return /* @__PURE__ */ jsx("div", {
|
|
940
2434
|
className: `${index_module_default.cell} ${isSelected ? index_module_default.cellActive : ""}`,
|
|
941
|
-
onMouseEnter: () =>
|
|
2435
|
+
onMouseEnter: () => onCellEnter(i)
|
|
942
2436
|
}, i);
|
|
943
2437
|
})
|
|
944
2438
|
}), /* @__PURE__ */ jsxs("div", {
|
|
945
2439
|
className: index_module_default.label,
|
|
946
2440
|
children: [
|
|
947
|
-
|
|
2441
|
+
size.rows,
|
|
948
2442
|
" x ",
|
|
949
|
-
|
|
2443
|
+
size.cols || 1
|
|
950
2444
|
]
|
|
951
2445
|
})]
|
|
952
2446
|
});
|
|
@@ -954,8 +2448,10 @@ function TablePicker({ onSelect }) {
|
|
|
954
2448
|
//#endregion
|
|
955
2449
|
//#region src/components/Toolbar/renderers/TablePicker/TableDropdown.tsx
|
|
956
2450
|
function TableDropdown({ editorView }) {
|
|
957
|
-
const [open, setOpen] =
|
|
958
|
-
const
|
|
2451
|
+
const [open, setOpen] = useState(false);
|
|
2452
|
+
const handleOpenChange = useCallback((next) => {
|
|
2453
|
+
setOpen(next);
|
|
2454
|
+
}, []);
|
|
959
2455
|
const handleTableSelect = useCallback((rows, cols) => {
|
|
960
2456
|
if (!editorView || rows <= 0 || cols <= 0) return;
|
|
961
2457
|
editorView.focus();
|
|
@@ -972,18 +2468,15 @@ function TableDropdown({ editorView }) {
|
|
|
972
2468
|
return /* @__PURE__ */ jsx(Dropdown, {
|
|
973
2469
|
trigger: ["click"],
|
|
974
2470
|
open,
|
|
975
|
-
onOpenChange:
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
} }, openCountRef.current)
|
|
985
|
-
});
|
|
986
|
-
},
|
|
2471
|
+
onOpenChange: handleOpenChange,
|
|
2472
|
+
destroyOnHidden: true,
|
|
2473
|
+
popupRender: () => /* @__PURE__ */ jsx("div", {
|
|
2474
|
+
style: { padding: 4 },
|
|
2475
|
+
children: /* @__PURE__ */ jsx(TablePicker, { onSelect: (size) => {
|
|
2476
|
+
handleTableSelect(size.rows, size.cols);
|
|
2477
|
+
setOpen(false);
|
|
2478
|
+
} })
|
|
2479
|
+
}),
|
|
987
2480
|
placement: "bottomLeft",
|
|
988
2481
|
children: /* @__PURE__ */ jsx(Button, {
|
|
989
2482
|
className: "toolbar-button",
|
|
@@ -996,10 +2489,11 @@ function TableDropdown({ editorView }) {
|
|
|
996
2489
|
}
|
|
997
2490
|
//#endregion
|
|
998
2491
|
//#region src/components/Toolbar/index.tsx
|
|
999
|
-
function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig }) {
|
|
2492
|
+
function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig, notify }) {
|
|
1000
2493
|
const { config, extraItemsConfig, handleClick } = useToolbar(editorView, {
|
|
1001
2494
|
extraItems,
|
|
1002
|
-
uploadConfig
|
|
2495
|
+
uploadConfig,
|
|
2496
|
+
notify
|
|
1003
2497
|
});
|
|
1004
2498
|
const renderFullscreen = useCallback(() => {
|
|
1005
2499
|
if (!onToggleFullscreen) return null;
|
|
@@ -1039,8 +2533,305 @@ function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems
|
|
|
1039
2533
|
]
|
|
1040
2534
|
});
|
|
1041
2535
|
}
|
|
2536
|
+
var Toolbar_default = memo(Toolbar);
|
|
1042
2537
|
//#endregion
|
|
1043
2538
|
//#region src/components/Dialog/EditDialog.tsx
|
|
2539
|
+
var import_dayjs_min = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
2540
|
+
(function(t, e) {
|
|
2541
|
+
"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();
|
|
2542
|
+
})(exports, (function() {
|
|
2543
|
+
"use strict";
|
|
2544
|
+
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 = {
|
|
2545
|
+
name: "en",
|
|
2546
|
+
weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
|
|
2547
|
+
months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
|
|
2548
|
+
ordinal: function(t) {
|
|
2549
|
+
var e = [
|
|
2550
|
+
"th",
|
|
2551
|
+
"st",
|
|
2552
|
+
"nd",
|
|
2553
|
+
"rd"
|
|
2554
|
+
], n = t % 100;
|
|
2555
|
+
return "[" + t + (e[(n - 20) % 10] || e[n] || e[0]) + "]";
|
|
2556
|
+
}
|
|
2557
|
+
}, m = function(t, e, n) {
|
|
2558
|
+
var r = String(t);
|
|
2559
|
+
return !r || r.length >= e ? t : "" + Array(e + 1 - r.length).join(n) + t;
|
|
2560
|
+
}, v = {
|
|
2561
|
+
s: m,
|
|
2562
|
+
z: function(t) {
|
|
2563
|
+
var e = -t.utcOffset(), n = Math.abs(e), r = Math.floor(n / 60), i = n % 60;
|
|
2564
|
+
return (e <= 0 ? "+" : "-") + m(r, 2, "0") + ":" + m(i, 2, "0");
|
|
2565
|
+
},
|
|
2566
|
+
m: function t(e, n) {
|
|
2567
|
+
if (e.date() < n.date()) return -t(n, e);
|
|
2568
|
+
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);
|
|
2569
|
+
return +(-(r + (n - i) / (s ? i - u : u - i)) || 0);
|
|
2570
|
+
},
|
|
2571
|
+
a: function(t) {
|
|
2572
|
+
return t < 0 ? Math.ceil(t) || 0 : Math.floor(t);
|
|
2573
|
+
},
|
|
2574
|
+
p: function(t) {
|
|
2575
|
+
return {
|
|
2576
|
+
M: c,
|
|
2577
|
+
y: h,
|
|
2578
|
+
w: o,
|
|
2579
|
+
d: a,
|
|
2580
|
+
D: d,
|
|
2581
|
+
h: u,
|
|
2582
|
+
m: s,
|
|
2583
|
+
s: i,
|
|
2584
|
+
ms: r,
|
|
2585
|
+
Q: f
|
|
2586
|
+
}[t] || String(t || "").toLowerCase().replace(/s$/, "");
|
|
2587
|
+
},
|
|
2588
|
+
u: function(t) {
|
|
2589
|
+
return void 0 === t;
|
|
2590
|
+
}
|
|
2591
|
+
}, g = "en", D = {};
|
|
2592
|
+
D[g] = M;
|
|
2593
|
+
var p = "$isDayjsObject", S = function(t) {
|
|
2594
|
+
return t instanceof _ || !(!t || !t[p]);
|
|
2595
|
+
}, w = function t(e, n, r) {
|
|
2596
|
+
var i;
|
|
2597
|
+
if (!e) return g;
|
|
2598
|
+
if ("string" == typeof e) {
|
|
2599
|
+
var s = e.toLowerCase();
|
|
2600
|
+
D[s] && (i = s), n && (D[s] = n, i = s);
|
|
2601
|
+
var u = e.split("-");
|
|
2602
|
+
if (!i && u.length > 1) return t(u[0]);
|
|
2603
|
+
} else {
|
|
2604
|
+
var a = e.name;
|
|
2605
|
+
D[a] = e, i = a;
|
|
2606
|
+
}
|
|
2607
|
+
return !r && i && (g = i), i || !r && g;
|
|
2608
|
+
}, O = function(t, e) {
|
|
2609
|
+
if (S(t)) return t.clone();
|
|
2610
|
+
var n = "object" == typeof e ? e : {};
|
|
2611
|
+
return n.date = t, n.args = arguments, new _(n);
|
|
2612
|
+
}, b = v;
|
|
2613
|
+
b.l = w, b.i = S, b.w = function(t, e) {
|
|
2614
|
+
return O(t, {
|
|
2615
|
+
locale: e.$L,
|
|
2616
|
+
utc: e.$u,
|
|
2617
|
+
x: e.$x,
|
|
2618
|
+
$offset: e.$offset
|
|
2619
|
+
});
|
|
2620
|
+
};
|
|
2621
|
+
var _ = function() {
|
|
2622
|
+
function M(t) {
|
|
2623
|
+
this.$L = w(t.locale, null, !0), this.parse(t), this.$x = this.$x || t.x || {}, this[p] = !0;
|
|
2624
|
+
}
|
|
2625
|
+
var m = M.prototype;
|
|
2626
|
+
return m.parse = function(t) {
|
|
2627
|
+
this.$d = function(t) {
|
|
2628
|
+
var e = t.date, n = t.utc;
|
|
2629
|
+
if (null === e) return /* @__PURE__ */ new Date(NaN);
|
|
2630
|
+
if (b.u(e)) return /* @__PURE__ */ new Date();
|
|
2631
|
+
if (e instanceof Date) return new Date(e);
|
|
2632
|
+
if ("string" == typeof e && !/Z$/i.test(e)) {
|
|
2633
|
+
var r = e.match($);
|
|
2634
|
+
if (r) {
|
|
2635
|
+
var i = r[2] - 1 || 0, s = (r[7] || "0").substring(0, 3);
|
|
2636
|
+
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);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
return new Date(e);
|
|
2640
|
+
}(t), this.init();
|
|
2641
|
+
}, m.init = function() {
|
|
2642
|
+
var t = this.$d;
|
|
2643
|
+
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();
|
|
2644
|
+
}, m.$utils = function() {
|
|
2645
|
+
return b;
|
|
2646
|
+
}, m.isValid = function() {
|
|
2647
|
+
return !(this.$d.toString() === l);
|
|
2648
|
+
}, m.isSame = function(t, e) {
|
|
2649
|
+
var n = O(t);
|
|
2650
|
+
return this.startOf(e) <= n && n <= this.endOf(e);
|
|
2651
|
+
}, m.isAfter = function(t, e) {
|
|
2652
|
+
return O(t) < this.startOf(e);
|
|
2653
|
+
}, m.isBefore = function(t, e) {
|
|
2654
|
+
return this.endOf(e) < O(t);
|
|
2655
|
+
}, m.$g = function(t, e, n) {
|
|
2656
|
+
return b.u(t) ? this[e] : this.set(n, t);
|
|
2657
|
+
}, m.unix = function() {
|
|
2658
|
+
return Math.floor(this.valueOf() / 1e3);
|
|
2659
|
+
}, m.valueOf = function() {
|
|
2660
|
+
return this.$d.getTime();
|
|
2661
|
+
}, m.startOf = function(t, e) {
|
|
2662
|
+
var n = this, r = !!b.u(e) || e, f = b.p(t), l = function(t, e) {
|
|
2663
|
+
var i = b.w(n.$u ? Date.UTC(n.$y, e, t) : new Date(n.$y, e, t), n);
|
|
2664
|
+
return r ? i : i.endOf(a);
|
|
2665
|
+
}, $ = function(t, e) {
|
|
2666
|
+
return b.w(n.toDate()[t].apply(n.toDate("s"), (r ? [
|
|
2667
|
+
0,
|
|
2668
|
+
0,
|
|
2669
|
+
0,
|
|
2670
|
+
0
|
|
2671
|
+
] : [
|
|
2672
|
+
23,
|
|
2673
|
+
59,
|
|
2674
|
+
59,
|
|
2675
|
+
999
|
|
2676
|
+
]).slice(e)), n);
|
|
2677
|
+
}, y = this.$W, M = this.$M, m = this.$D, v = "set" + (this.$u ? "UTC" : "");
|
|
2678
|
+
switch (f) {
|
|
2679
|
+
case h: return r ? l(1, 0) : l(31, 11);
|
|
2680
|
+
case c: return r ? l(1, M) : l(0, M + 1);
|
|
2681
|
+
case o:
|
|
2682
|
+
var g = this.$locale().weekStart || 0, D = (y < g ? y + 7 : y) - g;
|
|
2683
|
+
return l(r ? m - D : m + (6 - D), M);
|
|
2684
|
+
case a:
|
|
2685
|
+
case d: return $(v + "Hours", 0);
|
|
2686
|
+
case u: return $(v + "Minutes", 1);
|
|
2687
|
+
case s: return $(v + "Seconds", 2);
|
|
2688
|
+
case i: return $(v + "Milliseconds", 3);
|
|
2689
|
+
default: return this.clone();
|
|
2690
|
+
}
|
|
2691
|
+
}, m.endOf = function(t) {
|
|
2692
|
+
return this.startOf(t, !1);
|
|
2693
|
+
}, m.$set = function(t, e) {
|
|
2694
|
+
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;
|
|
2695
|
+
if (o === c || o === h) {
|
|
2696
|
+
var y = this.clone().set(d, 1);
|
|
2697
|
+
y.$d[l]($), y.init(), this.$d = y.set(d, Math.min(this.$D, y.daysInMonth())).$d;
|
|
2698
|
+
} else l && this.$d[l]($);
|
|
2699
|
+
return this.init(), this;
|
|
2700
|
+
}, m.set = function(t, e) {
|
|
2701
|
+
return this.clone().$set(t, e);
|
|
2702
|
+
}, m.get = function(t) {
|
|
2703
|
+
return this[b.p(t)]();
|
|
2704
|
+
}, m.add = function(r, f) {
|
|
2705
|
+
var d, l = this;
|
|
2706
|
+
r = Number(r);
|
|
2707
|
+
var $ = b.p(f), y = function(t) {
|
|
2708
|
+
var e = O(l);
|
|
2709
|
+
return b.w(e.date(e.date() + Math.round(t * r)), l);
|
|
2710
|
+
};
|
|
2711
|
+
if ($ === c) return this.set(c, this.$M + r);
|
|
2712
|
+
if ($ === h) return this.set(h, this.$y + r);
|
|
2713
|
+
if ($ === a) return y(1);
|
|
2714
|
+
if ($ === o) return y(7);
|
|
2715
|
+
var M = (d = {}, d[s] = e, d[u] = n, d[i] = t, d)[$] || 1, m = this.$d.getTime() + r * M;
|
|
2716
|
+
return b.w(m, this);
|
|
2717
|
+
}, m.subtract = function(t, e) {
|
|
2718
|
+
return this.add(-1 * t, e);
|
|
2719
|
+
}, m.format = function(t) {
|
|
2720
|
+
var e = this, n = this.$locale();
|
|
2721
|
+
if (!this.isValid()) return n.invalidDate || l;
|
|
2722
|
+
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) {
|
|
2723
|
+
return t && (t[n] || t(e, r)) || i[n].slice(0, s);
|
|
2724
|
+
}, d = function(t) {
|
|
2725
|
+
return b.s(s % 12 || 12, t, "0");
|
|
2726
|
+
}, $ = f || function(t, e, n) {
|
|
2727
|
+
var r = t < 12 ? "AM" : "PM";
|
|
2728
|
+
return n ? r.toLowerCase() : r;
|
|
2729
|
+
};
|
|
2730
|
+
return r.replace(y, (function(t, r) {
|
|
2731
|
+
return r || function(t) {
|
|
2732
|
+
switch (t) {
|
|
2733
|
+
case "YY": return String(e.$y).slice(-2);
|
|
2734
|
+
case "YYYY": return b.s(e.$y, 4, "0");
|
|
2735
|
+
case "M": return a + 1;
|
|
2736
|
+
case "MM": return b.s(a + 1, 2, "0");
|
|
2737
|
+
case "MMM": return h(n.monthsShort, a, c, 3);
|
|
2738
|
+
case "MMMM": return h(c, a);
|
|
2739
|
+
case "D": return e.$D;
|
|
2740
|
+
case "DD": return b.s(e.$D, 2, "0");
|
|
2741
|
+
case "d": return String(e.$W);
|
|
2742
|
+
case "dd": return h(n.weekdaysMin, e.$W, o, 2);
|
|
2743
|
+
case "ddd": return h(n.weekdaysShort, e.$W, o, 3);
|
|
2744
|
+
case "dddd": return o[e.$W];
|
|
2745
|
+
case "H": return String(s);
|
|
2746
|
+
case "HH": return b.s(s, 2, "0");
|
|
2747
|
+
case "h": return d(1);
|
|
2748
|
+
case "hh": return d(2);
|
|
2749
|
+
case "a": return $(s, u, !0);
|
|
2750
|
+
case "A": return $(s, u, !1);
|
|
2751
|
+
case "m": return String(u);
|
|
2752
|
+
case "mm": return b.s(u, 2, "0");
|
|
2753
|
+
case "s": return String(e.$s);
|
|
2754
|
+
case "ss": return b.s(e.$s, 2, "0");
|
|
2755
|
+
case "SSS": return b.s(e.$ms, 3, "0");
|
|
2756
|
+
case "Z": return i;
|
|
2757
|
+
}
|
|
2758
|
+
return null;
|
|
2759
|
+
}(t) || i.replace(":", "");
|
|
2760
|
+
}));
|
|
2761
|
+
}, m.utcOffset = function() {
|
|
2762
|
+
return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
|
|
2763
|
+
}, m.diff = function(r, d, l) {
|
|
2764
|
+
var $, y = this, M = b.p(d), m = O(r), v = (m.utcOffset() - this.utcOffset()) * e, g = this - m, D = function() {
|
|
2765
|
+
return b.m(y, m);
|
|
2766
|
+
};
|
|
2767
|
+
switch (M) {
|
|
2768
|
+
case h:
|
|
2769
|
+
$ = D() / 12;
|
|
2770
|
+
break;
|
|
2771
|
+
case c:
|
|
2772
|
+
$ = D();
|
|
2773
|
+
break;
|
|
2774
|
+
case f:
|
|
2775
|
+
$ = D() / 3;
|
|
2776
|
+
break;
|
|
2777
|
+
case o:
|
|
2778
|
+
$ = (g - v) / 6048e5;
|
|
2779
|
+
break;
|
|
2780
|
+
case a:
|
|
2781
|
+
$ = (g - v) / 864e5;
|
|
2782
|
+
break;
|
|
2783
|
+
case u:
|
|
2784
|
+
$ = g / n;
|
|
2785
|
+
break;
|
|
2786
|
+
case s:
|
|
2787
|
+
$ = g / e;
|
|
2788
|
+
break;
|
|
2789
|
+
case i:
|
|
2790
|
+
$ = g / t;
|
|
2791
|
+
break;
|
|
2792
|
+
default: $ = g;
|
|
2793
|
+
}
|
|
2794
|
+
return l ? $ : b.a($);
|
|
2795
|
+
}, m.daysInMonth = function() {
|
|
2796
|
+
return this.endOf(c).$D;
|
|
2797
|
+
}, m.$locale = function() {
|
|
2798
|
+
return D[this.$L];
|
|
2799
|
+
}, m.locale = function(t, e) {
|
|
2800
|
+
if (!t) return this.$L;
|
|
2801
|
+
var n = this.clone(), r = w(t, e, !0);
|
|
2802
|
+
return r && (n.$L = r), n;
|
|
2803
|
+
}, m.clone = function() {
|
|
2804
|
+
return b.w(this.$d, this);
|
|
2805
|
+
}, m.toDate = function() {
|
|
2806
|
+
return new Date(this.valueOf());
|
|
2807
|
+
}, m.toJSON = function() {
|
|
2808
|
+
return this.isValid() ? this.toISOString() : null;
|
|
2809
|
+
}, m.toISOString = function() {
|
|
2810
|
+
return this.$d.toISOString();
|
|
2811
|
+
}, m.toString = function() {
|
|
2812
|
+
return this.$d.toUTCString();
|
|
2813
|
+
}, M;
|
|
2814
|
+
}(), Y = _.prototype;
|
|
2815
|
+
return O.prototype = Y, [
|
|
2816
|
+
["$ms", r],
|
|
2817
|
+
["$s", i],
|
|
2818
|
+
["$m", s],
|
|
2819
|
+
["$H", u],
|
|
2820
|
+
["$W", a],
|
|
2821
|
+
["$M", c],
|
|
2822
|
+
["$y", h],
|
|
2823
|
+
["$D", d]
|
|
2824
|
+
].forEach((function(t) {
|
|
2825
|
+
Y[t[1]] = function(e) {
|
|
2826
|
+
return this.$g(e, t[0], t[1]);
|
|
2827
|
+
};
|
|
2828
|
+
})), O.extend = function(t, e) {
|
|
2829
|
+
return t.$i || (t(e, _, O), t.$i = !0), O;
|
|
2830
|
+
}, O.locale = w, O.isDayjs = S, O.unix = function(t) {
|
|
2831
|
+
return O(1e3 * t);
|
|
2832
|
+
}, O.en = D[g], O.Ls = D, O.p = {}, O;
|
|
2833
|
+
}));
|
|
2834
|
+
})))(), 1);
|
|
1044
2835
|
/**
|
|
1045
2836
|
* 组件类型到 antd 表单组件的映射
|
|
1046
2837
|
*/
|
|
@@ -1057,7 +2848,7 @@ var FormComponents = {
|
|
|
1057
2848
|
dateRange: DatePicker.RangePicker
|
|
1058
2849
|
};
|
|
1059
2850
|
/**
|
|
1060
|
-
* 渲染对应类型的 antd
|
|
2851
|
+
* 渲染对应类型的 antd 表单组件(仅接收 componentProps,不再与 Form.Item props 混用)
|
|
1061
2852
|
*/
|
|
1062
2853
|
function renderFormItemComponent(field) {
|
|
1063
2854
|
const props = field.componentProps || {};
|
|
@@ -1072,13 +2863,14 @@ function renderAutoForm(form, fields) {
|
|
|
1072
2863
|
return /* @__PURE__ */ jsx(Form, {
|
|
1073
2864
|
form,
|
|
1074
2865
|
layout: "vertical",
|
|
2866
|
+
preserve: false,
|
|
1075
2867
|
children: fields.map((field) => {
|
|
1076
2868
|
if (!field.componentType) return null;
|
|
1077
2869
|
const formItemProps = {
|
|
1078
2870
|
name: field.key,
|
|
1079
2871
|
label: field.name || field.key,
|
|
1080
2872
|
valuePropName: field.componentType === "switch" ? "checked" : void 0,
|
|
1081
|
-
...field.
|
|
2873
|
+
...field.formItemProps
|
|
1082
2874
|
};
|
|
1083
2875
|
return /* @__PURE__ */ jsx(Form.Item, {
|
|
1084
2876
|
...formItemProps,
|
|
@@ -1087,6 +2879,39 @@ function renderAutoForm(form, fields) {
|
|
|
1087
2879
|
})
|
|
1088
2880
|
});
|
|
1089
2881
|
}
|
|
2882
|
+
/** 字符串形式的历史属性值('true'/'false')还原为布尔,供 Switch 初始化 */
|
|
2883
|
+
function toFormInitialValue(field, value) {
|
|
2884
|
+
if (value === void 0) return field.defaultValue ?? (field.componentType === "switch" ? false : void 0);
|
|
2885
|
+
if (field.componentType === "switch") {
|
|
2886
|
+
if (typeof value === "boolean") return value;
|
|
2887
|
+
return value === "true" || value === 1 || value === "1";
|
|
2888
|
+
}
|
|
2889
|
+
if (field.componentType === "number" || field.componentType === "slider" || field.componentType === "rate") {
|
|
2890
|
+
const num = Number(value);
|
|
2891
|
+
return Number.isNaN(num) ? void 0 : num;
|
|
2892
|
+
}
|
|
2893
|
+
if (field.componentType === "date") {
|
|
2894
|
+
const d = (0, import_dayjs_min.default)(typeof value === "boolean" ? String(value) : value);
|
|
2895
|
+
return d.isValid() ? d : void 0;
|
|
2896
|
+
}
|
|
2897
|
+
if (field.componentType === "dateRange") {
|
|
2898
|
+
const parts = String(value).split(",").map((s) => s.trim()).filter(Boolean);
|
|
2899
|
+
if (parts.length !== 2) return void 0;
|
|
2900
|
+
const [start, end] = parts.map((p) => (0, import_dayjs_min.default)(p));
|
|
2901
|
+
return start.isValid() && end.isValid() ? [start, end] : void 0;
|
|
2902
|
+
}
|
|
2903
|
+
return value;
|
|
2904
|
+
}
|
|
2905
|
+
/** 表单控件值归一化为容器属性可存储的字符串(容器语法仅支持扁平原始值) */
|
|
2906
|
+
function normalizeValue(field, value) {
|
|
2907
|
+
if (value === null || value === void 0) return "";
|
|
2908
|
+
if (field?.componentType === "date" && import_dayjs_min.default.isDayjs(value)) return value.format("YYYY-MM-DD");
|
|
2909
|
+
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(", ");
|
|
2910
|
+
const colorLike = value;
|
|
2911
|
+
if (colorLike && typeof colorLike === "object" && typeof colorLike.toHexString === "function") return colorLike.toHexString();
|
|
2912
|
+
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
2913
|
+
return String(value);
|
|
2914
|
+
}
|
|
1090
2915
|
/**
|
|
1091
2916
|
* 属性编辑弹窗组件
|
|
1092
2917
|
* 根据组件 schema 的 renderDialog 函数渲染弹窗内容
|
|
@@ -1095,55 +2920,79 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
1095
2920
|
const schema = componentRegistry.get(typeName);
|
|
1096
2921
|
const [formProps, setFormProps] = useState({});
|
|
1097
2922
|
const [form] = Form.useForm();
|
|
2923
|
+
const onSaveRef = useRef(onSave);
|
|
2924
|
+
onSaveRef.current = onSave;
|
|
2925
|
+
const dirtyRef = useRef(false);
|
|
1098
2926
|
const mergedProps = useMemo(() => {
|
|
1099
2927
|
if (!schema) return currentProps;
|
|
1100
|
-
const
|
|
1101
|
-
for (const field of schema.fields || [])
|
|
2928
|
+
const merged = {};
|
|
2929
|
+
for (const field of schema.fields || []) if (field.defaultValue !== void 0) merged[field.key] = field.defaultValue;
|
|
1102
2930
|
return {
|
|
1103
|
-
...
|
|
2931
|
+
...merged,
|
|
1104
2932
|
...currentProps
|
|
1105
2933
|
};
|
|
1106
2934
|
}, [schema, currentProps]);
|
|
1107
2935
|
useEffect(() => {
|
|
1108
2936
|
if (visible) {
|
|
1109
|
-
form.setFieldsValue(mergedProps);
|
|
1110
2937
|
setFormProps({});
|
|
2938
|
+
const initial = {};
|
|
2939
|
+
for (const [key, value] of Object.entries(mergedProps)) {
|
|
2940
|
+
const field = schema?.fields?.find((f) => f.key === key);
|
|
2941
|
+
const formValue = toFormInitialValue(field ?? { key }, value);
|
|
2942
|
+
if (formValue !== void 0) initial[key] = formValue;
|
|
2943
|
+
}
|
|
2944
|
+
form.setFieldsValue(initial);
|
|
2945
|
+
dirtyRef.current = false;
|
|
1111
2946
|
}
|
|
1112
|
-
}, [
|
|
1113
|
-
visible,
|
|
1114
|
-
mergedProps,
|
|
1115
|
-
form
|
|
1116
|
-
]);
|
|
2947
|
+
}, [visible, form]);
|
|
1117
2948
|
const handleDialogChange = (key, value) => {
|
|
1118
2949
|
setFormProps((prev) => ({
|
|
1119
2950
|
...prev,
|
|
1120
2951
|
[key]: value
|
|
1121
2952
|
}));
|
|
2953
|
+
dirtyRef.current = true;
|
|
1122
2954
|
};
|
|
1123
2955
|
const handleOk = async () => {
|
|
1124
|
-
let finalProps = visible ? {
|
|
1125
|
-
...mergedProps,
|
|
1126
|
-
...formProps
|
|
1127
|
-
} : mergedProps;
|
|
1128
2956
|
try {
|
|
1129
2957
|
const formValues = await form.validateFields();
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
2958
|
+
for (const [key, value] of Object.entries(formValues)) formProps[key] = value;
|
|
2959
|
+
} catch {
|
|
2960
|
+
return;
|
|
2961
|
+
}
|
|
2962
|
+
const finalProps = {};
|
|
2963
|
+
for (const [key, value] of Object.entries({
|
|
2964
|
+
...mergedProps,
|
|
2965
|
+
...formProps
|
|
2966
|
+
})) {
|
|
2967
|
+
const field = schema?.fields?.find((f) => f.key === key);
|
|
2968
|
+
finalProps[key] = normalizeValue(field, value);
|
|
2969
|
+
}
|
|
2970
|
+
onSaveRef.current(finalProps);
|
|
2971
|
+
dirtyRef.current = false;
|
|
2972
|
+
onClose();
|
|
1136
2973
|
};
|
|
1137
2974
|
const handleClose = () => {
|
|
2975
|
+
if (dirtyRef.current && !window.confirm("属性修改尚未保存,确定关闭吗?")) return;
|
|
1138
2976
|
setFormProps({});
|
|
2977
|
+
dirtyRef.current = false;
|
|
1139
2978
|
onClose();
|
|
1140
2979
|
};
|
|
1141
2980
|
if (!schema) return null;
|
|
2981
|
+
const contextSave = (props) => {
|
|
2982
|
+
setFormProps((prev) => ({
|
|
2983
|
+
...prev,
|
|
2984
|
+
...props
|
|
2985
|
+
}));
|
|
2986
|
+
dirtyRef.current = true;
|
|
2987
|
+
};
|
|
1142
2988
|
const context = {
|
|
1143
|
-
props:
|
|
2989
|
+
props: {
|
|
2990
|
+
...mergedProps,
|
|
2991
|
+
...formProps
|
|
2992
|
+
},
|
|
1144
2993
|
form,
|
|
1145
2994
|
onChange: handleDialogChange,
|
|
1146
|
-
onSave
|
|
2995
|
+
onSave: contextSave
|
|
1147
2996
|
};
|
|
1148
2997
|
const renderDialogContent = () => {
|
|
1149
2998
|
if (schema.renderDialog) return schema.renderDialog(context);
|
|
@@ -1163,36 +3012,46 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
|
|
|
1163
3012
|
//#endregion
|
|
1164
3013
|
//#region src/utils/writeContainer.ts
|
|
1165
3014
|
/**
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
3015
|
+
* 从属性对象生成属性行。
|
|
3016
|
+
* 使用 JSON5 序列化:单引号风格与旧格式兼容,特殊字符会被正确转义,
|
|
3017
|
+
* 配合 parseContainerProps 保证读写往返无损。
|
|
1168
3018
|
*/
|
|
1169
3019
|
function writeContainerProps(props) {
|
|
1170
|
-
|
|
1171
|
-
return entries ? `{ ${entries} }` : "{}";
|
|
3020
|
+
return import_dist.default.stringify(props) ?? "{}";
|
|
1172
3021
|
}
|
|
1173
3022
|
/**
|
|
1174
3023
|
* 更新编辑器文档中的容器属性。
|
|
1175
|
-
*
|
|
3024
|
+
* 已有属性行则整行替换;没有属性行则在容器头行后插入一行。
|
|
3025
|
+
* @param headerPos 容器头行(:::type)任意位置,用于无属性行时定位插入点
|
|
1176
3026
|
*/
|
|
1177
|
-
function updateContainerProps(view, propsLineFrom, propsLineTo, newProps) {
|
|
3027
|
+
function updateContainerProps(view, headerPos, propsLineFrom, propsLineTo, newProps) {
|
|
1178
3028
|
const newPropsLine = writeContainerProps(newProps);
|
|
1179
|
-
view.dispatch({ changes: {
|
|
3029
|
+
if (propsLineTo > propsLineFrom) view.dispatch({ changes: {
|
|
1180
3030
|
from: propsLineFrom,
|
|
1181
3031
|
to: propsLineTo,
|
|
1182
3032
|
insert: newPropsLine
|
|
1183
3033
|
} });
|
|
3034
|
+
else {
|
|
3035
|
+
const headerLine = view.state.doc.lineAt(headerPos);
|
|
3036
|
+
view.dispatch({ changes: {
|
|
3037
|
+
from: headerLine.to,
|
|
3038
|
+
insert: `\n${newPropsLine}`
|
|
3039
|
+
} });
|
|
3040
|
+
}
|
|
1184
3041
|
}
|
|
1185
3042
|
/**
|
|
1186
3043
|
* 在当前光标位置插入新容器。
|
|
1187
|
-
* 创建 :::type 打开行 +
|
|
3044
|
+
* 创建 :::type 打开行 + 属性行 + ::: 关闭行的结构。
|
|
1188
3045
|
*/
|
|
1189
3046
|
function insertContainer(view, typeName, defaultProps) {
|
|
1190
3047
|
const { from } = view.state.selection.main;
|
|
1191
|
-
const
|
|
3048
|
+
const propsLine = writeContainerProps(defaultProps);
|
|
3049
|
+
const container = `\n:::${typeName}\n${propsLine}\n:::\n`;
|
|
1192
3050
|
view.dispatch({ changes: {
|
|
1193
3051
|
from,
|
|
1194
3052
|
insert: container
|
|
1195
3053
|
} });
|
|
3054
|
+
view.dispatch({ selection: { anchor: from + `\n:::${typeName}\n${propsLine}\n`.length } });
|
|
1196
3055
|
}
|
|
1197
3056
|
//#endregion
|
|
1198
3057
|
//#region src/hooks/useFullscreen.ts
|
|
@@ -1229,145 +3088,190 @@ function useFullscreen() {
|
|
|
1229
3088
|
//#endregion
|
|
1230
3089
|
//#region src/hooks/useScrollSync.ts
|
|
1231
3090
|
/**
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
3091
|
+
* 双向滚动同步 Hook
|
|
3092
|
+
* 编辑器与预览区互相同步滚动位置(基于比例)
|
|
3093
|
+
* 使用 syncing 锁防止双向循环触发
|
|
3094
|
+
*
|
|
3095
|
+
* 直接接收滚动容器元素(而非 ref):元素变化时 effect 重新执行并重新绑定监听,
|
|
3096
|
+
* 避免"挂载时容器尚未就绪 / 编辑器 view 被重建"导致监听永久失效或绑到旧节点。
|
|
1234
3097
|
*/
|
|
1235
|
-
function useScrollSync(
|
|
3098
|
+
function useScrollSync(source, target) {
|
|
1236
3099
|
const rafIdRef = useRef(null);
|
|
3100
|
+
const syncingRef = useRef(null);
|
|
3101
|
+
const syncScroll = (from, fromEl, toEl) => {
|
|
3102
|
+
if (rafIdRef.current) return;
|
|
3103
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
3104
|
+
const fromScrollHeight = fromEl.scrollHeight - fromEl.clientHeight;
|
|
3105
|
+
if (fromScrollHeight <= 0) {
|
|
3106
|
+
rafIdRef.current = null;
|
|
3107
|
+
syncingRef.current = null;
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3110
|
+
const ratio = fromEl.scrollTop / fromScrollHeight;
|
|
3111
|
+
const toScrollHeight = toEl.scrollHeight - toEl.clientHeight;
|
|
3112
|
+
if (toScrollHeight > 0) {
|
|
3113
|
+
syncingRef.current = from;
|
|
3114
|
+
toEl.scrollTop = ratio * toScrollHeight;
|
|
3115
|
+
requestAnimationFrame(() => {
|
|
3116
|
+
syncingRef.current = null;
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
rafIdRef.current = null;
|
|
3120
|
+
});
|
|
3121
|
+
};
|
|
1237
3122
|
useEffect(() => {
|
|
1238
|
-
const source = sourceRef.current;
|
|
1239
|
-
const target = targetRef.current;
|
|
1240
3123
|
if (!source || !target) return;
|
|
1241
|
-
const
|
|
1242
|
-
if (
|
|
1243
|
-
|
|
1244
|
-
const s = sourceRef.current;
|
|
1245
|
-
const t = targetRef.current;
|
|
1246
|
-
if (!s || !t) {
|
|
1247
|
-
rafIdRef.current = null;
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
const sourceScrollHeight = s.scrollHeight - s.clientHeight;
|
|
1251
|
-
if (sourceScrollHeight <= 0) {
|
|
1252
|
-
rafIdRef.current = null;
|
|
1253
|
-
return;
|
|
1254
|
-
}
|
|
1255
|
-
const ratio = s.scrollTop / sourceScrollHeight;
|
|
1256
|
-
const targetScrollHeight = t.scrollHeight - t.clientHeight;
|
|
1257
|
-
if (targetScrollHeight > 0) t.scrollTop = ratio * targetScrollHeight;
|
|
1258
|
-
rafIdRef.current = null;
|
|
1259
|
-
});
|
|
3124
|
+
const onSourceScroll = () => {
|
|
3125
|
+
if (syncingRef.current !== null) return;
|
|
3126
|
+
syncScroll("source", source, target);
|
|
1260
3127
|
};
|
|
1261
|
-
|
|
3128
|
+
const onTargetScroll = () => {
|
|
3129
|
+
if (syncingRef.current !== null) return;
|
|
3130
|
+
syncScroll("target", target, source);
|
|
3131
|
+
};
|
|
3132
|
+
source.addEventListener("scroll", onSourceScroll, { passive: true });
|
|
3133
|
+
target.addEventListener("scroll", onTargetScroll, { passive: true });
|
|
1262
3134
|
return () => {
|
|
1263
|
-
source.removeEventListener("scroll",
|
|
1264
|
-
|
|
3135
|
+
source.removeEventListener("scroll", onSourceScroll);
|
|
3136
|
+
target.removeEventListener("scroll", onTargetScroll);
|
|
3137
|
+
if (rafIdRef.current) {
|
|
3138
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
3139
|
+
rafIdRef.current = null;
|
|
3140
|
+
}
|
|
3141
|
+
syncingRef.current = null;
|
|
1265
3142
|
};
|
|
1266
|
-
}, [
|
|
3143
|
+
}, [source, target]);
|
|
1267
3144
|
}
|
|
1268
3145
|
//#endregion
|
|
1269
3146
|
//#region src/MarkdownEditor.tsx
|
|
1270
|
-
|
|
3147
|
+
/** 订阅注册中心版本,注册变化时触发重渲染 */
|
|
3148
|
+
function useRegistryVersion() {
|
|
3149
|
+
const subscribe = useCallback((onChange) => componentRegistry.subscribe(onChange), []);
|
|
3150
|
+
const getSnapshot = useCallback(() => componentRegistry.getVersion(), []);
|
|
3151
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
3152
|
+
}
|
|
3153
|
+
var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = true, fullscreen: fullscreenProp = true, previewOptions, uploadConfig, schemas, onNotify }, ref) => {
|
|
1271
3154
|
const [content, setContent] = useState(value ?? defaultValue);
|
|
1272
3155
|
const [editorView, setEditorView] = useState(null);
|
|
1273
|
-
const
|
|
1274
|
-
const
|
|
3156
|
+
const [scrollDOM, setScrollDOM] = useState(null);
|
|
3157
|
+
const [previewEl, setPreviewEl] = useState(null);
|
|
1275
3158
|
const { fullscreen, toggleFullscreen } = useFullscreen();
|
|
1276
|
-
useScrollSync(
|
|
3159
|
+
useScrollSync(scrollDOM, previewEl);
|
|
1277
3160
|
const [dialogVisible, setDialogVisible] = useState(false);
|
|
1278
3161
|
const [dialogTypeName, setDialogTypeName] = useState("");
|
|
1279
|
-
const [
|
|
1280
|
-
const
|
|
3162
|
+
const [dialogContainer, setDialogContainer] = useState(null);
|
|
3163
|
+
const app = App.useApp();
|
|
3164
|
+
const notify = useCallback((type, text) => {
|
|
3165
|
+
if (onNotify) {
|
|
3166
|
+
onNotify(type, text);
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
(app?.message ?? message)[type](text);
|
|
3170
|
+
}, [onNotify, app]);
|
|
3171
|
+
const lastEmittedRef = useRef(void 0);
|
|
1281
3172
|
useEffect(() => {
|
|
1282
|
-
if (value !== void 0) setContent(value);
|
|
3173
|
+
if (value !== void 0 && value !== lastEmittedRef.current) setContent(value);
|
|
1283
3174
|
}, [value]);
|
|
1284
3175
|
const internalSetContent = useCallback((newContent) => {
|
|
1285
3176
|
setContent(newContent);
|
|
3177
|
+
lastEmittedRef.current = newContent;
|
|
1286
3178
|
onChange?.(newContent);
|
|
1287
3179
|
}, [onChange]);
|
|
1288
3180
|
useImperativeHandle(ref, () => ({ getContent: () => content }), [content]);
|
|
1289
|
-
const
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
3181
|
+
const registryVersion = useRegistryVersion();
|
|
3182
|
+
const extraToolbarItems = useMemo(() => {
|
|
3183
|
+
const merged = /* @__PURE__ */ new Map();
|
|
3184
|
+
for (const schema of componentRegistry.getAll()) merged.set(schema.name, schema);
|
|
3185
|
+
for (const schema of schemas ?? []) merged.set(schema.name, schema);
|
|
3186
|
+
return [...merged.values()].flatMap((schema) => {
|
|
3187
|
+
if (schema.wrapTags) return {
|
|
3188
|
+
id: `wrap-${schema.name}`,
|
|
3189
|
+
label: schema.label,
|
|
3190
|
+
icon: schema.icon ?? ReadOutlined,
|
|
3191
|
+
wrapTags: schema.wrapTags
|
|
3192
|
+
};
|
|
3193
|
+
const defaultProps = {};
|
|
3194
|
+
for (const field of schema.fields ?? []) if (field.defaultValue !== void 0) defaultProps[field.key] = field.defaultValue;
|
|
3195
|
+
return {
|
|
3196
|
+
id: `container-${schema.name}`,
|
|
3197
|
+
label: schema.label,
|
|
3198
|
+
icon: schema.icon ?? ReadOutlined,
|
|
3199
|
+
handler: (view) => insertContainer(view, schema.name, defaultProps)
|
|
3200
|
+
};
|
|
3201
|
+
});
|
|
3202
|
+
}, [registryVersion, schemas]);
|
|
3203
|
+
const handleScrollReady = useCallback((dom) => {
|
|
3204
|
+
setScrollDOM(dom);
|
|
1307
3205
|
}, []);
|
|
1308
3206
|
const handlePreviewRef = useCallback((node) => {
|
|
1309
|
-
|
|
3207
|
+
setPreviewEl(node);
|
|
1310
3208
|
}, []);
|
|
1311
3209
|
const handleViewReady = useCallback((view) => {
|
|
1312
3210
|
setEditorView(view);
|
|
1313
3211
|
}, []);
|
|
1314
|
-
const handleEditContainer = useCallback((_view,
|
|
1315
|
-
setDialogTypeName(typeName);
|
|
1316
|
-
|
|
1317
|
-
setDialogPropsRange([propsLineFrom, propsLineTo]);
|
|
3212
|
+
const handleEditContainer = useCallback((_view, container) => {
|
|
3213
|
+
setDialogTypeName(container.typeName);
|
|
3214
|
+
setDialogContainer(container);
|
|
1318
3215
|
setDialogVisible(true);
|
|
1319
3216
|
}, []);
|
|
1320
3217
|
const handleDialogSave = useCallback((newProps) => {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
}, [editorView, dialogPropsRange]);
|
|
3218
|
+
if (editorView && dialogContainer) updateContainerProps(editorView, dialogContainer.startPos, dialogContainer.propsLineFrom, dialogContainer.propsLineTo, newProps);
|
|
3219
|
+
}, [editorView, dialogContainer]);
|
|
1324
3220
|
const handleDialogClose = useCallback(() => {
|
|
1325
3221
|
setDialogVisible(false);
|
|
1326
3222
|
}, []);
|
|
3223
|
+
const editorNode = /* @__PURE__ */ jsx(Editor, {
|
|
3224
|
+
value: content,
|
|
3225
|
+
onChange: internalSetContent,
|
|
3226
|
+
onScrollReady: handleScrollReady,
|
|
3227
|
+
onViewReady: handleViewReady,
|
|
3228
|
+
onEditContainer: handleEditContainer,
|
|
3229
|
+
uploadConfig,
|
|
3230
|
+
onMessageNoUploadConfig: () => notify("warning", "请先配置图片上传功能")
|
|
3231
|
+
});
|
|
1327
3232
|
return /* @__PURE__ */ jsxs("div", {
|
|
1328
3233
|
className: fullscreen ? "markdown-editor-app fullscreen" : "markdown-editor-app",
|
|
1329
3234
|
children: [
|
|
1330
|
-
/* @__PURE__ */ jsx(
|
|
3235
|
+
/* @__PURE__ */ jsx(Toolbar_default, {
|
|
1331
3236
|
editorView,
|
|
1332
3237
|
fullscreen,
|
|
1333
3238
|
onToggleFullscreen: fullscreenProp ? toggleFullscreen : void 0,
|
|
1334
3239
|
extraItems: extraToolbarItems,
|
|
1335
|
-
uploadConfig
|
|
3240
|
+
uploadConfig,
|
|
3241
|
+
notify
|
|
1336
3242
|
}),
|
|
1337
3243
|
showPreview ? /* @__PURE__ */ jsx(SplitPanels, {
|
|
1338
|
-
leftPanel:
|
|
1339
|
-
|
|
1340
|
-
onChange: internalSetContent,
|
|
1341
|
-
onScrollReady: handleScrollReady,
|
|
1342
|
-
onViewReady: handleViewReady,
|
|
1343
|
-
onEditContainer: handleEditContainer,
|
|
1344
|
-
uploadConfig,
|
|
1345
|
-
onMessageNoUploadConfig: () => message.warning("请先配置图片上传功能")
|
|
1346
|
-
}),
|
|
1347
|
-
rightPanel: /* @__PURE__ */ jsx(Preview, {
|
|
3244
|
+
leftPanel: editorNode,
|
|
3245
|
+
rightPanel: /* @__PURE__ */ jsx(Preview_default, {
|
|
1348
3246
|
content,
|
|
1349
3247
|
ref: handlePreviewRef,
|
|
1350
3248
|
previewOptions
|
|
1351
3249
|
})
|
|
1352
|
-
}) :
|
|
1353
|
-
value: content,
|
|
1354
|
-
onChange: internalSetContent,
|
|
1355
|
-
onScrollReady: handleScrollReady,
|
|
1356
|
-
onViewReady: handleViewReady,
|
|
1357
|
-
onEditContainer: handleEditContainer,
|
|
1358
|
-
uploadConfig,
|
|
1359
|
-
onMessageNoUploadConfig: () => message.warning("请先配置图片上传功能")
|
|
1360
|
-
}),
|
|
3250
|
+
}) : editorNode,
|
|
1361
3251
|
/* @__PURE__ */ jsx(EditDialog, {
|
|
1362
3252
|
visible: dialogVisible,
|
|
1363
3253
|
typeName: dialogTypeName,
|
|
1364
|
-
currentProps:
|
|
3254
|
+
currentProps: dialogContainer?.props ?? {},
|
|
1365
3255
|
onSave: handleDialogSave,
|
|
1366
3256
|
onClose: handleDialogClose
|
|
1367
3257
|
})
|
|
1368
3258
|
]
|
|
1369
3259
|
});
|
|
1370
|
-
}
|
|
3260
|
+
};
|
|
3261
|
+
var MarkdownEditor = forwardRef(MarkdownEditorInner);
|
|
3262
|
+
/**
|
|
3263
|
+
* 包一层 antd App:为库内部的 message 等反馈组件提供上下文;
|
|
3264
|
+
* 宿主已有 App 包裹时内层仅作兜底(component={false} 不额外渲染 DOM)。
|
|
3265
|
+
*/
|
|
3266
|
+
function MarkdownEditorWithApp({ ref, ...props }) {
|
|
3267
|
+
return /* @__PURE__ */ jsx(App, {
|
|
3268
|
+
component: false,
|
|
3269
|
+
children: /* @__PURE__ */ jsx(MarkdownEditor, {
|
|
3270
|
+
...props,
|
|
3271
|
+
ref
|
|
3272
|
+
})
|
|
3273
|
+
});
|
|
3274
|
+
}
|
|
1371
3275
|
//#endregion
|
|
1372
3276
|
//#region src/hooks/useRegisterToolbar.ts
|
|
1373
3277
|
/**
|
|
@@ -1464,14 +3368,17 @@ var MarkdownEditor_default = forwardRef(function MarkdownEditor({ defaultValue =
|
|
|
1464
3368
|
* @example 批量注册
|
|
1465
3369
|
* ```tsx
|
|
1466
3370
|
* function MyPage() {
|
|
3371
|
+
* // 注意:schema 需声明为稳定引用(组件外常量或 useMemo),
|
|
3372
|
+
* // 否则每次渲染都会重新注册;多实例互不干扰的场景请改用
|
|
3373
|
+
* // <MarkdownEditor schemas={[...]} /> 局部注册
|
|
1467
3374
|
* useRegisterToolbar([schema1, schema2, schema3])
|
|
1468
3375
|
* return <MarkdownEditor />
|
|
1469
3376
|
* }
|
|
1470
3377
|
* ```
|
|
1471
3378
|
*/
|
|
1472
3379
|
function useRegisterToolbar(schemas) {
|
|
1473
|
-
const schemaList = Array.isArray(schemas) ? schemas : [schemas];
|
|
1474
3380
|
useEffect(() => {
|
|
3381
|
+
const schemaList = Array.isArray(schemas) ? schemas : [schemas];
|
|
1475
3382
|
schemaList.forEach((schema) => {
|
|
1476
3383
|
componentRegistry.register(schema.name, schema);
|
|
1477
3384
|
});
|
|
@@ -1480,9 +3387,9 @@ function useRegisterToolbar(schemas) {
|
|
|
1480
3387
|
componentRegistry.unregister(schema.name);
|
|
1481
3388
|
});
|
|
1482
3389
|
};
|
|
1483
|
-
}, [
|
|
3390
|
+
}, [schemas]);
|
|
1484
3391
|
}
|
|
1485
3392
|
//#endregion
|
|
1486
|
-
export {
|
|
3393
|
+
export { MarkdownEditorWithApp as MarkdownEditor, getIconfontScriptUrl, setIconfontScriptUrl, useRegisterToolbar };
|
|
1487
3394
|
|
|
1488
3395
|
//# sourceMappingURL=index.js.map
|