@vervedoc/core 3.3.15 → 3.3.16

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.
@@ -21,166 +21,171 @@ const d = [
21
21
  { label: "Courier New", value: "Courier New", css: '"Courier New", "Liberation Mono", monospace' },
22
22
  { label: "Verdana", value: "Verdana", css: 'Verdana, "DejaVu Sans", sans-serif' }
23
23
  ];
24
- d.map((t) => t.label);
24
+ d.map((e) => e.label);
25
25
  Object.fromEntries(
26
- d.map((t) => [t.label, t.value])
26
+ d.map((e) => [e.label, e.value])
27
27
  );
28
28
  Object.fromEntries(
29
- d.flatMap((t) => [
30
- [t.value, t.label],
31
- ...(t.aliases ?? []).map((u) => [u, t.label])
29
+ d.flatMap((e) => [
30
+ [e.value, e.label],
31
+ ...(e.aliases ?? []).map((u) => [u, e.label])
32
32
  ])
33
33
  );
34
34
  Object.fromEntries(
35
- d.flatMap((t) => [
36
- [t.value, t.css],
37
- ...(t.aliases ?? []).map((u) => [u, t.css])
35
+ d.flatMap((e) => [
36
+ [e.value, e.css],
37
+ ...(e.aliases ?? []).map((u) => [u, e.css])
38
38
  ])
39
39
  );
40
- function j(t) {
41
- return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
40
+ function j(e) {
41
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
42
42
  }
43
43
  var C, w;
44
44
  function A() {
45
45
  if (w) return C;
46
46
  w = 1, C = u;
47
- function t(a) {
48
- return a instanceof Buffer ? Buffer.from(a) : new a.constructor(a.buffer.slice(), a.byteOffset, a.length);
47
+ function e(o) {
48
+ return o instanceof Buffer ? Buffer.from(o) : new o.constructor(o.buffer.slice(), o.byteOffset, o.length);
49
49
  }
50
- function u(a) {
51
- if (a = a || {}, a.circles) return p(a);
52
- const o = /* @__PURE__ */ new Map();
53
- if (o.set(Date, (s) => new Date(s)), o.set(Map, (s, i) => new Map(g(Array.from(s), i))), o.set(Set, (s, i) => new Set(g(Array.from(s), i))), a.constructorHandlers)
54
- for (const s of a.constructorHandlers)
55
- o.set(s[0], s[1]);
50
+ function u(o) {
51
+ if (o = o || {}, o.circles) return p(o);
52
+ const a = /* @__PURE__ */ new Map();
53
+ if (a.set(Date, (s) => new Date(s)), a.set(Map, (s, i) => new Map(g(Array.from(s), i))), a.set(Set, (s, i) => new Set(g(Array.from(s), i))), o.constructorHandlers)
54
+ for (const s of o.constructorHandlers)
55
+ a.set(s[0], s[1]);
56
56
  let l = null;
57
- return a.proto ? b : c;
57
+ return o.proto ? b : c;
58
58
  function g(s, i) {
59
- const e = Object.keys(s), r = new Array(e.length);
60
- for (let f = 0; f < e.length; f++) {
61
- const n = e[f], S = s[n];
62
- typeof S != "object" || S === null ? r[n] = S : S.constructor !== Object && (l = o.get(S.constructor)) ? r[n] = l(S, i) : ArrayBuffer.isView(S) ? r[n] = t(S) : r[n] = i(S);
59
+ const t = Object.keys(s), r = new Array(t.length);
60
+ for (let f = 0; f < t.length; f++) {
61
+ const n = t[f], S = s[n];
62
+ typeof S != "object" || S === null ? r[n] = S : S.constructor !== Object && (l = a.get(S.constructor)) ? r[n] = l(S, i) : ArrayBuffer.isView(S) ? r[n] = e(S) : r[n] = i(S);
63
63
  }
64
64
  return r;
65
65
  }
66
66
  function c(s) {
67
67
  if (typeof s != "object" || s === null) return s;
68
68
  if (Array.isArray(s)) return g(s, c);
69
- if (s.constructor !== Object && (l = o.get(s.constructor)))
69
+ if (s.constructor !== Object && (l = a.get(s.constructor)))
70
70
  return l(s, c);
71
71
  const i = {};
72
- for (const e in s) {
73
- if (Object.hasOwnProperty.call(s, e) === !1) continue;
74
- const r = s[e];
75
- typeof r != "object" || r === null ? i[e] = r : r.constructor !== Object && (l = o.get(r.constructor)) ? i[e] = l(r, c) : ArrayBuffer.isView(r) ? i[e] = t(r) : i[e] = c(r);
72
+ for (const t in s) {
73
+ if (Object.hasOwnProperty.call(s, t) === !1) continue;
74
+ const r = s[t];
75
+ typeof r != "object" || r === null ? i[t] = r : r.constructor !== Object && (l = a.get(r.constructor)) ? i[t] = l(r, c) : ArrayBuffer.isView(r) ? i[t] = e(r) : i[t] = c(r);
76
76
  }
77
77
  return i;
78
78
  }
79
79
  function b(s) {
80
80
  if (typeof s != "object" || s === null) return s;
81
81
  if (Array.isArray(s)) return g(s, b);
82
- if (s.constructor !== Object && (l = o.get(s.constructor)))
82
+ if (s.constructor !== Object && (l = a.get(s.constructor)))
83
83
  return l(s, b);
84
84
  const i = {};
85
- for (const e in s) {
86
- const r = s[e];
87
- typeof r != "object" || r === null ? i[e] = r : r.constructor !== Object && (l = o.get(r.constructor)) ? i[e] = l(r, b) : ArrayBuffer.isView(r) ? i[e] = t(r) : i[e] = b(r);
85
+ for (const t in s) {
86
+ const r = s[t];
87
+ typeof r != "object" || r === null ? i[t] = r : r.constructor !== Object && (l = a.get(r.constructor)) ? i[t] = l(r, b) : ArrayBuffer.isView(r) ? i[t] = e(r) : i[t] = b(r);
88
88
  }
89
89
  return i;
90
90
  }
91
91
  }
92
- function p(a) {
93
- const o = [], l = [], g = /* @__PURE__ */ new Map();
94
- if (g.set(Date, (e) => new Date(e)), g.set(Map, (e, r) => new Map(b(Array.from(e), r))), g.set(Set, (e, r) => new Set(b(Array.from(e), r))), a.constructorHandlers)
95
- for (const e of a.constructorHandlers)
96
- g.set(e[0], e[1]);
92
+ function p(o) {
93
+ const a = [], l = [], g = /* @__PURE__ */ new Map();
94
+ if (g.set(Date, (t) => new Date(t)), g.set(Map, (t, r) => new Map(b(Array.from(t), r))), g.set(Set, (t, r) => new Set(b(Array.from(t), r))), o.constructorHandlers)
95
+ for (const t of o.constructorHandlers)
96
+ g.set(t[0], t[1]);
97
97
  let c = null;
98
- return a.proto ? i : s;
99
- function b(e, r) {
100
- const f = Object.keys(e), n = new Array(f.length);
98
+ return o.proto ? i : s;
99
+ function b(t, r) {
100
+ const f = Object.keys(t), n = new Array(f.length);
101
101
  for (let S = 0; S < f.length; S++) {
102
- const h = f[S], y = e[h];
102
+ const h = f[S], y = t[h];
103
103
  if (typeof y != "object" || y === null)
104
104
  n[h] = y;
105
105
  else if (y.constructor !== Object && (c = g.get(y.constructor)))
106
106
  n[h] = c(y, r);
107
107
  else if (ArrayBuffer.isView(y))
108
- n[h] = t(y);
108
+ n[h] = e(y);
109
109
  else {
110
- const v = o.indexOf(y);
111
- v !== -1 ? n[h] = l[v] : n[h] = r(y);
110
+ const T = a.indexOf(y);
111
+ T !== -1 ? n[h] = l[T] : n[h] = r(y);
112
112
  }
113
113
  }
114
114
  return n;
115
115
  }
116
- function s(e) {
117
- if (typeof e != "object" || e === null) return e;
118
- if (Array.isArray(e)) return b(e, s);
119
- if (e.constructor !== Object && (c = g.get(e.constructor)))
120
- return c(e, s);
116
+ function s(t) {
117
+ if (typeof t != "object" || t === null) return t;
118
+ if (Array.isArray(t)) return b(t, s);
119
+ if (t.constructor !== Object && (c = g.get(t.constructor)))
120
+ return c(t, s);
121
121
  const r = {};
122
- o.push(e), l.push(r);
123
- for (const f in e) {
124
- if (Object.hasOwnProperty.call(e, f) === !1) continue;
125
- const n = e[f];
122
+ a.push(t), l.push(r);
123
+ for (const f in t) {
124
+ if (Object.hasOwnProperty.call(t, f) === !1) continue;
125
+ const n = t[f];
126
126
  if (typeof n != "object" || n === null)
127
127
  r[f] = n;
128
128
  else if (n.constructor !== Object && (c = g.get(n.constructor)))
129
129
  r[f] = c(n, s);
130
130
  else if (ArrayBuffer.isView(n))
131
- r[f] = t(n);
131
+ r[f] = e(n);
132
132
  else {
133
- const S = o.indexOf(n);
133
+ const S = a.indexOf(n);
134
134
  S !== -1 ? r[f] = l[S] : r[f] = s(n);
135
135
  }
136
136
  }
137
- return o.pop(), l.pop(), r;
137
+ return a.pop(), l.pop(), r;
138
138
  }
139
- function i(e) {
140
- if (typeof e != "object" || e === null) return e;
141
- if (Array.isArray(e)) return b(e, i);
142
- if (e.constructor !== Object && (c = g.get(e.constructor)))
143
- return c(e, i);
139
+ function i(t) {
140
+ if (typeof t != "object" || t === null) return t;
141
+ if (Array.isArray(t)) return b(t, i);
142
+ if (t.constructor !== Object && (c = g.get(t.constructor)))
143
+ return c(t, i);
144
144
  const r = {};
145
- o.push(e), l.push(r);
146
- for (const f in e) {
147
- const n = e[f];
145
+ a.push(t), l.push(r);
146
+ for (const f in t) {
147
+ const n = t[f];
148
148
  if (typeof n != "object" || n === null)
149
149
  r[f] = n;
150
150
  else if (n.constructor !== Object && (c = g.get(n.constructor)))
151
151
  r[f] = c(n, i);
152
152
  else if (ArrayBuffer.isView(n))
153
- r[f] = t(n);
153
+ r[f] = e(n);
154
154
  else {
155
- const S = o.indexOf(n);
155
+ const S = a.indexOf(n);
156
156
  S !== -1 ? r[f] = l[S] : r[f] = i(n);
157
157
  }
158
158
  }
159
- return o.pop(), l.pop(), r;
159
+ return a.pop(), l.pop(), r;
160
160
  }
161
161
  }
162
162
  return C;
163
163
  }
164
164
  var O = A(), K = /* @__PURE__ */ j(O);
165
- const N = K({ proto: !1, circles: !1 });
166
- function L(t) {
167
- return t === null || typeof t != "object" ? t : N(t);
165
+ const L = K({ proto: !1, circles: !1 });
166
+ function N(e) {
167
+ return e === null || typeof e != "object" ? e : L(e);
168
168
  }
169
- function M(t) {
170
- return ((t == null ? void 0 : t.type) === "title" || (t == null ? void 0 : t.type) === "list") && Array.isArray(t.valueList);
169
+ function k(e) {
170
+ return ((e == null ? void 0 : e.type) === "title" || (e == null ? void 0 : e.type) === "list") && Array.isArray(e.valueList);
171
171
  }
172
- function k(t) {
173
- return (t == null ? void 0 : t.type) === "table" && Array.isArray(t.trList);
172
+ function M(e) {
173
+ return (e == null ? void 0 : e.type) === "table" && Array.isArray(e.trList);
174
174
  }
175
- function m(t, u, p = []) {
176
- for (let a = 0; a < t.length; a++) {
177
- const o = t[a], l = [...p, a];
178
- if (u(o, { parent: t, path: l, index: a }) !== !1) {
179
- if (M(o))
180
- m(o.valueList, u, [...l, "valueList"]);
181
- else if (k(o))
182
- for (let c = 0; c < o.trList.length; c++) {
183
- const b = o.trList[c];
175
+ function H(e) {
176
+ return (e == null ? void 0 : e.type) === "control" && typeof e.control == "object" && e.control !== null;
177
+ }
178
+ function m(e, u, p = []) {
179
+ for (let o = 0; o < e.length; o++) {
180
+ const a = e[o], l = [...p, o];
181
+ if (u(a, { parent: e, path: l, index: o }) !== !1) {
182
+ if (k(a))
183
+ m(a.valueList, u, [...l, "valueList"]);
184
+ else if ((H(a) || a.type === "hyperlink") && Array.isArray(a.valueList))
185
+ m(a.valueList, u, [...l, "valueList"]);
186
+ else if (M(a))
187
+ for (let c = 0; c < a.trList.length; c++) {
188
+ const b = a.trList[c];
184
189
  for (let s = 0; s < b.tdList.length; s++) {
185
190
  const i = b.tdList[s];
186
191
  m(i.value, u, [...l, "trList", c, "tdList", s, "value"]);
@@ -189,56 +194,56 @@ function m(t, u, p = []) {
189
194
  }
190
195
  }
191
196
  }
192
- const H = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6 };
193
- function F(t) {
197
+ const F = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6 };
198
+ function J(e) {
194
199
  const u = [], p = /* @__PURE__ */ new Map();
195
- return m(t, (a, o) => {
196
- if (a.type !== "title") return;
197
- const l = a, g = (l.valueList ?? []).map((i) => i.type === "text" ? i.value : "").join(""), c = H[l.level] ?? 1;
200
+ return m(e, (o, a) => {
201
+ if (o.type !== "title") return;
202
+ const l = o, g = (l.valueList ?? []).map((i) => i.type === "text" ? i.value : "").join(""), c = F[l.level] ?? 1;
198
203
  let b;
199
204
  const s = l.listNumbering;
200
205
  if (s && s.numFmt !== "bullet") {
201
- const i = s.numId ?? s.abstractNumId ?? "default", e = s.level ?? 0, r = `${i}:${e}`, f = p.get(r), n = (f ?? (s.start ?? 1) - 1) + 1;
206
+ const i = s.numId ?? s.abstractNumId ?? "default", t = s.level ?? 0, r = `${i}:${t}`, f = p.get(r), n = (f ?? (s.start ?? 1) - 1) + 1;
202
207
  p.set(r, n);
203
208
  for (const S of p.keys())
204
- S.startsWith(`${i}:`) && Number(S.slice(i.length + 1)) > e && p.delete(S);
209
+ S.startsWith(`${i}:`) && Number(S.slice(i.length + 1)) > t && p.delete(S);
205
210
  b = (s.lvlText ?? "%1.").replace(/%([1-9])/g, (S, h) => {
206
211
  const y = Number(h) - 1;
207
- return String(y === e ? n : p.get(`${i}:${y}`) ?? s.start ?? 1);
212
+ return String(y === t ? n : p.get(`${i}:${y}`) ?? s.start ?? 1);
208
213
  });
209
214
  }
210
- u.push({ id: JSON.stringify(o.path), level: c, name: g, number: b });
215
+ u.push({ id: JSON.stringify(a.path), level: c, name: g, number: b });
211
216
  }), { toc: u };
212
217
  }
213
- function J(t, u) {
218
+ function x(e, u) {
214
219
  const p = [];
215
220
  if (!u) return { results: p, count: 0 };
216
- const a = u.toLowerCase();
217
- return m(t, (o, l) => {
218
- if (o.type !== "text") return;
219
- const g = (o.value || "").toLowerCase();
220
- let c = g.indexOf(a);
221
+ const o = u.toLowerCase();
222
+ return m(e, (a, l) => {
223
+ if (a.type !== "text") return;
224
+ const g = (a.value || "").toLowerCase();
225
+ let c = g.indexOf(o);
221
226
  for (; c !== -1; )
222
- p.push({ path: [...l.path], offset: c, length: u.length }), c = g.indexOf(a, c + 1);
227
+ p.push({ path: [...l.path], offset: c, length: u.length }), c = g.indexOf(o, c + 1);
223
228
  }), { results: p, count: p.length };
224
229
  }
225
- let T = [];
226
- self.onmessage = (t) => {
230
+ let v = [];
231
+ self.onmessage = (e) => {
227
232
  try {
228
- const u = t.data;
233
+ const u = e.data;
229
234
  switch (u.type) {
230
235
  case "update":
231
- T = u.elements, self.postMessage({ type: "toc-result", ...F(T) });
236
+ v = u.elements, self.postMessage({ type: "toc-result", ...J(v) });
232
237
  break;
233
238
  case "search":
234
- self.postMessage({ type: "search-result", ...J(T, u.keyword) });
239
+ self.postMessage({ type: "search-result", ...x(v, u.keyword) });
235
240
  break;
236
241
  case "clone":
237
- self.postMessage({ type: "clone-result", data: L(u.data) });
242
+ self.postMessage({ type: "clone-result", data: N(u.data) });
238
243
  break;
239
244
  }
240
245
  } catch (u) {
241
246
  self.postMessage({ type: "error", message: (u == null ? void 0 : u.message) || String(u) });
242
247
  }
243
248
  };
244
- //# sourceMappingURL=editor-worker-CG2Et0Mg.js.map
249
+ //# sourceMappingURL=editor-worker-Ck24954m.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor-worker-CG2Et0Mg.js","sources":["../../../plugins/docx-editor-schema/src/constants.ts","../../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js","../../../plugins/docx-editor-schema/src/walk.ts","../src/workers/compute.ts","../src/workers/editor-worker.ts"],"sourcesContent":["/**\r\n * VerveDocs Schema —— 常量\r\n */\r\n\r\nimport type { IEditorOption } from './types'\r\n\r\n/** 当前 Schema 版本号 */\r\nexport const SCHEMA_VERSION = '4.0.0-tree'\r\n\r\n/** 默认编辑器选项 */\r\nexport const DEFAULT_EDITOR_OPTION: Required<Pick<IEditorOption,\r\n 'defaultFont' | 'defaultSize' | 'defaultLineHeight' | 'defaultRowMargin' |\r\n 'pageMode' | 'pageWidth' | 'pageHeight' | 'pageMargins' | 'scale' | 'devicePixelRatio' |\r\n 'historyMaxRecordCount'\r\n>> = {\r\n defaultFont: 'Microsoft YaHei',\r\n defaultSize: 16,\r\n defaultLineHeight: 1.5,\r\n defaultRowMargin: 5,\r\n pageMode: 'paging',\r\n pageWidth: 794, // A4 @ 96dpi\r\n pageHeight: 1123,\r\n pageMargins: [100, 120, 100, 120],\r\n scale: 1,\r\n devicePixelRatio: typeof window !== 'undefined' ? (window.devicePixelRatio || 1) : 1,\r\n historyMaxRecordCount: 100\r\n}\r\n\r\n/** 段落级属性字段名(用于从 run 上剥离/继承) */\r\nexport const PARAGRAPH_ATTR_KEYS = [\r\n 'rowFlex',\r\n 'paragraphStyleId',\r\n 'paragraphFirstLineIndent',\r\n 'paragraphIndentLeft',\r\n 'paragraphSpacingBefore',\r\n 'paragraphSpacingAfter',\r\n 'lineHeight',\r\n 'lineHeightRule',\r\n 'groupIds'\r\n] as const\r\n\r\n/** 段落容器类型 */\r\nexport const PARAGRAPH_CONTAINER_TYPES = new Set(['title', 'list'])\r\n\r\n/** 段落级块类型(占独立段) */\r\nexport const BLOCK_LEVEL_TYPES = new Set([\r\n 'title', 'list', 'table', 'image', 'pageBreak', 'separator', 'block'\r\n])\r\n\r\n/** 列表类型 */\r\nexport const LIST_TYPE = {\r\n UL: 'ul',\r\n OL: 'ol'\r\n} as const\r\n\r\n/** 列表样式(项目符号 16 种 + 编号格式 13 种,对齐 WPS 全量) */\r\nexport const LIST_STYLE = {\r\n // 项目符号\r\n DISC: 'disc',\r\n CIRCLE: 'circle',\r\n SQUARE: 'square',\r\n EMPTY_SQUARE: 'emptySquare',\r\n FILLED_DIAMOND: 'filledDiamond',\r\n DIAMOND: 'diamond',\r\n ARROW: 'arrow',\r\n ARROW_FILLED: 'arrowFilled',\r\n CHECK: 'check',\r\n CROSS: 'cross',\r\n BULLET: 'bullet',\r\n TRIANGLE: 'triangle',\r\n STAR: 'star',\r\n HEART: 'heart',\r\n DASH: 'dash',\r\n HYPHEN: 'hyphen',\r\n // 编号格式\r\n DECIMAL: 'decimal',\r\n DECIMAL_ZERO: 'decimalZero',\r\n LOWER_LETTER: 'lowerLetter',\r\n UPPER_LETTER: 'upperLetter',\r\n LOWER_ROMAN: 'lowerRoman',\r\n UPPER_ROMAN: 'upperRoman',\r\n CHINESE_COUNTING: 'chineseCounting',\r\n CHINESE_COUNTING_THOUSAND: 'chineseCountingThousand',\r\n IDEOGRAPH_DIGITAL: 'ideographDigital',\r\n JAPANESE_COUNTING: 'japaneseCounting',\r\n KOREAN_COUNTING: 'koreanCounting',\r\n TAIWANESE_COUNTING: 'taiwaneseCounting'\r\n} as const\r\n\r\n/** 段落对齐方式 */\r\nexport const ROW_FLEX = {\r\n LEFT: 'left',\r\n CENTER: 'center',\r\n RIGHT: 'right',\r\n JUSTIFY: 'justify',\r\n ALIGNMENT: 'alignment',\r\n DISTRIBUTE: 'distribute'\r\n} as const\r\n\r\n/** 标题级别 */\r\nexport const TITLE_LEVEL = {\r\n FIRST: 'first',\r\n SECOND: 'second',\r\n THIRD: 'third',\r\n FOURTH: 'fourth',\r\n FIFTH: 'fifth',\r\n SIXTH: 'sixth'\r\n} as const\r\n\r\n/** 字体族常量(对齐 WPS 常用字体,代码内引用用) */\r\nexport const FONT_FAMILY = {\r\n SIM_SUN: 'SimSun',\r\n SIM_HEI: 'SimHei',\r\n KAI_TI: 'KaiTi',\r\n FANG_SONG: 'FangSong',\r\n MICROSOFT_YAHEI: 'Microsoft YaHei',\r\n DENG_XIAN: 'DengXian',\r\n ST_SONG: 'STSong',\r\n ST_HEITI: 'STHeiti',\r\n ST_KAITI: 'STKaiti',\r\n ST_FANGSONG: 'STFangsong',\r\n ST_ZHONGSONG: 'STZhongsong',\r\n ST_XIHEI: 'STXihei',\r\n ST_XINGKAI: 'STXingkai',\r\n ST_LITI: 'STLiti',\r\n ST_XINWEI: 'STXinwei',\r\n ST_CAIYUN: 'STCaiyun',\r\n TIMES_NEW_ROMAN: 'Times New Roman',\r\n ARIAL: 'Arial',\r\n CALIBRI: 'Calibri',\r\n COURIER_NEW: 'Courier New',\r\n VERDANA: 'Verdana'\r\n} as const\r\n\r\n/**\r\n * 字体映射条目(三层结构)\r\n * - label: 显示名(工具栏下拉显示)\r\n * - value: 存储名(文档里存的,WPS/Office 兼容)\r\n * - css: CSS font-family 值(带跨平台 fallback,引用系统字体不侵权 + 开源字体兜底)\r\n * - aliases: 文档里可能存的其他名字(中文名、大小写变体等)\r\n */\r\nexport interface FontFamilyEntry {\r\n label: string\r\n value: string\r\n css: string\r\n aliases?: string[]\r\n}\r\n\r\n/**\r\n * WPS 常用字体完整映射表(16 中文字体 + 5 英文字体)\r\n * CSS fallback 策略:Windows 系统字体 → macOS 对应字体 → 开源字体兜底 → 通用字体族\r\n */\r\nexport const FONT_FAMILY_MAP: FontFamilyEntry[] = [\r\n { label: '宋体', value: 'SimSun', css: '\"SimSun\", \"Songti SC\", \"Noto Serif CJK SC\", serif', aliases: ['宋体', 'simsun'] },\r\n { label: '黑体', value: 'SimHei', css: '\"SimHei\", \"STHeiti\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['黑体', 'simhei'] },\r\n { label: '楷体', value: 'KaiTi', css: '\"KaiTi\", \"Kaiti SC\", \"STKaiti\", \"LXGW WenKai\", serif', aliases: ['楷体', 'kaiti'] },\r\n { label: '仿宋', value: 'FangSong', css: '\"FangSong\", \"STFangsong\", \"Noto Serif CJK SC\", serif', aliases: ['仿宋', 'fangsong'] },\r\n { label: '微软雅黑', value: 'Microsoft YaHei', css: '\"Microsoft YaHei\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['微软雅黑', 'microsoft yahei'] },\r\n { label: '等线', value: 'DengXian', css: '\"DengXian\", \"Noto Sans CJK SC\", sans-serif', aliases: ['等线', 'dengxian'] },\r\n { label: '华文宋体', value: 'STSong', css: '\"STSong\", \"SimSun\", \"Songti SC\", \"Noto Serif CJK SC\", serif', aliases: ['华文宋体'] },\r\n { label: '华文黑体', value: 'STHeiti', css: '\"STHeiti\", \"SimHei\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文黑体'] },\r\n { label: '华文楷体', value: 'STKaiti', css: '\"STKaiti\", \"KaiTi\", \"Kaiti SC\", \"LXGW WenKai\", serif', aliases: ['华文楷体'] },\r\n { label: '华文仿宋', value: 'STFangsong', css: '\"STFangsong\", \"FangSong\", \"Noto Serif CJK SC\", serif', aliases: ['华文仿宋'] },\r\n { label: '华文中宋', value: 'STZhongsong', css: '\"STZhongsong\", \"STSong\", \"SimSun\", \"Noto Serif CJK SC\", serif', aliases: ['华文中宋'] },\r\n { label: '华文细黑', value: 'STXihei', css: '\"STXihei\", \"STHeiti\", \"SimHei\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文细黑'] },\r\n { label: '华文行楷', value: 'STXingkai', css: '\"STXingkai\", \"STKaiti\", \"KaiTi\", \"LXGW WenKai\", serif', aliases: ['华文行楷'] },\r\n { label: '华文隶书', value: 'STLiti', css: '\"STLiti\", \"STFangsong\", \"FangSong\", \"Noto Serif CJK SC\", serif', aliases: ['华文隶书'] },\r\n { label: '华文新魏', value: 'STXinwei', css: '\"STXinwei\", \"STXihei\", \"SimHei\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文新魏'] },\r\n { label: '华文彩云', value: 'STCaiyun', css: '\"STCaiyun\", \"STSong\", \"SimSun\", \"Noto Serif CJK SC\", serif', aliases: ['华文彩云'] },\r\n { label: 'Times New Roman', value: 'Times New Roman', css: '\"Times New Roman\", \"Liberation Serif\", serif' },\r\n { label: 'Arial', value: 'Arial', css: 'Arial, \"Liberation Sans\", sans-serif' },\r\n { label: 'Calibri', value: 'Calibri', css: 'Calibri, \"Liberation Sans\", sans-serif' },\r\n { label: 'Courier New', value: 'Courier New', css: '\"Courier New\", \"Liberation Mono\", monospace' },\r\n { label: 'Verdana', value: 'Verdana', css: 'Verdana, \"DejaVu Sans\", sans-serif' }\r\n]\r\n\r\n/** 字体下拉选项(显示名列表,有序) */\r\nexport const FONT_FAMILY_LIST: string[] = FONT_FAMILY_MAP.map(e => e.label)\r\n\r\n/** 显示名 → 存储名(工具栏选中后存文档用) */\r\nexport const FONT_FAMILY_VALUE: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.map(e => [e.label, e.value])\r\n)\r\n\r\n/** 存储名/别名 → 显示名(用于回显,认中文名和英文名) */\r\nexport const FONT_FAMILY_LABEL: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.flatMap(e => [\r\n [e.value, e.label],\r\n ...(e.aliases ?? []).map(a => [a, e.label] as [string, string])\r\n ])\r\n)\r\n\r\n/** 存储名/别名 → CSS font-family 值(用于渲染,带跨平台 fallback) */\r\nexport const FONT_FAMILY_CSS: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.flatMap(e => [\r\n [e.value, e.css],\r\n ...(e.aliases ?? []).map(a => [a, e.css] as [string, string])\r\n ])\r\n)\r\n\r\n/**\r\n * WPS 字号表(中文字号名 → pt 值)\r\n * 完整覆盖 WPS 全部预设字号:初号~八号 + 小初~小六\r\n */\r\nexport const FONT_SIZE: Record<string, number> = {\r\n '初号': 42,\r\n '小初': 36,\r\n '一号': 26,\r\n '小一': 24,\r\n '二号': 22,\r\n '小二': 18,\r\n '三号': 16,\r\n '小三': 15,\r\n '四号': 14,\r\n '小四': 12,\r\n '五号': 10.5,\r\n '小五': 9,\r\n '六号': 7.5,\r\n '小六': 6.5,\r\n '七号': 5.5,\r\n '八号': 5\r\n}\r\n\r\n/**\r\n * 字号下拉选项(有序,中文字号 + 常用数字字号)\r\n * WPS 风格:先列中文字号,再列常用数字字号\r\n */\r\nexport const FONT_SIZE_LIST = [\r\n '初号', '小初', '一号', '小一', '二号', '小二', '三号', '小三', '四号', '小四',\r\n '五号', '小五', '六号', '小六', '七号', '八号',\r\n '5', '5.5', '6.5', '7.5', '8', '9', '10', '10.5', '11', '12', '14', '15', '16',\r\n '18', '20', '22', '24', '26', '28', '30', '36', '42', '48', '54', '60', '72'\r\n] as const\r\n\r\n/* ========== 纸张方向 / 表格边框 ========== */\r\n\r\n/** 纸张方向 */\r\nexport const PaperDirection = {\r\n VERTICAL: 'vertical',\r\n HORIZONTAL: 'horizontal'\r\n} as const\r\n\r\n/** 表格边框类型 */\r\nexport const TableBorder = {\r\n NONE: 'none',\r\n OUTSIDE: 'outside',\r\n ALL: 'all',\r\n INSIDE: 'inside',\r\n INSIDE_HORIZONTAL: 'inside-horizontal',\r\n INSIDE_VERTICAL: 'inside-vertical',\r\n TOP: 'top',\r\n BOTTOM: 'bottom',\r\n LEFT: 'left',\r\n RIGHT: 'right'\r\n} as const\r\n\r\nexport type TableBorderPreset = typeof TableBorder[keyof typeof TableBorder]\r\n\r\n/* ========== 单位换算(96 DPI) ========== */\r\n\r\n/** 屏幕 DPI 常量 */\r\nexport const DPI = 96\r\n\r\n/**\r\n * 磅(pt)转像素(px)\r\n * @param pt 磅值\r\n * @returns 像素值(保留两位小数)\r\n */\r\nexport function ptToPx(pt: number): number {\r\n return Math.round(pt * (DPI / 72) * 100) / 100\r\n}\r\n\r\n/**\r\n * 像素(px)转磅(pt)\r\n * @param px 像素值\r\n * @returns 磅值(保留一位小数,0.5 步进)\r\n */\r\nexport function pxToPt(px: number): number {\r\n return Math.round(px * (72 / DPI) * 2) / 2\r\n}\r\n\r\n/* ========== 纸张大小(对齐 WPS/Office,96 DPI) ========== */\r\n\r\nexport interface PaperSize {\r\n /** 纸张标识(唯一 key) */\r\n key: string\r\n /** 显示名称 */\r\n label: string\r\n /** 纸张宽度(px @ 96dpi) */\r\n width: number\r\n /** 纸张高度(px @ 96dpi) */\r\n height: number\r\n /** 分类 */\r\n category: 'a-series' | 'b-series' | 'us' | 'cn' | 'envelope' | 'other'\r\n}\r\n\r\n/**\r\n * WPS/Office 纸张预设列表(覆盖 80%+ 常用纸张)\r\n * 像素值按 96 DPI 换算:px = mm * 96 / 25.4\r\n */\r\nexport const PAPER_SIZE_LIST: PaperSize[] = [\r\n // A 系列(ISO 216)\r\n { key: 'a0', label: 'A0 (84.1×118.9cm)', width: 3179, height: 4494, category: 'a-series' },\r\n { key: 'a1', label: 'A1 (59.4×84.1cm)', width: 2245, height: 3179, category: 'a-series' },\r\n { key: 'a2', label: 'A2 (42×59.4cm)', width: 1587, height: 2245, category: 'a-series' },\r\n { key: 'a3', label: 'A3 (29.7×42cm)', width: 1123, height: 1587, category: 'a-series' },\r\n { key: 'a4', label: 'A4 (21×29.7cm)', width: 794, height: 1123, category: 'a-series' },\r\n { key: 'a5', label: 'A5 (14.8×21cm)', width: 559, height: 794, category: 'a-series' },\r\n { key: 'a6', label: 'A6 (10.5×14.8cm)', width: 397, height: 559, category: 'a-series' },\r\n // B 系列(JIS)\r\n { key: 'b4', label: 'B4 (25.7×36.4cm)', width: 971, height: 1376, category: 'b-series' },\r\n { key: 'b5', label: 'B5 (18.2×25.7cm)', width: 688, height: 971, category: 'b-series' },\r\n { key: 'b6', label: 'B6 (12.8×18.2cm)', width: 484, height: 688, category: 'b-series' },\r\n // 美式\r\n { key: 'letter', label: 'Letter (21.6×27.9cm)', width: 816, height: 1056, category: 'us' },\r\n { key: 'legal', label: 'Legal (21.6×35.6cm)', width: 816, height: 1344, category: 'us' },\r\n { key: 'tabloid', label: 'Tabloid (27.9×43.2cm)', width: 1056, height: 1633, category: 'us' },\r\n { key: 'executive', label: 'Executive (18.4×26.7cm)', width: 696, height: 1009, category: 'us' },\r\n { key: 'statement', label: 'Statement (14×21.6cm)', width: 529, height: 816, category: 'us' },\r\n { key: 'folio', label: 'Folio (21.6×33cm)', width: 816, height: 1247, category: 'us' },\r\n // 中式\r\n { key: '16k', label: '16K (19.5×27cm)', width: 737, height: 1020, category: 'cn' },\r\n { key: '32k', label: '32K (13×19cm)', width: 491, height: 718, category: 'cn' },\r\n { key: '32k-large', label: '大32K (14×20.3cm)', width: 529, height: 767, category: 'cn' },\r\n // 信封\r\n { key: 'env-10', label: '信封 #10 (10.5×24.1cm)', width: 397, height: 910, category: 'envelope' },\r\n { key: 'env-dl', label: '信封 DL (11×22cm)', width: 416, height: 831, category: 'envelope' },\r\n { key: 'env-c5', label: '信封 C5 (16.2×22.9cm)', width: 612, height: 865, category: 'envelope' },\r\n { key: 'env-c6', label: '信封 C6 (11.4×16.2cm)', width: 430, height: 612, category: 'envelope' },\r\n { key: 'env-monarch', label: '信封 Monarch (9.8×19cm)', width: 370, height: 718, category: 'envelope' },\r\n // 其他\r\n { key: 'photo-4x6', label: '照片 4×6 (10.2×15.2cm)', width: 386, height: 574, category: 'other' },\r\n { key: 'postcard', label: '明信片 (10×14.8cm)', width: 378, height: 559, category: 'other' }\r\n]\r\n\r\n/** 默认纸张大小(A4) */\r\nexport const DEFAULT_PAPER_SIZE: PaperSize = PAPER_SIZE_LIST[4]\r\n\r\n/* ========== 项目符号 / 编号样式 ========== */\r\n\r\n/** 项目符号样式 */\r\nexport const BULLET_STYLES = [\r\n { style: 'disc', icon: '●', label: '实心圆点' },\r\n { style: 'circle', icon: '○', label: '空心圆点' },\r\n { style: 'square', icon: '■', label: '实心方块' },\r\n { style: 'hollow-square', icon: '□', label: '空心方块' },\r\n { style: 'diamond', icon: '◆', label: '实心菱形' },\r\n { style: 'hollow-diamond', icon: '◇', label: '空心菱形' },\r\n { style: 'arrow', icon: '▶', label: '箭头' },\r\n { style: 'check', icon: '✓', label: '对勾' }\r\n]\r\n\r\n/** 编号样式 */\r\nexport const NUMBER_STYLES = [\r\n { style: 'decimal', numFmt: 'decimal', lvlText: '%1.', samples: ['1.', '2.', '3.'], label: '阿拉伯数字' },\r\n { style: 'decimal-bracket', numFmt: 'decimal', lvlText: '%1)', samples: ['1)', '2)', '3)'], label: '数字右括号' },\r\n { style: 'decimal-paren', numFmt: 'decimal', lvlText: '(%1)', samples: ['(1)', '(2)', '(3)'], label: '数字括号' },\r\n { style: 'upper-alpha', numFmt: 'upperLetter', lvlText: '%1.', samples: ['A.', 'B.', 'C.'], label: '大写字母' },\r\n { style: 'lower-alpha-dot', numFmt: 'lowerLetter', lvlText: '%1.', samples: ['a.', 'b.', 'c.'], label: '小写字母' },\r\n { style: 'chinese', numFmt: 'chineseCounting', lvlText: '%1、', samples: ['一、', '二、', '三、'], label: '中文数字' },\r\n { style: 'chinese-bracket', numFmt: 'chineseCounting', lvlText: '(%1)', samples: ['(一)', '(二)', '(三)'], label: '中文括号' },\r\n { style: 'decimal-circle', numFmt: 'decimalEnclosedCircle', lvlText: '%1', samples: ['①', '②', '③'], label: '圈码' }\r\n]\r\n\r\n/* ========== 行距 / 页边距 / 缩放 ========== */\r\n\r\n/** 行距选项 */\r\nexport const LINE_HEIGHT_OPTIONS = [\r\n { value: 1, label: '单倍行距' },\r\n { value: 1.15, label: '1.15 倍行距' },\r\n { value: 1.5, label: '1.5 倍行距' },\r\n { value: 2, label: '双倍行距' },\r\n { value: 2.5, label: '2.5 倍行距' },\r\n { value: 3, label: '三倍行距' }\r\n]\r\n\r\n/** 页边距预设 */\r\nexport const MARGIN_PRESETS = [\r\n { name: '普通', margins: [96, 120, 96, 120], style: { margin: '14px 18px' } },\r\n { name: '窄', margins: [48, 48, 48, 48], style: { margin: '7px 7px' } },\r\n { name: '适中', margins: [96, 72, 96, 72], style: { margin: '14px 11px' } },\r\n { name: '宽', margins: [96, 192, 96, 192], style: { margin: '14px 28px' } }\r\n]\r\n\r\n/** 缩放级别 */\r\nexport const ZOOM_LEVELS = [50, 75, 100, 125, 150, 200]\r\n\r\n/* ========== 分割线样式 ========== */\r\n\r\n/** 分割线样式 */\r\nexport const SEPARATOR_STYLES = [\r\n { name: '极细实线', type: 'solid', width: 0.5, dashArray: [0, 0] },\r\n { name: '细实线', type: 'solid', width: 1, dashArray: [0, 0] },\r\n { name: '中实线', type: 'solid', width: 2, dashArray: [0, 0] },\r\n { name: '粗实线', type: 'solid', width: 3, dashArray: [0, 0] },\r\n { name: '特粗实线', type: 'solid', width: 4, dashArray: [0, 0] },\r\n { name: '细点线', type: 'dotted', width: 0.5, dashArray: [1, 1] },\r\n { name: '点线', type: 'dotted', width: 1, dashArray: [1, 1] },\r\n { name: '粗点线', type: 'dotted', width: 2, dashArray: [1, 1] },\r\n { name: '大点线', type: 'dotted', width: 3, dashArray: [2, 2] },\r\n { name: '细短虚线', type: 'dashed', width: 0.5, dashArray: [3, 2] },\r\n { name: '短虚线', type: 'dashed', width: 1, dashArray: [3, 2] },\r\n { name: '粗短虚线', type: 'dashed', width: 2, dashArray: [3, 2] },\r\n { name: '细长虚线', type: 'dashed', width: 0.5, dashArray: [6, 3] },\r\n { name: '长虚线', type: 'dashed', width: 1, dashArray: [6, 3] },\r\n { name: '粗长虚线', type: 'dashed', width: 2, dashArray: [6, 3] },\r\n { name: '特长虚线', type: 'dashed', width: 1, dashArray: [10, 5] },\r\n { name: '点划线', type: 'dashed', width: 1, dashArray: [6, 2, 1, 2] },\r\n { name: '粗点划线', type: 'dashed', width: 2, dashArray: [6, 2, 1, 2] },\r\n { name: '双点划线', type: 'dashed', width: 1, dashArray: [6, 2, 1, 2, 1, 2] },\r\n { name: '粗双点划线', type: 'dashed', width: 2, dashArray: [6, 2, 1, 2, 1, 2] },\r\n { name: '细双线', type: 'double', width: 2, dashArray: [0, 0] },\r\n { name: '双线', type: 'double', width: 3, dashArray: [0, 0] },\r\n { name: '粗双线', type: 'double', width: 4, dashArray: [0, 0] },\r\n { name: '特粗双线', type: 'double', width: 5, dashArray: [0, 0] },\r\n { name: '三线', type: 'triple', width: 4, dashArray: [0, 0] },\r\n { name: '细波浪线', type: 'wavy', width: 0.5, dashArray: [0, 0] },\r\n { name: '波浪线', type: 'wavy', width: 1, dashArray: [0, 0] },\r\n { name: '粗波浪线', type: 'wavy', width: 2, dashArray: [0, 0] },\r\n { name: '渐变线', type: 'gradient', width: 2, dashArray: [0, 0] },\r\n { name: '阴影线', type: 'shadow', width: 2, dashArray: [0, 0] },\r\n { name: '浮雕线', type: 'emboss', width: 3, dashArray: [0, 0] }\r\n]\r\n\r\n/* ========== 标题级别映射 ========== */\r\n\r\n/** 标题级别映射 */\r\nexport const TITLE_LEVEL_MAP: Record<string, string> = {\r\n first: '标题1',\r\n second: '标题2',\r\n third: '标题3',\r\n fourth: '标题4',\r\n fifth: '标题5',\r\n sixth: '标题6'\r\n}\r\n","'use strict'\nmodule.exports = rfdc\n\nfunction copyBuffer (cur) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur)\n }\n\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n}\n\nfunction rfdc (opts) {\n opts = opts || {}\n if (opts.circles) return rfdcCircles(opts)\n\n const constructorHandlers = new Map()\n constructorHandlers.set(Date, (o) => new Date(o))\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))\n if (opts.constructorHandlers) {\n for (const handler of opts.constructorHandlers) {\n constructorHandlers.set(handler[0], handler[1])\n }\n }\n\n let handler = null\n\n return opts.proto ? cloneProto : clone\n\n function cloneArray (a, fn) {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n a2[k] = fn(cur)\n }\n }\n return a2\n }\n\n function clone (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone)\n }\n const o2 = {}\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = clone(cur)\n }\n }\n return o2\n }\n\n function cloneProto (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, cloneProto)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto)\n }\n const o2 = {}\n for (const k in o) {\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, cloneProto)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = cloneProto(cur)\n }\n }\n return o2\n }\n}\n\nfunction rfdcCircles (opts) {\n const refs = []\n const refsNew = []\n\n const constructorHandlers = new Map()\n constructorHandlers.set(Date, (o) => new Date(o))\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))\n if (opts.constructorHandlers) {\n for (const handler of opts.constructorHandlers) {\n constructorHandlers.set(handler[0], handler[1])\n }\n }\n\n let handler = null\n return opts.proto ? cloneProto : clone\n\n function cloneArray (a, fn) {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n if (index !== -1) {\n a2[k] = refsNew[index]\n } else {\n a2[k] = fn(cur)\n }\n }\n }\n return a2\n }\n\n function clone (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone)\n }\n const o2 = {}\n refs.push(o)\n refsNew.push(o2)\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n if (i !== -1) {\n o2[k] = refsNew[i]\n } else {\n o2[k] = clone(cur)\n }\n }\n }\n refs.pop()\n refsNew.pop()\n return o2\n }\n\n function cloneProto (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, cloneProto)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto)\n }\n const o2 = {}\n refs.push(o)\n refsNew.push(o2)\n for (const k in o) {\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, cloneProto)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n if (i !== -1) {\n o2[k] = refsNew[i]\n } else {\n o2[k] = cloneProto(cur)\n }\n }\n }\n refs.pop()\n refsNew.pop()\n return o2\n }\n}\n","\r\n/**\r\n * VerveDocs Schema —— 树遍历与路径寻址\r\n *\r\n * 所有遍历严格保持树形语义,不做扁平化。\r\n */\r\n\r\nimport rfdc from 'rfdc'\r\nimport type { IElement, Path, PathSegment, IPosition, ITableElement, ITd, ITr } from './types'\r\n\r\n/* -------------------- 深拷贝 -------------------- */\r\n\r\n/** rfdc 深拷贝实例(关闭原型拷贝与循环引用检测以提升性能) */\r\nconst _clone = rfdc({ proto: false, circles: false })\r\n\r\n/**\r\n * 深拷贝树节点。\r\n * @param node 待拷贝的节点\r\n * @returns 拷贝后的新节点(基本类型直接返回)\r\n */\r\nexport function cloneTree<T>(node: T): T {\r\n if (node === null || typeof node !== 'object') return node\r\n return _clone(node)\r\n}\r\n\r\n/* -------------------- 类型守卫 -------------------- */\r\n\r\n/**\r\n * 判断元素是否为段落容器(title/list 且拥有 valueList 数组)。\r\n * @param el 待判断元素\r\n * @returns 是段落容器则返回 true,并收窄类型\r\n */\r\nexport function isParagraphContainer(el: IElement): el is IElement & { valueList: IElement[] } {\r\n return (el?.type === 'title' || el?.type === 'list') && Array.isArray((el as { valueList?: unknown }).valueList)\r\n}\r\n\r\n/**\r\n * 判断元素是否为表格(type='table' 且拥有 trList 数组)。\r\n * @param el 待判断元素\r\n * @returns 是表格则返回 true,并收窄类型\r\n */\r\nexport function isTable(el: IElement): el is ITableElement {\r\n return el?.type === 'table' && Array.isArray((el as ITableElement).trList)\r\n}\r\n\r\n/* -------------------- 访问器 -------------------- */\r\n\r\n/** 遍历上下文:携带父节点、路径与索引信息 */\r\nexport interface VisitContext {\r\n /** 父节点(数组或单个元素,根数组时为 null) */\r\n parent: IElement[] | IElement | null\r\n /** 当前节点路径 */\r\n path: Path\r\n /** 在父容器中的索引 */\r\n index: number\r\n}\r\n\r\n/** 访问者函数类型:返回 false 可跳过当前节点的子树 */\r\nexport type Visitor = (node: IElement, ctx: VisitContext) => void | boolean\r\n\r\n/**\r\n * 深度优先遍历(返回 false 可跳过子树)。\r\n * 遍历顺序:elements[i] → 若为段落容器则 valueList[i];若为 table 则 trList[j].tdList[k].value[m]。\r\n */\r\nexport function walkTree(elements: IElement[], visitor: Visitor, parentPath: Path = []): void {\r\n for (let i = 0; i < elements.length; i++) {\r\n const node = elements[i]\r\n const path: Path = [...parentPath, i]\r\n const shouldDescend = visitor(node, { parent: elements, path, index: i })\r\n if (shouldDescend === false) continue\r\n\r\n if (isParagraphContainer(node)) {\r\n walkTree(node.valueList, visitor, [...path, 'valueList'])\r\n } else if (isTable(node)) {\r\n for (let tr = 0; tr < node.trList.length; tr++) {\r\n const row = node.trList[tr]\r\n for (let td = 0; td < row.tdList.length; td++) {\r\n const cell = row.tdList[td]\r\n walkTree(cell.value, visitor, [...path, 'trList', tr, 'tdList', td, 'value'])\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* -------------------- 路径寻址 -------------------- */\r\n\r\n/**\r\n * 根据路径获取节点。\r\n * 路径示例:\r\n * [3] → elements[3]\r\n * [3, 'valueList', 1] → elements[3].valueList[1]\r\n * [5, 'trList', 0, 'tdList', 2, 'value', 1] → table 第 0 行第 2 单元格第 1 子元素\r\n */\r\nexport function getByPath(root: IElement[], path: Path): IElement | null {\r\n if (path.length === 0) return null\r\n let current: unknown = root\r\n for (const seg of path) {\r\n if (current == null) return null\r\n if (typeof seg === 'number') {\r\n if (!Array.isArray(current)) return null\r\n current = current[seg]\r\n } else {\r\n current = (current as Record<string, unknown>)[seg]\r\n }\r\n }\r\n return (current as IElement) ?? null\r\n}\r\n\r\n/**\r\n * 获取路径末段对应的父容器数组。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @returns 父容器数组;若路径非法或末段不是数组索引则返回 null\r\n */\r\nexport function getParentContainer(root: IElement[], path: Path): IElement[] | null {\r\n if (path.length === 0) return null\r\n const parentPath = path.slice(0, -1)\r\n const lastSeg = path[path.length - 1]\r\n if (typeof lastSeg !== 'number') return null // 末段必须是数组索引\r\n if (parentPath.length === 0) return root\r\n let current: unknown = root\r\n for (const seg of parentPath) {\r\n if (typeof seg === 'number') {\r\n if (!Array.isArray(current)) return null\r\n current = current[seg]\r\n } else {\r\n current = (current as Record<string, unknown>)[seg]\r\n }\r\n }\r\n return Array.isArray(current) ? (current as IElement[]) : null\r\n}\r\n\r\n/**\r\n * 在路径指定位置替换节点。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @param node 新节点\r\n * @returns 替换成功返回 true,路径非法返回 false\r\n */\r\nexport function replaceAtPath(root: IElement[], path: Path, node: IElement): boolean {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return false\r\n const idx = path[path.length - 1] as number\r\n parent[idx] = node\r\n return true\r\n}\r\n\r\n/**\r\n * 在路径指定位置插入节点(插入到该索引前)。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @param node 待插入节点\r\n * @returns 插入成功返回 true,路径非法返回 false\r\n */\r\nexport function insertAtPath(root: IElement[], path: Path, node: IElement): boolean {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return false\r\n const idx = path[path.length - 1] as number\r\n parent.splice(idx, 0, node)\r\n return true\r\n}\r\n\r\n/**\r\n * 移除路径指定位置的节点。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @returns 被移除的节点;路径非法返回 null\r\n */\r\nexport function removeAtPath(root: IElement[], path: Path): IElement | null {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return null\r\n const idx = path[path.length - 1] as number\r\n const [removed] = parent.splice(idx, 1)\r\n return removed ?? null\r\n}\r\n\r\n/* -------------------- 位置工具 -------------------- */\r\n\r\n/**\r\n * 判断两条路径是否完全相同。\r\n * @param a 路径 a\r\n * @param b 路径 b\r\n * @returns 相同返回 true\r\n */\r\nexport function isSamePath(a: Path, b: Path): boolean {\r\n if (a.length !== b.length) return false\r\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false\r\n return true\r\n}\r\n\r\n/**\r\n * 比较两条路径的字典序(数字段按数值比较,字符串段按字符串比较)。\r\n * @param a 路径 a\r\n * @param b 路径 b\r\n * @returns a<b 返回负数,a=b 返回 0,a>b 返回正数\r\n */\r\nexport function comparePath(a: Path, b: Path): number {\r\n const n = Math.min(a.length, b.length)\r\n for (let i = 0; i < n; i++) {\r\n const av = a[i]; const bv = b[i]\r\n if (av === bv) continue\r\n if (typeof av === 'number' && typeof bv === 'number') return av - bv\r\n return String(av) < String(bv) ? -1 : 1\r\n }\r\n return a.length - b.length\r\n}\r\n\r\n/**\r\n * 比较两个文档位置:先比较路径,路径相同再比较 offset。\r\n * @param a 位置 a\r\n * @param b 位置 b\r\n * @returns a<b 返回负数,a=b 返回 0,a>b 返回正数\r\n */\r\nexport function comparePosition(a: IPosition, b: IPosition): number {\r\n const c = comparePath(a.path, b.path)\r\n if (c !== 0) return c\r\n return a.offset - b.offset\r\n}\r\n\r\n/* -------------------- 表格辅助 -------------------- */\r\n\r\n/**\r\n * 遍历表格所有单元格,对每个单元格调用回调。\r\n * @param table 表格元素\r\n * @param fn 回调函数,接收单元格、行、行索引、列索引\r\n */\r\nexport function forEachCell(\r\n table: ITableElement,\r\n fn: (cell: ITd, tr: ITr, trIndex: number, tdIndex: number) => void\r\n) {\r\n for (let i = 0; i < table.trList.length; i++) {\r\n const row = table.trList[i]\r\n for (let j = 0; j < row.tdList.length; j++) {\r\n fn(row.tdList[j], row, i, j)\r\n }\r\n }\r\n}\r\n\r\n/** 计算表格列数(不考虑合并) */\r\nexport function getTableColCount(table: ITableElement): number {\r\n if (Array.isArray(table.colgroup)) return table.colgroup.length\r\n return table.trList[0]?.tdList.reduce((sum, td) => sum + (td.colspan || 1), 0) ?? 0\r\n}\r\n\r\n/** 计算某段路径所在的段落容器(title/list/纯段落用父数组表示) */\r\nexport function _pathSegAsKey(seg: PathSegment): string {\r\n return typeof seg === 'number' ? String(seg) : seg\r\n}\r\n","import { walkTree } from '@vervedoc/docx-editor-schema'\r\nimport type { IElement, ITitleElement, ITextElement, PathSegment } from '@vervedoc/docx-editor-schema'\r\n\r\nconst levelMap: Record<string, number> = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6 }\r\n\r\nexport function computeToc(elements: IElement[]) {\r\n const toc: { id: string; level: number; name: string; number?: string }[] = []\r\n const counters = new Map<string, number>()\r\n walkTree(elements, (node, ctx) => {\r\n if (node.type !== 'title') return\r\n const t = node as ITitleElement\r\n const name = (t.valueList ?? []).map(v => v.type === 'text' ? (v as ITextElement).value : '').join('')\r\n const level = levelMap[t.level] ?? 1\r\n let number: string | undefined\r\n const num = (t as unknown as { listNumbering?: { numFmt: string; lvlText: string; start: number; numId?: string; abstractNumId?: string; level?: number } }).listNumbering\r\n if (num && num.numFmt !== 'bullet') {\r\n const numId = num.numId ?? num.abstractNumId ?? 'default'\r\n const numLevel = num.level ?? 0\r\n const key = `${numId}:${numLevel}`\r\n const prev = counters.get(key)\r\n const current = (prev == null ? (num.start ?? 1) - 1 : prev) + 1\r\n counters.set(key, current)\r\n for (const k of counters.keys()) {\r\n if (k.startsWith(`${numId}:`) && Number(k.slice(numId.length + 1)) > numLevel) counters.delete(k)\r\n }\r\n number = (num.lvlText ?? '%1.').replace(/%([1-9])/g, (_, d: string) => {\r\n const lvl = Number(d) - 1\r\n return String(lvl === numLevel ? current : counters.get(`${numId}:${lvl}`) ?? (num.start ?? 1))\r\n })\r\n }\r\n toc.push({ id: JSON.stringify(ctx.path), level, name, number })\r\n })\r\n return { toc }\r\n}\r\n\r\nexport function computeSearch(elements: IElement[], keyword: string) {\r\n const results: { path: PathSegment[]; offset: number; length: number }[] = []\r\n if (!keyword) return { results, count: 0 }\r\n const lowerKeyword = keyword.toLowerCase()\r\n walkTree(elements, (node, ctx) => {\r\n if (node.type !== 'text') return\r\n const text = ((node as ITextElement).value || '').toLowerCase()\r\n let idx = text.indexOf(lowerKeyword)\r\n while (idx !== -1) {\r\n results.push({ path: [...ctx.path], offset: idx, length: keyword.length })\r\n idx = text.indexOf(lowerKeyword, idx + 1)\r\n }\r\n })\r\n return { results, count: results.length }\r\n}\r\n","/// <reference lib=\"webworker\" />\r\nimport { cloneTree } from '@vervedoc/docx-editor-schema'\r\nimport type { IElement } from '@vervedoc/docx-editor-schema'\r\nimport { computeToc, computeSearch } from './compute'\r\n\r\ntype WorkerRequest =\r\n | { type: 'update'; elements: IElement[] }\r\n | { type: 'search'; keyword: string }\r\n | { type: 'clone'; data: unknown }\r\n\r\nlet currentElements: IElement[] = []\r\nself.onmessage = (e: MessageEvent<WorkerRequest>): void => {\r\n try {\r\n const req = e.data\r\n switch (req.type) {\r\n case 'update':\r\n currentElements = req.elements\r\n self.postMessage({ type: 'toc-result', ...computeToc(currentElements) })\r\n break\r\n case 'search':\r\n self.postMessage({ type: 'search-result', ...computeSearch(currentElements, req.keyword) })\r\n break\r\n case 'clone':\r\n self.postMessage({ type: 'clone-result', data: cloneTree(req.data) })\r\n break\r\n }\r\n } catch (error: any) {\r\n self.postMessage({ type: 'error', message: error?.message || String(error) })\r\n }\r\n}\r\n"],"names":["FONT_FAMILY_MAP","e","a","rfdc_1","rfdc","copyBuffer","cur","opts","rfdcCircles","constructorHandlers","o","fn","cloneArray","handler","cloneProto","clone","keys","a2","i","k","o2","refs","refsNew","index","_clone","cloneTree","node","isParagraphContainer","el","isTable","walkTree","elements","visitor","parentPath","path","tr","row","td","cell","levelMap","computeToc","toc","counters","ctx","t","name","v","level","number","num","numId","numLevel","key","prev","current","_","d","lvl","computeSearch","keyword","results","lowerKeyword","text","idx","currentElements","req","error"],"mappings":"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","x_google_ignoreList":[1]}
1
+ {"version":3,"file":"editor-worker-Ck24954m.js","sources":["../../../plugins/docx-editor-schema/src/constants.ts","../../../node_modules/.pnpm/rfdc@1.4.1/node_modules/rfdc/index.js","../../../plugins/docx-editor-schema/src/walk.ts","../src/workers/compute.ts","../src/workers/editor-worker.ts"],"sourcesContent":["/**\r\n * VerveDocs Schema —— 常量\r\n */\r\n\r\nimport type { IEditorOption } from './types'\r\n\r\n/** 当前 Schema 版本号 */\r\nexport const SCHEMA_VERSION = '4.0.0-tree'\r\n\r\n/** 默认编辑器选项 */\r\nexport const DEFAULT_EDITOR_OPTION: Required<Pick<IEditorOption,\r\n 'defaultFont' | 'defaultSize' | 'defaultLineHeight' | 'defaultRowMargin' |\r\n 'pageMode' | 'pageWidth' | 'pageHeight' | 'pageMargins' | 'scale' | 'devicePixelRatio' |\r\n 'historyMaxRecordCount'\r\n>> = {\r\n defaultFont: 'Microsoft YaHei',\r\n defaultSize: 16,\r\n defaultLineHeight: 1.5,\r\n defaultRowMargin: 5,\r\n pageMode: 'paging',\r\n pageWidth: 794, // A4 @ 96dpi\r\n pageHeight: 1123,\r\n pageMargins: [100, 120, 100, 120],\r\n scale: 1,\r\n devicePixelRatio: typeof window !== 'undefined' ? (window.devicePixelRatio || 1) : 1,\r\n historyMaxRecordCount: 100\r\n}\r\n\r\n/** 段落级属性字段名(用于从 run 上剥离/继承) */\r\nexport const PARAGRAPH_ATTR_KEYS = [\r\n 'rowFlex',\r\n 'paragraphStyleId',\r\n 'paragraphFirstLineIndent',\r\n 'paragraphIndentLeft',\r\n 'paragraphSpacingBefore',\r\n 'paragraphSpacingAfter',\r\n 'lineHeight',\r\n 'lineHeightRule',\r\n 'groupIds'\r\n] as const\r\n\r\n/** 段落容器类型 */\r\nexport const PARAGRAPH_CONTAINER_TYPES = new Set(['title', 'list'])\r\n\r\n/** 段落级块类型(占独立段) */\r\nexport const BLOCK_LEVEL_TYPES = new Set([\r\n 'title', 'list', 'table', 'image', 'pageBreak', 'separator', 'block'\r\n])\r\n\r\n/** 列表类型 */\r\nexport const LIST_TYPE = {\r\n UL: 'ul',\r\n OL: 'ol'\r\n} as const\r\n\r\n/** 列表样式(项目符号 16 种 + 编号格式 13 种,对齐 WPS 全量) */\r\nexport const LIST_STYLE = {\r\n // 项目符号\r\n DISC: 'disc',\r\n CIRCLE: 'circle',\r\n SQUARE: 'square',\r\n EMPTY_SQUARE: 'emptySquare',\r\n FILLED_DIAMOND: 'filledDiamond',\r\n DIAMOND: 'diamond',\r\n ARROW: 'arrow',\r\n ARROW_FILLED: 'arrowFilled',\r\n CHECK: 'check',\r\n CROSS: 'cross',\r\n BULLET: 'bullet',\r\n TRIANGLE: 'triangle',\r\n STAR: 'star',\r\n HEART: 'heart',\r\n DASH: 'dash',\r\n HYPHEN: 'hyphen',\r\n // 编号格式\r\n DECIMAL: 'decimal',\r\n DECIMAL_ZERO: 'decimalZero',\r\n LOWER_LETTER: 'lowerLetter',\r\n UPPER_LETTER: 'upperLetter',\r\n LOWER_ROMAN: 'lowerRoman',\r\n UPPER_ROMAN: 'upperRoman',\r\n CHINESE_COUNTING: 'chineseCounting',\r\n CHINESE_COUNTING_THOUSAND: 'chineseCountingThousand',\r\n IDEOGRAPH_DIGITAL: 'ideographDigital',\r\n JAPANESE_COUNTING: 'japaneseCounting',\r\n KOREAN_COUNTING: 'koreanCounting',\r\n TAIWANESE_COUNTING: 'taiwaneseCounting'\r\n} as const\r\n\r\n/** 段落对齐方式 */\r\nexport const ROW_FLEX = {\r\n LEFT: 'left',\r\n CENTER: 'center',\r\n RIGHT: 'right',\r\n JUSTIFY: 'justify',\r\n ALIGNMENT: 'alignment',\r\n DISTRIBUTE: 'distribute'\r\n} as const\r\n\r\n/** 标题级别 */\r\nexport const TITLE_LEVEL = {\r\n FIRST: 'first',\r\n SECOND: 'second',\r\n THIRD: 'third',\r\n FOURTH: 'fourth',\r\n FIFTH: 'fifth',\r\n SIXTH: 'sixth'\r\n} as const\r\n\r\n/** 字体族常量(对齐 WPS 常用字体,代码内引用用) */\r\nexport const FONT_FAMILY = {\r\n SIM_SUN: 'SimSun',\r\n SIM_HEI: 'SimHei',\r\n KAI_TI: 'KaiTi',\r\n FANG_SONG: 'FangSong',\r\n MICROSOFT_YAHEI: 'Microsoft YaHei',\r\n DENG_XIAN: 'DengXian',\r\n ST_SONG: 'STSong',\r\n ST_HEITI: 'STHeiti',\r\n ST_KAITI: 'STKaiti',\r\n ST_FANGSONG: 'STFangsong',\r\n ST_ZHONGSONG: 'STZhongsong',\r\n ST_XIHEI: 'STXihei',\r\n ST_XINGKAI: 'STXingkai',\r\n ST_LITI: 'STLiti',\r\n ST_XINWEI: 'STXinwei',\r\n ST_CAIYUN: 'STCaiyun',\r\n TIMES_NEW_ROMAN: 'Times New Roman',\r\n ARIAL: 'Arial',\r\n CALIBRI: 'Calibri',\r\n COURIER_NEW: 'Courier New',\r\n VERDANA: 'Verdana'\r\n} as const\r\n\r\n/**\r\n * 字体映射条目(三层结构)\r\n * - label: 显示名(工具栏下拉显示)\r\n * - value: 存储名(文档里存的,WPS/Office 兼容)\r\n * - css: CSS font-family 值(带跨平台 fallback,引用系统字体不侵权 + 开源字体兜底)\r\n * - aliases: 文档里可能存的其他名字(中文名、大小写变体等)\r\n */\r\nexport interface FontFamilyEntry {\r\n label: string\r\n value: string\r\n css: string\r\n aliases?: string[]\r\n}\r\n\r\n/**\r\n * WPS 常用字体完整映射表(16 中文字体 + 5 英文字体)\r\n * CSS fallback 策略:Windows 系统字体 → macOS 对应字体 → 开源字体兜底 → 通用字体族\r\n */\r\nexport const FONT_FAMILY_MAP: FontFamilyEntry[] = [\r\n { label: '宋体', value: 'SimSun', css: '\"SimSun\", \"Songti SC\", \"Noto Serif CJK SC\", serif', aliases: ['宋体', 'simsun'] },\r\n { label: '黑体', value: 'SimHei', css: '\"SimHei\", \"STHeiti\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['黑体', 'simhei'] },\r\n { label: '楷体', value: 'KaiTi', css: '\"KaiTi\", \"Kaiti SC\", \"STKaiti\", \"LXGW WenKai\", serif', aliases: ['楷体', 'kaiti'] },\r\n { label: '仿宋', value: 'FangSong', css: '\"FangSong\", \"STFangsong\", \"Noto Serif CJK SC\", serif', aliases: ['仿宋', 'fangsong'] },\r\n { label: '微软雅黑', value: 'Microsoft YaHei', css: '\"Microsoft YaHei\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['微软雅黑', 'microsoft yahei'] },\r\n { label: '等线', value: 'DengXian', css: '\"DengXian\", \"Noto Sans CJK SC\", sans-serif', aliases: ['等线', 'dengxian'] },\r\n { label: '华文宋体', value: 'STSong', css: '\"STSong\", \"SimSun\", \"Songti SC\", \"Noto Serif CJK SC\", serif', aliases: ['华文宋体'] },\r\n { label: '华文黑体', value: 'STHeiti', css: '\"STHeiti\", \"SimHei\", \"PingFang SC\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文黑体'] },\r\n { label: '华文楷体', value: 'STKaiti', css: '\"STKaiti\", \"KaiTi\", \"Kaiti SC\", \"LXGW WenKai\", serif', aliases: ['华文楷体'] },\r\n { label: '华文仿宋', value: 'STFangsong', css: '\"STFangsong\", \"FangSong\", \"Noto Serif CJK SC\", serif', aliases: ['华文仿宋'] },\r\n { label: '华文中宋', value: 'STZhongsong', css: '\"STZhongsong\", \"STSong\", \"SimSun\", \"Noto Serif CJK SC\", serif', aliases: ['华文中宋'] },\r\n { label: '华文细黑', value: 'STXihei', css: '\"STXihei\", \"STHeiti\", \"SimHei\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文细黑'] },\r\n { label: '华文行楷', value: 'STXingkai', css: '\"STXingkai\", \"STKaiti\", \"KaiTi\", \"LXGW WenKai\", serif', aliases: ['华文行楷'] },\r\n { label: '华文隶书', value: 'STLiti', css: '\"STLiti\", \"STFangsong\", \"FangSong\", \"Noto Serif CJK SC\", serif', aliases: ['华文隶书'] },\r\n { label: '华文新魏', value: 'STXinwei', css: '\"STXinwei\", \"STXihei\", \"SimHei\", \"Noto Sans CJK SC\", sans-serif', aliases: ['华文新魏'] },\r\n { label: '华文彩云', value: 'STCaiyun', css: '\"STCaiyun\", \"STSong\", \"SimSun\", \"Noto Serif CJK SC\", serif', aliases: ['华文彩云'] },\r\n { label: 'Times New Roman', value: 'Times New Roman', css: '\"Times New Roman\", \"Liberation Serif\", serif' },\r\n { label: 'Arial', value: 'Arial', css: 'Arial, \"Liberation Sans\", sans-serif' },\r\n { label: 'Calibri', value: 'Calibri', css: 'Calibri, \"Liberation Sans\", sans-serif' },\r\n { label: 'Courier New', value: 'Courier New', css: '\"Courier New\", \"Liberation Mono\", monospace' },\r\n { label: 'Verdana', value: 'Verdana', css: 'Verdana, \"DejaVu Sans\", sans-serif' }\r\n]\r\n\r\n/** 字体下拉选项(显示名列表,有序) */\r\nexport const FONT_FAMILY_LIST: string[] = FONT_FAMILY_MAP.map(e => e.label)\r\n\r\n/** 显示名 → 存储名(工具栏选中后存文档用) */\r\nexport const FONT_FAMILY_VALUE: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.map(e => [e.label, e.value])\r\n)\r\n\r\n/** 存储名/别名 → 显示名(用于回显,认中文名和英文名) */\r\nexport const FONT_FAMILY_LABEL: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.flatMap(e => [\r\n [e.value, e.label],\r\n ...(e.aliases ?? []).map(a => [a, e.label] as [string, string])\r\n ])\r\n)\r\n\r\n/** 存储名/别名 → CSS font-family 值(用于渲染,带跨平台 fallback) */\r\nexport const FONT_FAMILY_CSS: Record<string, string> = Object.fromEntries(\r\n FONT_FAMILY_MAP.flatMap(e => [\r\n [e.value, e.css],\r\n ...(e.aliases ?? []).map(a => [a, e.css] as [string, string])\r\n ])\r\n)\r\n\r\n/**\r\n * WPS 字号表(中文字号名 → pt 值)\r\n * 完整覆盖 WPS 全部预设字号:初号~八号 + 小初~小六\r\n */\r\nexport const FONT_SIZE: Record<string, number> = {\r\n '初号': 42,\r\n '小初': 36,\r\n '一号': 26,\r\n '小一': 24,\r\n '二号': 22,\r\n '小二': 18,\r\n '三号': 16,\r\n '小三': 15,\r\n '四号': 14,\r\n '小四': 12,\r\n '五号': 10.5,\r\n '小五': 9,\r\n '六号': 7.5,\r\n '小六': 6.5,\r\n '七号': 5.5,\r\n '八号': 5\r\n}\r\n\r\n/**\r\n * 字号下拉选项(有序,中文字号 + 常用数字字号)\r\n * WPS 风格:先列中文字号,再列常用数字字号\r\n */\r\nexport const FONT_SIZE_LIST = [\r\n '初号', '小初', '一号', '小一', '二号', '小二', '三号', '小三', '四号', '小四',\r\n '五号', '小五', '六号', '小六', '七号', '八号',\r\n '5', '5.5', '6.5', '7.5', '8', '9', '10', '10.5', '11', '12', '14', '15', '16',\r\n '18', '20', '22', '24', '26', '28', '30', '36', '42', '48', '54', '60', '72'\r\n] as const\r\n\r\n/* ========== 纸张方向 / 表格边框 ========== */\r\n\r\n/** 纸张方向 */\r\nexport const PaperDirection = {\r\n VERTICAL: 'vertical',\r\n HORIZONTAL: 'horizontal'\r\n} as const\r\n\r\n/** 表格边框类型 */\r\nexport const TableBorder = {\r\n NONE: 'none',\r\n OUTSIDE: 'outside',\r\n ALL: 'all',\r\n INSIDE: 'inside',\r\n INSIDE_HORIZONTAL: 'inside-horizontal',\r\n INSIDE_VERTICAL: 'inside-vertical',\r\n TOP: 'top',\r\n BOTTOM: 'bottom',\r\n LEFT: 'left',\r\n RIGHT: 'right'\r\n} as const\r\n\r\nexport type TableBorderPreset = typeof TableBorder[keyof typeof TableBorder]\r\n\r\n/* ========== 单位换算(96 DPI) ========== */\r\n\r\n/** 屏幕 DPI 常量 */\r\nexport const DPI = 96\r\n\r\n/**\r\n * 磅(pt)转像素(px)\r\n * @param pt 磅值\r\n * @returns 像素值(保留两位小数)\r\n */\r\nexport function ptToPx(pt: number): number {\r\n return Math.round(pt * (DPI / 72) * 100) / 100\r\n}\r\n\r\n/**\r\n * 像素(px)转磅(pt)\r\n * @param px 像素值\r\n * @returns 磅值(保留一位小数,0.5 步进)\r\n */\r\nexport function pxToPt(px: number): number {\r\n return Math.round(px * (72 / DPI) * 2) / 2\r\n}\r\n\r\n/* ========== 纸张大小(对齐 WPS/Office,96 DPI) ========== */\r\n\r\nexport interface PaperSize {\r\n /** 纸张标识(唯一 key) */\r\n key: string\r\n /** 显示名称 */\r\n label: string\r\n /** 纸张宽度(px @ 96dpi) */\r\n width: number\r\n /** 纸张高度(px @ 96dpi) */\r\n height: number\r\n /** 分类 */\r\n category: 'a-series' | 'b-series' | 'us' | 'cn' | 'envelope' | 'other'\r\n}\r\n\r\n/**\r\n * WPS/Office 纸张预设列表(覆盖 80%+ 常用纸张)\r\n * 像素值按 96 DPI 换算:px = mm * 96 / 25.4\r\n */\r\nexport const PAPER_SIZE_LIST: PaperSize[] = [\r\n // A 系列(ISO 216)\r\n { key: 'a0', label: 'A0 (84.1×118.9cm)', width: 3179, height: 4494, category: 'a-series' },\r\n { key: 'a1', label: 'A1 (59.4×84.1cm)', width: 2245, height: 3179, category: 'a-series' },\r\n { key: 'a2', label: 'A2 (42×59.4cm)', width: 1587, height: 2245, category: 'a-series' },\r\n { key: 'a3', label: 'A3 (29.7×42cm)', width: 1123, height: 1587, category: 'a-series' },\r\n { key: 'a4', label: 'A4 (21×29.7cm)', width: 794, height: 1123, category: 'a-series' },\r\n { key: 'a5', label: 'A5 (14.8×21cm)', width: 559, height: 794, category: 'a-series' },\r\n { key: 'a6', label: 'A6 (10.5×14.8cm)', width: 397, height: 559, category: 'a-series' },\r\n // B 系列(JIS)\r\n { key: 'b4', label: 'B4 (25.7×36.4cm)', width: 971, height: 1376, category: 'b-series' },\r\n { key: 'b5', label: 'B5 (18.2×25.7cm)', width: 688, height: 971, category: 'b-series' },\r\n { key: 'b6', label: 'B6 (12.8×18.2cm)', width: 484, height: 688, category: 'b-series' },\r\n // 美式\r\n { key: 'letter', label: 'Letter (21.6×27.9cm)', width: 816, height: 1056, category: 'us' },\r\n { key: 'legal', label: 'Legal (21.6×35.6cm)', width: 816, height: 1344, category: 'us' },\r\n { key: 'tabloid', label: 'Tabloid (27.9×43.2cm)', width: 1056, height: 1633, category: 'us' },\r\n { key: 'executive', label: 'Executive (18.4×26.7cm)', width: 696, height: 1009, category: 'us' },\r\n { key: 'statement', label: 'Statement (14×21.6cm)', width: 529, height: 816, category: 'us' },\r\n { key: 'folio', label: 'Folio (21.6×33cm)', width: 816, height: 1247, category: 'us' },\r\n // 中式\r\n { key: '16k', label: '16K (19.5×27cm)', width: 737, height: 1020, category: 'cn' },\r\n { key: '32k', label: '32K (13×19cm)', width: 491, height: 718, category: 'cn' },\r\n { key: '32k-large', label: '大32K (14×20.3cm)', width: 529, height: 767, category: 'cn' },\r\n // 信封\r\n { key: 'env-10', label: '信封 #10 (10.5×24.1cm)', width: 397, height: 910, category: 'envelope' },\r\n { key: 'env-dl', label: '信封 DL (11×22cm)', width: 416, height: 831, category: 'envelope' },\r\n { key: 'env-c5', label: '信封 C5 (16.2×22.9cm)', width: 612, height: 865, category: 'envelope' },\r\n { key: 'env-c6', label: '信封 C6 (11.4×16.2cm)', width: 430, height: 612, category: 'envelope' },\r\n { key: 'env-monarch', label: '信封 Monarch (9.8×19cm)', width: 370, height: 718, category: 'envelope' },\r\n // 其他\r\n { key: 'photo-4x6', label: '照片 4×6 (10.2×15.2cm)', width: 386, height: 574, category: 'other' },\r\n { key: 'postcard', label: '明信片 (10×14.8cm)', width: 378, height: 559, category: 'other' }\r\n]\r\n\r\n/** 默认纸张大小(A4) */\r\nexport const DEFAULT_PAPER_SIZE: PaperSize = PAPER_SIZE_LIST[4]\r\n\r\n/* ========== 项目符号 / 编号样式 ========== */\r\n\r\n/** 项目符号样式 */\r\nexport const BULLET_STYLES = [\r\n { style: 'disc', icon: '●', label: '实心圆点' },\r\n { style: 'circle', icon: '○', label: '空心圆点' },\r\n { style: 'square', icon: '■', label: '实心方块' },\r\n { style: 'hollow-square', icon: '□', label: '空心方块' },\r\n { style: 'diamond', icon: '◆', label: '实心菱形' },\r\n { style: 'hollow-diamond', icon: '◇', label: '空心菱形' },\r\n { style: 'arrow', icon: '▶', label: '箭头' },\r\n { style: 'check', icon: '✓', label: '对勾' }\r\n]\r\n\r\n/** 编号样式 */\r\nexport const NUMBER_STYLES = [\r\n { style: 'decimal', numFmt: 'decimal', lvlText: '%1.', samples: ['1.', '2.', '3.'], label: '阿拉伯数字' },\r\n { style: 'decimal-bracket', numFmt: 'decimal', lvlText: '%1)', samples: ['1)', '2)', '3)'], label: '数字右括号' },\r\n { style: 'decimal-paren', numFmt: 'decimal', lvlText: '(%1)', samples: ['(1)', '(2)', '(3)'], label: '数字括号' },\r\n { style: 'upper-alpha', numFmt: 'upperLetter', lvlText: '%1.', samples: ['A.', 'B.', 'C.'], label: '大写字母' },\r\n { style: 'lower-alpha-dot', numFmt: 'lowerLetter', lvlText: '%1.', samples: ['a.', 'b.', 'c.'], label: '小写字母' },\r\n { style: 'chinese', numFmt: 'chineseCounting', lvlText: '%1、', samples: ['一、', '二、', '三、'], label: '中文数字' },\r\n { style: 'chinese-bracket', numFmt: 'chineseCounting', lvlText: '(%1)', samples: ['(一)', '(二)', '(三)'], label: '中文括号' },\r\n { style: 'decimal-circle', numFmt: 'decimalEnclosedCircle', lvlText: '%1', samples: ['①', '②', '③'], label: '圈码' }\r\n]\r\n\r\n/* ========== 行距 / 页边距 / 缩放 ========== */\r\n\r\n/** 行距选项 */\r\nexport const LINE_HEIGHT_OPTIONS = [\r\n { value: 1, label: '单倍行距' },\r\n { value: 1.15, label: '1.15 倍行距' },\r\n { value: 1.5, label: '1.5 倍行距' },\r\n { value: 2, label: '双倍行距' },\r\n { value: 2.5, label: '2.5 倍行距' },\r\n { value: 3, label: '三倍行距' }\r\n]\r\n\r\n/** 页边距预设 */\r\nexport const MARGIN_PRESETS = [\r\n { name: '普通', margins: [96, 120, 96, 120], style: { margin: '14px 18px' } },\r\n { name: '窄', margins: [48, 48, 48, 48], style: { margin: '7px 7px' } },\r\n { name: '适中', margins: [96, 72, 96, 72], style: { margin: '14px 11px' } },\r\n { name: '宽', margins: [96, 192, 96, 192], style: { margin: '14px 28px' } }\r\n]\r\n\r\n/** 缩放级别 */\r\nexport const ZOOM_LEVELS = [50, 75, 100, 125, 150, 200]\r\n\r\n/* ========== 分割线样式 ========== */\r\n\r\n/** 分割线样式 */\r\nexport const SEPARATOR_STYLES = [\r\n { name: '极细实线', type: 'solid', width: 0.5, dashArray: [0, 0] },\r\n { name: '细实线', type: 'solid', width: 1, dashArray: [0, 0] },\r\n { name: '中实线', type: 'solid', width: 2, dashArray: [0, 0] },\r\n { name: '粗实线', type: 'solid', width: 3, dashArray: [0, 0] },\r\n { name: '特粗实线', type: 'solid', width: 4, dashArray: [0, 0] },\r\n { name: '细点线', type: 'dotted', width: 0.5, dashArray: [1, 1] },\r\n { name: '点线', type: 'dotted', width: 1, dashArray: [1, 1] },\r\n { name: '粗点线', type: 'dotted', width: 2, dashArray: [1, 1] },\r\n { name: '大点线', type: 'dotted', width: 3, dashArray: [2, 2] },\r\n { name: '细短虚线', type: 'dashed', width: 0.5, dashArray: [3, 2] },\r\n { name: '短虚线', type: 'dashed', width: 1, dashArray: [3, 2] },\r\n { name: '粗短虚线', type: 'dashed', width: 2, dashArray: [3, 2] },\r\n { name: '细长虚线', type: 'dashed', width: 0.5, dashArray: [6, 3] },\r\n { name: '长虚线', type: 'dashed', width: 1, dashArray: [6, 3] },\r\n { name: '粗长虚线', type: 'dashed', width: 2, dashArray: [6, 3] },\r\n { name: '特长虚线', type: 'dashed', width: 1, dashArray: [10, 5] },\r\n { name: '点划线', type: 'dashed', width: 1, dashArray: [6, 2, 1, 2] },\r\n { name: '粗点划线', type: 'dashed', width: 2, dashArray: [6, 2, 1, 2] },\r\n { name: '双点划线', type: 'dashed', width: 1, dashArray: [6, 2, 1, 2, 1, 2] },\r\n { name: '粗双点划线', type: 'dashed', width: 2, dashArray: [6, 2, 1, 2, 1, 2] },\r\n { name: '细双线', type: 'double', width: 2, dashArray: [0, 0] },\r\n { name: '双线', type: 'double', width: 3, dashArray: [0, 0] },\r\n { name: '粗双线', type: 'double', width: 4, dashArray: [0, 0] },\r\n { name: '特粗双线', type: 'double', width: 5, dashArray: [0, 0] },\r\n { name: '三线', type: 'triple', width: 4, dashArray: [0, 0] },\r\n { name: '细波浪线', type: 'wavy', width: 0.5, dashArray: [0, 0] },\r\n { name: '波浪线', type: 'wavy', width: 1, dashArray: [0, 0] },\r\n { name: '粗波浪线', type: 'wavy', width: 2, dashArray: [0, 0] },\r\n { name: '渐变线', type: 'gradient', width: 2, dashArray: [0, 0] },\r\n { name: '阴影线', type: 'shadow', width: 2, dashArray: [0, 0] },\r\n { name: '浮雕线', type: 'emboss', width: 3, dashArray: [0, 0] }\r\n]\r\n\r\n/* ========== 标题级别映射 ========== */\r\n\r\n/** 标题级别映射 */\r\nexport const TITLE_LEVEL_MAP: Record<string, string> = {\r\n first: '标题1',\r\n second: '标题2',\r\n third: '标题3',\r\n fourth: '标题4',\r\n fifth: '标题5',\r\n sixth: '标题6'\r\n}\r\n","'use strict'\nmodule.exports = rfdc\n\nfunction copyBuffer (cur) {\n if (cur instanceof Buffer) {\n return Buffer.from(cur)\n }\n\n return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n}\n\nfunction rfdc (opts) {\n opts = opts || {}\n if (opts.circles) return rfdcCircles(opts)\n\n const constructorHandlers = new Map()\n constructorHandlers.set(Date, (o) => new Date(o))\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))\n if (opts.constructorHandlers) {\n for (const handler of opts.constructorHandlers) {\n constructorHandlers.set(handler[0], handler[1])\n }\n }\n\n let handler = null\n\n return opts.proto ? cloneProto : clone\n\n function cloneArray (a, fn) {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n a2[k] = fn(cur)\n }\n }\n return a2\n }\n\n function clone (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone)\n }\n const o2 = {}\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = clone(cur)\n }\n }\n return o2\n }\n\n function cloneProto (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, cloneProto)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto)\n }\n const o2 = {}\n for (const k in o) {\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, cloneProto)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n o2[k] = cloneProto(cur)\n }\n }\n return o2\n }\n}\n\nfunction rfdcCircles (opts) {\n const refs = []\n const refsNew = []\n\n const constructorHandlers = new Map()\n constructorHandlers.set(Date, (o) => new Date(o))\n constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))\n if (opts.constructorHandlers) {\n for (const handler of opts.constructorHandlers) {\n constructorHandlers.set(handler[0], handler[1])\n }\n }\n\n let handler = null\n return opts.proto ? cloneProto : clone\n\n function cloneArray (a, fn) {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n } else if (ArrayBuffer.isView(cur)) {\n a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n if (index !== -1) {\n a2[k] = refsNew[index]\n } else {\n a2[k] = fn(cur)\n }\n }\n }\n return a2\n }\n\n function clone (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, clone)\n }\n const o2 = {}\n refs.push(o)\n refsNew.push(o2)\n for (const k in o) {\n if (Object.hasOwnProperty.call(o, k) === false) continue\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n if (i !== -1) {\n o2[k] = refsNew[i]\n } else {\n o2[k] = clone(cur)\n }\n }\n }\n refs.pop()\n refsNew.pop()\n return o2\n }\n\n function cloneProto (o) {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, cloneProto)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {\n return handler(o, cloneProto)\n }\n const o2 = {}\n refs.push(o)\n refsNew.push(o2)\n for (const k in o) {\n const cur = o[k]\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, cloneProto)\n } else if (ArrayBuffer.isView(cur)) {\n o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n if (i !== -1) {\n o2[k] = refsNew[i]\n } else {\n o2[k] = cloneProto(cur)\n }\n }\n }\n refs.pop()\n refsNew.pop()\n return o2\n }\n}\n","\r\n/**\r\n * VerveDocs Schema —— 树遍历与路径寻址\r\n *\r\n * 所有遍历严格保持树形语义,不做扁平化。\r\n */\r\n\r\nimport rfdc from 'rfdc'\r\nimport type { IElement, Path, PathSegment, IPosition, ITableElement, ITd, ITr, IControlElement, ControlDataValue } from './types'\r\n\r\n/* -------------------- 深拷贝 -------------------- */\r\n\r\n/** rfdc 深拷贝实例(关闭原型拷贝与循环引用检测以提升性能) */\r\nconst _clone = rfdc({ proto: false, circles: false })\r\n\r\n/**\r\n * 深拷贝树节点。\r\n * @param node 待拷贝的节点\r\n * @returns 拷贝后的新节点(基本类型直接返回)\r\n */\r\nexport function cloneTree<T>(node: T): T {\r\n if (node === null || typeof node !== 'object') return node\r\n return _clone(node)\r\n}\r\n\r\n/* -------------------- 类型守卫 -------------------- */\r\n\r\n/**\r\n * 判断元素是否为段落容器(title/list 且拥有 valueList 数组)。\r\n * @param el 待判断元素\r\n * @returns 是段落容器则返回 true,并收窄类型\r\n */\r\nexport function isParagraphContainer(el: IElement): el is IElement & { valueList: IElement[] } {\r\n return (el?.type === 'title' || el?.type === 'list') && Array.isArray((el as { valueList?: unknown }).valueList)\r\n}\r\n\r\n/**\r\n * 判断元素是否为表格(type='table' 且拥有 trList 数组)。\r\n * @param el 待判断元素\r\n * @returns 是表格则返回 true,并收窄类型\r\n */\r\nexport function isTable(el: IElement): el is ITableElement {\r\n return el?.type === 'table' && Array.isArray((el as ITableElement).trList)\r\n}\r\n\r\n/**\r\n * 判断元素是否为内置内容控件(type='control' 且 control 配置存在)。\r\n * @param el 待判断元素\r\n * @returns 是控件则返回 true,并收窄类型\r\n */\r\nexport function isControl(el: IElement): el is IControlElement {\r\n return el?.type === 'control' && typeof (el as IControlElement).control === 'object' && (el as IControlElement).control !== null\r\n}\r\n\r\n/* -------------------- 访问器 -------------------- */\r\n\r\n/** 遍历上下文:携带父节点、路径与索引信息 */\r\nexport interface VisitContext {\r\n /** 父节点(数组或单个元素,根数组时为 null) */\r\n parent: IElement[] | IElement | null\r\n /** 当前节点路径 */\r\n path: Path\r\n /** 在父容器中的索引 */\r\n index: number\r\n}\r\n\r\n/** 访问者函数类型:返回 false 可跳过当前节点的子树 */\r\nexport type Visitor = (node: IElement, ctx: VisitContext) => void | boolean\r\n\r\n/**\r\n * 深度优先遍历(返回 false 可跳过子树)。\r\n * 遍历顺序:elements[i] → 若为段落容器则 valueList[i];若为 table 则 trList[j].tdList[k].value[m]。\r\n */\r\nexport function walkTree(elements: IElement[], visitor: Visitor, parentPath: Path = []): void {\r\n for (let i = 0; i < elements.length; i++) {\r\n const node = elements[i]\r\n const path: Path = [...parentPath, i]\r\n const shouldDescend = visitor(node, { parent: elements, path, index: i })\r\n if (shouldDescend === false) continue\r\n\r\n if (isParagraphContainer(node)) {\r\n walkTree(node.valueList, visitor, [...path, 'valueList'])\r\n } else if ((isControl(node) || node.type === 'hyperlink') && Array.isArray(node.valueList)) {\r\n walkTree(node.valueList, visitor, [...path, 'valueList'])\r\n } else if (isTable(node)) {\r\n for (let tr = 0; tr < node.trList.length; tr++) {\r\n const row = node.trList[tr]\r\n for (let td = 0; td < row.tdList.length; td++) {\r\n const cell = row.tdList[td]\r\n walkTree(cell.value, visitor, [...path, 'trList', tr, 'tdList', td, 'value'])\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* -------------------- 控件归一化 -------------------- */\r\n\r\n/**\r\n * 将旧的 checkbox/radio/date 类型元素归一化为统一的 control 类型。\r\n * 在文档加载边界调用,确保历史数据平滑迁移到新模型。\r\n * 保留未知字段,不丢弃原始数据。\r\n */\r\nexport function normalizeControlElement(el: IElement): IElement {\r\n if (el.type === 'checkbox') {\r\n const old = el as IElement & { value?: string }\r\n const checked = old.value === 'true' || old.value === '1' || old.value === 'checked'\r\n return {\r\n ...el,\r\n type: 'control' as const,\r\n control: { kind: 'checkbox' as const },\r\n dataValue: checked as ControlDataValue,\r\n value: old.value ?? '',\r\n } as IControlElement\r\n }\r\n if (el.type === 'radio') {\r\n const old = el as IElement & { value?: string }\r\n return {\r\n ...el,\r\n type: 'control' as const,\r\n control: { kind: 'radioGroup' as const },\r\n dataValue: (old.value ?? null) as ControlDataValue,\r\n value: old.value ?? '',\r\n } as IControlElement\r\n }\r\n if (el.type === 'date') {\r\n const old = el as IElement & { value?: string; valueList?: { value: string }[]; dateFormat?: string }\r\n const dateValue = old.valueList?.[0]?.value ?? null\r\n return {\r\n ...el,\r\n type: 'control' as const,\r\n control: { kind: 'date' as const, format: old.dateFormat },\r\n dataValue: dateValue as ControlDataValue,\r\n value: dateValue ?? old.value ?? '',\r\n } as IControlElement\r\n }\r\n return el\r\n}\r\n\r\n/**\r\n * 对整棵文档树执行控件归一化(原地替换节点)。\r\n * 遍历段落容器、控件 valueList、表格单元格,将旧类型元素转换为统一 control 类型。\r\n */\r\nexport function normalizeControlTree(elements: IElement[]): IElement[] {\r\n for (let i = 0; i < elements.length; i++) {\r\n elements[i] = normalizeControlElement(elements[i])\r\n const node = elements[i]\r\n if (isParagraphContainer(node)) {\r\n normalizeControlTree(node.valueList)\r\n } else if (isControl(node) && Array.isArray(node.valueList)) {\r\n normalizeControlTree(node.valueList)\r\n } else if (isTable(node)) {\r\n for (const tr of node.trList) {\r\n for (const td of tr.tdList) {\r\n normalizeControlTree(td.value)\r\n }\r\n }\r\n }\r\n }\r\n return elements\r\n}\r\n\r\n/* -------------------- 路径寻址 -------------------- */\r\n\r\n/**\r\n * 根据路径获取节点。\r\n * 路径示例:\r\n * [3] → elements[3]\r\n * [3, 'valueList', 1] → elements[3].valueList[1]\r\n * [5, 'trList', 0, 'tdList', 2, 'value', 1] → table 第 0 行第 2 单元格第 1 子元素\r\n */\r\nexport function getByPath(root: IElement[], path: Path): IElement | null {\r\n if (path.length === 0) return null\r\n let current: unknown = root\r\n for (const seg of path) {\r\n if (current == null) return null\r\n if (typeof seg === 'number') {\r\n if (!Array.isArray(current)) return null\r\n current = current[seg]\r\n } else {\r\n current = (current as Record<string, unknown>)[seg]\r\n }\r\n }\r\n return (current as IElement) ?? null\r\n}\r\n\r\n/**\r\n * 获取路径末段对应的父容器数组。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @returns 父容器数组;若路径非法或末段不是数组索引则返回 null\r\n */\r\nexport function getParentContainer(root: IElement[], path: Path): IElement[] | null {\r\n if (path.length === 0) return null\r\n const parentPath = path.slice(0, -1)\r\n const lastSeg = path[path.length - 1]\r\n if (typeof lastSeg !== 'number') return null // 末段必须是数组索引\r\n if (parentPath.length === 0) return root\r\n let current: unknown = root\r\n for (const seg of parentPath) {\r\n if (typeof seg === 'number') {\r\n if (!Array.isArray(current)) return null\r\n current = current[seg]\r\n } else {\r\n current = (current as Record<string, unknown>)[seg]\r\n }\r\n }\r\n return Array.isArray(current) ? (current as IElement[]) : null\r\n}\r\n\r\n/**\r\n * 在路径指定位置替换节点。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @param node 新节点\r\n * @returns 替换成功返回 true,路径非法返回 false\r\n */\r\nexport function replaceAtPath(root: IElement[], path: Path, node: IElement): boolean {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return false\r\n const idx = path[path.length - 1] as number\r\n parent[idx] = node\r\n return true\r\n}\r\n\r\n/**\r\n * 在路径指定位置插入节点(插入到该索引前)。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @param node 待插入节点\r\n * @returns 插入成功返回 true,路径非法返回 false\r\n */\r\nexport function insertAtPath(root: IElement[], path: Path, node: IElement): boolean {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return false\r\n const idx = path[path.length - 1] as number\r\n parent.splice(idx, 0, node)\r\n return true\r\n}\r\n\r\n/**\r\n * 移除路径指定位置的节点。\r\n * @param root 根元素数组\r\n * @param path 目标路径\r\n * @returns 被移除的节点;路径非法返回 null\r\n */\r\nexport function removeAtPath(root: IElement[], path: Path): IElement | null {\r\n const parent = getParentContainer(root, path)\r\n if (!parent) return null\r\n const idx = path[path.length - 1] as number\r\n const [removed] = parent.splice(idx, 1)\r\n return removed ?? null\r\n}\r\n\r\n/* -------------------- 位置工具 -------------------- */\r\n\r\n/**\r\n * 判断两条路径是否完全相同。\r\n * @param a 路径 a\r\n * @param b 路径 b\r\n * @returns 相同返回 true\r\n */\r\nexport function isSamePath(a: Path, b: Path): boolean {\r\n if (a.length !== b.length) return false\r\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false\r\n return true\r\n}\r\n\r\n/**\r\n * 比较两条路径的字典序(数字段按数值比较,字符串段按字符串比较)。\r\n * @param a 路径 a\r\n * @param b 路径 b\r\n * @returns a<b 返回负数,a=b 返回 0,a>b 返回正数\r\n */\r\nexport function comparePath(a: Path, b: Path): number {\r\n const n = Math.min(a.length, b.length)\r\n for (let i = 0; i < n; i++) {\r\n const av = a[i]; const bv = b[i]\r\n if (av === bv) continue\r\n if (typeof av === 'number' && typeof bv === 'number') return av - bv\r\n return String(av) < String(bv) ? -1 : 1\r\n }\r\n return a.length - b.length\r\n}\r\n\r\n/**\r\n * 比较两个文档位置:先比较路径,路径相同再比较 offset。\r\n * @param a 位置 a\r\n * @param b 位置 b\r\n * @returns a<b 返回负数,a=b 返回 0,a>b 返回正数\r\n */\r\nexport function comparePosition(a: IPosition, b: IPosition): number {\r\n const c = comparePath(a.path, b.path)\r\n if (c !== 0) return c\r\n return a.offset - b.offset\r\n}\r\n\r\n/* -------------------- 表格辅助 -------------------- */\r\n\r\n/**\r\n * 遍历表格所有单元格,对每个单元格调用回调。\r\n * @param table 表格元素\r\n * @param fn 回调函数,接收单元格、行、行索引、列索引\r\n */\r\nexport function forEachCell(\r\n table: ITableElement,\r\n fn: (cell: ITd, tr: ITr, trIndex: number, tdIndex: number) => void\r\n) {\r\n for (let i = 0; i < table.trList.length; i++) {\r\n const row = table.trList[i]\r\n for (let j = 0; j < row.tdList.length; j++) {\r\n fn(row.tdList[j], row, i, j)\r\n }\r\n }\r\n}\r\n\r\n/** 计算表格列数(不考虑合并) */\r\nexport function getTableColCount(table: ITableElement): number {\r\n if (Array.isArray(table.colgroup)) return table.colgroup.length\r\n return table.trList[0]?.tdList.reduce((sum, td) => sum + (td.colspan || 1), 0) ?? 0\r\n}\r\n\r\n/** 计算某段路径所在的段落容器(title/list/纯段落用父数组表示) */\r\nexport function _pathSegAsKey(seg: PathSegment): string {\r\n return typeof seg === 'number' ? String(seg) : seg\r\n}\r\n","import { walkTree } from '@vervedoc/docx-editor-schema'\r\nimport type { IElement, ITitleElement, ITextElement, PathSegment } from '@vervedoc/docx-editor-schema'\r\n\r\nconst levelMap: Record<string, number> = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6 }\r\n\r\nexport function computeToc(elements: IElement[]) {\r\n const toc: { id: string; level: number; name: string; number?: string }[] = []\r\n const counters = new Map<string, number>()\r\n walkTree(elements, (node, ctx) => {\r\n if (node.type !== 'title') return\r\n const t = node as ITitleElement\r\n const name = (t.valueList ?? []).map(v => v.type === 'text' ? (v as ITextElement).value : '').join('')\r\n const level = levelMap[t.level] ?? 1\r\n let number: string | undefined\r\n const num = (t as unknown as { listNumbering?: { numFmt: string; lvlText: string; start: number; numId?: string; abstractNumId?: string; level?: number } }).listNumbering\r\n if (num && num.numFmt !== 'bullet') {\r\n const numId = num.numId ?? num.abstractNumId ?? 'default'\r\n const numLevel = num.level ?? 0\r\n const key = `${numId}:${numLevel}`\r\n const prev = counters.get(key)\r\n const current = (prev == null ? (num.start ?? 1) - 1 : prev) + 1\r\n counters.set(key, current)\r\n for (const k of counters.keys()) {\r\n if (k.startsWith(`${numId}:`) && Number(k.slice(numId.length + 1)) > numLevel) counters.delete(k)\r\n }\r\n number = (num.lvlText ?? '%1.').replace(/%([1-9])/g, (_, d: string) => {\r\n const lvl = Number(d) - 1\r\n return String(lvl === numLevel ? current : counters.get(`${numId}:${lvl}`) ?? (num.start ?? 1))\r\n })\r\n }\r\n toc.push({ id: JSON.stringify(ctx.path), level, name, number })\r\n })\r\n return { toc }\r\n}\r\n\r\nexport function computeSearch(elements: IElement[], keyword: string) {\r\n const results: { path: PathSegment[]; offset: number; length: number }[] = []\r\n if (!keyword) return { results, count: 0 }\r\n const lowerKeyword = keyword.toLowerCase()\r\n walkTree(elements, (node, ctx) => {\r\n if (node.type !== 'text') return\r\n const text = ((node as ITextElement).value || '').toLowerCase()\r\n let idx = text.indexOf(lowerKeyword)\r\n while (idx !== -1) {\r\n results.push({ path: [...ctx.path], offset: idx, length: keyword.length })\r\n idx = text.indexOf(lowerKeyword, idx + 1)\r\n }\r\n })\r\n return { results, count: results.length }\r\n}\r\n","/// <reference lib=\"webworker\" />\r\nimport { cloneTree } from '@vervedoc/docx-editor-schema'\r\nimport type { IElement } from '@vervedoc/docx-editor-schema'\r\nimport { computeToc, computeSearch } from './compute'\r\n\r\ntype WorkerRequest =\r\n | { type: 'update'; elements: IElement[] }\r\n | { type: 'search'; keyword: string }\r\n | { type: 'clone'; data: unknown }\r\n\r\nlet currentElements: IElement[] = []\r\nself.onmessage = (e: MessageEvent<WorkerRequest>): void => {\r\n try {\r\n const req = e.data\r\n switch (req.type) {\r\n case 'update':\r\n currentElements = req.elements\r\n self.postMessage({ type: 'toc-result', ...computeToc(currentElements) })\r\n break\r\n case 'search':\r\n self.postMessage({ type: 'search-result', ...computeSearch(currentElements, req.keyword) })\r\n break\r\n case 'clone':\r\n self.postMessage({ type: 'clone-result', data: cloneTree(req.data) })\r\n break\r\n }\r\n } catch (error: any) {\r\n self.postMessage({ type: 'error', message: error?.message || String(error) })\r\n }\r\n}\r\n"],"names":["FONT_FAMILY_MAP","a","rfdc_1","rfdc","copyBuffer","cur","opts","rfdcCircles","constructorHandlers","o","fn","cloneArray","handler","cloneProto","clone","keys","a2","i","k","o2","refs","refsNew","index","_clone","cloneTree","node","isParagraphContainer","el","isTable","isControl","walkTree","elements","visitor","parentPath","path","tr","row","td","cell","levelMap","computeToc","toc","counters","ctx","t","name","v","level","number","num","numId","numLevel","key","prev","current","_","d","lvl","computeSearch","keyword","results","lowerKeyword","text","idx","currentElements","req","error"],"mappings":"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","x_google_ignoreList":[1]}