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/index.cjs CHANGED
@@ -6,6 +6,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
10
  var __copyProps = (to, from, except, desc) => {
10
11
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
12
  key = keys[i];
@@ -30,88 +31,1201 @@ let _codemirror_view = require("@codemirror/view");
30
31
  let _codemirror_commands = require("@codemirror/commands");
31
32
  let _codemirror_lang_markdown = require("@codemirror/lang-markdown");
32
33
  let _codemirror_theme_one_dark = require("@codemirror/theme-one-dark");
34
+ let _codemirror_language = require("@codemirror/language");
33
35
  let react_jsx_runtime = require("react/jsx-runtime");
34
36
  let remons_render_markdown = require("remons-render-markdown");
35
37
  remons_render_markdown = __toESM(remons_render_markdown, 1);
36
38
  require("remons-render-markdown/dist/index.css");
37
39
  let _ant_design_icons = require("@ant-design/icons");
38
- //#region src/utils/parseContainer.ts
39
- /**
40
- * 解析容器属性 JSON 字符串。
41
- * 支持标准 JSON 和宽松格式: { key: 'value', key2: 'value2' }
42
- */
43
- function parseContainerProps(jsonStr) {
44
- try {
45
- const props = {};
46
- const trimmed = jsonStr.trim();
47
- if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
48
- const inner = trimmed.slice(1, -1).trim();
49
- if (!inner) return props;
50
- const matches = inner.matchAll(/(?:["']?)(\w+)(?:["']?)\s*:\s*(?:"([^"]*)"|'([^']*)'|(\d+))/g);
51
- for (const m of matches) props[m[1]] = m[2] ?? m[3] ?? m[4] ?? "";
40
+ //#endregion
41
+ //#region src/registry/componentRegistry.tsx
42
+ var import_dist = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
43
+ (function(global, factory) {
44
+ typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.JSON5 = factory();
45
+ })(exports, (function() {
46
+ "use strict";
47
+ function createCommonjsModule(fn, module$1) {
48
+ return module$1 = { exports: {} }, fn(module$1, module$1.exports), module$1.exports;
52
49
  }
53
- return props;
54
- } catch {
55
- return {};
56
- }
57
- }
58
- function findContainers(docText) {
59
- const containers = [];
60
- const lines = docText.split("\n");
61
- let i = 0;
62
- while (i < lines.length) {
63
- const line = lines[i];
64
- const match = line.match(/^:::(\w+)$/);
65
- if (match) {
66
- const typeName = match[1];
67
- let charPos = 0;
68
- for (let l = 0; l < i; l++) charPos += lines[l].length + 1;
69
- let props = {};
70
- let propsLineFrom = 0;
71
- let propsLineTo = 0;
72
- let propsLineIndex = i + 1;
73
- if (propsLineIndex < lines.length) {
74
- const propsLine = lines[propsLineIndex].trim();
75
- if (propsLine.match(/^\{[\s\S]*\}$/)) {
76
- props = parseContainerProps(propsLine);
77
- propsLineFrom = charPos + line.length + 1;
78
- propsLineTo = propsLineFrom + lines[propsLineIndex].length;
50
+ var _global = createCommonjsModule(function(module$2) {
51
+ var global = module$2.exports = typeof window != "undefined" && window.Math == Math ? window : typeof self != "undefined" && self.Math == Math ? self : Function("return this")();
52
+ if (typeof __g == "number") __g = global;
53
+ });
54
+ var _core = createCommonjsModule(function(module$3) {
55
+ var core = module$3.exports = { version: "2.6.5" };
56
+ if (typeof __e == "number") __e = core;
57
+ });
58
+ _core.version;
59
+ var _isObject = function(it) {
60
+ return typeof it === "object" ? it !== null : typeof it === "function";
61
+ };
62
+ var _anObject = function(it) {
63
+ if (!_isObject(it)) throw TypeError(it + " is not an object!");
64
+ return it;
65
+ };
66
+ var _fails = function(exec) {
67
+ try {
68
+ return !!exec();
69
+ } catch (e) {
70
+ return true;
71
+ }
72
+ };
73
+ var _descriptors = !_fails(function() {
74
+ return Object.defineProperty({}, "a", { get: function() {
75
+ return 7;
76
+ } }).a != 7;
77
+ });
78
+ var document = _global.document;
79
+ var is = _isObject(document) && _isObject(document.createElement);
80
+ var _domCreate = function(it) {
81
+ return is ? document.createElement(it) : {};
82
+ };
83
+ var _ie8DomDefine = !_descriptors && !_fails(function() {
84
+ return Object.defineProperty(_domCreate("div"), "a", { get: function() {
85
+ return 7;
86
+ } }).a != 7;
87
+ });
88
+ var _toPrimitive = function(it, S) {
89
+ if (!_isObject(it)) return it;
90
+ var fn, val;
91
+ if (S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) return val;
92
+ if (typeof (fn = it.valueOf) == "function" && !_isObject(val = fn.call(it))) return val;
93
+ if (!S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) return val;
94
+ throw TypeError("Can't convert object to primitive value");
95
+ };
96
+ var dP = Object.defineProperty;
97
+ var _objectDp = { f: _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
98
+ _anObject(O);
99
+ P = _toPrimitive(P, true);
100
+ _anObject(Attributes);
101
+ if (_ie8DomDefine) try {
102
+ return dP(O, P, Attributes);
103
+ } catch (e) {}
104
+ if ("get" in Attributes || "set" in Attributes) throw TypeError("Accessors not supported!");
105
+ if ("value" in Attributes) O[P] = Attributes.value;
106
+ return O;
107
+ } };
108
+ var _propertyDesc = function(bitmap, value) {
109
+ return {
110
+ enumerable: !(bitmap & 1),
111
+ configurable: !(bitmap & 2),
112
+ writable: !(bitmap & 4),
113
+ value
114
+ };
115
+ };
116
+ var _hide = _descriptors ? function(object, key, value) {
117
+ return _objectDp.f(object, key, _propertyDesc(1, value));
118
+ } : function(object, key, value) {
119
+ object[key] = value;
120
+ return object;
121
+ };
122
+ var hasOwnProperty = {}.hasOwnProperty;
123
+ var _has = function(it, key) {
124
+ return hasOwnProperty.call(it, key);
125
+ };
126
+ var id = 0;
127
+ var px = Math.random();
128
+ var _uid = function(key) {
129
+ return "Symbol(".concat(key === void 0 ? "" : key, ")_", (++id + px).toString(36));
130
+ };
131
+ var _library = false;
132
+ var _functionToString = createCommonjsModule(function(module$4) {
133
+ var SHARED = "__core-js_shared__";
134
+ var store = _global[SHARED] || (_global[SHARED] = {});
135
+ (module$4.exports = function(key, value) {
136
+ return store[key] || (store[key] = value !== void 0 ? value : {});
137
+ })("versions", []).push({
138
+ version: _core.version,
139
+ mode: _library ? "pure" : "global",
140
+ copyright: "© 2019 Denis Pushkarev (zloirock.ru)"
141
+ });
142
+ })("native-function-to-string", Function.toString);
143
+ var _redefine = createCommonjsModule(function(module$5) {
144
+ var SRC = _uid("src");
145
+ var TO_STRING = "toString";
146
+ var TPL = ("" + _functionToString).split(TO_STRING);
147
+ _core.inspectSource = function(it) {
148
+ return _functionToString.call(it);
149
+ };
150
+ (module$5.exports = function(O, key, val, safe) {
151
+ var isFunction = typeof val == "function";
152
+ if (isFunction) _has(val, "name") || _hide(val, "name", key);
153
+ if (O[key] === val) return;
154
+ if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? "" + O[key] : TPL.join(String(key)));
155
+ if (O === _global) O[key] = val;
156
+ else if (!safe) {
157
+ delete O[key];
158
+ _hide(O, key, val);
159
+ } else if (O[key]) O[key] = val;
160
+ else _hide(O, key, val);
161
+ })(Function.prototype, TO_STRING, function toString() {
162
+ return typeof this == "function" && this[SRC] || _functionToString.call(this);
163
+ });
164
+ });
165
+ var _aFunction = function(it) {
166
+ if (typeof it != "function") throw TypeError(it + " is not a function!");
167
+ return it;
168
+ };
169
+ var _ctx = function(fn, that, length) {
170
+ _aFunction(fn);
171
+ if (that === void 0) return fn;
172
+ switch (length) {
173
+ case 1: return function(a) {
174
+ return fn.call(that, a);
175
+ };
176
+ case 2: return function(a, b) {
177
+ return fn.call(that, a, b);
178
+ };
179
+ case 3: return function(a, b, c) {
180
+ return fn.call(that, a, b, c);
181
+ };
182
+ }
183
+ return function() {
184
+ return fn.apply(that, arguments);
185
+ };
186
+ };
187
+ var PROTOTYPE = "prototype";
188
+ var $export = function(type, name, source) {
189
+ var IS_FORCED = type & $export.F;
190
+ var IS_GLOBAL = type & $export.G;
191
+ var IS_STATIC = type & $export.S;
192
+ var IS_PROTO = type & $export.P;
193
+ var IS_BIND = type & $export.B;
194
+ var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE];
195
+ var exports$1 = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
196
+ var expProto = exports$1[PROTOTYPE] || (exports$1[PROTOTYPE] = {});
197
+ var key, own, out, exp;
198
+ if (IS_GLOBAL) source = name;
199
+ for (key in source) {
200
+ own = !IS_FORCED && target && target[key] !== void 0;
201
+ out = (own ? target : source)[key];
202
+ exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == "function" ? _ctx(Function.call, out) : out;
203
+ if (target) _redefine(target, key, out, type & $export.U);
204
+ if (exports$1[key] != out) _hide(exports$1, key, exp);
205
+ if (IS_PROTO && expProto[key] != out) expProto[key] = out;
206
+ }
207
+ };
208
+ _global.core = _core;
209
+ $export.F = 1;
210
+ $export.G = 2;
211
+ $export.S = 4;
212
+ $export.P = 8;
213
+ $export.B = 16;
214
+ $export.W = 32;
215
+ $export.U = 64;
216
+ $export.R = 128;
217
+ var _export = $export;
218
+ var ceil = Math.ceil;
219
+ var floor = Math.floor;
220
+ var _toInteger = function(it) {
221
+ return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
222
+ };
223
+ var _defined = function(it) {
224
+ if (it == void 0) throw TypeError("Can't call method on " + it);
225
+ return it;
226
+ };
227
+ var _stringAt = function(TO_STRING) {
228
+ return function(that, pos) {
229
+ var s = String(_defined(that));
230
+ var i = _toInteger(pos);
231
+ var l = s.length;
232
+ var a, b;
233
+ if (i < 0 || i >= l) return TO_STRING ? "" : void 0;
234
+ a = s.charCodeAt(i);
235
+ 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;
236
+ };
237
+ };
238
+ var $at = _stringAt(false);
239
+ _export(_export.P, "String", { codePointAt: function codePointAt(pos) {
240
+ return $at(this, pos);
241
+ } });
242
+ _core.String.codePointAt;
243
+ var max = Math.max;
244
+ var min = Math.min;
245
+ var _toAbsoluteIndex = function(index, length) {
246
+ index = _toInteger(index);
247
+ return index < 0 ? max(index + length, 0) : min(index, length);
248
+ };
249
+ var fromCharCode = String.fromCharCode;
250
+ var $fromCodePoint = String.fromCodePoint;
251
+ _export(_export.S + _export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), "String", { fromCodePoint: function fromCodePoint(x) {
252
+ var arguments$1 = arguments;
253
+ var res = [];
254
+ var aLen = arguments.length;
255
+ var i = 0;
256
+ var code;
257
+ while (aLen > i) {
258
+ code = +arguments$1[i++];
259
+ if (_toAbsoluteIndex(code, 1114111) !== code) throw RangeError(code + " is not a valid code point");
260
+ res.push(code < 65536 ? fromCharCode(code) : fromCharCode(((code -= 65536) >> 10) + 55296, code % 1024 + 56320));
261
+ }
262
+ return res.join("");
263
+ } });
264
+ _core.String.fromCodePoint;
265
+ var unicode = {
266
+ Space_Separator: /[\u1680\u2000-\u200A\u202F\u205F\u3000]/,
267
+ 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]/,
268
+ 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]/
269
+ };
270
+ var util = {
271
+ isSpaceSeparator: function isSpaceSeparator(c) {
272
+ return typeof c === "string" && unicode.Space_Separator.test(c);
273
+ },
274
+ isIdStartChar: function isIdStartChar(c) {
275
+ return typeof c === "string" && (c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "$" || c === "_" || unicode.ID_Start.test(c));
276
+ },
277
+ isIdContinueChar: function isIdContinueChar(c) {
278
+ 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));
279
+ },
280
+ isDigit: function isDigit(c) {
281
+ return typeof c === "string" && /[0-9]/.test(c);
282
+ },
283
+ isHexDigit: function isHexDigit(c) {
284
+ return typeof c === "string" && /[0-9A-Fa-f]/.test(c);
285
+ }
286
+ };
287
+ var source;
288
+ var parseState;
289
+ var stack;
290
+ var pos;
291
+ var line;
292
+ var column;
293
+ var token;
294
+ var key;
295
+ var root;
296
+ var parse = function parse(text, reviver) {
297
+ source = String(text);
298
+ parseState = "start";
299
+ stack = [];
300
+ pos = 0;
301
+ line = 1;
302
+ column = 0;
303
+ token = void 0;
304
+ key = void 0;
305
+ root = void 0;
306
+ do {
307
+ token = lex();
308
+ parseStates[parseState]();
309
+ } while (token.type !== "eof");
310
+ if (typeof reviver === "function") return internalize({ "": root }, "", reviver);
311
+ return root;
312
+ };
313
+ function internalize(holder, name, reviver) {
314
+ var value = holder[name];
315
+ if (value != null && typeof value === "object") {
316
+ if (Array.isArray(value)) for (var i = 0; i < value.length; i++) {
317
+ var key = String(i);
318
+ var replacement = internalize(value, key, reviver);
319
+ if (replacement === void 0) delete value[key];
320
+ else Object.defineProperty(value, key, {
321
+ value: replacement,
322
+ writable: true,
323
+ enumerable: true,
324
+ configurable: true
325
+ });
326
+ }
327
+ else for (var key$1 in value) {
328
+ var replacement$1 = internalize(value, key$1, reviver);
329
+ if (replacement$1 === void 0) delete value[key$1];
330
+ else Object.defineProperty(value, key$1, {
331
+ value: replacement$1,
332
+ writable: true,
333
+ enumerable: true,
334
+ configurable: true
335
+ });
79
336
  }
80
337
  }
81
- let endPos = 0;
82
- for (let j = i + 1; j < lines.length; j++) if (lines[j].trim() === ":::") {
83
- let endCharPos = 0;
84
- for (let l = 0; l < j; l++) endCharPos += lines[l].length + 1;
85
- endPos = endCharPos;
86
- i = j + 1;
87
- break;
338
+ return reviver.call(holder, name, value);
339
+ }
340
+ var lexState;
341
+ var buffer;
342
+ var doubleQuote;
343
+ var sign;
344
+ var c;
345
+ function lex() {
346
+ lexState = "default";
347
+ buffer = "";
348
+ doubleQuote = false;
349
+ sign = 1;
350
+ for (;;) {
351
+ c = peek();
352
+ var token = lexStates[lexState]();
353
+ if (token) return token;
88
354
  }
89
- containers.push({
90
- startPos: charPos,
91
- typeName,
92
- propsLineFrom,
93
- propsLineTo,
94
- props,
95
- endPos
96
- });
97
355
  }
98
- i++;
99
- }
100
- return containers;
101
- }
102
- //#endregion
103
- //#region src/registry/componentRegistry.tsx
104
- /**
105
- * 组件注册中心,用于管理自定义组件的 schema。
106
- * 每个容器组件(如 :::linkCard)在此注册其可编辑字段。
107
- */
356
+ function peek() {
357
+ if (source[pos]) return String.fromCodePoint(source.codePointAt(pos));
358
+ }
359
+ function read() {
360
+ var c = peek();
361
+ if (c === "\n") {
362
+ line++;
363
+ column = 0;
364
+ } else if (c) column += c.length;
365
+ else column++;
366
+ if (c) pos += c.length;
367
+ return c;
368
+ }
369
+ var lexStates = {
370
+ default: function default$1() {
371
+ switch (c) {
372
+ case " ":
373
+ case "\v":
374
+ case "\f":
375
+ case " ":
376
+ case "\xA0":
377
+ case "":
378
+ case "\n":
379
+ case "\r":
380
+ case "\u2028":
381
+ case "\u2029":
382
+ read();
383
+ return;
384
+ case "/":
385
+ read();
386
+ lexState = "comment";
387
+ return;
388
+ case void 0:
389
+ read();
390
+ return newToken("eof");
391
+ }
392
+ if (util.isSpaceSeparator(c)) {
393
+ read();
394
+ return;
395
+ }
396
+ return lexStates[parseState]();
397
+ },
398
+ comment: function comment() {
399
+ switch (c) {
400
+ case "*":
401
+ read();
402
+ lexState = "multiLineComment";
403
+ return;
404
+ case "/":
405
+ read();
406
+ lexState = "singleLineComment";
407
+ return;
408
+ }
409
+ throw invalidChar(read());
410
+ },
411
+ multiLineComment: function multiLineComment() {
412
+ switch (c) {
413
+ case "*":
414
+ read();
415
+ lexState = "multiLineCommentAsterisk";
416
+ return;
417
+ case void 0: throw invalidChar(read());
418
+ }
419
+ read();
420
+ },
421
+ multiLineCommentAsterisk: function multiLineCommentAsterisk() {
422
+ switch (c) {
423
+ case "*":
424
+ read();
425
+ return;
426
+ case "/":
427
+ read();
428
+ lexState = "default";
429
+ return;
430
+ case void 0: throw invalidChar(read());
431
+ }
432
+ read();
433
+ lexState = "multiLineComment";
434
+ },
435
+ singleLineComment: function singleLineComment() {
436
+ switch (c) {
437
+ case "\n":
438
+ case "\r":
439
+ case "\u2028":
440
+ case "\u2029":
441
+ read();
442
+ lexState = "default";
443
+ return;
444
+ case void 0:
445
+ read();
446
+ return newToken("eof");
447
+ }
448
+ read();
449
+ },
450
+ value: function value() {
451
+ switch (c) {
452
+ case "{":
453
+ case "[": return newToken("punctuator", read());
454
+ case "n":
455
+ read();
456
+ literal("ull");
457
+ return newToken("null", null);
458
+ case "t":
459
+ read();
460
+ literal("rue");
461
+ return newToken("boolean", true);
462
+ case "f":
463
+ read();
464
+ literal("alse");
465
+ return newToken("boolean", false);
466
+ case "-":
467
+ case "+":
468
+ if (read() === "-") sign = -1;
469
+ lexState = "sign";
470
+ return;
471
+ case ".":
472
+ buffer = read();
473
+ lexState = "decimalPointLeading";
474
+ return;
475
+ case "0":
476
+ buffer = read();
477
+ lexState = "zero";
478
+ return;
479
+ case "1":
480
+ case "2":
481
+ case "3":
482
+ case "4":
483
+ case "5":
484
+ case "6":
485
+ case "7":
486
+ case "8":
487
+ case "9":
488
+ buffer = read();
489
+ lexState = "decimalInteger";
490
+ return;
491
+ case "I":
492
+ read();
493
+ literal("nfinity");
494
+ return newToken("numeric", Infinity);
495
+ case "N":
496
+ read();
497
+ literal("aN");
498
+ return newToken("numeric", NaN);
499
+ case "\"":
500
+ case "'":
501
+ doubleQuote = read() === "\"";
502
+ buffer = "";
503
+ lexState = "string";
504
+ return;
505
+ }
506
+ throw invalidChar(read());
507
+ },
508
+ identifierNameStartEscape: function identifierNameStartEscape() {
509
+ if (c !== "u") throw invalidChar(read());
510
+ read();
511
+ var u = unicodeEscape();
512
+ switch (u) {
513
+ case "$":
514
+ case "_": break;
515
+ default: if (!util.isIdStartChar(u)) throw invalidIdentifier();
516
+ }
517
+ buffer += u;
518
+ lexState = "identifierName";
519
+ },
520
+ identifierName: function identifierName() {
521
+ switch (c) {
522
+ case "$":
523
+ case "_":
524
+ case "‌":
525
+ case "‍":
526
+ buffer += read();
527
+ return;
528
+ case "\\":
529
+ read();
530
+ lexState = "identifierNameEscape";
531
+ return;
532
+ }
533
+ if (util.isIdContinueChar(c)) {
534
+ buffer += read();
535
+ return;
536
+ }
537
+ return newToken("identifier", buffer);
538
+ },
539
+ identifierNameEscape: function identifierNameEscape() {
540
+ if (c !== "u") throw invalidChar(read());
541
+ read();
542
+ var u = unicodeEscape();
543
+ switch (u) {
544
+ case "$":
545
+ case "_":
546
+ case "‌":
547
+ case "‍": break;
548
+ default: if (!util.isIdContinueChar(u)) throw invalidIdentifier();
549
+ }
550
+ buffer += u;
551
+ lexState = "identifierName";
552
+ },
553
+ sign: function sign$1() {
554
+ switch (c) {
555
+ case ".":
556
+ buffer = read();
557
+ lexState = "decimalPointLeading";
558
+ return;
559
+ case "0":
560
+ buffer = read();
561
+ lexState = "zero";
562
+ return;
563
+ case "1":
564
+ case "2":
565
+ case "3":
566
+ case "4":
567
+ case "5":
568
+ case "6":
569
+ case "7":
570
+ case "8":
571
+ case "9":
572
+ buffer = read();
573
+ lexState = "decimalInteger";
574
+ return;
575
+ case "I":
576
+ read();
577
+ literal("nfinity");
578
+ return newToken("numeric", sign * Infinity);
579
+ case "N":
580
+ read();
581
+ literal("aN");
582
+ return newToken("numeric", NaN);
583
+ }
584
+ throw invalidChar(read());
585
+ },
586
+ zero: function zero() {
587
+ switch (c) {
588
+ case ".":
589
+ buffer += read();
590
+ lexState = "decimalPoint";
591
+ return;
592
+ case "e":
593
+ case "E":
594
+ buffer += read();
595
+ lexState = "decimalExponent";
596
+ return;
597
+ case "x":
598
+ case "X":
599
+ buffer += read();
600
+ lexState = "hexadecimal";
601
+ return;
602
+ }
603
+ return newToken("numeric", sign * 0);
604
+ },
605
+ decimalInteger: function decimalInteger() {
606
+ switch (c) {
607
+ case ".":
608
+ buffer += read();
609
+ lexState = "decimalPoint";
610
+ return;
611
+ case "e":
612
+ case "E":
613
+ buffer += read();
614
+ lexState = "decimalExponent";
615
+ return;
616
+ }
617
+ if (util.isDigit(c)) {
618
+ buffer += read();
619
+ return;
620
+ }
621
+ return newToken("numeric", sign * Number(buffer));
622
+ },
623
+ decimalPointLeading: function decimalPointLeading() {
624
+ if (util.isDigit(c)) {
625
+ buffer += read();
626
+ lexState = "decimalFraction";
627
+ return;
628
+ }
629
+ throw invalidChar(read());
630
+ },
631
+ decimalPoint: function decimalPoint() {
632
+ switch (c) {
633
+ case "e":
634
+ case "E":
635
+ buffer += read();
636
+ lexState = "decimalExponent";
637
+ return;
638
+ }
639
+ if (util.isDigit(c)) {
640
+ buffer += read();
641
+ lexState = "decimalFraction";
642
+ return;
643
+ }
644
+ return newToken("numeric", sign * Number(buffer));
645
+ },
646
+ decimalFraction: function decimalFraction() {
647
+ switch (c) {
648
+ case "e":
649
+ case "E":
650
+ buffer += read();
651
+ lexState = "decimalExponent";
652
+ return;
653
+ }
654
+ if (util.isDigit(c)) {
655
+ buffer += read();
656
+ return;
657
+ }
658
+ return newToken("numeric", sign * Number(buffer));
659
+ },
660
+ decimalExponent: function decimalExponent() {
661
+ switch (c) {
662
+ case "+":
663
+ case "-":
664
+ buffer += read();
665
+ lexState = "decimalExponentSign";
666
+ return;
667
+ }
668
+ if (util.isDigit(c)) {
669
+ buffer += read();
670
+ lexState = "decimalExponentInteger";
671
+ return;
672
+ }
673
+ throw invalidChar(read());
674
+ },
675
+ decimalExponentSign: function decimalExponentSign() {
676
+ if (util.isDigit(c)) {
677
+ buffer += read();
678
+ lexState = "decimalExponentInteger";
679
+ return;
680
+ }
681
+ throw invalidChar(read());
682
+ },
683
+ decimalExponentInteger: function decimalExponentInteger() {
684
+ if (util.isDigit(c)) {
685
+ buffer += read();
686
+ return;
687
+ }
688
+ return newToken("numeric", sign * Number(buffer));
689
+ },
690
+ hexadecimal: function hexadecimal() {
691
+ if (util.isHexDigit(c)) {
692
+ buffer += read();
693
+ lexState = "hexadecimalInteger";
694
+ return;
695
+ }
696
+ throw invalidChar(read());
697
+ },
698
+ hexadecimalInteger: function hexadecimalInteger() {
699
+ if (util.isHexDigit(c)) {
700
+ buffer += read();
701
+ return;
702
+ }
703
+ return newToken("numeric", sign * Number(buffer));
704
+ },
705
+ string: function string() {
706
+ switch (c) {
707
+ case "\\":
708
+ read();
709
+ buffer += escape();
710
+ return;
711
+ case "\"":
712
+ if (doubleQuote) {
713
+ read();
714
+ return newToken("string", buffer);
715
+ }
716
+ buffer += read();
717
+ return;
718
+ case "'":
719
+ if (!doubleQuote) {
720
+ read();
721
+ return newToken("string", buffer);
722
+ }
723
+ buffer += read();
724
+ return;
725
+ case "\n":
726
+ case "\r": throw invalidChar(read());
727
+ case "\u2028":
728
+ case "\u2029":
729
+ separatorChar(c);
730
+ break;
731
+ case void 0: throw invalidChar(read());
732
+ }
733
+ buffer += read();
734
+ },
735
+ start: function start() {
736
+ switch (c) {
737
+ case "{":
738
+ case "[": return newToken("punctuator", read());
739
+ }
740
+ lexState = "value";
741
+ },
742
+ beforePropertyName: function beforePropertyName() {
743
+ switch (c) {
744
+ case "$":
745
+ case "_":
746
+ buffer = read();
747
+ lexState = "identifierName";
748
+ return;
749
+ case "\\":
750
+ read();
751
+ lexState = "identifierNameStartEscape";
752
+ return;
753
+ case "}": return newToken("punctuator", read());
754
+ case "\"":
755
+ case "'":
756
+ doubleQuote = read() === "\"";
757
+ lexState = "string";
758
+ return;
759
+ }
760
+ if (util.isIdStartChar(c)) {
761
+ buffer += read();
762
+ lexState = "identifierName";
763
+ return;
764
+ }
765
+ throw invalidChar(read());
766
+ },
767
+ afterPropertyName: function afterPropertyName() {
768
+ if (c === ":") return newToken("punctuator", read());
769
+ throw invalidChar(read());
770
+ },
771
+ beforePropertyValue: function beforePropertyValue() {
772
+ lexState = "value";
773
+ },
774
+ afterPropertyValue: function afterPropertyValue() {
775
+ switch (c) {
776
+ case ",":
777
+ case "}": return newToken("punctuator", read());
778
+ }
779
+ throw invalidChar(read());
780
+ },
781
+ beforeArrayValue: function beforeArrayValue() {
782
+ if (c === "]") return newToken("punctuator", read());
783
+ lexState = "value";
784
+ },
785
+ afterArrayValue: function afterArrayValue() {
786
+ switch (c) {
787
+ case ",":
788
+ case "]": return newToken("punctuator", read());
789
+ }
790
+ throw invalidChar(read());
791
+ },
792
+ end: function end() {
793
+ throw invalidChar(read());
794
+ }
795
+ };
796
+ function newToken(type, value) {
797
+ return {
798
+ type,
799
+ value,
800
+ line,
801
+ column
802
+ };
803
+ }
804
+ function literal(s) {
805
+ for (var i = 0, list = s; i < list.length; i += 1) {
806
+ var c = list[i];
807
+ if (peek() !== c) throw invalidChar(read());
808
+ read();
809
+ }
810
+ }
811
+ function escape() {
812
+ switch (peek()) {
813
+ case "b":
814
+ read();
815
+ return "\b";
816
+ case "f":
817
+ read();
818
+ return "\f";
819
+ case "n":
820
+ read();
821
+ return "\n";
822
+ case "r":
823
+ read();
824
+ return "\r";
825
+ case "t":
826
+ read();
827
+ return " ";
828
+ case "v":
829
+ read();
830
+ return "\v";
831
+ case "0":
832
+ read();
833
+ if (util.isDigit(peek())) throw invalidChar(read());
834
+ return "\0";
835
+ case "x":
836
+ read();
837
+ return hexEscape();
838
+ case "u":
839
+ read();
840
+ return unicodeEscape();
841
+ case "\n":
842
+ case "\u2028":
843
+ case "\u2029":
844
+ read();
845
+ return "";
846
+ case "\r":
847
+ read();
848
+ if (peek() === "\n") read();
849
+ return "";
850
+ case "1":
851
+ case "2":
852
+ case "3":
853
+ case "4":
854
+ case "5":
855
+ case "6":
856
+ case "7":
857
+ case "8":
858
+ case "9": throw invalidChar(read());
859
+ case void 0: throw invalidChar(read());
860
+ }
861
+ return read();
862
+ }
863
+ function hexEscape() {
864
+ var buffer = "";
865
+ var c = peek();
866
+ if (!util.isHexDigit(c)) throw invalidChar(read());
867
+ buffer += read();
868
+ c = peek();
869
+ if (!util.isHexDigit(c)) throw invalidChar(read());
870
+ buffer += read();
871
+ return String.fromCodePoint(parseInt(buffer, 16));
872
+ }
873
+ function unicodeEscape() {
874
+ var buffer = "";
875
+ var count = 4;
876
+ while (count-- > 0) {
877
+ var c = peek();
878
+ if (!util.isHexDigit(c)) throw invalidChar(read());
879
+ buffer += read();
880
+ }
881
+ return String.fromCodePoint(parseInt(buffer, 16));
882
+ }
883
+ var parseStates = {
884
+ start: function start() {
885
+ if (token.type === "eof") throw invalidEOF();
886
+ push();
887
+ },
888
+ beforePropertyName: function beforePropertyName() {
889
+ switch (token.type) {
890
+ case "identifier":
891
+ case "string":
892
+ key = token.value;
893
+ parseState = "afterPropertyName";
894
+ return;
895
+ case "punctuator":
896
+ pop();
897
+ return;
898
+ case "eof": throw invalidEOF();
899
+ }
900
+ },
901
+ afterPropertyName: function afterPropertyName() {
902
+ if (token.type === "eof") throw invalidEOF();
903
+ parseState = "beforePropertyValue";
904
+ },
905
+ beforePropertyValue: function beforePropertyValue() {
906
+ if (token.type === "eof") throw invalidEOF();
907
+ push();
908
+ },
909
+ beforeArrayValue: function beforeArrayValue() {
910
+ if (token.type === "eof") throw invalidEOF();
911
+ if (token.type === "punctuator" && token.value === "]") {
912
+ pop();
913
+ return;
914
+ }
915
+ push();
916
+ },
917
+ afterPropertyValue: function afterPropertyValue() {
918
+ if (token.type === "eof") throw invalidEOF();
919
+ switch (token.value) {
920
+ case ",":
921
+ parseState = "beforePropertyName";
922
+ return;
923
+ case "}": pop();
924
+ }
925
+ },
926
+ afterArrayValue: function afterArrayValue() {
927
+ if (token.type === "eof") throw invalidEOF();
928
+ switch (token.value) {
929
+ case ",":
930
+ parseState = "beforeArrayValue";
931
+ return;
932
+ case "]": pop();
933
+ }
934
+ },
935
+ end: function end() {}
936
+ };
937
+ function push() {
938
+ var value;
939
+ switch (token.type) {
940
+ case "punctuator":
941
+ switch (token.value) {
942
+ case "{":
943
+ value = {};
944
+ break;
945
+ case "[": value = [];
946
+ }
947
+ break;
948
+ case "null":
949
+ case "boolean":
950
+ case "numeric":
951
+ case "string": value = token.value;
952
+ }
953
+ if (root === void 0) root = value;
954
+ else {
955
+ var parent = stack[stack.length - 1];
956
+ if (Array.isArray(parent)) parent.push(value);
957
+ else Object.defineProperty(parent, key, {
958
+ value,
959
+ writable: true,
960
+ enumerable: true,
961
+ configurable: true
962
+ });
963
+ }
964
+ if (value !== null && typeof value === "object") {
965
+ stack.push(value);
966
+ if (Array.isArray(value)) parseState = "beforeArrayValue";
967
+ else parseState = "beforePropertyName";
968
+ } else {
969
+ var current = stack[stack.length - 1];
970
+ if (current == null) parseState = "end";
971
+ else if (Array.isArray(current)) parseState = "afterArrayValue";
972
+ else parseState = "afterPropertyValue";
973
+ }
974
+ }
975
+ function pop() {
976
+ stack.pop();
977
+ var current = stack[stack.length - 1];
978
+ if (current == null) parseState = "end";
979
+ else if (Array.isArray(current)) parseState = "afterArrayValue";
980
+ else parseState = "afterPropertyValue";
981
+ }
982
+ function invalidChar(c) {
983
+ if (c === void 0) return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
984
+ return syntaxError("JSON5: invalid character '" + formatChar(c) + "' at " + line + ":" + column);
985
+ }
986
+ function invalidEOF() {
987
+ return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
988
+ }
989
+ function invalidIdentifier() {
990
+ column -= 5;
991
+ return syntaxError("JSON5: invalid identifier character at " + line + ":" + column);
992
+ }
993
+ function separatorChar(c) {
994
+ console.warn("JSON5: '" + formatChar(c) + "' in strings is not valid ECMAScript; consider escaping");
995
+ }
996
+ function formatChar(c) {
997
+ var replacements = {
998
+ "'": "\\'",
999
+ "\"": "\\\"",
1000
+ "\\": "\\\\",
1001
+ "\b": "\\b",
1002
+ "\f": "\\f",
1003
+ "\n": "\\n",
1004
+ "\r": "\\r",
1005
+ " ": "\\t",
1006
+ "\v": "\\v",
1007
+ "\0": "\\0",
1008
+ "\u2028": "\\u2028",
1009
+ "\u2029": "\\u2029"
1010
+ };
1011
+ if (replacements[c]) return replacements[c];
1012
+ if (c < " ") {
1013
+ var hexString = c.charCodeAt(0).toString(16);
1014
+ return "\\x" + ("00" + hexString).substring(hexString.length);
1015
+ }
1016
+ return c;
1017
+ }
1018
+ function syntaxError(message) {
1019
+ var err = new SyntaxError(message);
1020
+ err.lineNumber = line;
1021
+ err.columnNumber = column;
1022
+ return err;
1023
+ }
1024
+ return {
1025
+ parse,
1026
+ stringify: function stringify(value, replacer, space) {
1027
+ var stack = [];
1028
+ var indent = "";
1029
+ var propertyList;
1030
+ var replacerFunc;
1031
+ var gap = "";
1032
+ var quote;
1033
+ if (replacer != null && typeof replacer === "object" && !Array.isArray(replacer)) {
1034
+ space = replacer.space;
1035
+ quote = replacer.quote;
1036
+ replacer = replacer.replacer;
1037
+ }
1038
+ if (typeof replacer === "function") replacerFunc = replacer;
1039
+ else if (Array.isArray(replacer)) {
1040
+ propertyList = [];
1041
+ for (var i = 0, list = replacer; i < list.length; i += 1) {
1042
+ var v = list[i];
1043
+ var item = void 0;
1044
+ if (typeof v === "string") item = v;
1045
+ else if (typeof v === "number" || v instanceof String || v instanceof Number) item = String(v);
1046
+ if (item !== void 0 && propertyList.indexOf(item) < 0) propertyList.push(item);
1047
+ }
1048
+ }
1049
+ if (space instanceof Number) space = Number(space);
1050
+ else if (space instanceof String) space = String(space);
1051
+ if (typeof space === "number") {
1052
+ if (space > 0) {
1053
+ space = Math.min(10, Math.floor(space));
1054
+ gap = " ".substr(0, space);
1055
+ }
1056
+ } else if (typeof space === "string") gap = space.substr(0, 10);
1057
+ return serializeProperty("", { "": value });
1058
+ function serializeProperty(key, holder) {
1059
+ var value = holder[key];
1060
+ if (value != null) {
1061
+ if (typeof value.toJSON5 === "function") value = value.toJSON5(key);
1062
+ else if (typeof value.toJSON === "function") value = value.toJSON(key);
1063
+ }
1064
+ if (replacerFunc) value = replacerFunc.call(holder, key, value);
1065
+ if (value instanceof Number) value = Number(value);
1066
+ else if (value instanceof String) value = String(value);
1067
+ else if (value instanceof Boolean) value = value.valueOf();
1068
+ switch (value) {
1069
+ case null: return "null";
1070
+ case true: return "true";
1071
+ case false: return "false";
1072
+ }
1073
+ if (typeof value === "string") return quoteString(value, false);
1074
+ if (typeof value === "number") return String(value);
1075
+ if (typeof value === "object") return Array.isArray(value) ? serializeArray(value) : serializeObject(value);
1076
+ }
1077
+ function quoteString(value) {
1078
+ var quotes = {
1079
+ "'": .1,
1080
+ "\"": .2
1081
+ };
1082
+ var replacements = {
1083
+ "'": "\\'",
1084
+ "\"": "\\\"",
1085
+ "\\": "\\\\",
1086
+ "\b": "\\b",
1087
+ "\f": "\\f",
1088
+ "\n": "\\n",
1089
+ "\r": "\\r",
1090
+ " ": "\\t",
1091
+ "\v": "\\v",
1092
+ "\0": "\\0",
1093
+ "\u2028": "\\u2028",
1094
+ "\u2029": "\\u2029"
1095
+ };
1096
+ var product = "";
1097
+ for (var i = 0; i < value.length; i++) {
1098
+ var c = value[i];
1099
+ switch (c) {
1100
+ case "'":
1101
+ case "\"":
1102
+ quotes[c]++;
1103
+ product += c;
1104
+ continue;
1105
+ case "\0": if (util.isDigit(value[i + 1])) {
1106
+ product += "\\x00";
1107
+ continue;
1108
+ }
1109
+ }
1110
+ if (replacements[c]) {
1111
+ product += replacements[c];
1112
+ continue;
1113
+ }
1114
+ if (c < " ") {
1115
+ var hexString = c.charCodeAt(0).toString(16);
1116
+ product += "\\x" + ("00" + hexString).substring(hexString.length);
1117
+ continue;
1118
+ }
1119
+ product += c;
1120
+ }
1121
+ var quoteChar = quote || Object.keys(quotes).reduce(function(a, b) {
1122
+ return quotes[a] < quotes[b] ? a : b;
1123
+ });
1124
+ product = product.replace(new RegExp(quoteChar, "g"), replacements[quoteChar]);
1125
+ return quoteChar + product + quoteChar;
1126
+ }
1127
+ function serializeObject(value) {
1128
+ if (stack.indexOf(value) >= 0) throw TypeError("Converting circular structure to JSON5");
1129
+ stack.push(value);
1130
+ var stepback = indent;
1131
+ indent = indent + gap;
1132
+ var keys = propertyList || Object.keys(value);
1133
+ var partial = [];
1134
+ for (var i = 0, list = keys; i < list.length; i += 1) {
1135
+ var key = list[i];
1136
+ var propertyString = serializeProperty(key, value);
1137
+ if (propertyString !== void 0) {
1138
+ var member = serializeKey(key) + ":";
1139
+ if (gap !== "") member += " ";
1140
+ member += propertyString;
1141
+ partial.push(member);
1142
+ }
1143
+ }
1144
+ var final;
1145
+ if (partial.length === 0) final = "{}";
1146
+ else {
1147
+ var properties;
1148
+ if (gap === "") {
1149
+ properties = partial.join(",");
1150
+ final = "{" + properties + "}";
1151
+ } else {
1152
+ var separator = ",\n" + indent;
1153
+ properties = partial.join(separator);
1154
+ final = "{\n" + indent + properties + ",\n" + stepback + "}";
1155
+ }
1156
+ }
1157
+ stack.pop();
1158
+ indent = stepback;
1159
+ return final;
1160
+ }
1161
+ function serializeKey(key) {
1162
+ if (key.length === 0) return quoteString(key, true);
1163
+ var firstChar = String.fromCodePoint(key.codePointAt(0));
1164
+ if (!util.isIdStartChar(firstChar)) return quoteString(key, true);
1165
+ for (var i = firstChar.length; i < key.length; i++) if (!util.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) return quoteString(key, true);
1166
+ return key;
1167
+ }
1168
+ function serializeArray(value) {
1169
+ if (stack.indexOf(value) >= 0) throw TypeError("Converting circular structure to JSON5");
1170
+ stack.push(value);
1171
+ var stepback = indent;
1172
+ indent = indent + gap;
1173
+ var partial = [];
1174
+ for (var i = 0; i < value.length; i++) {
1175
+ var propertyString = serializeProperty(String(i), value);
1176
+ partial.push(propertyString !== void 0 ? propertyString : "null");
1177
+ }
1178
+ var final;
1179
+ if (partial.length === 0) final = "[]";
1180
+ else if (gap === "") final = "[" + partial.join(",") + "]";
1181
+ else {
1182
+ var separator = ",\n" + indent;
1183
+ var properties$1 = partial.join(separator);
1184
+ final = "[\n" + indent + properties$1 + ",\n" + stepback + "]";
1185
+ }
1186
+ stack.pop();
1187
+ indent = stepback;
1188
+ return final;
1189
+ }
1190
+ }
1191
+ };
1192
+ }));
1193
+ })))(), 1);
108
1194
  var ComponentRegistry = class {
109
1195
  schemas = /* @__PURE__ */ new Map();
1196
+ listeners = /* @__PURE__ */ new Set();
1197
+ version = 0;
110
1198
  /**
111
1199
  * 注册组件 schema
112
1200
  */
113
1201
  register(name, schema) {
114
1202
  this.schemas.set(name, schema);
1203
+ this.emit();
1204
+ }
1205
+ /**
1206
+ * 移除组件注册
1207
+ */
1208
+ unregister(name) {
1209
+ if (this.schemas.delete(name)) this.emit();
1210
+ }
1211
+ /**
1212
+ * 当前版本号,任意注册变更都会自增
1213
+ */
1214
+ getVersion() {
1215
+ return this.version;
1216
+ }
1217
+ /**
1218
+ * 订阅注册变更,返回退订函数
1219
+ */
1220
+ subscribe(listener) {
1221
+ this.listeners.add(listener);
1222
+ return () => {
1223
+ this.listeners.delete(listener);
1224
+ };
1225
+ }
1226
+ emit() {
1227
+ this.version += 1;
1228
+ this.listeners.forEach((listener) => listener(this.version));
115
1229
  }
116
1230
  /**
117
1231
  * 根据组件名获取已注册的 schema
@@ -137,29 +1251,97 @@ var ComponentRegistry = class {
137
1251
  getAll() {
138
1252
  return Array.from(this.schemas.values());
139
1253
  }
140
- /**
141
- * 移除组件注册
142
- */
143
- unregister(name) {
144
- this.schemas.delete(name);
145
- }
146
1254
  };
147
1255
  var componentRegistry = new ComponentRegistry();
148
1256
  //#endregion
1257
+ //#region src/utils/parseContainer.ts
1258
+ /**
1259
+ * 解析容器属性行。
1260
+ * 优先按 JSON5 解析(兼容标准 JSON 与 { key: 'value' } 宽松写法),
1261
+ * 失败时返回空对象,保证往返编辑不丢数据。
1262
+ */
1263
+ function parseContainerProps(line) {
1264
+ const trimmed = line.trim();
1265
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return {};
1266
+ try {
1267
+ const parsed = import_dist.default.parse(trimmed);
1268
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1269
+ const props = {};
1270
+ for (const [key, value] of Object.entries(parsed)) {
1271
+ if (value === null || value === void 0) continue;
1272
+ if (typeof value === "object") continue;
1273
+ props[key] = value;
1274
+ }
1275
+ return props;
1276
+ } catch {
1277
+ return {};
1278
+ }
1279
+ }
1280
+ /**
1281
+ * 在编辑器文档中查找容器块。
1282
+ * 单次遍历 + 预累计行偏移,复杂度 O(行数)。
1283
+ */
1284
+ function findContainers(docText) {
1285
+ const containers = [];
1286
+ const lines = docText.split("\n");
1287
+ const offsets = new Array(lines.length);
1288
+ let pos = 0;
1289
+ for (let i = 0; i < lines.length; i++) {
1290
+ offsets[i] = pos;
1291
+ pos += lines[i].length + 1;
1292
+ }
1293
+ for (let i = 0; i < lines.length; i++) {
1294
+ const match = lines[i].match(/^:::(\w+)$/);
1295
+ if (!match) continue;
1296
+ const typeName = match[1];
1297
+ const headerPos = offsets[i];
1298
+ let props = {};
1299
+ let propsLineFrom = 0;
1300
+ let propsLineTo = 0;
1301
+ const propsLine = lines[i + 1];
1302
+ if (propsLine && propsLine.trim().startsWith("{") && propsLine.trim().endsWith("}")) {
1303
+ props = parseContainerProps(propsLine);
1304
+ propsLineFrom = offsets[i + 1];
1305
+ propsLineTo = propsLineFrom + propsLine.length;
1306
+ }
1307
+ let endPos = 0;
1308
+ for (let j = i + 1; j < lines.length; j++) if (lines[j].trim() === ":::") {
1309
+ endPos = offsets[j];
1310
+ i = j;
1311
+ break;
1312
+ }
1313
+ containers.push({
1314
+ startPos: headerPos,
1315
+ typeName,
1316
+ propsLineFrom,
1317
+ propsLineTo,
1318
+ props,
1319
+ endPos,
1320
+ registered: componentRegistry.has(typeName)
1321
+ });
1322
+ }
1323
+ return containers;
1324
+ }
1325
+ //#endregion
149
1326
  //#region src/components/Editor/containerWidget.ts
150
1327
  /**
151
1328
  * 自定义 facet 用于传递编辑回调
152
1329
  */
153
- var containerEditCallback = _codemirror_state.Facet.define({ combine: (values) => values[0] });
1330
+ var containerEditCallback = _codemirror_state.Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
154
1331
  /**
155
1332
  * 只读的容器头行 Widget(显示 :::typeName + 编辑按钮)
156
- * 使用 Decoration.replace 替换原始文本,使其不可直接编辑
1333
+ * 使用 Decoration.replace 替换原始文本,使其不可直接编辑。
1334
+ * widget 直接携带所属容器索引与类型,点击时无需再做位置猜测。
157
1335
  */
158
1336
  var ContainerHeaderWidget = class extends _codemirror_view.WidgetType {
159
1337
  typeName;
160
- constructor(typeName) {
1338
+ containerIndex;
1339
+ registered;
1340
+ constructor(typeName, containerIndex, registered) {
161
1341
  super();
162
1342
  this.typeName = typeName;
1343
+ this.containerIndex = containerIndex;
1344
+ this.registered = registered;
163
1345
  }
164
1346
  toDOM() {
165
1347
  const container = document.createElement("span");
@@ -167,17 +1349,20 @@ var ContainerHeaderWidget = class extends _codemirror_view.WidgetType {
167
1349
  const text = document.createElement("span");
168
1350
  text.className = "container-widget-text";
169
1351
  text.textContent = `:::${this.typeName}`;
170
- const button = document.createElement("button");
171
- button.className = "container-edit-btn";
172
- button.title = `编辑 ${componentRegistry.get(this.typeName)?.label ?? this.typeName}`;
173
- button.textContent = "✎";
174
- button.__typeName = this.typeName;
175
1352
  container.appendChild(text);
176
- container.appendChild(button);
1353
+ if (this.registered) {
1354
+ const button = document.createElement("button");
1355
+ button.className = "container-edit-btn";
1356
+ button.title = `编辑 ${this.typeName}`;
1357
+ button.textContent = "✎";
1358
+ button.dataset.containerIndex = String(this.containerIndex);
1359
+ button.dataset.typeName = this.typeName;
1360
+ container.appendChild(button);
1361
+ }
177
1362
  return container;
178
1363
  }
179
1364
  eq(other) {
180
- return this.typeName === other.typeName;
1365
+ return this.typeName === other.typeName && this.containerIndex === other.containerIndex && this.registered === other.registered;
181
1366
  }
182
1367
  ignoreEvent() {
183
1368
  return false;
@@ -185,7 +1370,6 @@ var ContainerHeaderWidget = class extends _codemirror_view.WidgetType {
185
1370
  };
186
1371
  /**
187
1372
  * 只读的容器属性行 Widget(显示 { key: value, ... })
188
- * 使用 Decoration.replace 替换原始文本,使其不可直接编辑
189
1373
  */
190
1374
  var ContainerPropsWidget = class extends _codemirror_view.WidgetType {
191
1375
  propsText;
@@ -208,7 +1392,6 @@ var ContainerPropsWidget = class extends _codemirror_view.WidgetType {
208
1392
  };
209
1393
  /**
210
1394
  * 只读的容器结束行 Widget(显示 :::)
211
- * 使用 Decoration.replace 替换原始文本,使其不可直接编辑
212
1395
  */
213
1396
  var ContainerCloseWidget = class extends _codemirror_view.WidgetType {
214
1397
  toDOM() {
@@ -231,20 +1414,19 @@ var ContainerCloseWidget = class extends _codemirror_view.WidgetType {
231
1414
  function findContainerDecorations(state) {
232
1415
  const containers = findContainers(state.doc.toString());
233
1416
  const decorations = [];
234
- for (const container of containers) {
1417
+ containers.forEach((container, index) => {
235
1418
  const headerLine = state.doc.lineAt(container.startPos);
236
1419
  decorations.push({
237
1420
  from: headerLine.from,
238
1421
  to: headerLine.to,
239
- value: _codemirror_view.Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName) })
1422
+ value: _codemirror_view.Decoration.replace({ widget: new ContainerHeaderWidget(container.typeName, index, container.registered) })
240
1423
  });
241
1424
  if (container.propsLineFrom > 0 && container.propsLineTo > 0) {
242
1425
  const propsLine = state.doc.lineAt(container.propsLineFrom);
243
- const propsText = propsLine.text;
244
1426
  decorations.push({
245
1427
  from: propsLine.from,
246
1428
  to: propsLine.to,
247
- value: _codemirror_view.Decoration.replace({ widget: new ContainerPropsWidget(propsText) })
1429
+ value: _codemirror_view.Decoration.replace({ widget: new ContainerPropsWidget(propsLine.text) })
248
1430
  });
249
1431
  }
250
1432
  if (container.endPos > 0) {
@@ -255,12 +1437,32 @@ function findContainerDecorations(state) {
255
1437
  value: _codemirror_view.Decoration.replace({ widget: new ContainerCloseWidget() })
256
1438
  });
257
1439
  }
258
- }
1440
+ });
259
1441
  return decorations;
260
1442
  }
261
1443
  /**
1444
+ * 点击编辑按钮时,依据按钮携带的容器索引回查最新属性并触发回调
1445
+ */
1446
+ function handleEditButtonClick(event, view) {
1447
+ const target = event.target;
1448
+ if (!target.classList.contains("container-edit-btn")) return false;
1449
+ event.preventDefault();
1450
+ event.stopPropagation();
1451
+ const indexAttr = target.dataset.containerIndex;
1452
+ if (indexAttr === void 0) return false;
1453
+ const container = findContainers(view.state.doc.toString())[Number(indexAttr)];
1454
+ if (!container || !container.registered) return false;
1455
+ const callback = view.state.facet(containerEditCallback);
1456
+ if (callback) callback(view, {
1457
+ ...container,
1458
+ props: { ...container.props }
1459
+ });
1460
+ return true;
1461
+ }
1462
+ /**
262
1463
  * 容器编辑 ViewPlugin
263
- * 将容器的 ::: 头行和 {} 属性行替换为只读 widget,使其无法在编辑器中直接编辑
1464
+ * 将容器的 ::: 头行和 {} 属性行替换为只读 widget,使其无法在编辑器中直接编辑。
1465
+ * 仅在文档内容变化时重建装饰,光标移动不触发全文扫描。
264
1466
  */
265
1467
  var containerWidgetPlugin = _codemirror_view.ViewPlugin.fromClass(class {
266
1468
  decorations;
@@ -268,29 +1470,20 @@ var containerWidgetPlugin = _codemirror_view.ViewPlugin.fromClass(class {
268
1470
  this.decorations = _codemirror_view.Decoration.set(findContainerDecorations(view.state), true);
269
1471
  }
270
1472
  update(update) {
271
- if (update.docChanged || update.selectionSet) this.decorations = _codemirror_view.Decoration.set(findContainerDecorations(update.state), true);
1473
+ if (update.docChanged) this.decorations = _codemirror_view.Decoration.set(findContainerDecorations(update.state), true);
272
1474
  }
273
1475
  }, {
274
1476
  decorations: (value) => value.decorations,
275
- eventHandlers: { click: (event, view) => {
276
- const target = event.target;
277
- if (target.classList.contains("container-edit-btn")) {
278
- if (target.__typeName) {
279
- const containers = findContainers(view.state.doc.toString());
280
- const buttonPos = view.posAtDOM(target);
281
- for (const container of containers) {
282
- const headerLine = view.state.doc.lineAt(container.startPos);
283
- if (buttonPos >= headerLine.from - 5 && buttonPos <= headerLine.to + 5) {
284
- const callback = view.state.facet(containerEditCallback);
285
- if (callback) callback(view, container.typeName, container.propsLineFrom, container.propsLineTo, { ...container.props });
286
- return true;
287
- }
288
- }
1477
+ eventHandlers: {
1478
+ mousedown: (event, _view) => {
1479
+ if (event.target.classList.contains("container-edit-btn")) {
1480
+ event.preventDefault();
1481
+ return true;
289
1482
  }
290
1483
  return false;
291
- }
292
- return false;
293
- } }
1484
+ },
1485
+ click: handleEditButtonClick
1486
+ }
294
1487
  });
295
1488
  //#endregion
296
1489
  //#region src/components/Toolbar/buttons.tsx
@@ -322,28 +1515,248 @@ function insertAtLineStart(view, text) {
322
1515
  view.dispatch({ selection: { anchor: line.from + text.length } });
323
1516
  }
324
1517
  /**
325
- * 上传图片
1518
+ * 切换标题:
1519
+ * - 当前行已是目标级别标题 → 移除行首 # 前缀(变回普通文本)
1520
+ * - 当前行是其他级别标题 → 替换为目标级别
1521
+ * - 当前行是普通文本 → 插入目标级别前缀
1522
+ * @param view - CodeMirror 编辑器实例
1523
+ * @param level - 标题级别(1-6)
1524
+ */
1525
+ function toggleHeading(view, level) {
1526
+ const line = view.state.doc.lineAt(view.state.selection.main.from);
1527
+ const m = line.text.match(/^(\s*)(#{1,6})(\s+|\s*$)/);
1528
+ const indent = m ? m[1] : "";
1529
+ const text = "#".repeat(level) + " ";
1530
+ if (m && m[2].length === level) view.dispatch({ changes: {
1531
+ from: line.from,
1532
+ to: line.from + m[0].length,
1533
+ insert: indent
1534
+ } });
1535
+ else {
1536
+ view.dispatch({ changes: {
1537
+ from: line.from,
1538
+ to: m ? line.from + m[0].length : line.from,
1539
+ insert: indent + text
1540
+ } });
1541
+ view.dispatch({ selection: { anchor: line.from + indent.length + text.length } });
1542
+ }
1543
+ }
1544
+ /**
1545
+ * 切换任务列表(checkbox 待办)
1546
+ * - 支持多行:对选区内每一行应用 `- [ ] `
1547
+ * - 普通列表项(如 `- 内容`)直接转换为 `- [ ] 内容`
1548
+ * - 切换:若所有目标行都已是任务项,则移除行首前缀
1549
+ */
1550
+ function toggleTaskList(view) {
1551
+ const doc = view.state.doc;
1552
+ const { from, to } = view.state.selection.main;
1553
+ const first = doc.lineAt(from);
1554
+ const last = doc.lineAt(to);
1555
+ const lines = [];
1556
+ for (let n = first.number; n <= last.number; n++) lines.push(doc.line(n));
1557
+ const taskRe = /^(\s*)([-*+])\s\[( |x)\]\s?/;
1558
+ const allTask = lines.every((line) => taskRe.test(line.text));
1559
+ const changes = [];
1560
+ for (const line of lines) {
1561
+ const taskMatch = line.text.match(taskRe);
1562
+ if (taskMatch) changes.push({
1563
+ from: line.from,
1564
+ to: line.from + taskMatch[0].length,
1565
+ insert: allTask ? "" : `${taskMatch[1]}${taskMatch[2]} [ ] `
1566
+ });
1567
+ else {
1568
+ const bulletMatch = line.text.match(/^(\s*)([-*+])\s/);
1569
+ if (bulletMatch) {
1570
+ const idx = line.from + bulletMatch[1].length + bulletMatch[2].length;
1571
+ changes.push({
1572
+ from: idx,
1573
+ to: idx + 1,
1574
+ insert: " [ ] "
1575
+ });
1576
+ } else changes.push({
1577
+ from: line.from,
1578
+ to: line.from,
1579
+ insert: "- [ ] "
1580
+ });
1581
+ }
1582
+ }
1583
+ const anchor = view.state.changes(changes).mapPos(from, 1);
1584
+ view.dispatch({
1585
+ changes,
1586
+ selection: { anchor }
1587
+ });
1588
+ }
1589
+ /**
1590
+ * 切换行首前缀(支持多行选区)
1591
+ * - 已是对应前缀的行 → 移除前缀(变回普通文本)
1592
+ * - 未加前缀的行 → 在行首插入前缀
1593
+ * @param view - CodeMirror 编辑器实例
1594
+ * @param pattern - 匹配行首前缀的正则
1595
+ * @param insertText - 未匹配时插入的前缀文本
1596
+ */
1597
+ function toggleLinePrefix(view, pattern, insertText) {
1598
+ const doc = view.state.doc;
1599
+ const { from, to } = view.state.selection.main;
1600
+ const first = doc.lineAt(from);
1601
+ const last = doc.lineAt(Math.max(to, from));
1602
+ const changes = [];
1603
+ for (let n = first.number; n <= last.number; n++) {
1604
+ const line = doc.line(n);
1605
+ const m = line.text.match(pattern);
1606
+ if (m) changes.push({
1607
+ from: line.from,
1608
+ to: line.from + m[0].length,
1609
+ insert: ""
1610
+ });
1611
+ else changes.push({
1612
+ from: line.from,
1613
+ to: line.from,
1614
+ insert: insertText
1615
+ });
1616
+ }
1617
+ const anchor = view.state.changes(changes).mapPos(from, 1);
1618
+ view.dispatch({
1619
+ changes,
1620
+ selection: { anchor }
1621
+ });
1622
+ }
1623
+ /** Markdown 列表行:缩进 + 列表标记(无序/有序)+ 空白 */
1624
+ var LIST_LINE_RE = /^(\s*)([-*+]|\d+\.)([ \t]+)/;
1625
+ /** 列表缩进台阶:4 个空格,确保缩进后能被解析为子列表 */
1626
+ var LIST_INDENT_WIDTH = 4;
1627
+ /** 判断位置是否位于代码块内(代码块内不参与列表缩进逻辑) */
1628
+ function isInCodeBlock(state, pos) {
1629
+ let node = (0, _codemirror_language.syntaxTree)(state).resolveInner(pos, 1);
1630
+ while (node) {
1631
+ if (node.name === "FencedCode" || node.name === "CodeBlock") return true;
1632
+ node = node.parent;
1633
+ }
1634
+ return false;
1635
+ }
1636
+ /**
1637
+ * 向上查找同缩进的前一个列表项,返回其序号
1638
+ * - 跳过更深的子列表行和空行
1639
+ * - 遇到非列表内容或更浅层列表时结束
1640
+ */
1641
+ function findPrevSiblingOrder(state, plans, lineNo, indent) {
1642
+ const doc = state.doc;
1643
+ for (let n = lineNo - 1; n >= 1; n--) {
1644
+ const plan = plans.get(n);
1645
+ if (plan) {
1646
+ if (plan.nextIndent === indent) return plan.nextOrder;
1647
+ if (plan.nextIndent < indent) return null;
1648
+ continue;
1649
+ }
1650
+ const text = doc.line(n).text;
1651
+ if (!text.trim()) continue;
1652
+ const m = text.match(LIST_LINE_RE);
1653
+ if (!m) return null;
1654
+ const lineIndent = m[1].length;
1655
+ if (lineIndent === indent) return /^\d+\.$/.test(m[2]) ? parseInt(m[2], 10) : null;
1656
+ if (lineIndent < indent) return null;
1657
+ }
1658
+ return null;
1659
+ }
1660
+ /**
1661
+ * 计算列表行缩进/反缩进的变更
1662
+ * - 仅当所有选区行都是列表行时生效,否则返回 null 交给默认缩进行为
1663
+ * - 有序列表缩进后重新编号,保证新一级子列表从 1 开始
1664
+ */
1665
+ function planListIndent(view, direction) {
1666
+ const { state } = view;
1667
+ const doc = state.doc;
1668
+ const plans = /* @__PURE__ */ new Map();
1669
+ for (const range of state.selection.ranges) {
1670
+ const first = doc.lineAt(range.from).number;
1671
+ const last = doc.lineAt(range.to).number;
1672
+ for (let n = first; n <= last; n++) {
1673
+ if (plans.has(n)) continue;
1674
+ const line = doc.line(n);
1675
+ if (isInCodeBlock(state, line.from)) return null;
1676
+ const m = line.text.match(LIST_LINE_RE);
1677
+ if (!m) return null;
1678
+ const indent = m[1].length;
1679
+ plans.set(n, {
1680
+ indent,
1681
+ nextIndent: direction === 1 ? indent + LIST_INDENT_WIDTH : Math.max(0, indent - LIST_INDENT_WIDTH),
1682
+ order: /^\d+\.$/.test(m[2]) ? parseInt(m[2], 10) : null,
1683
+ nextOrder: null
1684
+ });
1685
+ }
1686
+ }
1687
+ if (plans.size === 0) return null;
1688
+ const ordered = [...plans.entries()].sort((a, b) => a[0] - b[0]);
1689
+ for (const [lineNo, info] of ordered) {
1690
+ if (info.order === null) continue;
1691
+ const prevOrder = findPrevSiblingOrder(state, plans, lineNo, info.nextIndent);
1692
+ info.nextOrder = prevOrder === null ? 1 : prevOrder + 1;
1693
+ }
1694
+ return ordered.map(([lineNo, info]) => {
1695
+ const line = doc.line(lineNo);
1696
+ const m = line.text.match(LIST_LINE_RE);
1697
+ const useNextOrder = (direction === 1 || info.indent > 0) && info.order !== null && info.nextOrder !== null && info.order !== info.nextOrder;
1698
+ return {
1699
+ from: line.from,
1700
+ to: line.from + m[0].length,
1701
+ insert: " ".repeat(info.nextIndent) + (useNextOrder ? `${info.nextOrder}.` : m[2]) + m[3]
1702
+ };
1703
+ });
1704
+ }
1705
+ /**
1706
+ * Tab:列表行缩进一级(4 空格)
1707
+ * - 普通行返回 false,继续走默认缩进
1708
+ * - 有序列表缩进后重排序号,子列表从 1 开始
1709
+ */
1710
+ function indentMarkdownList(view) {
1711
+ const changes = planListIndent(view, 1);
1712
+ if (!changes) return false;
1713
+ view.dispatch({
1714
+ changes,
1715
+ userEvent: "input.indent"
1716
+ });
1717
+ return true;
1718
+ }
1719
+ /**
1720
+ * Shift-Tab:列表行反缩进一级
1721
+ * - 普通行返回 false,继续走默认缩进
1722
+ * - 有序列表反缩进后并入上一层并重排序号
1723
+ */
1724
+ function dedentMarkdownList(view) {
1725
+ const changes = planListIndent(view, -1);
1726
+ if (!changes) return false;
1727
+ view.dispatch({
1728
+ changes,
1729
+ userEvent: "delete.dedent"
1730
+ });
1731
+ return true;
1732
+ }
1733
+ /**
1734
+ * 上传图片:失败(含网络异常)统一返回 null,不抛错
326
1735
  * @param file - 要上传的文件
327
1736
  * @param uploadConfig - 上传配置
328
1737
  */
329
1738
  async function uploadFileToServer(file, uploadConfig) {
330
- if (uploadConfig.onUploadImage) return uploadConfig.onUploadImage(file);
331
- if (uploadConfig.uploadUrl) {
332
- const formData = new FormData();
333
- formData.append("file", file);
334
- const response = await fetch(uploadConfig.uploadUrl, {
335
- method: "POST",
336
- body: formData
337
- });
338
- if (!response.ok) return null;
339
- const result = await response.json();
340
- if (uploadConfig.onGetUploadUrl) return uploadConfig.onGetUploadUrl(result);
341
- return result.data?.path || null;
1739
+ try {
1740
+ if (uploadConfig.onUploadImage) return await uploadConfig.onUploadImage(file);
1741
+ if (uploadConfig.uploadUrl) {
1742
+ const formData = new FormData();
1743
+ formData.append("file", file);
1744
+ const response = await fetch(uploadConfig.uploadUrl, {
1745
+ method: "POST",
1746
+ body: formData
1747
+ });
1748
+ if (!response.ok) return null;
1749
+ const result = await response.json();
1750
+ if (uploadConfig.onGetUploadUrl) return uploadConfig.onGetUploadUrl(result);
1751
+ return result?.data?.path ?? null;
1752
+ }
1753
+ return null;
1754
+ } catch {
1755
+ return null;
342
1756
  }
343
- return null;
344
1757
  }
345
1758
  /**
346
- * 判断是否配置了图片上传
1759
+ * 判断是否配置了图片上传(类型谓词,守卫后可安全访问配置)
347
1760
  */
348
1761
  function isUploadConfigured(uploadConfig) {
349
1762
  return !!(uploadConfig?.uploadUrl || uploadConfig?.onUploadImage);
@@ -357,7 +1770,6 @@ function uploadImage(view, uploadConfig) {
357
1770
  const input = document.createElement("input");
358
1771
  input.type = "file";
359
1772
  input.accept = "image/*";
360
- input.style.display = "none";
361
1773
  input.addEventListener("change", async () => {
362
1774
  if (!input.files || input.files.length === 0) return;
363
1775
  const file = input.files[0];
@@ -374,7 +1786,6 @@ function uploadImage(view, uploadConfig) {
374
1786
  }
375
1787
  input.remove();
376
1788
  });
377
- document.body.appendChild(input);
378
1789
  input.click();
379
1790
  }
380
1791
  /**
@@ -432,10 +1843,14 @@ function toggleWrap(view, openTag, closeTag) {
432
1843
  }
433
1844
  //#endregion
434
1845
  //#region src/components/Editor/codemirrorExtensions.ts
435
- /** 图片上传配置 facet */
436
- var uploadConfigFacet = _codemirror_state.Facet.define({ combine: (values) => values[values.length - 1] });
437
- /** 未配置上传时的提示回调 facet */
438
- var messageFacet = _codemirror_state.Facet.define({ combine: (values) => values[values.length - 1] });
1846
+ /**
1847
+ * 图片上传配置 facet。
1848
+ * 传入 getter 而非配置本身:扩展只在 mount 时创建一次,
1849
+ * 运行期通过 getter 读取最新配置,避免闭包过期。
1850
+ */
1851
+ var uploadConfigFacet = _codemirror_state.Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
1852
+ /** 未配置上传时的提示回调 facet(同为 getter 形式) */
1853
+ var messageFacet = _codemirror_state.Facet.define({ combine: (values) => values.length ? values[values.length - 1] : null });
439
1854
  /** 粘贴事件处理:拦截图片并上传 */
440
1855
  var pasteHandler = _codemirror_view.EditorView.domEventHandlers({ paste: (event, view) => {
441
1856
  const files = event.clipboardData?.files;
@@ -443,23 +1858,38 @@ var pasteHandler = _codemirror_view.EditorView.domEventHandlers({ paste: (event,
443
1858
  const imageFiles = Array.from(files).filter((f) => f.type.startsWith("image/"));
444
1859
  if (imageFiles.length === 0) return false;
445
1860
  event.preventDefault();
446
- const uploadConfig = view.state.facet(uploadConfigFacet);
447
- const showMessage = view.state.facet(messageFacet);
1861
+ const uploadConfig = view.state.facet(uploadConfigFacet)?.();
1862
+ const showMessage = view.state.facet(messageFacet)?.();
448
1863
  if (!isUploadConfigured(uploadConfig)) {
449
1864
  showMessage?.();
450
1865
  return true;
451
1866
  }
452
- const { from, to } = view.state.selection.main;
453
- let offset = 0;
454
- for (const file of imageFiles) uploadFileToServer(file, uploadConfig).then((url) => {
455
- if (url) {
456
- const insert = `![${file.name.replace(/\.[^.]+$/, "")}](${url})`;
457
- view.dispatch({ changes: {
458
- from: from + offset,
459
- to: to + offset,
460
- insert
461
- } });
462
- offset += insert.length;
1867
+ const config = uploadConfig;
1868
+ let isFirst = true;
1869
+ for (const file of imageFiles) uploadFileToServer(file, config).then((url) => {
1870
+ if (!url) return;
1871
+ const insert = `![${file.name.replace(/\.[^.]+$/, "")}](${url})`;
1872
+ const { state } = view;
1873
+ if (isFirst) {
1874
+ isFirst = false;
1875
+ const { from, to } = state.selection.main;
1876
+ view.dispatch({
1877
+ changes: {
1878
+ from,
1879
+ to,
1880
+ insert
1881
+ },
1882
+ selection: { anchor: from + insert.length }
1883
+ });
1884
+ } else {
1885
+ const end = state.doc.length;
1886
+ view.dispatch({
1887
+ changes: {
1888
+ from: end,
1889
+ insert: `\n${insert}`
1890
+ },
1891
+ selection: { anchor: end + insert.length + 1 }
1892
+ });
463
1893
  }
464
1894
  });
465
1895
  return true;
@@ -468,7 +1898,18 @@ var getCodeMirrorExtensions = (opts) => {
468
1898
  const extensions = [
469
1899
  (0, _codemirror_lang_markdown.markdown)(),
470
1900
  _codemirror_theme_one_dark.oneDark,
471
- _codemirror_view.keymap.of([..._codemirror_commands.defaultKeymap, _codemirror_commands.indentWithTab]),
1901
+ _codemirror_view.keymap.of([
1902
+ {
1903
+ key: "Tab",
1904
+ run: indentMarkdownList
1905
+ },
1906
+ {
1907
+ key: "Shift-Tab",
1908
+ run: dedentMarkdownList
1909
+ },
1910
+ ..._codemirror_commands.defaultKeymap,
1911
+ _codemirror_commands.indentWithTab
1912
+ ]),
472
1913
  _codemirror_view.EditorView.lineWrapping,
473
1914
  pasteHandler,
474
1915
  _codemirror_view.EditorView.baseTheme({
@@ -508,8 +1949,8 @@ var getCodeMirrorExtensions = (opts) => {
508
1949
  ];
509
1950
  extensions.push(containerWidgetPlugin);
510
1951
  if (opts?.onEditContainer) extensions.push(containerEditCallback.of(opts.onEditContainer));
511
- if (opts?.uploadConfig) extensions.push(uploadConfigFacet.of(opts.uploadConfig));
512
- if (opts?.onMessageNoUploadConfig) extensions.push(messageFacet.of(opts.onMessageNoUploadConfig));
1952
+ if (opts?.getUploadConfig) extensions.push(uploadConfigFacet.of(opts.getUploadConfig));
1953
+ if (opts?.getOnMessageNoUploadConfig) extensions.push(messageFacet.of(opts.getOnMessageNoUploadConfig));
513
1954
  return extensions;
514
1955
  };
515
1956
  //#endregion
@@ -517,17 +1958,29 @@ var getCodeMirrorExtensions = (opts) => {
517
1958
  function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer, uploadConfig, onMessageNoUploadConfig }) {
518
1959
  const editorRef = (0, react.useRef)(null);
519
1960
  const viewRef = (0, react.useRef)(null);
1961
+ const latestRef = (0, react.useRef)({
1962
+ onChange,
1963
+ onEditContainer,
1964
+ uploadConfig,
1965
+ onMessageNoUploadConfig
1966
+ });
1967
+ latestRef.current = {
1968
+ onChange,
1969
+ onEditContainer,
1970
+ uploadConfig,
1971
+ onMessageNoUploadConfig
1972
+ };
520
1973
  (0, react.useEffect)(() => {
521
1974
  if (!editorRef.current) return;
522
1975
  const extensions = [
523
1976
  codemirror.basicSetup,
524
1977
  ...getCodeMirrorExtensions({
525
- onEditContainer,
526
- uploadConfig,
527
- onMessageNoUploadConfig
1978
+ getUploadConfig: () => latestRef.current.uploadConfig,
1979
+ getOnMessageNoUploadConfig: () => latestRef.current.onMessageNoUploadConfig,
1980
+ onEditContainer: (view, container) => latestRef.current.onEditContainer?.(view, container)
528
1981
  }),
529
1982
  codemirror.EditorView.updateListener.of((update) => {
530
- if (update.docChanged) onChange(update.state.doc.toString());
1983
+ if (update.docChanged) latestRef.current.onChange(update.state.doc.toString());
531
1984
  })
532
1985
  ];
533
1986
  const state = _codemirror_state.EditorState.create({
@@ -538,18 +1991,26 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
538
1991
  state,
539
1992
  parent: editorRef.current
540
1993
  });
541
- if (onScrollReady && viewRef.current) onScrollReady(viewRef.current.scrollDOM);
542
- if (onViewReady) onViewReady(viewRef.current);
1994
+ if (viewRef.current) {
1995
+ onScrollReady?.(viewRef.current.scrollDOM);
1996
+ onViewReady?.(viewRef.current);
1997
+ }
543
1998
  return () => {
544
1999
  viewRef.current?.destroy();
2000
+ viewRef.current = null;
545
2001
  };
546
2002
  }, []);
547
2003
  (0, react.useEffect)(() => {
548
- if (viewRef.current && viewRef.current.state.doc.toString() !== value) viewRef.current.dispatch({ changes: {
549
- from: 0,
550
- to: viewRef.current.state.doc.length,
551
- insert: value
552
- } });
2004
+ const view = viewRef.current;
2005
+ if (view && view.state.doc.toString() !== value) view.dispatch({
2006
+ changes: {
2007
+ from: 0,
2008
+ to: view.state.doc.length,
2009
+ insert: value
2010
+ },
2011
+ effects: view.scrollSnapshot(),
2012
+ scrollIntoView: false
2013
+ });
553
2014
  }, [value]);
554
2015
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
555
2016
  ref: editorRef,
@@ -558,23 +2019,25 @@ function Editor({ value, onChange, onScrollReady, onViewReady, onEditContainer,
558
2019
  }
559
2020
  //#endregion
560
2021
  //#region src/components/Preview/index.tsx
561
- var Preview = (0, react.forwardRef)(({ content, previewOptions }, ref) => {
2022
+ var Preview = (0, react.forwardRef)(({ content, previewOptions, languages }, ref) => {
562
2023
  (0, react.useEffect)(() => {
563
2024
  (0, remons_render_markdown.initHighlighter)({
564
2025
  ...remons_render_markdown.languagesCommon,
565
- ...previewOptions?.languages ? previewOptions?.languages : {}
2026
+ ...languages ?? {}
566
2027
  });
567
- }, [previewOptions?.languages]);
2028
+ }, [languages]);
2029
+ const { languages: _ignored, ...restOptions } = previewOptions ?? {};
568
2030
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
569
2031
  ref,
570
2032
  className: "preview",
571
2033
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(remons_render_markdown.default, {
572
2034
  content,
573
- ...previewOptions
2035
+ ...restOptions
574
2036
  })
575
2037
  });
576
2038
  });
577
2039
  Preview.displayName = "Preview";
2040
+ var Preview_default = (0, react.memo)(Preview);
578
2041
  //#endregion
579
2042
  //#region src/components/Panel/SplitPanels.tsx
580
2043
  var { Panel } = antd.Splitter;
@@ -590,13 +2053,53 @@ function SplitPanels({ leftPanel, rightPanel }) {
590
2053
  });
591
2054
  }
592
2055
  //#endregion
2056
+ //#region src/components/Icon/config.ts
2057
+ var scriptUrl = "https://at.alicdn.com/t/c/font_5241307_xoojyr52dqn.js";
2058
+ var IconComp = null;
2059
+ /**
2060
+ * 配置 iconfont 脚本地址(宿主在应用入口调用),需在首次渲染前设置;
2061
+ * 变更后重置内部缓存,下次渲染时以新地址重建图标组件。
2062
+ */
2063
+ function setIconfontScriptUrl(url) {
2064
+ if (url === scriptUrl) return;
2065
+ scriptUrl = url;
2066
+ IconComp = null;
2067
+ }
2068
+ /** 读取当前 iconfont 脚本地址 */
2069
+ function getIconfontScriptUrl() {
2070
+ return scriptUrl;
2071
+ }
2072
+ /** 懒创建图标组件:首次渲染时才注入 iconfont 脚本,避免模块层副作用 */
2073
+ function getIconComponent() {
2074
+ if (!IconComp) IconComp = (0, _ant_design_icons.createFromIconfontCN)({ scriptUrl });
2075
+ return IconComp;
2076
+ }
2077
+ //#endregion
2078
+ //#region src/components/Icon/index.tsx
2079
+ function IconComponent(type, className) {
2080
+ const Icon = getIconComponent();
2081
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
2082
+ type: `icon-${type}`,
2083
+ className
2084
+ });
2085
+ }
2086
+ //#endregion
593
2087
  //#region src/components/Toolbar/config.ts
2088
+ function Quote() {
2089
+ return IconComponent("quote");
2090
+ }
2091
+ function InlineCode() {
2092
+ return IconComponent("inlinecode");
2093
+ }
2094
+ /** 未配置图片上传时的提示文案 */
2095
+ var UPLOAD_CONFIG_MISSING_MESSAGE = "请先配置图片上传功能";
594
2096
  /**
595
2097
  * 创建工具栏配置
596
2098
  * @param options - 配置选项
597
2099
  */
598
2100
  function createToolbarConfig(options) {
599
- const hasUploadConfig = isUploadConfigured(options);
2101
+ const hasUploadConfig = isUploadConfigured(options?.upload);
2102
+ const notify = options?.notify;
600
2103
  return [
601
2104
  {
602
2105
  id: "heading",
@@ -605,39 +2108,33 @@ function createToolbarConfig(options) {
605
2108
  children: [
606
2109
  {
607
2110
  id: "heading1",
608
- label: "标题 1",
609
- icon: _ant_design_icons.FontSizeOutlined,
610
- handler: (v) => insertAtLineStart(v, "# ")
2111
+ label: "H1",
2112
+ handler: (v) => toggleHeading(v, 1)
611
2113
  },
612
2114
  {
613
2115
  id: "heading2",
614
- label: "标题 2",
615
- icon: _ant_design_icons.FontSizeOutlined,
616
- handler: (v) => insertAtLineStart(v, "## ")
2116
+ label: "H2",
2117
+ handler: (v) => toggleHeading(v, 2)
617
2118
  },
618
2119
  {
619
2120
  id: "heading3",
620
- label: "标题 3",
621
- icon: _ant_design_icons.FontSizeOutlined,
622
- handler: (v) => insertAtLineStart(v, "### ")
2121
+ label: "H3",
2122
+ handler: (v) => toggleHeading(v, 3)
623
2123
  },
624
2124
  {
625
2125
  id: "heading4",
626
- label: "标题 4",
627
- icon: _ant_design_icons.FontSizeOutlined,
628
- handler: (v) => insertAtLineStart(v, "#### ")
2126
+ label: "H4",
2127
+ handler: (v) => toggleHeading(v, 4)
629
2128
  },
630
2129
  {
631
2130
  id: "heading5",
632
- label: "标题 5",
633
- icon: _ant_design_icons.FontSizeOutlined,
634
- handler: (v) => insertAtLineStart(v, "##### ")
2131
+ label: "H5",
2132
+ handler: (v) => toggleHeading(v, 5)
635
2133
  },
636
2134
  {
637
2135
  id: "heading6",
638
- label: "标题 6",
639
- icon: _ant_design_icons.FontSizeOutlined,
640
- handler: (v) => insertAtLineStart(v, "###### ")
2136
+ label: "H6",
2137
+ handler: (v) => toggleHeading(v, 6)
641
2138
  }
642
2139
  ]
643
2140
  },
@@ -646,38 +2143,44 @@ function createToolbarConfig(options) {
646
2143
  id: "bold",
647
2144
  label: "加粗",
648
2145
  icon: _ant_design_icons.BoldOutlined,
649
- handler: (v) => wrapSelection(v, "**", "**")
2146
+ handler: (v) => toggleWrap(v, "**", "**")
650
2147
  },
651
2148
  {
652
2149
  id: "italic",
653
2150
  label: "斜体",
654
2151
  icon: _ant_design_icons.ItalicOutlined,
655
- handler: (v) => wrapSelection(v, "*", "*")
2152
+ handler: (v) => toggleWrap(v, "*", "*")
656
2153
  },
657
2154
  {
658
2155
  id: "strikethrough",
659
2156
  label: "删除线",
660
2157
  icon: _ant_design_icons.StrikethroughOutlined,
661
- handler: (v) => wrapSelection(v, "~~", "~~")
2158
+ handler: (v) => toggleWrap(v, "~~", "~~")
662
2159
  },
663
2160
  {
664
2161
  id: "underline",
665
2162
  label: "下划线",
666
2163
  icon: _ant_design_icons.UnderlineOutlined,
667
- handler: (v) => wrapSelection(v, "<u>", "</u>")
2164
+ handler: (v) => toggleWrap(v, "<u>", "</u>")
668
2165
  },
669
2166
  { separatorBefore: true },
670
2167
  {
671
2168
  id: "ul",
672
2169
  label: "无序列表",
673
2170
  icon: _ant_design_icons.UnorderedListOutlined,
674
- handler: (v) => insertAtLineStart(v, "- ")
2171
+ handler: (v) => toggleLinePrefix(v, /^(\s*)-(?!\s*\[)\s/, "- ")
675
2172
  },
676
2173
  {
677
2174
  id: "ol",
678
2175
  label: "有序列表",
679
2176
  icon: _ant_design_icons.OrderedListOutlined,
680
- handler: (v) => insertAtLineStart(v, "1. ")
2177
+ handler: (v) => toggleLinePrefix(v, /^(\s*)\d+\.\s/, "1. ")
2178
+ },
2179
+ {
2180
+ id: "checkbox",
2181
+ label: "待办",
2182
+ icon: _ant_design_icons.CheckSquareOutlined,
2183
+ handler: (v) => toggleTaskList(v)
681
2184
  },
682
2185
  { separatorBefore: true },
683
2186
  {
@@ -688,19 +2191,15 @@ function createToolbarConfig(options) {
688
2191
  },
689
2192
  {
690
2193
  id: "image",
691
- label: hasUploadConfig ? "图片" : "请配置图片上传地址",
2194
+ label: "图片",
692
2195
  icon: _ant_design_icons.PictureOutlined,
693
- disabled: !hasUploadConfig,
694
- handler: hasUploadConfig ? (v) => uploadImage(v, {
695
- uploadUrl: options?.uploadUrl,
696
- onUploadImage: options?.onUploadImage
697
- }) : void 0
2196
+ handler: hasUploadConfig && options?.upload ? (v) => uploadImage(v, options.upload) : () => notify?.("warning", UPLOAD_CONFIG_MISSING_MESSAGE)
698
2197
  },
699
2198
  { separatorBefore: true },
700
2199
  {
701
2200
  id: "code",
702
2201
  label: "行内代码",
703
- icon: _ant_design_icons.FieldStringOutlined,
2202
+ icon: InlineCode,
704
2203
  handler: (v) => wrapSelection(v, "`", "`")
705
2204
  },
706
2205
  {
@@ -721,7 +2220,7 @@ function createToolbarConfig(options) {
721
2220
  {
722
2221
  id: "quote",
723
2222
  label: "引用",
724
- icon: _ant_design_icons.BlockOutlined,
2223
+ icon: Quote,
725
2224
  handler: (v) => insertAtLineStart(v, "> ")
726
2225
  },
727
2226
  {
@@ -741,11 +2240,14 @@ function createToolbarConfig(options) {
741
2240
  //#endregion
742
2241
  //#region src/components/Toolbar/hooks/useToolbar.ts
743
2242
  function useToolbar(editorView, options) {
744
- const { extraItems, uploadConfig } = options || {};
2243
+ const { extraItems, uploadConfig, notify } = options || {};
745
2244
  return {
746
2245
  config: (0, react.useMemo)(() => {
747
- return createToolbarConfig(uploadConfig);
748
- }, [uploadConfig]),
2246
+ return createToolbarConfig({
2247
+ upload: uploadConfig,
2248
+ notify
2249
+ });
2250
+ }, [uploadConfig, notify]),
749
2251
  extraItemsConfig: (0, react.useMemo)(() => {
750
2252
  return extraItems || [];
751
2253
  }, [extraItems]),
@@ -765,37 +2267,52 @@ function useToolbar(editorView, options) {
765
2267
  }
766
2268
  //#endregion
767
2269
  //#region src/components/Toolbar/renderers/ToolbarItemRenderer.tsx
2270
+ /**
2271
+ * 渲染图标:统一接受组件类型;兼容传入 ReactNode 的旧用法。
2272
+ * 组件类型不仅指函数/class,也包括 forwardRef、memo 包装出的对象
2273
+ * (@ant-design/icons 即为 forwardRef,不能当作普通 child 直接渲染)。
2274
+ */
2275
+ var REACT_FORWARD_REF = Symbol.for("react.forward_ref");
2276
+ var REACT_MEMO = Symbol.for("react.memo");
2277
+ function isComponentType(icon) {
2278
+ if (typeof icon === "function") return true;
2279
+ if (typeof icon === "object" && icon !== null) {
2280
+ const t = icon.$$typeof;
2281
+ return t === REACT_FORWARD_REF || t === REACT_MEMO;
2282
+ }
2283
+ return false;
2284
+ }
2285
+ function renderIcon(icon) {
2286
+ if (isComponentType(icon)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(icon, {});
2287
+ return icon;
2288
+ }
768
2289
  function ToolbarItemRenderer({ item, onClick }) {
769
- const Icon = item.icon;
770
2290
  if (item.children && item.children.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [item.separatorBefore && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "toolbar-separator" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
771
2291
  className: "toolbar-group",
772
2292
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Tooltip, {
773
2293
  title: item.label,
774
2294
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Dropdown, {
775
- menu: { items: item.children.map((child) => ({
776
- type: "item",
777
- key: child.id ?? "",
778
- label: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
779
- onClick: () => onClick(child),
780
- children: [
781
- child.icon && (() => {
782
- const ChildIcon = child.icon;
783
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChildIcon, {});
784
- })(),
2295
+ menu: {
2296
+ items: item.children.map((child) => ({
2297
+ key: child.id ?? "",
2298
+ label: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
2299
+ child.icon && renderIcon(child.icon),
785
2300
  " ",
786
2301
  child.label
787
- ]
788
- })
789
- })) },
2302
+ ] }),
2303
+ disabled: child.disabled
2304
+ })),
2305
+ onClick: ({ key }) => {
2306
+ const child = item.children?.find((c) => c.id === key);
2307
+ if (child && !child.disabled) onClick(child);
2308
+ }
2309
+ },
790
2310
  placement: "bottomLeft",
791
2311
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(antd.Button, {
792
2312
  className: "toolbar-button",
793
2313
  type: "text",
794
2314
  size: "small",
795
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ant_design_icons.DownOutlined, { style: {
796
- marginLeft: 2,
797
- fontSize: 10
798
- } })]
2315
+ children: [item.icon && renderIcon(item.icon), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ant_design_icons.DownOutlined, { style: { fontSize: 10 } })]
799
2316
  })
800
2317
  })
801
2318
  })
@@ -812,7 +2329,7 @@ function ToolbarItemRenderer({ item, onClick }) {
812
2329
  size: "small",
813
2330
  disabled: isDisabled,
814
2331
  onClick: () => !isDisabled && onClick(item),
815
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {})
2332
+ children: item.icon && renderIcon(item.icon)
816
2333
  })
817
2334
  })
818
2335
  })] });
@@ -830,125 +2347,81 @@ var index_module_default = {
830
2347
  var MAX_ROW = 8;
831
2348
  var MAX_COL = 8;
832
2349
  function TablePicker({ onSelect }) {
833
- const [hoverSize, setHoverSize] = (0, react.useState)({
834
- row: 0,
835
- col: 0
2350
+ /** 当前高亮区域(rows x cols),渲染唯一依赖此状态 */
2351
+ const [size, setSize] = (0, react.useState)({
2352
+ rows: 0,
2353
+ cols: 0
836
2354
  });
837
- const [confirmedSize, setConfirmedSize] = (0, react.useState)({
838
- row: 0,
839
- col: 0
840
- });
841
- const maxColRef = (0, react.useRef)(0);
2355
+ /** 鼠标回撤(向上/向左)后需要重置列跟踪,prevRow 与 pending 成对出现,仅事件处理内使用 */
842
2356
  const prevRowRef = (0, react.useRef)(0);
843
- const timerIdRef = (0, react.useRef)(null);
844
- const refreshTimerRef = (0, react.useRef)(null);
845
- const commitRef = (0, react.useRef)(null);
846
- const clearTimer = (0, react.useCallback)(() => {
847
- if (timerIdRef.current) {
848
- clearTimeout(timerIdRef.current);
849
- timerIdRef.current = null;
850
- }
851
- }, []);
2357
+ const pendingColsRef = (0, react.useRef)(0);
2358
+ const flashTimerRef = (0, react.useRef)(null);
852
2359
  const clearFlash = (0, react.useCallback)(() => {
853
- if (refreshTimerRef.current) {
854
- clearInterval(refreshTimerRef.current);
855
- refreshTimerRef.current = null;
2360
+ if (flashTimerRef.current) {
2361
+ clearInterval(flashTimerRef.current);
2362
+ flashTimerRef.current = null;
856
2363
  }
857
2364
  }, []);
858
2365
  (0, react.useEffect)(() => () => {
859
- if (timerIdRef.current) clearTimeout(timerIdRef.current);
860
- if (refreshTimerRef.current) clearInterval(refreshTimerRef.current);
861
- }, []);
2366
+ clearFlash();
2367
+ }, [clearFlash]);
862
2368
  /**
863
2369
  * 扩展选中区域至 (col, row)
864
2370
  */
865
2371
  function extend(col, row) {
866
- if (row < prevRowRef.current || col < maxColRef.current) maxColRef.current = 0;
867
- if (col > maxColRef.current) maxColRef.current = col;
868
- setHoverSize({
869
- row,
870
- col
871
- });
872
- setConfirmedSize({
873
- row,
874
- col: maxColRef.current
2372
+ if (row < prevRowRef.current || col < pendingColsRef.current) pendingColsRef.current = 0;
2373
+ if (col > pendingColsRef.current) pendingColsRef.current = col;
2374
+ const cols = pendingColsRef.current;
2375
+ setSize({
2376
+ rows: row,
2377
+ cols
875
2378
  });
876
- if (row === 1) commitRef.current = {
877
- cols: maxColRef.current,
878
- rows: 1
879
- };
2379
+ prevRowRef.current = row;
880
2380
  }
881
2381
  /**
882
- * 跳跃动画效果
2382
+ * 跳跃动画效果:逐行推进高亮,结束后落到 (col, limit)
883
2383
  */
884
- function flash(col, dir, limit, finalCallback) {
2384
+ function flash(col, dir, limit) {
2385
+ clearFlash();
885
2386
  let current = dir === 1 ? 1 : limit;
886
2387
  const step = dir === 1 ? 1 : -1;
887
- refreshTimerRef.current = setInterval(() => {
888
- setHoverSize({
889
- row: current,
890
- col
891
- });
892
- if (current > confirmedSize.row || dir === -1) maxColRef.current = Math.min(MAX_COL, col);
893
- current += step;
2388
+ flashTimerRef.current = setInterval(() => {
894
2389
  if (dir === 1 && current > limit || dir === -1 && current < 1) {
895
- clearInterval(refreshTimerRef.current);
896
- refreshTimerRef.current = null;
2390
+ clearFlash();
897
2391
  const finalRow = current - step;
898
- setHoverSize({
899
- row: finalRow,
900
- col
2392
+ setSize({
2393
+ rows: finalRow,
2394
+ cols: col
901
2395
  });
902
- finalCallback(col, finalRow);
2396
+ return;
903
2397
  }
2398
+ setSize({
2399
+ rows: current,
2400
+ cols: col
2401
+ });
2402
+ current += step;
904
2403
  }, 50);
905
2404
  }
906
2405
  /**
907
2406
  * 核心逻辑:鼠标进入格子
908
2407
  */
909
- function onCellEnterCheck(index) {
910
- clearTimer();
2408
+ function onCellEnter(index) {
911
2409
  clearFlash();
912
2410
  const row = Math.floor(index / MAX_COL) + 1;
913
2411
  const col = index % MAX_COL + 1;
914
- const prevRow = prevRowRef.current;
915
- const isJump = Math.abs(row - prevRow) > 1;
916
- const isDown = row > prevRow;
2412
+ const maxCol = pendingColsRef.current;
2413
+ const isJump = Math.abs(row - prevRowRef.current) > 1;
917
2414
  prevRowRef.current = row;
918
2415
  if (!isJump) extend(col, row);
919
- else if (isDown) {
920
- if (col > maxColRef.current || maxColRef.current >= MAX_COL) flash(col, 1, Math.min(row, MAX_ROW), (c, r) => {
921
- setConfirmedSize({
922
- row: r,
923
- col: c
924
- });
925
- });
926
- else extend(col, row);
2416
+ else if (row > 0 && (col > maxCol || maxCol >= MAX_COL)) {
2417
+ pendingColsRef.current = Math.min(MAX_COL, col);
2418
+ flash(Math.min(MAX_COL, col), 1, Math.min(row, MAX_ROW));
927
2419
  } else {
928
- maxColRef.current = 0;
929
- flash(col, -1, row, (c, r) => {
930
- setConfirmedSize({
931
- row: r,
932
- col: c
933
- });
934
- if (r === 1) {
935
- commitRef.current = {
936
- cols: Math.min(MAX_COL, col),
937
- rows: 1
938
- };
939
- setConfirmedSize({
940
- row: 1,
941
- col: Math.min(MAX_COL, col)
942
- });
943
- }
944
- });
2420
+ pendingColsRef.current = 0;
2421
+ extend(col, row);
945
2422
  }
946
2423
  }
947
2424
  function onMouseDown() {
948
- const size = commitRef.current || {
949
- cols: maxColRef.current,
950
- rows: confirmedSize.row
951
- };
952
2425
  if (size.rows > 0 && size.cols > 0) onSelect(size);
953
2426
  }
954
2427
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -960,18 +2433,18 @@ function TablePicker({ onSelect }) {
960
2433
  children: Array.from({ length: 64 }).map((_, i) => {
961
2434
  const row = Math.floor(i / MAX_COL) + 1;
962
2435
  const col = i % MAX_COL + 1;
963
- const isSelected = row <= hoverSize.row && col <= maxColRef.current;
2436
+ const isSelected = row <= size.rows && col <= size.cols;
964
2437
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
965
2438
  className: `${index_module_default.cell} ${isSelected ? index_module_default.cellActive : ""}`,
966
- onMouseEnter: () => onCellEnterCheck(i)
2439
+ onMouseEnter: () => onCellEnter(i)
967
2440
  }, i);
968
2441
  })
969
2442
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
970
2443
  className: index_module_default.label,
971
2444
  children: [
972
- hoverSize.row,
2445
+ size.rows,
973
2446
  " x ",
974
- maxColRef.current || 1
2447
+ size.cols || 1
975
2448
  ]
976
2449
  })]
977
2450
  });
@@ -979,8 +2452,10 @@ function TablePicker({ onSelect }) {
979
2452
  //#endregion
980
2453
  //#region src/components/Toolbar/renderers/TablePicker/TableDropdown.tsx
981
2454
  function TableDropdown({ editorView }) {
982
- const [open, setOpen] = react.default.useState(false);
983
- const openCountRef = (0, react.useRef)(0);
2455
+ const [open, setOpen] = (0, react.useState)(false);
2456
+ const handleOpenChange = (0, react.useCallback)((next) => {
2457
+ setOpen(next);
2458
+ }, []);
984
2459
  const handleTableSelect = (0, react.useCallback)((rows, cols) => {
985
2460
  if (!editorView || rows <= 0 || cols <= 0) return;
986
2461
  editorView.focus();
@@ -997,18 +2472,15 @@ function TableDropdown({ editorView }) {
997
2472
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Dropdown, {
998
2473
  trigger: ["click"],
999
2474
  open,
1000
- onOpenChange: setOpen,
1001
- popupRender: () => {
1002
- openCountRef.current++;
1003
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1004
- style: { padding: 4 },
1005
- onClick: (e) => e.stopPropagation(),
1006
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TablePicker, { onSelect: (size) => {
1007
- handleTableSelect(size.rows, size.cols);
1008
- setOpen(false);
1009
- } }, openCountRef.current)
1010
- });
1011
- },
2475
+ onOpenChange: handleOpenChange,
2476
+ destroyOnHidden: true,
2477
+ popupRender: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2478
+ style: { padding: 4 },
2479
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TablePicker, { onSelect: (size) => {
2480
+ handleTableSelect(size.rows, size.cols);
2481
+ setOpen(false);
2482
+ } })
2483
+ }),
1012
2484
  placement: "bottomLeft",
1013
2485
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Button, {
1014
2486
  className: "toolbar-button",
@@ -1021,10 +2493,11 @@ function TableDropdown({ editorView }) {
1021
2493
  }
1022
2494
  //#endregion
1023
2495
  //#region src/components/Toolbar/index.tsx
1024
- function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig }) {
2496
+ function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems, uploadConfig, notify }) {
1025
2497
  const { config, extraItemsConfig, handleClick } = useToolbar(editorView, {
1026
2498
  extraItems,
1027
- uploadConfig
2499
+ uploadConfig,
2500
+ notify
1028
2501
  });
1029
2502
  const renderFullscreen = (0, react.useCallback)(() => {
1030
2503
  if (!onToggleFullscreen) return null;
@@ -1064,8 +2537,305 @@ function Toolbar({ editorView, fullscreen = true, onToggleFullscreen, extraItems
1064
2537
  ]
1065
2538
  });
1066
2539
  }
2540
+ var Toolbar_default = (0, react.memo)(Toolbar);
1067
2541
  //#endregion
1068
2542
  //#region src/components/Dialog/EditDialog.tsx
2543
+ var import_dayjs_min = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
2544
+ (function(t, e) {
2545
+ "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();
2546
+ })(exports, (function() {
2547
+ "use strict";
2548
+ 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 = {
2549
+ name: "en",
2550
+ weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
2551
+ months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
2552
+ ordinal: function(t) {
2553
+ var e = [
2554
+ "th",
2555
+ "st",
2556
+ "nd",
2557
+ "rd"
2558
+ ], n = t % 100;
2559
+ return "[" + t + (e[(n - 20) % 10] || e[n] || e[0]) + "]";
2560
+ }
2561
+ }, m = function(t, e, n) {
2562
+ var r = String(t);
2563
+ return !r || r.length >= e ? t : "" + Array(e + 1 - r.length).join(n) + t;
2564
+ }, v = {
2565
+ s: m,
2566
+ z: function(t) {
2567
+ var e = -t.utcOffset(), n = Math.abs(e), r = Math.floor(n / 60), i = n % 60;
2568
+ return (e <= 0 ? "+" : "-") + m(r, 2, "0") + ":" + m(i, 2, "0");
2569
+ },
2570
+ m: function t(e, n) {
2571
+ if (e.date() < n.date()) return -t(n, e);
2572
+ 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);
2573
+ return +(-(r + (n - i) / (s ? i - u : u - i)) || 0);
2574
+ },
2575
+ a: function(t) {
2576
+ return t < 0 ? Math.ceil(t) || 0 : Math.floor(t);
2577
+ },
2578
+ p: function(t) {
2579
+ return {
2580
+ M: c,
2581
+ y: h,
2582
+ w: o,
2583
+ d: a,
2584
+ D: d,
2585
+ h: u,
2586
+ m: s,
2587
+ s: i,
2588
+ ms: r,
2589
+ Q: f
2590
+ }[t] || String(t || "").toLowerCase().replace(/s$/, "");
2591
+ },
2592
+ u: function(t) {
2593
+ return void 0 === t;
2594
+ }
2595
+ }, g = "en", D = {};
2596
+ D[g] = M;
2597
+ var p = "$isDayjsObject", S = function(t) {
2598
+ return t instanceof _ || !(!t || !t[p]);
2599
+ }, w = function t(e, n, r) {
2600
+ var i;
2601
+ if (!e) return g;
2602
+ if ("string" == typeof e) {
2603
+ var s = e.toLowerCase();
2604
+ D[s] && (i = s), n && (D[s] = n, i = s);
2605
+ var u = e.split("-");
2606
+ if (!i && u.length > 1) return t(u[0]);
2607
+ } else {
2608
+ var a = e.name;
2609
+ D[a] = e, i = a;
2610
+ }
2611
+ return !r && i && (g = i), i || !r && g;
2612
+ }, O = function(t, e) {
2613
+ if (S(t)) return t.clone();
2614
+ var n = "object" == typeof e ? e : {};
2615
+ return n.date = t, n.args = arguments, new _(n);
2616
+ }, b = v;
2617
+ b.l = w, b.i = S, b.w = function(t, e) {
2618
+ return O(t, {
2619
+ locale: e.$L,
2620
+ utc: e.$u,
2621
+ x: e.$x,
2622
+ $offset: e.$offset
2623
+ });
2624
+ };
2625
+ var _ = function() {
2626
+ function M(t) {
2627
+ this.$L = w(t.locale, null, !0), this.parse(t), this.$x = this.$x || t.x || {}, this[p] = !0;
2628
+ }
2629
+ var m = M.prototype;
2630
+ return m.parse = function(t) {
2631
+ this.$d = function(t) {
2632
+ var e = t.date, n = t.utc;
2633
+ if (null === e) return /* @__PURE__ */ new Date(NaN);
2634
+ if (b.u(e)) return /* @__PURE__ */ new Date();
2635
+ if (e instanceof Date) return new Date(e);
2636
+ if ("string" == typeof e && !/Z$/i.test(e)) {
2637
+ var r = e.match($);
2638
+ if (r) {
2639
+ var i = r[2] - 1 || 0, s = (r[7] || "0").substring(0, 3);
2640
+ 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);
2641
+ }
2642
+ }
2643
+ return new Date(e);
2644
+ }(t), this.init();
2645
+ }, m.init = function() {
2646
+ var t = this.$d;
2647
+ 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();
2648
+ }, m.$utils = function() {
2649
+ return b;
2650
+ }, m.isValid = function() {
2651
+ return !(this.$d.toString() === l);
2652
+ }, m.isSame = function(t, e) {
2653
+ var n = O(t);
2654
+ return this.startOf(e) <= n && n <= this.endOf(e);
2655
+ }, m.isAfter = function(t, e) {
2656
+ return O(t) < this.startOf(e);
2657
+ }, m.isBefore = function(t, e) {
2658
+ return this.endOf(e) < O(t);
2659
+ }, m.$g = function(t, e, n) {
2660
+ return b.u(t) ? this[e] : this.set(n, t);
2661
+ }, m.unix = function() {
2662
+ return Math.floor(this.valueOf() / 1e3);
2663
+ }, m.valueOf = function() {
2664
+ return this.$d.getTime();
2665
+ }, m.startOf = function(t, e) {
2666
+ var n = this, r = !!b.u(e) || e, f = b.p(t), l = function(t, e) {
2667
+ var i = b.w(n.$u ? Date.UTC(n.$y, e, t) : new Date(n.$y, e, t), n);
2668
+ return r ? i : i.endOf(a);
2669
+ }, $ = function(t, e) {
2670
+ return b.w(n.toDate()[t].apply(n.toDate("s"), (r ? [
2671
+ 0,
2672
+ 0,
2673
+ 0,
2674
+ 0
2675
+ ] : [
2676
+ 23,
2677
+ 59,
2678
+ 59,
2679
+ 999
2680
+ ]).slice(e)), n);
2681
+ }, y = this.$W, M = this.$M, m = this.$D, v = "set" + (this.$u ? "UTC" : "");
2682
+ switch (f) {
2683
+ case h: return r ? l(1, 0) : l(31, 11);
2684
+ case c: return r ? l(1, M) : l(0, M + 1);
2685
+ case o:
2686
+ var g = this.$locale().weekStart || 0, D = (y < g ? y + 7 : y) - g;
2687
+ return l(r ? m - D : m + (6 - D), M);
2688
+ case a:
2689
+ case d: return $(v + "Hours", 0);
2690
+ case u: return $(v + "Minutes", 1);
2691
+ case s: return $(v + "Seconds", 2);
2692
+ case i: return $(v + "Milliseconds", 3);
2693
+ default: return this.clone();
2694
+ }
2695
+ }, m.endOf = function(t) {
2696
+ return this.startOf(t, !1);
2697
+ }, m.$set = function(t, e) {
2698
+ 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;
2699
+ if (o === c || o === h) {
2700
+ var y = this.clone().set(d, 1);
2701
+ y.$d[l]($), y.init(), this.$d = y.set(d, Math.min(this.$D, y.daysInMonth())).$d;
2702
+ } else l && this.$d[l]($);
2703
+ return this.init(), this;
2704
+ }, m.set = function(t, e) {
2705
+ return this.clone().$set(t, e);
2706
+ }, m.get = function(t) {
2707
+ return this[b.p(t)]();
2708
+ }, m.add = function(r, f) {
2709
+ var d, l = this;
2710
+ r = Number(r);
2711
+ var $ = b.p(f), y = function(t) {
2712
+ var e = O(l);
2713
+ return b.w(e.date(e.date() + Math.round(t * r)), l);
2714
+ };
2715
+ if ($ === c) return this.set(c, this.$M + r);
2716
+ if ($ === h) return this.set(h, this.$y + r);
2717
+ if ($ === a) return y(1);
2718
+ if ($ === o) return y(7);
2719
+ var M = (d = {}, d[s] = e, d[u] = n, d[i] = t, d)[$] || 1, m = this.$d.getTime() + r * M;
2720
+ return b.w(m, this);
2721
+ }, m.subtract = function(t, e) {
2722
+ return this.add(-1 * t, e);
2723
+ }, m.format = function(t) {
2724
+ var e = this, n = this.$locale();
2725
+ if (!this.isValid()) return n.invalidDate || l;
2726
+ 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) {
2727
+ return t && (t[n] || t(e, r)) || i[n].slice(0, s);
2728
+ }, d = function(t) {
2729
+ return b.s(s % 12 || 12, t, "0");
2730
+ }, $ = f || function(t, e, n) {
2731
+ var r = t < 12 ? "AM" : "PM";
2732
+ return n ? r.toLowerCase() : r;
2733
+ };
2734
+ return r.replace(y, (function(t, r) {
2735
+ return r || function(t) {
2736
+ switch (t) {
2737
+ case "YY": return String(e.$y).slice(-2);
2738
+ case "YYYY": return b.s(e.$y, 4, "0");
2739
+ case "M": return a + 1;
2740
+ case "MM": return b.s(a + 1, 2, "0");
2741
+ case "MMM": return h(n.monthsShort, a, c, 3);
2742
+ case "MMMM": return h(c, a);
2743
+ case "D": return e.$D;
2744
+ case "DD": return b.s(e.$D, 2, "0");
2745
+ case "d": return String(e.$W);
2746
+ case "dd": return h(n.weekdaysMin, e.$W, o, 2);
2747
+ case "ddd": return h(n.weekdaysShort, e.$W, o, 3);
2748
+ case "dddd": return o[e.$W];
2749
+ case "H": return String(s);
2750
+ case "HH": return b.s(s, 2, "0");
2751
+ case "h": return d(1);
2752
+ case "hh": return d(2);
2753
+ case "a": return $(s, u, !0);
2754
+ case "A": return $(s, u, !1);
2755
+ case "m": return String(u);
2756
+ case "mm": return b.s(u, 2, "0");
2757
+ case "s": return String(e.$s);
2758
+ case "ss": return b.s(e.$s, 2, "0");
2759
+ case "SSS": return b.s(e.$ms, 3, "0");
2760
+ case "Z": return i;
2761
+ }
2762
+ return null;
2763
+ }(t) || i.replace(":", "");
2764
+ }));
2765
+ }, m.utcOffset = function() {
2766
+ return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
2767
+ }, m.diff = function(r, d, l) {
2768
+ var $, y = this, M = b.p(d), m = O(r), v = (m.utcOffset() - this.utcOffset()) * e, g = this - m, D = function() {
2769
+ return b.m(y, m);
2770
+ };
2771
+ switch (M) {
2772
+ case h:
2773
+ $ = D() / 12;
2774
+ break;
2775
+ case c:
2776
+ $ = D();
2777
+ break;
2778
+ case f:
2779
+ $ = D() / 3;
2780
+ break;
2781
+ case o:
2782
+ $ = (g - v) / 6048e5;
2783
+ break;
2784
+ case a:
2785
+ $ = (g - v) / 864e5;
2786
+ break;
2787
+ case u:
2788
+ $ = g / n;
2789
+ break;
2790
+ case s:
2791
+ $ = g / e;
2792
+ break;
2793
+ case i:
2794
+ $ = g / t;
2795
+ break;
2796
+ default: $ = g;
2797
+ }
2798
+ return l ? $ : b.a($);
2799
+ }, m.daysInMonth = function() {
2800
+ return this.endOf(c).$D;
2801
+ }, m.$locale = function() {
2802
+ return D[this.$L];
2803
+ }, m.locale = function(t, e) {
2804
+ if (!t) return this.$L;
2805
+ var n = this.clone(), r = w(t, e, !0);
2806
+ return r && (n.$L = r), n;
2807
+ }, m.clone = function() {
2808
+ return b.w(this.$d, this);
2809
+ }, m.toDate = function() {
2810
+ return new Date(this.valueOf());
2811
+ }, m.toJSON = function() {
2812
+ return this.isValid() ? this.toISOString() : null;
2813
+ }, m.toISOString = function() {
2814
+ return this.$d.toISOString();
2815
+ }, m.toString = function() {
2816
+ return this.$d.toUTCString();
2817
+ }, M;
2818
+ }(), Y = _.prototype;
2819
+ return O.prototype = Y, [
2820
+ ["$ms", r],
2821
+ ["$s", i],
2822
+ ["$m", s],
2823
+ ["$H", u],
2824
+ ["$W", a],
2825
+ ["$M", c],
2826
+ ["$y", h],
2827
+ ["$D", d]
2828
+ ].forEach((function(t) {
2829
+ Y[t[1]] = function(e) {
2830
+ return this.$g(e, t[0], t[1]);
2831
+ };
2832
+ })), O.extend = function(t, e) {
2833
+ return t.$i || (t(e, _, O), t.$i = !0), O;
2834
+ }, O.locale = w, O.isDayjs = S, O.unix = function(t) {
2835
+ return O(1e3 * t);
2836
+ }, O.en = D[g], O.Ls = D, O.p = {}, O;
2837
+ }));
2838
+ })))(), 1);
1069
2839
  /**
1070
2840
  * 组件类型到 antd 表单组件的映射
1071
2841
  */
@@ -1082,7 +2852,7 @@ var FormComponents = {
1082
2852
  dateRange: antd.DatePicker.RangePicker
1083
2853
  };
1084
2854
  /**
1085
- * 渲染对应类型的 antd 表单组件
2855
+ * 渲染对应类型的 antd 表单组件(仅接收 componentProps,不再与 Form.Item props 混用)
1086
2856
  */
1087
2857
  function renderFormItemComponent(field) {
1088
2858
  const props = field.componentProps || {};
@@ -1097,13 +2867,14 @@ function renderAutoForm(form, fields) {
1097
2867
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Form, {
1098
2868
  form,
1099
2869
  layout: "vertical",
2870
+ preserve: false,
1100
2871
  children: fields.map((field) => {
1101
2872
  if (!field.componentType) return null;
1102
2873
  const formItemProps = {
1103
2874
  name: field.key,
1104
2875
  label: field.name || field.key,
1105
2876
  valuePropName: field.componentType === "switch" ? "checked" : void 0,
1106
- ...field.componentProps
2877
+ ...field.formItemProps
1107
2878
  };
1108
2879
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.Form.Item, {
1109
2880
  ...formItemProps,
@@ -1112,6 +2883,39 @@ function renderAutoForm(form, fields) {
1112
2883
  })
1113
2884
  });
1114
2885
  }
2886
+ /** 字符串形式的历史属性值('true'/'false')还原为布尔,供 Switch 初始化 */
2887
+ function toFormInitialValue(field, value) {
2888
+ if (value === void 0) return field.defaultValue ?? (field.componentType === "switch" ? false : void 0);
2889
+ if (field.componentType === "switch") {
2890
+ if (typeof value === "boolean") return value;
2891
+ return value === "true" || value === 1 || value === "1";
2892
+ }
2893
+ if (field.componentType === "number" || field.componentType === "slider" || field.componentType === "rate") {
2894
+ const num = Number(value);
2895
+ return Number.isNaN(num) ? void 0 : num;
2896
+ }
2897
+ if (field.componentType === "date") {
2898
+ const d = (0, import_dayjs_min.default)(typeof value === "boolean" ? String(value) : value);
2899
+ return d.isValid() ? d : void 0;
2900
+ }
2901
+ if (field.componentType === "dateRange") {
2902
+ const parts = String(value).split(",").map((s) => s.trim()).filter(Boolean);
2903
+ if (parts.length !== 2) return void 0;
2904
+ const [start, end] = parts.map((p) => (0, import_dayjs_min.default)(p));
2905
+ return start.isValid() && end.isValid() ? [start, end] : void 0;
2906
+ }
2907
+ return value;
2908
+ }
2909
+ /** 表单控件值归一化为容器属性可存储的字符串(容器语法仅支持扁平原始值) */
2910
+ function normalizeValue(field, value) {
2911
+ if (value === null || value === void 0) return "";
2912
+ if (field?.componentType === "date" && import_dayjs_min.default.isDayjs(value)) return value.format("YYYY-MM-DD");
2913
+ 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(", ");
2914
+ const colorLike = value;
2915
+ if (colorLike && typeof colorLike === "object" && typeof colorLike.toHexString === "function") return colorLike.toHexString();
2916
+ if (typeof value === "boolean" || typeof value === "number") return value;
2917
+ return String(value);
2918
+ }
1115
2919
  /**
1116
2920
  * 属性编辑弹窗组件
1117
2921
  * 根据组件 schema 的 renderDialog 函数渲染弹窗内容
@@ -1120,55 +2924,79 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
1120
2924
  const schema = componentRegistry.get(typeName);
1121
2925
  const [formProps, setFormProps] = (0, react.useState)({});
1122
2926
  const [form] = antd.Form.useForm();
2927
+ const onSaveRef = (0, react.useRef)(onSave);
2928
+ onSaveRef.current = onSave;
2929
+ const dirtyRef = (0, react.useRef)(false);
1123
2930
  const mergedProps = (0, react.useMemo)(() => {
1124
2931
  if (!schema) return currentProps;
1125
- const defaults = {};
1126
- for (const field of schema.fields || []) defaults[field.key] = field.defaultValue ?? "";
2932
+ const merged = {};
2933
+ for (const field of schema.fields || []) if (field.defaultValue !== void 0) merged[field.key] = field.defaultValue;
1127
2934
  return {
1128
- ...defaults,
2935
+ ...merged,
1129
2936
  ...currentProps
1130
2937
  };
1131
2938
  }, [schema, currentProps]);
1132
2939
  (0, react.useEffect)(() => {
1133
2940
  if (visible) {
1134
- form.setFieldsValue(mergedProps);
1135
2941
  setFormProps({});
2942
+ const initial = {};
2943
+ for (const [key, value] of Object.entries(mergedProps)) {
2944
+ const field = schema?.fields?.find((f) => f.key === key);
2945
+ const formValue = toFormInitialValue(field ?? { key }, value);
2946
+ if (formValue !== void 0) initial[key] = formValue;
2947
+ }
2948
+ form.setFieldsValue(initial);
2949
+ dirtyRef.current = false;
1136
2950
  }
1137
- }, [
1138
- visible,
1139
- mergedProps,
1140
- form
1141
- ]);
2951
+ }, [visible, form]);
1142
2952
  const handleDialogChange = (key, value) => {
1143
2953
  setFormProps((prev) => ({
1144
2954
  ...prev,
1145
2955
  [key]: value
1146
2956
  }));
2957
+ dirtyRef.current = true;
1147
2958
  };
1148
2959
  const handleOk = async () => {
1149
- let finalProps = visible ? {
1150
- ...mergedProps,
1151
- ...formProps
1152
- } : mergedProps;
1153
2960
  try {
1154
2961
  const formValues = await form.validateFields();
1155
- finalProps = {
1156
- ...finalProps,
1157
- ...formValues
1158
- };
1159
- } catch {}
1160
- onSave(finalProps);
2962
+ for (const [key, value] of Object.entries(formValues)) formProps[key] = value;
2963
+ } catch {
2964
+ return;
2965
+ }
2966
+ const finalProps = {};
2967
+ for (const [key, value] of Object.entries({
2968
+ ...mergedProps,
2969
+ ...formProps
2970
+ })) {
2971
+ const field = schema?.fields?.find((f) => f.key === key);
2972
+ finalProps[key] = normalizeValue(field, value);
2973
+ }
2974
+ onSaveRef.current(finalProps);
2975
+ dirtyRef.current = false;
2976
+ onClose();
1161
2977
  };
1162
2978
  const handleClose = () => {
2979
+ if (dirtyRef.current && !window.confirm("属性修改尚未保存,确定关闭吗?")) return;
1163
2980
  setFormProps({});
2981
+ dirtyRef.current = false;
1164
2982
  onClose();
1165
2983
  };
1166
2984
  if (!schema) return null;
2985
+ const contextSave = (props) => {
2986
+ setFormProps((prev) => ({
2987
+ ...prev,
2988
+ ...props
2989
+ }));
2990
+ dirtyRef.current = true;
2991
+ };
1167
2992
  const context = {
1168
- props: mergedProps,
2993
+ props: {
2994
+ ...mergedProps,
2995
+ ...formProps
2996
+ },
1169
2997
  form,
1170
2998
  onChange: handleDialogChange,
1171
- onSave
2999
+ onSave: contextSave
1172
3000
  };
1173
3001
  const renderDialogContent = () => {
1174
3002
  if (schema.renderDialog) return schema.renderDialog(context);
@@ -1188,36 +3016,46 @@ function EditDialog({ visible, typeName, currentProps, onSave, onClose }) {
1188
3016
  //#endregion
1189
3017
  //#region src/utils/writeContainer.ts
1190
3018
  /**
1191
- * 从属性对象生成 JSON 属性行。
1192
- * 格式: { key: 'value', key2: 'value2' }
3019
+ * 从属性对象生成属性行。
3020
+ * 使用 JSON5 序列化:单引号风格与旧格式兼容,特殊字符会被正确转义,
3021
+ * 配合 parseContainerProps 保证读写往返无损。
1193
3022
  */
1194
3023
  function writeContainerProps(props) {
1195
- const entries = Object.entries(props).map(([k, v]) => `${k}: '${v}'`).join(", ");
1196
- return entries ? `{ ${entries} }` : "{}";
3024
+ return import_dist.default.stringify(props) ?? "{}";
1197
3025
  }
1198
3026
  /**
1199
3027
  * 更新编辑器文档中的容器属性。
1200
- * 替换 JSON 属性行(::: 打开行之后的一行)为新属性。
3028
+ * 已有属性行则整行替换;没有属性行则在容器头行后插入一行。
3029
+ * @param headerPos 容器头行(:::type)任意位置,用于无属性行时定位插入点
1201
3030
  */
1202
- function updateContainerProps(view, propsLineFrom, propsLineTo, newProps) {
3031
+ function updateContainerProps(view, headerPos, propsLineFrom, propsLineTo, newProps) {
1203
3032
  const newPropsLine = writeContainerProps(newProps);
1204
- view.dispatch({ changes: {
3033
+ if (propsLineTo > propsLineFrom) view.dispatch({ changes: {
1205
3034
  from: propsLineFrom,
1206
3035
  to: propsLineTo,
1207
3036
  insert: newPropsLine
1208
3037
  } });
3038
+ else {
3039
+ const headerLine = view.state.doc.lineAt(headerPos);
3040
+ view.dispatch({ changes: {
3041
+ from: headerLine.to,
3042
+ insert: `\n${newPropsLine}`
3043
+ } });
3044
+ }
1209
3045
  }
1210
3046
  /**
1211
3047
  * 在当前光标位置插入新容器。
1212
- * 创建 :::type 打开行 + JSON 属性 + ::: 关闭行的结构。
3048
+ * 创建 :::type 打开行 + 属性行 + ::: 关闭行的结构。
1213
3049
  */
1214
3050
  function insertContainer(view, typeName, defaultProps) {
1215
3051
  const { from } = view.state.selection.main;
1216
- const container = `:::${typeName}\n${writeContainerProps(defaultProps)}\n:::\n`;
3052
+ const propsLine = writeContainerProps(defaultProps);
3053
+ const container = `\n:::${typeName}\n${propsLine}\n:::\n`;
1217
3054
  view.dispatch({ changes: {
1218
3055
  from,
1219
3056
  insert: container
1220
3057
  } });
3058
+ view.dispatch({ selection: { anchor: from + `\n:::${typeName}\n${propsLine}\n`.length } });
1221
3059
  }
1222
3060
  //#endregion
1223
3061
  //#region src/hooks/useFullscreen.ts
@@ -1254,145 +3092,190 @@ function useFullscreen() {
1254
3092
  //#endregion
1255
3093
  //#region src/hooks/useScrollSync.ts
1256
3094
  /**
1257
- * 滚动同步 Hook
1258
- * 将源滚动容器的滚动位置同步到目标预览容器
3095
+ * 双向滚动同步 Hook
3096
+ * 编辑器与预览区互相同步滚动位置(基于比例)
3097
+ * 使用 syncing 锁防止双向循环触发
3098
+ *
3099
+ * 直接接收滚动容器元素(而非 ref):元素变化时 effect 重新执行并重新绑定监听,
3100
+ * 避免"挂载时容器尚未就绪 / 编辑器 view 被重建"导致监听永久失效或绑到旧节点。
1259
3101
  */
1260
- function useScrollSync(sourceRef, targetRef) {
3102
+ function useScrollSync(source, target) {
1261
3103
  const rafIdRef = (0, react.useRef)(null);
3104
+ const syncingRef = (0, react.useRef)(null);
3105
+ const syncScroll = (from, fromEl, toEl) => {
3106
+ if (rafIdRef.current) return;
3107
+ rafIdRef.current = requestAnimationFrame(() => {
3108
+ const fromScrollHeight = fromEl.scrollHeight - fromEl.clientHeight;
3109
+ if (fromScrollHeight <= 0) {
3110
+ rafIdRef.current = null;
3111
+ syncingRef.current = null;
3112
+ return;
3113
+ }
3114
+ const ratio = fromEl.scrollTop / fromScrollHeight;
3115
+ const toScrollHeight = toEl.scrollHeight - toEl.clientHeight;
3116
+ if (toScrollHeight > 0) {
3117
+ syncingRef.current = from;
3118
+ toEl.scrollTop = ratio * toScrollHeight;
3119
+ requestAnimationFrame(() => {
3120
+ syncingRef.current = null;
3121
+ });
3122
+ }
3123
+ rafIdRef.current = null;
3124
+ });
3125
+ };
1262
3126
  (0, react.useEffect)(() => {
1263
- const source = sourceRef.current;
1264
- const target = targetRef.current;
1265
3127
  if (!source || !target) return;
1266
- const listener = () => {
1267
- if (rafIdRef.current) return;
1268
- rafIdRef.current = requestAnimationFrame(() => {
1269
- const s = sourceRef.current;
1270
- const t = targetRef.current;
1271
- if (!s || !t) {
1272
- rafIdRef.current = null;
1273
- return;
1274
- }
1275
- const sourceScrollHeight = s.scrollHeight - s.clientHeight;
1276
- if (sourceScrollHeight <= 0) {
1277
- rafIdRef.current = null;
1278
- return;
1279
- }
1280
- const ratio = s.scrollTop / sourceScrollHeight;
1281
- const targetScrollHeight = t.scrollHeight - t.clientHeight;
1282
- if (targetScrollHeight > 0) t.scrollTop = ratio * targetScrollHeight;
1283
- rafIdRef.current = null;
1284
- });
3128
+ const onSourceScroll = () => {
3129
+ if (syncingRef.current !== null) return;
3130
+ syncScroll("source", source, target);
1285
3131
  };
1286
- source.addEventListener("scroll", listener, { passive: true });
3132
+ const onTargetScroll = () => {
3133
+ if (syncingRef.current !== null) return;
3134
+ syncScroll("target", target, source);
3135
+ };
3136
+ source.addEventListener("scroll", onSourceScroll, { passive: true });
3137
+ target.addEventListener("scroll", onTargetScroll, { passive: true });
1287
3138
  return () => {
1288
- source.removeEventListener("scroll", listener);
1289
- if (rafIdRef.current) cancelAnimationFrame(rafIdRef.current);
3139
+ source.removeEventListener("scroll", onSourceScroll);
3140
+ target.removeEventListener("scroll", onTargetScroll);
3141
+ if (rafIdRef.current) {
3142
+ cancelAnimationFrame(rafIdRef.current);
3143
+ rafIdRef.current = null;
3144
+ }
3145
+ syncingRef.current = null;
1290
3146
  };
1291
- }, [sourceRef, targetRef]);
3147
+ }, [source, target]);
1292
3148
  }
1293
3149
  //#endregion
1294
3150
  //#region src/MarkdownEditor.tsx
1295
- var MarkdownEditor_default = (0, react.forwardRef)(function MarkdownEditor({ defaultValue = "", value, onChange, showPreview = true, fullscreen: fullscreenProp = true, previewOptions, uploadConfig }, ref) {
3151
+ /** 订阅注册中心版本,注册变化时触发重渲染 */
3152
+ function useRegistryVersion() {
3153
+ const subscribe = (0, react.useCallback)((onChange) => componentRegistry.subscribe(onChange), []);
3154
+ const getSnapshot = (0, react.useCallback)(() => componentRegistry.getVersion(), []);
3155
+ return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
3156
+ }
3157
+ var MarkdownEditorInner = ({ defaultValue = "", value, onChange, showPreview = true, fullscreen: fullscreenProp = true, previewOptions, uploadConfig, schemas, onNotify }, ref) => {
1296
3158
  const [content, setContent] = (0, react.useState)(value ?? defaultValue);
1297
3159
  const [editorView, setEditorView] = (0, react.useState)(null);
1298
- const scrollDOMRef = (0, react.useRef)(null);
1299
- const previewElRef = (0, react.useRef)(null);
3160
+ const [scrollDOM, setScrollDOM] = (0, react.useState)(null);
3161
+ const [previewEl, setPreviewEl] = (0, react.useState)(null);
1300
3162
  const { fullscreen, toggleFullscreen } = useFullscreen();
1301
- useScrollSync(scrollDOMRef, previewElRef);
3163
+ useScrollSync(scrollDOM, previewEl);
1302
3164
  const [dialogVisible, setDialogVisible] = (0, react.useState)(false);
1303
3165
  const [dialogTypeName, setDialogTypeName] = (0, react.useState)("");
1304
- const [dialogProps, setDialogProps] = (0, react.useState)({});
1305
- const [dialogPropsRange, setDialogPropsRange] = (0, react.useState)([0, 0]);
3166
+ const [dialogContainer, setDialogContainer] = (0, react.useState)(null);
3167
+ const app = antd.App.useApp();
3168
+ const notify = (0, react.useCallback)((type, text) => {
3169
+ if (onNotify) {
3170
+ onNotify(type, text);
3171
+ return;
3172
+ }
3173
+ (app?.message ?? antd.message)[type](text);
3174
+ }, [onNotify, app]);
3175
+ const lastEmittedRef = (0, react.useRef)(void 0);
1306
3176
  (0, react.useEffect)(() => {
1307
- if (value !== void 0) setContent(value);
3177
+ if (value !== void 0 && value !== lastEmittedRef.current) setContent(value);
1308
3178
  }, [value]);
1309
3179
  const internalSetContent = (0, react.useCallback)((newContent) => {
1310
3180
  setContent(newContent);
3181
+ lastEmittedRef.current = newContent;
1311
3182
  onChange?.(newContent);
1312
3183
  }, [onChange]);
1313
3184
  (0, react.useImperativeHandle)(ref, () => ({ getContent: () => content }), [content]);
1314
- const extraToolbarItems = componentRegistry.getAll().flatMap((schema) => {
1315
- if (schema.wrapTags) return {
1316
- id: `wrap-${schema.name}`,
1317
- label: schema.label,
1318
- icon: () => schema.icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ant_design_icons.ReadOutlined, {}),
1319
- wrapTags: schema.wrapTags
1320
- };
1321
- const defaultProps = {};
1322
- for (const field of schema?.fields ?? []) defaultProps[field.key] = field.defaultValue ?? "";
1323
- return {
1324
- id: `container-${schema.name}`,
1325
- label: schema.label,
1326
- icon: () => schema.icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_ant_design_icons.ReadOutlined, {}),
1327
- handler: (view, _state) => insertContainer(view, schema.name, defaultProps)
1328
- };
1329
- });
1330
- const handleScrollReady = (0, react.useCallback)((scrollDOM) => {
1331
- scrollDOMRef.current = scrollDOM;
3185
+ const registryVersion = useRegistryVersion();
3186
+ const extraToolbarItems = (0, react.useMemo)(() => {
3187
+ const merged = /* @__PURE__ */ new Map();
3188
+ for (const schema of componentRegistry.getAll()) merged.set(schema.name, schema);
3189
+ for (const schema of schemas ?? []) merged.set(schema.name, schema);
3190
+ return [...merged.values()].flatMap((schema) => {
3191
+ if (schema.wrapTags) return {
3192
+ id: `wrap-${schema.name}`,
3193
+ label: schema.label,
3194
+ icon: schema.icon ?? _ant_design_icons.ReadOutlined,
3195
+ wrapTags: schema.wrapTags
3196
+ };
3197
+ const defaultProps = {};
3198
+ for (const field of schema.fields ?? []) if (field.defaultValue !== void 0) defaultProps[field.key] = field.defaultValue;
3199
+ return {
3200
+ id: `container-${schema.name}`,
3201
+ label: schema.label,
3202
+ icon: schema.icon ?? _ant_design_icons.ReadOutlined,
3203
+ handler: (view) => insertContainer(view, schema.name, defaultProps)
3204
+ };
3205
+ });
3206
+ }, [registryVersion, schemas]);
3207
+ const handleScrollReady = (0, react.useCallback)((dom) => {
3208
+ setScrollDOM(dom);
1332
3209
  }, []);
1333
3210
  const handlePreviewRef = (0, react.useCallback)((node) => {
1334
- previewElRef.current = node;
3211
+ setPreviewEl(node);
1335
3212
  }, []);
1336
3213
  const handleViewReady = (0, react.useCallback)((view) => {
1337
3214
  setEditorView(view);
1338
3215
  }, []);
1339
- const handleEditContainer = (0, react.useCallback)((_view, typeName, propsLineFrom, propsLineTo, currentProps) => {
1340
- setDialogTypeName(typeName);
1341
- setDialogProps({ ...currentProps });
1342
- setDialogPropsRange([propsLineFrom, propsLineTo]);
3216
+ const handleEditContainer = (0, react.useCallback)((_view, container) => {
3217
+ setDialogTypeName(container.typeName);
3218
+ setDialogContainer(container);
1343
3219
  setDialogVisible(true);
1344
3220
  }, []);
1345
3221
  const handleDialogSave = (0, react.useCallback)((newProps) => {
1346
- setDialogVisible(false);
1347
- if (editorView) updateContainerProps(editorView, dialogPropsRange[0], dialogPropsRange[1], newProps);
1348
- }, [editorView, dialogPropsRange]);
3222
+ if (editorView && dialogContainer) updateContainerProps(editorView, dialogContainer.startPos, dialogContainer.propsLineFrom, dialogContainer.propsLineTo, newProps);
3223
+ }, [editorView, dialogContainer]);
1349
3224
  const handleDialogClose = (0, react.useCallback)(() => {
1350
3225
  setDialogVisible(false);
1351
3226
  }, []);
3227
+ const editorNode = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Editor, {
3228
+ value: content,
3229
+ onChange: internalSetContent,
3230
+ onScrollReady: handleScrollReady,
3231
+ onViewReady: handleViewReady,
3232
+ onEditContainer: handleEditContainer,
3233
+ uploadConfig,
3234
+ onMessageNoUploadConfig: () => notify("warning", "请先配置图片上传功能")
3235
+ });
1352
3236
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1353
3237
  className: fullscreen ? "markdown-editor-app fullscreen" : "markdown-editor-app",
1354
3238
  children: [
1355
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toolbar, {
3239
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toolbar_default, {
1356
3240
  editorView,
1357
3241
  fullscreen,
1358
3242
  onToggleFullscreen: fullscreenProp ? toggleFullscreen : void 0,
1359
3243
  extraItems: extraToolbarItems,
1360
- uploadConfig
3244
+ uploadConfig,
3245
+ notify
1361
3246
  }),
1362
3247
  showPreview ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SplitPanels, {
1363
- leftPanel: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Editor, {
1364
- value: content,
1365
- onChange: internalSetContent,
1366
- onScrollReady: handleScrollReady,
1367
- onViewReady: handleViewReady,
1368
- onEditContainer: handleEditContainer,
1369
- uploadConfig,
1370
- onMessageNoUploadConfig: () => antd.message.warning("请先配置图片上传功能")
1371
- }),
1372
- rightPanel: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Preview, {
3248
+ leftPanel: editorNode,
3249
+ rightPanel: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Preview_default, {
1373
3250
  content,
1374
3251
  ref: handlePreviewRef,
1375
3252
  previewOptions
1376
3253
  })
1377
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Editor, {
1378
- value: content,
1379
- onChange: internalSetContent,
1380
- onScrollReady: handleScrollReady,
1381
- onViewReady: handleViewReady,
1382
- onEditContainer: handleEditContainer,
1383
- uploadConfig,
1384
- onMessageNoUploadConfig: () => antd.message.warning("请先配置图片上传功能")
1385
- }),
3254
+ }) : editorNode,
1386
3255
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EditDialog, {
1387
3256
  visible: dialogVisible,
1388
3257
  typeName: dialogTypeName,
1389
- currentProps: dialogProps,
3258
+ currentProps: dialogContainer?.props ?? {},
1390
3259
  onSave: handleDialogSave,
1391
3260
  onClose: handleDialogClose
1392
3261
  })
1393
3262
  ]
1394
3263
  });
1395
- });
3264
+ };
3265
+ var MarkdownEditor = (0, react.forwardRef)(MarkdownEditorInner);
3266
+ /**
3267
+ * 包一层 antd App:为库内部的 message 等反馈组件提供上下文;
3268
+ * 宿主已有 App 包裹时内层仅作兜底(component={false} 不额外渲染 DOM)。
3269
+ */
3270
+ function MarkdownEditorWithApp({ ref, ...props }) {
3271
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(antd.App, {
3272
+ component: false,
3273
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownEditor, {
3274
+ ...props,
3275
+ ref
3276
+ })
3277
+ });
3278
+ }
1396
3279
  //#endregion
1397
3280
  //#region src/hooks/useRegisterToolbar.ts
1398
3281
  /**
@@ -1489,14 +3372,17 @@ var MarkdownEditor_default = (0, react.forwardRef)(function MarkdownEditor({ def
1489
3372
  * @example 批量注册
1490
3373
  * ```tsx
1491
3374
  * function MyPage() {
3375
+ * // 注意:schema 需声明为稳定引用(组件外常量或 useMemo),
3376
+ * // 否则每次渲染都会重新注册;多实例互不干扰的场景请改用
3377
+ * // <MarkdownEditor schemas={[...]} /> 局部注册
1492
3378
  * useRegisterToolbar([schema1, schema2, schema3])
1493
3379
  * return <MarkdownEditor />
1494
3380
  * }
1495
3381
  * ```
1496
3382
  */
1497
3383
  function useRegisterToolbar(schemas) {
1498
- const schemaList = Array.isArray(schemas) ? schemas : [schemas];
1499
3384
  (0, react.useEffect)(() => {
3385
+ const schemaList = Array.isArray(schemas) ? schemas : [schemas];
1500
3386
  schemaList.forEach((schema) => {
1501
3387
  componentRegistry.register(schema.name, schema);
1502
3388
  });
@@ -1505,10 +3391,12 @@ function useRegisterToolbar(schemas) {
1505
3391
  componentRegistry.unregister(schema.name);
1506
3392
  });
1507
3393
  };
1508
- }, [schemaList]);
3394
+ }, [schemas]);
1509
3395
  }
1510
3396
  //#endregion
1511
- exports.MarkdownEditor = MarkdownEditor_default;
3397
+ exports.MarkdownEditor = MarkdownEditorWithApp;
3398
+ exports.getIconfontScriptUrl = getIconfontScriptUrl;
3399
+ exports.setIconfontScriptUrl = setIconfontScriptUrl;
1512
3400
  exports.useRegisterToolbar = useRegisterToolbar;
1513
3401
 
1514
3402
  //# sourceMappingURL=index.cjs.map