@a3s-lab/office 0.29.0 → 0.30.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.
Files changed (50) hide show
  1. package/README.md +100 -3
  2. package/dist/{0~7043.js → 0~7231.js} +160 -2
  3. package/dist/{0~5093.js → 0~7360.js} +233 -52
  4. package/dist/0~document-editor.js +1159 -149
  5. package/dist/0~spreadsheet-editor.js +183 -34
  6. package/dist/0~work-docx-export.js +299 -11
  7. package/dist/0~work-docx-import.js +30 -7
  8. package/dist/0~work-office-diagnostics.js +125 -5
  9. package/dist/1544.js +13 -1
  10. package/dist/4104.js +29 -6
  11. package/dist/4121.js +1939 -1
  12. package/dist/6282.js +501 -1006
  13. package/dist/internal/features/work/editors/document-command-catalog.d.ts +18 -0
  14. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +5 -2
  15. package/dist/internal/features/work/editors/document-font-dialog-run-shading-model.d.ts +23 -0
  16. package/dist/internal/features/work/editors/document-font-dialog-run-shading-section.d.ts +8 -0
  17. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  18. package/dist/internal/features/work/editors/document-proofing-dialog-model.d.ts +22 -0
  19. package/dist/internal/features/work/editors/document-proofing-dialog.d.ts +7 -0
  20. package/dist/internal/features/work/editors/document-table-of-contents-dialog.d.ts +10 -0
  21. package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
  22. package/dist/internal/features/work/editors/spreadsheet-data-validation.d.ts +7 -1
  23. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +2 -0
  24. package/dist/internal/features/work/work-document-character-formatting.d.ts +8 -0
  25. package/dist/internal/features/work/work-document-format-changes.d.ts +6 -0
  26. package/dist/internal/features/work/work-document-highlight.d.ts +9 -0
  27. package/dist/internal/features/work/work-document-outline.d.ts +1 -0
  28. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +6 -0
  29. package/dist/internal/features/work/work-document-proofing.d.ts +19 -0
  30. package/dist/internal/features/work/work-document-run-shading.d.ts +12 -0
  31. package/dist/internal/features/work/work-document-table-of-contents-node.d.ts +18 -0
  32. package/dist/internal/features/work/work-document-table-of-contents.d.ts +51 -0
  33. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +3 -0
  34. package/dist/internal/features/work/work-docx-field-instructions.d.ts +1 -1
  35. package/dist/internal/features/work/work-docx-import.d.ts +3 -1
  36. package/dist/internal/features/work/work-docx-proofing-diagnostics.d.ts +3 -0
  37. package/dist/internal/features/work/work-docx-proofing.d.ts +38 -0
  38. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +7 -0
  39. package/dist/internal/features/work/work-docx-run-shading-diagnostics.d.ts +3 -0
  40. package/dist/internal/features/work/work-docx-run-shading-export.d.ts +17 -0
  41. package/dist/internal/features/work/work-docx-run-shading.d.ts +20 -0
  42. package/dist/internal/features/work/work-docx-table-of-contents-export.d.ts +11 -0
  43. package/dist/internal/features/work/work-docx-table-of-contents-import.d.ts +15 -0
  44. package/dist/internal/features/work/work-spreadsheet-data-validation.d.ts +7 -0
  45. package/dist/internal/features/work/work-types.d.ts +9 -0
  46. package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -0
  47. package/dist/office-kernel.wasm +0 -0
  48. package/dist/styles.css +311 -4
  49. package/docs/latest/en/browser-editor-architecture.md +50 -1
  50. package/package.json +12 -2
package/dist/4121.js CHANGED
@@ -1,4 +1,73 @@
1
1
  import jszip from "jszip";
2
+ import { Extension } from "@tiptap/core";
3
+ import { isHistoryTransaction } from "@tiptap/pm/history";
4
+ import { Plugin } from "@tiptap/pm/state";
5
+ import { Mapping } from "@tiptap/pm/transform";
6
+ const DOCUMENT_INTEGRITY_BOOKMARK = 1;
7
+ const DOCUMENT_INTEGRITY_FIELD = 2;
8
+ const DOCUMENT_INTEGRITY_IMAGE = 4;
9
+ const DOCUMENT_INTEGRITY_NOTE = 8;
10
+ const DOCUMENT_INTEGRITY_PARAGRAPH_IDENTITY = 16;
11
+ const DOCUMENT_INTEGRITY_TABLE_ROW_IDENTITY = 32;
12
+ const featureCache = new WeakMap();
13
+ function documentHasIntegrityFeature(document, feature) {
14
+ return (documentIntegrityFeatures(document, true) & feature) !== 0;
15
+ }
16
+ function primeDocumentIntegrityFeatures(document) {
17
+ document.forEach(primeDocumentIntegrityNode);
18
+ }
19
+ function primeDocumentIntegrityNode(node) {
20
+ if ('documentChunk' === node.type.name) {
21
+ const features = nonNegativeInteger(node.attrs.integrityFeatures);
22
+ if (null !== features) featureCache.set(node, features);
23
+ if (true !== node.attrs.windowContainer) return;
24
+ }
25
+ node.forEach(primeDocumentIntegrityNode);
26
+ }
27
+ function documentIntegrityFeatures(node, cacheNode) {
28
+ if (cacheNode) {
29
+ const cached = featureCache.get(node);
30
+ if (void 0 !== cached) return cached;
31
+ }
32
+ let features = nodeIntegrityFeatures(node);
33
+ node.forEach((child)=>{
34
+ features |= documentIntegrityFeatures(child, 'documentChunk' === child.type.name);
35
+ });
36
+ if (cacheNode) featureCache.set(node, features);
37
+ return features;
38
+ }
39
+ function nodeIntegrityFeatures(node) {
40
+ let features = 0;
41
+ switch(node.type.name){
42
+ case 'documentBookmarkBoundary':
43
+ features |= DOCUMENT_INTEGRITY_BOOKMARK;
44
+ break;
45
+ case 'documentCrossReference':
46
+ if ('bookmark' === node.attrs.targetType) features |= DOCUMENT_INTEGRITY_BOOKMARK;
47
+ break;
48
+ case 'documentField':
49
+ features |= DOCUMENT_INTEGRITY_FIELD;
50
+ break;
51
+ case 'image':
52
+ features |= DOCUMENT_INTEGRITY_IMAGE;
53
+ break;
54
+ case 'documentNote':
55
+ case 'documentNoteReference':
56
+ features |= DOCUMENT_INTEGRITY_NOTE;
57
+ break;
58
+ }
59
+ if (node.isText && node.marks.some((mark)=>'link' === mark.type.name && 'string' == typeof mark.attrs.href && mark.attrs.href.startsWith('#'))) features |= DOCUMENT_INTEGRITY_BOOKMARK;
60
+ if (identityComponent(node.attrs.paragraphId) || identityComponent(node.attrs.textId)) features |= DOCUMENT_INTEGRITY_PARAGRAPH_IDENTITY;
61
+ if (identityComponent(node.attrs.rowId) || identityComponent(node.attrs.rowTextId)) features |= DOCUMENT_INTEGRITY_TABLE_ROW_IDENTITY;
62
+ return features;
63
+ }
64
+ function identityComponent(value) {
65
+ return 'string' == typeof value && value.trim().length > 0;
66
+ }
67
+ function nonNegativeInteger(value) {
68
+ const number = Number(value);
69
+ return Number.isSafeInteger(number) && number >= 0 ? number : null;
70
+ }
2
71
  function normalizeCssColor(source) {
3
72
  const value = source?.trim().toLowerCase();
4
73
  if (!value) return null;
@@ -971,6 +1040,1489 @@ function cssBorderStyle(style) {
971
1040
  function work_document_run_border_formatPixels(value) {
972
1041
  return Number(value.toFixed(3)).toString();
973
1042
  }
1043
+ const work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS = new Set([
1044
+ 'nil',
1045
+ 'clear',
1046
+ 'solid',
1047
+ 'horzStripe',
1048
+ 'vertStripe',
1049
+ 'reverseDiagStripe',
1050
+ 'diagStripe',
1051
+ 'horzCross',
1052
+ 'diagCross',
1053
+ 'thinHorzStripe',
1054
+ 'thinVertStripe',
1055
+ 'thinReverseDiagStripe',
1056
+ 'thinDiagStripe',
1057
+ 'thinHorzCross',
1058
+ 'thinDiagCross',
1059
+ 'pct5',
1060
+ 'pct10',
1061
+ 'pct12',
1062
+ 'pct15',
1063
+ 'pct20',
1064
+ 'pct25',
1065
+ 'pct30',
1066
+ 'pct35',
1067
+ 'pct37',
1068
+ 'pct40',
1069
+ 'pct45',
1070
+ 'pct50',
1071
+ 'pct55',
1072
+ 'pct60',
1073
+ 'pct62',
1074
+ 'pct65',
1075
+ 'pct70',
1076
+ 'pct75',
1077
+ 'pct80',
1078
+ 'pct85',
1079
+ 'pct87',
1080
+ 'pct90',
1081
+ 'pct95'
1082
+ ]);
1083
+ function normalizeDocumentParagraphShading(source) {
1084
+ if (!source || 'object' != typeof source) return null;
1085
+ const value = source;
1086
+ const pattern = value.pattern;
1087
+ if ('string' != typeof pattern || !work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS.has(pattern)) return null;
1088
+ const color = normalizeShadingColor(value.color);
1089
+ const fill = normalizeShadingColor(value.fill);
1090
+ if (void 0 !== value.color && !color || void 0 !== value.fill && !fill) return null;
1091
+ return {
1092
+ pattern: pattern,
1093
+ ...color ? {
1094
+ color
1095
+ } : {},
1096
+ ...fill ? {
1097
+ fill
1098
+ } : {}
1099
+ };
1100
+ }
1101
+ function parseDocumentParagraphShading(source) {
1102
+ if ('string' != typeof source) return normalizeDocumentParagraphShading(source);
1103
+ if (!source.trim()) return null;
1104
+ try {
1105
+ return normalizeDocumentParagraphShading(JSON.parse(source));
1106
+ } catch {
1107
+ return null;
1108
+ }
1109
+ }
1110
+ function serializeDocumentParagraphShading(source) {
1111
+ const shading = normalizeDocumentParagraphShading(source);
1112
+ if (!shading) return;
1113
+ return JSON.stringify({
1114
+ pattern: shading.pattern,
1115
+ ...shading.color ? {
1116
+ color: serializedShadingColor(shading.color)
1117
+ } : {},
1118
+ ...shading.fill ? {
1119
+ fill: serializedShadingColor(shading.fill)
1120
+ } : {}
1121
+ });
1122
+ }
1123
+ function parseDocumentParagraphShadingElement(element) {
1124
+ const semantic = parseDocumentParagraphShading(element.dataset.officeParagraphShading);
1125
+ const background = normalizeCssColor(element.style.backgroundColor);
1126
+ if (semantic) {
1127
+ const presentation = documentParagraphShadingPresentation(semantic);
1128
+ const expected = normalizeCssColor(presentation.backgroundColor);
1129
+ if (background && expected && background !== expected) {
1130
+ if ('transparent' === background) return {
1131
+ pattern: 'nil'
1132
+ };
1133
+ if (paragraphShadingBackgroundUsesForeground(semantic)) return {
1134
+ ...semantic,
1135
+ color: {
1136
+ value: background
1137
+ }
1138
+ };
1139
+ return {
1140
+ ...semantic,
1141
+ fill: {
1142
+ value: background
1143
+ }
1144
+ };
1145
+ }
1146
+ return semantic;
1147
+ }
1148
+ return background && 'transparent' !== background ? {
1149
+ pattern: 'clear',
1150
+ fill: {
1151
+ value: background
1152
+ }
1153
+ } : null;
1154
+ }
1155
+ function documentParagraphShadingDomAttributes(source) {
1156
+ const shading = normalizeDocumentParagraphShading(source);
1157
+ const serialized = serializeDocumentParagraphShading(shading);
1158
+ if (!shading || !serialized) return {};
1159
+ const presentation = documentParagraphShadingPresentation(shading);
1160
+ const styles = [
1161
+ `background-color: ${presentation.backgroundColor}`,
1162
+ presentation.backgroundImage ? `background-image: ${presentation.backgroundImage}` : '',
1163
+ presentation.backgroundSize ? `background-size: ${presentation.backgroundSize}` : ''
1164
+ ].filter(Boolean);
1165
+ return {
1166
+ 'data-office-paragraph-shading': serialized,
1167
+ style: styles.join('; ')
1168
+ };
1169
+ }
1170
+ function normalizeShadingColor(source) {
1171
+ if (!source || 'object' != typeof source) return null;
1172
+ const value = source;
1173
+ const theme = parseDocxThemeReference('string' == typeof value.theme ? value.theme : value.theme ? JSON.stringify(value.theme) : void 0);
1174
+ const direct = 'auto' === value.value ? 'auto' : 'string' == typeof value.value ? normalizeCssColor(value.value) : null;
1175
+ const resolved = direct ?? theme?.resolved ?? null;
1176
+ if (!resolved || 'transparent' === resolved) return null;
1177
+ if (theme && resolved !== theme.resolved) return null;
1178
+ return {
1179
+ value: resolved,
1180
+ ...theme ? {
1181
+ theme
1182
+ } : {}
1183
+ };
1184
+ }
1185
+ function serializedShadingColor(color) {
1186
+ const theme = serializeDocxThemeReference(color.theme ?? null);
1187
+ return {
1188
+ value: color.value,
1189
+ ...theme ? {
1190
+ theme: JSON.parse(theme)
1191
+ } : {}
1192
+ };
1193
+ }
1194
+ function documentParagraphShadingPresentation(shading) {
1195
+ if ('nil' === shading.pattern) return {
1196
+ backgroundColor: 'transparent'
1197
+ };
1198
+ const foreground = shadingColor(shading.color, '#000000');
1199
+ const background = shadingColor(shading.fill, 'transparent');
1200
+ if ('clear' === shading.pattern) return {
1201
+ backgroundColor: background
1202
+ };
1203
+ if ('solid' === shading.pattern) return {
1204
+ backgroundColor: foreground
1205
+ };
1206
+ const percentage = shadingPercentage(shading.pattern);
1207
+ if (null !== percentage) {
1208
+ const inverted = percentage > 50;
1209
+ const dotColor = inverted ? background : foreground;
1210
+ const baseColor = inverted ? foreground : background;
1211
+ const density = Math.min(50, inverted ? 100 - percentage : percentage);
1212
+ const spacing = Math.max(2, Math.round(9 - density / 7));
1213
+ return {
1214
+ backgroundColor: baseColor,
1215
+ backgroundImage: `radial-gradient(circle, ${dotColor} 0 1px, transparent 1.2px)`,
1216
+ backgroundSize: `${spacing}px ${spacing}px`
1217
+ };
1218
+ }
1219
+ const thin = shading.pattern.startsWith('thin');
1220
+ const width = thin ? 1 : 2;
1221
+ const period = thin ? 7 : 6;
1222
+ const stripe = (angle)=>`repeating-linear-gradient(${angle}deg, ${foreground} 0 ${width}px, transparent ${width}px ${period}px)`;
1223
+ const angles = shadingPatternAngles(shading.pattern);
1224
+ return {
1225
+ backgroundColor: background,
1226
+ backgroundImage: angles.map(stripe).join(', ')
1227
+ };
1228
+ }
1229
+ function shadingColor(color, fallback) {
1230
+ return color && 'auto' !== color.value ? color.value : fallback;
1231
+ }
1232
+ function shadingPercentage(pattern) {
1233
+ const match = /^pct(\d+)$/.exec(pattern);
1234
+ return match?.[1] ? Number(match[1]) : null;
1235
+ }
1236
+ function paragraphShadingBackgroundUsesForeground(shading) {
1237
+ if ('solid' === shading.pattern) return true;
1238
+ const percentage = shadingPercentage(shading.pattern);
1239
+ return null !== percentage && percentage > 50;
1240
+ }
1241
+ function shadingPatternAngles(pattern) {
1242
+ if (pattern.includes('HorzCross')) return [
1243
+ 0,
1244
+ 90
1245
+ ];
1246
+ if (pattern.includes('DiagCross')) return [
1247
+ 45,
1248
+ -45
1249
+ ];
1250
+ if (pattern.includes('VertStripe')) return [
1251
+ 90
1252
+ ];
1253
+ if (pattern.includes('ReverseDiagStripe')) return [
1254
+ -45
1255
+ ];
1256
+ if (pattern.includes('DiagStripe')) return [
1257
+ 45
1258
+ ];
1259
+ return [
1260
+ 0
1261
+ ];
1262
+ }
1263
+ const DOCUMENT_HIGHLIGHT_ATTRIBUTE = 'data-office-highlight';
1264
+ const DOCUMENT_HIGHLIGHT_VALUES = new Set([
1265
+ 'black',
1266
+ 'blue',
1267
+ 'cyan',
1268
+ 'darkBlue',
1269
+ 'darkCyan',
1270
+ 'darkGray',
1271
+ 'darkGreen',
1272
+ 'darkMagenta',
1273
+ 'darkRed',
1274
+ 'darkYellow',
1275
+ 'green',
1276
+ 'lightGray',
1277
+ 'magenta',
1278
+ 'none',
1279
+ 'red',
1280
+ 'white',
1281
+ 'yellow'
1282
+ ]);
1283
+ const HIGHLIGHT_COLORS = {
1284
+ black: '#000000',
1285
+ blue: '#0000ff',
1286
+ cyan: '#00ffff',
1287
+ darkBlue: '#000080',
1288
+ darkCyan: '#008080',
1289
+ darkGray: '#808080',
1290
+ darkGreen: '#008000',
1291
+ darkMagenta: '#800080',
1292
+ darkRed: '#800000',
1293
+ darkYellow: '#808000',
1294
+ green: '#00ff00',
1295
+ lightGray: '#c0c0c0',
1296
+ magenta: '#ff00ff',
1297
+ none: 'transparent',
1298
+ red: '#ff0000',
1299
+ white: '#ffffff',
1300
+ yellow: '#ffff00'
1301
+ };
1302
+ function normalizeDocumentHighlight(source) {
1303
+ return 'string' == typeof source && DOCUMENT_HIGHLIGHT_VALUES.has(source) ? source : null;
1304
+ }
1305
+ function documentHighlightFromDocxValue(source) {
1306
+ if ('string' != typeof source) return null;
1307
+ const normalized = source.trim().toLowerCase();
1308
+ for (const value of DOCUMENT_HIGHLIGHT_VALUES)if (value.toLowerCase() === normalized) return value;
1309
+ return null;
1310
+ }
1311
+ function documentHighlightCssColor(source) {
1312
+ const value = normalizeDocumentHighlight(source);
1313
+ return value ? HIGHLIGHT_COLORS[value] : null;
1314
+ }
1315
+ function documentHighlightForCssColor(source) {
1316
+ const color = normalizeCssColor('string' == typeof source ? source : null);
1317
+ if (!color) return null;
1318
+ for (const [value, candidate] of Object.entries(HIGHLIGHT_COLORS))if (candidate === color) return value;
1319
+ return null;
1320
+ }
1321
+ function documentHighlightFromElement(element) {
1322
+ return normalizeDocumentHighlight(element.getAttribute(DOCUMENT_HIGHLIGHT_ATTRIBUTE)) ?? documentHighlightForCssColor(element.style.backgroundColor);
1323
+ }
1324
+ function documentHighlightDomAttributes(source) {
1325
+ const value = normalizeDocumentHighlight(source);
1326
+ const color = documentHighlightCssColor(value);
1327
+ return value && color ? {
1328
+ [DOCUMENT_HIGHLIGHT_ATTRIBUTE]: value,
1329
+ style: `background-color: ${color}`
1330
+ } : {};
1331
+ }
1332
+ const DOCUMENT_RUN_SHADING_ATTRIBUTE = 'data-office-run-shading';
1333
+ const MAX_SERIALIZED_RUN_SHADING_BYTES = 4096;
1334
+ const RUN_SHADING_KEYS = new Set([
1335
+ 'pattern',
1336
+ 'color',
1337
+ 'fill'
1338
+ ]);
1339
+ const RUN_SHADING_COLOR_KEYS = new Set([
1340
+ 'value',
1341
+ 'theme'
1342
+ ]);
1343
+ const THEME_REFERENCE_KEYS = new Set([
1344
+ 'theme',
1345
+ 'resolved',
1346
+ 'tint',
1347
+ 'shade'
1348
+ ]);
1349
+ function normalizeDocumentRunShading(source) {
1350
+ if (!isRecordWithKeys(source, RUN_SHADING_KEYS)) return null;
1351
+ for (const name of [
1352
+ 'color',
1353
+ 'fill'
1354
+ ]){
1355
+ const color = source[name];
1356
+ if (void 0 !== color) {
1357
+ if (!isRecordWithKeys(color, RUN_SHADING_COLOR_KEYS)) return null;
1358
+ if (void 0 !== color.theme && !isRecordWithKeys(color.theme, THEME_REFERENCE_KEYS)) return null;
1359
+ }
1360
+ }
1361
+ return normalizeDocumentParagraphShading(source);
1362
+ }
1363
+ function parseDocumentRunShading(source) {
1364
+ if ('string' != typeof source) return normalizeDocumentRunShading(source);
1365
+ if (!source.trim() || source.length > MAX_SERIALIZED_RUN_SHADING_BYTES) return null;
1366
+ try {
1367
+ return normalizeDocumentRunShading(JSON.parse(source));
1368
+ } catch {
1369
+ return null;
1370
+ }
1371
+ }
1372
+ function serializeDocumentRunShading(source) {
1373
+ const shading = normalizeDocumentRunShading(source);
1374
+ const serialized = shading ? serializeDocumentParagraphShading(shading) : void 0;
1375
+ return serialized && serialized.length <= MAX_SERIALIZED_RUN_SHADING_BYTES ? serialized : void 0;
1376
+ }
1377
+ function parseDocumentRunShadingElement(element) {
1378
+ const semantic = parseDocumentRunShading(element.getAttribute(DOCUMENT_RUN_SHADING_ATTRIBUTE));
1379
+ if (!semantic) return null;
1380
+ if (element.hasAttribute(DOCUMENT_HIGHLIGHT_ATTRIBUTE)) return semantic;
1381
+ const background = normalizeCssColor(element.style.backgroundColor);
1382
+ const expected = normalizeCssColor(documentParagraphShadingPresentation(semantic).backgroundColor);
1383
+ if (!background || !expected || background === expected) return semantic;
1384
+ if ('transparent' === background) return {
1385
+ pattern: 'nil'
1386
+ };
1387
+ return paragraphShadingBackgroundUsesForeground(semantic) ? {
1388
+ ...semantic,
1389
+ color: {
1390
+ value: background
1391
+ }
1392
+ } : {
1393
+ ...semantic,
1394
+ fill: {
1395
+ value: background
1396
+ }
1397
+ };
1398
+ }
1399
+ function documentRunShadingDomAttributes(source) {
1400
+ const shading = normalizeDocumentRunShading(source);
1401
+ const serialized = serializeDocumentRunShading(shading);
1402
+ if (!shading || !serialized) return {};
1403
+ const paragraphAttributes = documentParagraphShadingDomAttributes(shading);
1404
+ const style = [
1405
+ paragraphAttributes.style,
1406
+ 'box-decoration-break: clone',
1407
+ '-webkit-box-decoration-break: clone'
1408
+ ].filter(Boolean).join('; ');
1409
+ return {
1410
+ [DOCUMENT_RUN_SHADING_ATTRIBUTE]: serialized,
1411
+ style
1412
+ };
1413
+ }
1414
+ function isRecordWithKeys(source, allowed) {
1415
+ return 'object' == typeof source && null !== source && !Array.isArray(source) && Object.keys(source).every((key)=>allowed.has(key));
1416
+ }
1417
+ const DOCUMENT_SCRIPT_FONTS_ATTRIBUTE = "data-office-script-fonts";
1418
+ const DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE = "data-office-script-font-slot";
1419
+ const MAX_FONT_NAME_LENGTH = 127;
1420
+ const MAX_SERIALIZED_SCRIPT_FONTS_LENGTH = 4096;
1421
+ const SCRIPT_FONT_KEYS = new Set([
1422
+ 'ascii',
1423
+ 'highAnsi',
1424
+ 'eastAsia',
1425
+ 'complexScript',
1426
+ 'hint'
1427
+ ]);
1428
+ const SCRIPT_FONT_FACE_KEYS = new Set([
1429
+ 'name',
1430
+ 'theme',
1431
+ 'resolved'
1432
+ ]);
1433
+ const SCRIPT_FONT_HINTS = new Set([
1434
+ 'default',
1435
+ 'eastAsia',
1436
+ 'cs'
1437
+ ]);
1438
+ const THEME_FONTS = new Set([
1439
+ 'majorEastAsia',
1440
+ 'majorBidi',
1441
+ 'majorAscii',
1442
+ 'majorHAnsi',
1443
+ 'minorEastAsia',
1444
+ 'minorBidi',
1445
+ 'minorAscii',
1446
+ 'minorHAnsi'
1447
+ ]);
1448
+ const SLOT_FALLBACK_ORDER = {
1449
+ ascii: [
1450
+ 'ascii',
1451
+ 'highAnsi',
1452
+ 'eastAsia',
1453
+ 'complexScript'
1454
+ ],
1455
+ highAnsi: [
1456
+ 'highAnsi',
1457
+ 'ascii',
1458
+ 'eastAsia',
1459
+ 'complexScript'
1460
+ ],
1461
+ eastAsia: [
1462
+ 'eastAsia',
1463
+ 'highAnsi',
1464
+ 'ascii',
1465
+ 'complexScript'
1466
+ ],
1467
+ complexScript: [
1468
+ 'complexScript',
1469
+ 'highAnsi',
1470
+ 'ascii',
1471
+ 'eastAsia'
1472
+ ]
1473
+ };
1474
+ const NEUTRAL_SCRIPT_CHARACTER = /^[\p{Cc}\p{Cf}\p{M}\p{N}\p{P}\p{S}\p{Z}]$/u;
1475
+ function normalizeDocumentScriptFonts(source) {
1476
+ if (!work_document_script_fonts_isRecordWithKeys(source, SCRIPT_FONT_KEYS)) return null;
1477
+ const normalized = {};
1478
+ for (const slot of scriptFontSlots){
1479
+ if (void 0 === source[slot]) continue;
1480
+ const face = normalizeDocumentScriptFontFace(source[slot]);
1481
+ if (!face) return null;
1482
+ normalized[slot] = face;
1483
+ }
1484
+ if (void 0 !== source.hint) {
1485
+ const hint = normalizeDocumentScriptFontHint(source.hint);
1486
+ if (!hint) return null;
1487
+ normalized.hint = hint;
1488
+ }
1489
+ return Object.keys(normalized).length ? normalized : null;
1490
+ }
1491
+ function serializeDocumentScriptFonts(source) {
1492
+ const fonts = normalizeDocumentScriptFonts(source);
1493
+ return fonts ? JSON.stringify(fonts) : null;
1494
+ }
1495
+ function parseDocumentScriptFonts(source) {
1496
+ if (!source || source.length > MAX_SERIALIZED_SCRIPT_FONTS_LENGTH) return null;
1497
+ try {
1498
+ return normalizeDocumentScriptFonts(JSON.parse(source));
1499
+ } catch {
1500
+ return null;
1501
+ }
1502
+ }
1503
+ function documentScriptFontsFromElement(element) {
1504
+ return parseDocumentScriptFonts(element.getAttribute(DOCUMENT_SCRIPT_FONTS_ATTRIBUTE));
1505
+ }
1506
+ function documentScriptFontSlotFromElement(element) {
1507
+ return normalizeDocumentScriptFontSlot(element.getAttribute(DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE));
1508
+ }
1509
+ function documentScriptFontsDomAttributes(source, slot) {
1510
+ const fonts = normalizeDocumentScriptFonts(source);
1511
+ const normalizedSlot = normalizeDocumentScriptFontSlot(slot);
1512
+ if (!fonts) return {};
1513
+ const serialized = serializeDocumentScriptFonts(fonts);
1514
+ if (!serialized) return {};
1515
+ const family = documentScriptFontFamily(fonts, normalizedSlot ?? documentScriptFontSlotFromHint(fonts.hint));
1516
+ return {
1517
+ [DOCUMENT_SCRIPT_FONTS_ATTRIBUTE]: serialized,
1518
+ ...normalizedSlot ? {
1519
+ [DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE]: normalizedSlot
1520
+ } : {},
1521
+ ...family ? {
1522
+ style: `font-family: ${family}`
1523
+ } : {}
1524
+ };
1525
+ }
1526
+ function documentScriptFontFamily(source, slot) {
1527
+ const fonts = normalizeDocumentScriptFonts(source);
1528
+ if (!fonts) return;
1529
+ const families = [];
1530
+ const seen = new Set();
1531
+ for (const candidate of documentScriptFontFallbackSlots(slot)){
1532
+ const family = documentScriptFontFaceFamily(fonts[candidate]);
1533
+ const key = family?.toLocaleLowerCase();
1534
+ if (!(!family || !key || seen.has(key))) {
1535
+ seen.add(key);
1536
+ families.push(cssFontFamily(family));
1537
+ }
1538
+ }
1539
+ return families.length ? families.join(', ') : void 0;
1540
+ }
1541
+ function documentScriptFontFallbackSlots(slot) {
1542
+ return SLOT_FALLBACK_ORDER[slot];
1543
+ }
1544
+ function documentScriptFontFamilyForRendering(source, slot, currentFontFamily) {
1545
+ const projected = documentScriptFontFamily(source, slot);
1546
+ const safeCurrent = safeCssFontFamilyList(currentFontFamily);
1547
+ if (!safeCurrent || !projected) return projected;
1548
+ const currentPrimary = documentFontNameFromCssFamily(safeCurrent);
1549
+ const projectedPrimary = documentFontNameFromCssFamily(projected);
1550
+ return currentPrimary && projectedPrimary && currentPrimary.toLocaleLowerCase() === projectedPrimary.toLocaleLowerCase() ? safeCurrent : projected;
1551
+ }
1552
+ function documentScriptFontDirectFamily(source, slot) {
1553
+ const fonts = normalizeDocumentScriptFonts(source);
1554
+ return fonts ? documentScriptFontFaceFamily(fonts[slot]) ?? null : null;
1555
+ }
1556
+ function documentScriptFontsForAllText(fontFamily) {
1557
+ const name = documentFontNameFromCssFamily(fontFamily);
1558
+ if (!name) return null;
1559
+ const face = {
1560
+ name,
1561
+ resolved: name
1562
+ };
1563
+ return {
1564
+ ascii: face,
1565
+ highAnsi: face,
1566
+ eastAsia: face,
1567
+ complexScript: face,
1568
+ hint: 'default'
1569
+ };
1570
+ }
1571
+ function patchDocumentScriptFonts(source, patch, fallbackFontFamily) {
1572
+ const current = normalizeDocumentScriptFonts(source) ?? documentScriptFontsForAllText(fallbackFontFamily) ?? {};
1573
+ const next = {
1574
+ ...current
1575
+ };
1576
+ if (void 0 !== patch.latin) {
1577
+ const face = directFontFace(patch.latin);
1578
+ if (face) {
1579
+ next.ascii = face;
1580
+ next.highAnsi = face;
1581
+ } else {
1582
+ delete next.ascii;
1583
+ delete next.highAnsi;
1584
+ }
1585
+ }
1586
+ if (void 0 !== patch.eastAsia) {
1587
+ const face = directFontFace(patch.eastAsia);
1588
+ if (face) next.eastAsia = face;
1589
+ else delete next.eastAsia;
1590
+ }
1591
+ if (void 0 !== patch.complexScript) {
1592
+ const face = directFontFace(patch.complexScript);
1593
+ if (face) next.complexScript = face;
1594
+ else delete next.complexScript;
1595
+ }
1596
+ return normalizeDocumentScriptFonts(next);
1597
+ }
1598
+ function documentScriptFontSegments(text, hint = 'default', forceComplexScript = false) {
1599
+ if (!text) return [];
1600
+ if (forceComplexScript) return [
1601
+ {
1602
+ from: 0,
1603
+ to: text.length,
1604
+ slot: 'complexScript'
1605
+ }
1606
+ ];
1607
+ const characters = [];
1608
+ let offset = 0;
1609
+ for (const character of text){
1610
+ const from = offset;
1611
+ offset += character.length;
1612
+ characters.push({
1613
+ from,
1614
+ to: offset,
1615
+ slot: strongDocumentScriptFontSlot(character)
1616
+ });
1617
+ }
1618
+ const fallback = documentScriptFontSlotFromHint(hint);
1619
+ let previous = null;
1620
+ for(let index = 0; index < characters.length; index += 1){
1621
+ const entry = characters[index];
1622
+ if (!entry) continue;
1623
+ if (entry.slot) {
1624
+ previous = entry.slot;
1625
+ continue;
1626
+ }
1627
+ let next = previous;
1628
+ if (!next) for(let cursor = index + 1; cursor < characters.length; cursor += 1){
1629
+ const candidate = characters[cursor]?.slot;
1630
+ if (candidate) {
1631
+ next = candidate;
1632
+ break;
1633
+ }
1634
+ }
1635
+ entry.slot = next ?? fallback;
1636
+ }
1637
+ const segments = [];
1638
+ for (const entry of characters){
1639
+ const slot = entry.slot ?? fallback;
1640
+ const prior = segments[segments.length - 1];
1641
+ if (prior?.slot === slot && prior.to === entry.from) prior.to = entry.to;
1642
+ else segments.push({
1643
+ from: entry.from,
1644
+ to: entry.to,
1645
+ slot
1646
+ });
1647
+ }
1648
+ return segments;
1649
+ }
1650
+ function normalizeDocumentScriptFontSlot(value) {
1651
+ return scriptFontSlots.includes(value) ? value : null;
1652
+ }
1653
+ function normalizeDocumentScriptFontHint(value) {
1654
+ return SCRIPT_FONT_HINTS.has(value) ? value : null;
1655
+ }
1656
+ function normalizeDocumentThemeFont(value) {
1657
+ return THEME_FONTS.has(value) ? value : null;
1658
+ }
1659
+ function documentScriptFontSlotFromHint(hint) {
1660
+ if ('eastAsia' === hint) return 'eastAsia';
1661
+ if ('cs' === hint) return 'complexScript';
1662
+ return 'ascii';
1663
+ }
1664
+ function documentFontNameFromCssFamily(value) {
1665
+ if ('string' != typeof value) return null;
1666
+ const source = value.trim();
1667
+ if (!source) return null;
1668
+ let family = '';
1669
+ const quote = source[0];
1670
+ if ('"' === quote || "'" === quote) {
1671
+ let closed = false;
1672
+ for(let index = 1; index < source.length; index += 1){
1673
+ const character = source[index];
1674
+ if (character === quote) {
1675
+ closed = true;
1676
+ break;
1677
+ }
1678
+ if ('\\' !== character) {
1679
+ family += character;
1680
+ continue;
1681
+ }
1682
+ const decoded = decodeCssEscape(source, index + 1);
1683
+ if (!decoded) return null;
1684
+ family += decoded.value;
1685
+ index = decoded.end - 1;
1686
+ }
1687
+ if (!closed) return null;
1688
+ } else family = source.split(',')[0] ?? '';
1689
+ return normalizeDocumentFontName(family);
1690
+ }
1691
+ function cssDocumentFontFamily(value) {
1692
+ const family = normalizeDocumentFontName(value);
1693
+ return family ? cssFontFamily(family) : null;
1694
+ }
1695
+ function normalizeDocumentFontName(value) {
1696
+ if ('string' != typeof value) return null;
1697
+ const normalized = value.trim();
1698
+ return normalized && normalized.length <= MAX_FONT_NAME_LENGTH && !/[\p{Cc}\p{Cs}]/u.test(normalized) ? normalized : null;
1699
+ }
1700
+ const scriptFontSlots = [
1701
+ 'ascii',
1702
+ 'highAnsi',
1703
+ 'eastAsia',
1704
+ 'complexScript'
1705
+ ];
1706
+ function normalizeDocumentScriptFontFace(source) {
1707
+ if (!work_document_script_fonts_isRecordWithKeys(source, SCRIPT_FONT_FACE_KEYS)) return null;
1708
+ const name = void 0 === source.name ? void 0 : normalizeDocumentFontName(source.name);
1709
+ const resolved = void 0 === source.resolved ? void 0 : normalizeDocumentFontName(source.resolved);
1710
+ const theme = void 0 === source.theme ? void 0 : normalizeDocumentThemeFont(source.theme);
1711
+ if (void 0 !== source.name && !name || void 0 !== source.resolved && !resolved || null === theme || !name && !theme && !resolved) return null;
1712
+ return {
1713
+ ...name ? {
1714
+ name
1715
+ } : {},
1716
+ ...theme ? {
1717
+ theme
1718
+ } : {},
1719
+ ...resolved ? {
1720
+ resolved
1721
+ } : {}
1722
+ };
1723
+ }
1724
+ function directFontFace(value) {
1725
+ if (null === value) return null;
1726
+ const name = documentFontNameFromCssFamily(value) ?? normalizeDocumentFontName(value);
1727
+ return name ? {
1728
+ name,
1729
+ resolved: name
1730
+ } : null;
1731
+ }
1732
+ function documentScriptFontFaceFamily(face) {
1733
+ return face?.resolved ?? face?.name;
1734
+ }
1735
+ function strongDocumentScriptFontSlot(character) {
1736
+ if (NEUTRAL_SCRIPT_CHARACTER.test(character)) return null;
1737
+ const codePoint = character.codePointAt(0);
1738
+ if (void 0 === codePoint) return null;
1739
+ if (isComplexScriptCodePoint(codePoint)) return 'complexScript';
1740
+ if (isEastAsianCodePoint(codePoint)) return 'eastAsia';
1741
+ return codePoint <= 0x7f ? 'ascii' : 'highAnsi';
1742
+ }
1743
+ function isComplexScriptCodePoint(codePoint) {
1744
+ return codePoint >= 0x0590 && codePoint <= 0x08ff || codePoint >= 0x0900 && codePoint <= 0x109f || codePoint >= 0x1780 && codePoint <= 0x18af || codePoint >= 0x1900 && codePoint <= 0x1cff || codePoint >= 0xa800 && codePoint <= 0xa8ff || codePoint >= 0xa980 && codePoint <= 0xa9df || codePoint >= 0xaa00 && codePoint <= 0xaa7f || codePoint >= 0xabc0 && codePoint <= 0xabff || codePoint >= 0xfb1d && codePoint <= 0xfdff || codePoint >= 0xfe70 && codePoint <= 0xfeff || codePoint >= 0x10a00 && codePoint <= 0x10fff || codePoint >= 0x11000 && codePoint <= 0x11fff || codePoint >= 0x1e900 && codePoint <= 0x1edff || codePoint >= 0x1ee00 && codePoint <= 0x1eeff;
1745
+ }
1746
+ function isEastAsianCodePoint(codePoint) {
1747
+ return codePoint >= 0x1100 && codePoint <= 0x11ff || codePoint >= 0x2e80 && codePoint <= 0xa4cf || codePoint >= 0xac00 && codePoint <= 0xd7af || codePoint >= 0xf900 && codePoint <= 0xfaff || codePoint >= 0xfe10 && codePoint <= 0xfe6f || codePoint >= 0xff00 && codePoint <= 0xffef || codePoint >= 0x20000 && codePoint <= 0x323af;
1748
+ }
1749
+ function cssFontFamily(value) {
1750
+ return /^(?:-?[\p{L}_])[\p{L}\p{N}_-]*$/u.test(value) ? value : `"${Array.from(value, cssStringCharacter).join('')}"`;
1751
+ }
1752
+ function cssStringCharacter(character) {
1753
+ return /[\\":;{}<>]/u.test(character) ? `\\${character.codePointAt(0)?.toString(16)} ` : character;
1754
+ }
1755
+ function safeCssFontFamilyList(value) {
1756
+ if ('string' != typeof value) return null;
1757
+ const source = value.trim();
1758
+ if (!source || source.length > 1024 || /[;{}]/u.test(source)) return null;
1759
+ const tokens = [];
1760
+ let start = 0;
1761
+ let quote = '';
1762
+ for(let index = 0; index < source.length; index += 1){
1763
+ const character = source[index] ?? '';
1764
+ if (quote) {
1765
+ if ('\\' === character) {
1766
+ index += 1;
1767
+ if (index >= source.length) return null;
1768
+ } else if (character === quote) quote = '';
1769
+ continue;
1770
+ }
1771
+ if ('"' === character || "'" === character) {
1772
+ quote = character;
1773
+ continue;
1774
+ }
1775
+ if (',' === character) {
1776
+ tokens.push(source.slice(start, index).trim());
1777
+ start = index + 1;
1778
+ }
1779
+ }
1780
+ if (quote) return null;
1781
+ tokens.push(source.slice(start).trim());
1782
+ return tokens.length && tokens.every(validCssFontFamilyToken) ? source : null;
1783
+ }
1784
+ function validCssFontFamilyToken(value) {
1785
+ if (!value) return false;
1786
+ if (value.startsWith('"')) return /^"(?:[^"\\\r\n\f]|\\(?:[\da-f]{1,6}\s?|[^\r\n\f]))*"$/iu.test(value) && null !== documentFontNameFromCssFamily(value);
1787
+ if (value.startsWith("'")) return /^'(?:[^'\\\r\n\f]|\\(?:[\da-f]{1,6}\s?|[^\r\n\f]))*'$/iu.test(value) && null !== documentFontNameFromCssFamily(value);
1788
+ return /[\p{L}_]/u.test(value) && /^[\p{L}_-][\p{L}\p{N}_ -]*$/u.test(value) && !/^(?:inherit|initial|revert(?:-layer)?|unset)$/iu.test(value);
1789
+ }
1790
+ function decodeCssEscape(source, start) {
1791
+ if (start >= source.length) return null;
1792
+ const hexadecimal = /^[\da-f]{1,6}/i.exec(source.slice(start))?.[0];
1793
+ if (hexadecimal) {
1794
+ const codePoint = Number.parseInt(hexadecimal, 16);
1795
+ if (0 === codePoint || codePoint > 0x10ffff || codePoint >= 0xd800 && codePoint <= 0xdfff) return null;
1796
+ let end = start + hexadecimal.length;
1797
+ if (/\s/u.test(source[end] ?? '')) end += 1;
1798
+ return {
1799
+ value: String.fromCodePoint(codePoint),
1800
+ end
1801
+ };
1802
+ }
1803
+ const value = source[start];
1804
+ return !value || /[\r\n\f]/u.test(value) ? null : {
1805
+ value,
1806
+ end: start + 1
1807
+ };
1808
+ }
1809
+ function work_document_script_fonts_isRecordWithKeys(value, allowed) {
1810
+ return 'object' == typeof value && null !== value && !Array.isArray(value) && Object.keys(value).every((key)=>allowed.has(key));
1811
+ }
1812
+ const DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE = 'data-office-proofing-languages';
1813
+ const DOCUMENT_NO_PROOF_ATTRIBUTE = 'data-office-no-proof';
1814
+ const PROOFING_LANGUAGE_KEYS = new Set([
1815
+ 'latin',
1816
+ 'eastAsia',
1817
+ 'bidi'
1818
+ ]);
1819
+ const PROOFING_LANGUAGE_ORDER = [
1820
+ 'latin',
1821
+ 'eastAsia',
1822
+ 'bidi'
1823
+ ];
1824
+ const MAX_LANGUAGE_TAG_LENGTH = 85;
1825
+ const MAX_SERIALIZED_PROOFING_LANGUAGES_BYTES = 384;
1826
+ function normalizeDocumentLanguageTag(source) {
1827
+ if ('string' != typeof source) return null;
1828
+ if (!source || source !== source.trim() || source.length > MAX_LANGUAGE_TAG_LENGTH || /[\p{Cc}\p{Cs}]/u.test(source)) return null;
1829
+ return /^(?:x-none|[a-z0-9]{1,8}(?:-[a-z0-9]{1,8})*)$/iu.test(source) ? source : null;
1830
+ }
1831
+ function normalizeDocumentProofingLanguages(source) {
1832
+ if (!isRecord(source)) return null;
1833
+ const keys = Object.keys(source);
1834
+ if (!keys.length || keys.some((key)=>!PROOFING_LANGUAGE_KEYS.has(key))) return null;
1835
+ const normalized = {};
1836
+ for (const key of PROOFING_LANGUAGE_ORDER){
1837
+ if (void 0 === source[key]) continue;
1838
+ const language = normalizeDocumentLanguageTag(source[key]);
1839
+ if (!language) return null;
1840
+ normalized[key] = language;
1841
+ }
1842
+ return Object.keys(normalized).length ? normalized : null;
1843
+ }
1844
+ function serializeDocumentProofingLanguages(source) {
1845
+ const normalized = normalizeDocumentProofingLanguages(source);
1846
+ if (!normalized) return;
1847
+ const serialized = JSON.stringify(normalized);
1848
+ return serialized.length <= MAX_SERIALIZED_PROOFING_LANGUAGES_BYTES ? serialized : void 0;
1849
+ }
1850
+ function parseDocumentProofingLanguages(source) {
1851
+ if ('string' != typeof source) return normalizeDocumentProofingLanguages(source);
1852
+ if (!source || source.length > MAX_SERIALIZED_PROOFING_LANGUAGES_BYTES) return null;
1853
+ try {
1854
+ const normalized = normalizeDocumentProofingLanguages(JSON.parse(source));
1855
+ return normalized && JSON.stringify(normalized) === source ? normalized : null;
1856
+ } catch {
1857
+ return null;
1858
+ }
1859
+ }
1860
+ function normalizeDocumentNoProof(source) {
1861
+ if (true === source || 'true' === source || '1' === source) return true;
1862
+ if (false === source || 'false' === source || '0' === source) return false;
1863
+ return null;
1864
+ }
1865
+ function documentProofingLanguagesFromElement(element) {
1866
+ return parseDocumentProofingLanguages(element.getAttribute(DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE));
1867
+ }
1868
+ function documentNoProofFromElement(element) {
1869
+ return normalizeDocumentNoProof(element.getAttribute(DOCUMENT_NO_PROOF_ATTRIBUTE));
1870
+ }
1871
+ function documentProofingLanguageForScript(source, slot) {
1872
+ const languages = normalizeDocumentProofingLanguages(source);
1873
+ if (!languages) return;
1874
+ if ('eastAsia' === slot) return languages.eastAsia ?? languages.latin;
1875
+ if ('complexScript' === slot) return languages.bidi ?? languages.latin;
1876
+ return languages.latin ?? languages.eastAsia ?? languages.bidi;
1877
+ }
1878
+ function documentProofingDomAttributes(languagesSource, noProofSource, slot) {
1879
+ const languages = normalizeDocumentProofingLanguages(languagesSource);
1880
+ const serialized = serializeDocumentProofingLanguages(languages);
1881
+ const noProof = normalizeDocumentNoProof(noProofSource);
1882
+ const language = documentProofingLanguageForScript(languages, slot);
1883
+ return {
1884
+ ...serialized ? {
1885
+ [DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE]: serialized
1886
+ } : {},
1887
+ ...null === noProof ? {} : {
1888
+ [DOCUMENT_NO_PROOF_ATTRIBUTE]: String(noProof)
1889
+ },
1890
+ ...slot ? {
1891
+ [DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE]: slot
1892
+ } : {},
1893
+ ...language && 'x-none' !== language ? {
1894
+ lang: language
1895
+ } : {},
1896
+ ...true === noProof ? {
1897
+ spellcheck: 'false'
1898
+ } : {}
1899
+ };
1900
+ }
1901
+ function patchDocumentProofingLanguages(source, patch) {
1902
+ const current = normalizeDocumentProofingLanguages(source) ?? {};
1903
+ const next = {
1904
+ ...current
1905
+ };
1906
+ for (const slot of PROOFING_LANGUAGE_ORDER){
1907
+ const value = patch[slot];
1908
+ if (void 0 === value) continue;
1909
+ if (null === value) {
1910
+ delete next[slot];
1911
+ continue;
1912
+ }
1913
+ const language = normalizeDocumentLanguageTag(value);
1914
+ if (!language) return null;
1915
+ next[slot] = language;
1916
+ }
1917
+ return Object.keys(next).length ? next : null;
1918
+ }
1919
+ function isRecord(source) {
1920
+ return 'object' == typeof source && null !== source && !Array.isArray(source);
1921
+ }
1922
+ const DOCUMENT_PARAGRAPH_ID_ATTRIBUTE = 'data-office-paragraph-id';
1923
+ const DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE = 'data-office-paragraph-text-id';
1924
+ const PARAGRAPH_ID_PATTERN = /^[0-9A-F]{8}$/;
1925
+ const MAX_PARAGRAPH_ID = 0x7fffffff;
1926
+ let fallbackIdentitySequence = 0;
1927
+ const DocumentParagraphIdentity = Extension.create({
1928
+ name: 'documentParagraphIdentity',
1929
+ addOptions () {
1930
+ return {
1931
+ rotateTextId: ()=>true,
1932
+ types: [
1933
+ 'paragraph',
1934
+ 'heading',
1935
+ 'documentCaption'
1936
+ ]
1937
+ };
1938
+ },
1939
+ addGlobalAttributes () {
1940
+ return [
1941
+ {
1942
+ types: this.options.types,
1943
+ attributes: {
1944
+ paragraphId: {
1945
+ default: null,
1946
+ parseHTML: (element)=>normalizeDocumentParagraphId(element.getAttribute(DOCUMENT_PARAGRAPH_ID_ATTRIBUTE)),
1947
+ renderHTML: (attributes)=>{
1948
+ const value = normalizeDocumentParagraphId(attributes.paragraphId);
1949
+ return value ? {
1950
+ [DOCUMENT_PARAGRAPH_ID_ATTRIBUTE]: value
1951
+ } : {};
1952
+ }
1953
+ },
1954
+ textId: {
1955
+ default: null,
1956
+ parseHTML: (element)=>normalizeDocumentParagraphId(element.getAttribute(DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE)),
1957
+ renderHTML: (attributes)=>{
1958
+ const value = normalizeDocumentParagraphId(attributes.textId);
1959
+ return value ? {
1960
+ [DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE]: value
1961
+ } : {};
1962
+ }
1963
+ }
1964
+ }
1965
+ }
1966
+ ];
1967
+ },
1968
+ addProseMirrorPlugins () {
1969
+ return [
1970
+ createDocumentParagraphIdentityPlugin(this.options.types, this.options.rotateTextId)
1971
+ ];
1972
+ }
1973
+ });
1974
+ function normalizeDocumentParagraphId(value) {
1975
+ if ('string' != typeof value) return null;
1976
+ const normalized = value.trim().toUpperCase();
1977
+ if (!PARAGRAPH_ID_PATTERN.test(normalized)) return null;
1978
+ const number = Number.parseInt(normalized, 16);
1979
+ return number > 0 && number <= MAX_PARAGRAPH_ID ? normalized : null;
1980
+ }
1981
+ function createDocumentParagraphIdentityRegistry() {
1982
+ return {
1983
+ paragraphIds: new Set()
1984
+ };
1985
+ }
1986
+ function normalizeDocumentParagraphIdentity(source) {
1987
+ const paragraphId = normalizeDocumentParagraphId(source.paragraphId);
1988
+ const textId = normalizeDocumentParagraphId(source.textId);
1989
+ return paragraphId && textId ? {
1990
+ paragraphId,
1991
+ textId
1992
+ } : null;
1993
+ }
1994
+ function documentParagraphIdentityFromElement(element) {
1995
+ return normalizeDocumentParagraphIdentity({
1996
+ paragraphId: element.getAttribute(DOCUMENT_PARAGRAPH_ID_ATTRIBUTE),
1997
+ textId: element.getAttribute(DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE)
1998
+ });
1999
+ }
2000
+ function applyDocumentParagraphIdentityToElement(element, source) {
2001
+ const identity = normalizeDocumentParagraphIdentity(source);
2002
+ if (!identity) {
2003
+ element.removeAttribute(DOCUMENT_PARAGRAPH_ID_ATTRIBUTE);
2004
+ element.removeAttribute(DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE);
2005
+ return null;
2006
+ }
2007
+ element.setAttribute(DOCUMENT_PARAGRAPH_ID_ATTRIBUTE, identity.paragraphId);
2008
+ element.setAttribute(DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE, identity.textId);
2009
+ return identity;
2010
+ }
2011
+ function createDocumentParagraphIdentityPlugin(types, rotateTextId) {
2012
+ const trackedTypes = new Set(types);
2013
+ return new Plugin({
2014
+ view (view) {
2015
+ const transaction = normalizeDocumentParagraphIdentities(view.state, trackedTypes, rotateTextId);
2016
+ if (transaction) {
2017
+ transaction.setMeta('addToHistory', false);
2018
+ view.dispatch(transaction);
2019
+ }
2020
+ return {};
2021
+ },
2022
+ appendTransaction (transactions, oldState, newState) {
2023
+ if (!transactions.some((transaction)=>transaction.docChanged)) return null;
2024
+ return normalizeDocumentParagraphIdentities(newState, trackedTypes, rotateTextId, oldState, transactions);
2025
+ }
2026
+ });
2027
+ }
2028
+ function normalizeDocumentParagraphIdentities(state, trackedTypes, rotateTextId, oldState, transactions = []) {
2029
+ if (!documentHasIntegrityFeature(state.doc, 16)) return null;
2030
+ const paragraphs = documentParagraphs(state.doc, trackedTypes);
2031
+ if (!paragraphs.length) return null;
2032
+ const retainedPositions = oldState ? retainedDocumentParagraphPositions(oldState, state, transactions, trackedTypes) : new Set();
2033
+ const editedPositions = oldState && rotateTextId() && !transactions.some(isHistoryTransaction) ? editedDocumentParagraphPositions(oldState, state, transactions, trackedTypes) : new Set();
2034
+ const ordered = [
2035
+ ...paragraphs.filter((item)=>retainedPositions.has(item.position)),
2036
+ ...paragraphs.filter((item)=>!retainedPositions.has(item.position))
2037
+ ];
2038
+ const registry = createDocumentParagraphIdentityRegistry();
2039
+ const updates = new Map();
2040
+ for (const paragraph of ordered){
2041
+ const current = paragraphIdentitySourceFromNode(paragraph.node);
2042
+ const source = editedPositions.has(paragraph.position) ? {
2043
+ ...current,
2044
+ textId: nextDocumentParagraphTextId(current.textId)
2045
+ } : current;
2046
+ const identity = uniqueDocumentParagraphIdentity(source, registry);
2047
+ if (!sameDocumentParagraphIdentity(current, identity)) updates.set(paragraph.position, identity);
2048
+ }
2049
+ if (!updates.size) return null;
2050
+ const transaction = state.tr;
2051
+ for (const paragraph of paragraphs){
2052
+ const identity = updates.get(paragraph.position);
2053
+ if (identity) transaction.setNodeMarkup(paragraph.position, void 0, {
2054
+ ...paragraph.node.attrs,
2055
+ ...identity
2056
+ });
2057
+ }
2058
+ if (!transaction.docChanged) return null;
2059
+ transaction.setMeta('addToHistory', false);
2060
+ return transaction;
2061
+ }
2062
+ function hasDocumentParagraphIdentityComponent(node) {
2063
+ return Boolean(normalizeDocumentParagraphId(node.attrs.paragraphId) || normalizeDocumentParagraphId(node.attrs.textId));
2064
+ }
2065
+ function retainedDocumentParagraphPositions(oldState, newState, transactions, trackedTypes) {
2066
+ const mapping = transactionMapping(transactions);
2067
+ const retained = new Set();
2068
+ for (const previous of documentParagraphs(oldState.doc, trackedTypes)){
2069
+ const paragraphId = normalizeDocumentParagraphId(previous.node.attrs.paragraphId);
2070
+ if (!paragraphId) continue;
2071
+ const mapped = mapping.mapResult(previous.position, 1);
2072
+ const current = newState.doc.nodeAt(mapped.pos);
2073
+ if (current && trackedTypes.has(current.type.name) && normalizeDocumentParagraphId(current.attrs.paragraphId) === paragraphId) retained.add(mapped.pos);
2074
+ }
2075
+ return retained;
2076
+ }
2077
+ function editedDocumentParagraphPositions(oldState, newState, transactions, trackedTypes) {
2078
+ const mapping = transactionMapping(transactions);
2079
+ const previousParagraphs = documentParagraphs(oldState.doc, trackedTypes);
2080
+ const currentParagraphs = documentParagraphs(newState.doc, trackedTypes);
2081
+ const previousById = paragraphsById(previousParagraphs);
2082
+ const currentById = paragraphsById(currentParagraphs);
2083
+ const edited = new Set();
2084
+ for (const previous of previousParagraphs){
2085
+ const identity = normalizeDocumentParagraphIdentity(paragraphIdentitySourceFromNode(previous.node));
2086
+ if (!identity) continue;
2087
+ const mapped = mapping.mapResult(previous.position, 1);
2088
+ const current = newState.doc.nodeAt(mapped.pos);
2089
+ if (current && trackedTypes.has(current.type.name) && normalizeDocumentParagraphId(current.attrs.paragraphId) === identity.paragraphId) {
2090
+ if (paragraphTextChanged(previous.node, current, identity.textId)) edited.add(mapped.pos);
2091
+ continue;
2092
+ }
2093
+ const previousMatches = previousById.get(identity.paragraphId) ?? [];
2094
+ const currentMatches = currentById.get(identity.paragraphId) ?? [];
2095
+ if (1 === previousMatches.length && 1 === currentMatches.length && paragraphTextChanged(previous.node, currentMatches[0].node, identity.textId)) edited.add(currentMatches[0].position);
2096
+ }
2097
+ return edited;
2098
+ }
2099
+ function paragraphTextChanged(previous, current, previousTextId) {
2100
+ return previous.textContent !== current.textContent && normalizeDocumentParagraphId(current.attrs.textId) === previousTextId;
2101
+ }
2102
+ function paragraphsById(paragraphs) {
2103
+ const result = new Map();
2104
+ for (const paragraph of paragraphs){
2105
+ const id = normalizeDocumentParagraphId(paragraph.node.attrs.paragraphId);
2106
+ if (!id) continue;
2107
+ const matches = result.get(id) ?? [];
2108
+ matches.push(paragraph);
2109
+ result.set(id, matches);
2110
+ }
2111
+ return result;
2112
+ }
2113
+ function documentParagraphs(document, trackedTypes) {
2114
+ const paragraphs = [];
2115
+ document.descendants((node, position)=>{
2116
+ if (trackedTypes.has(node.type.name) && hasDocumentParagraphIdentityComponent(node)) paragraphs.push({
2117
+ node,
2118
+ position
2119
+ });
2120
+ });
2121
+ return paragraphs;
2122
+ }
2123
+ function paragraphIdentitySourceFromNode(node) {
2124
+ return {
2125
+ paragraphId: node.attrs.paragraphId,
2126
+ textId: node.attrs.textId
2127
+ };
2128
+ }
2129
+ function uniqueDocumentParagraphIdentity(source, registry) {
2130
+ const preferred = normalizeDocumentParagraphIdentity(source);
2131
+ if (preferred && !registry.paragraphIds.has(preferred.paragraphId)) {
2132
+ registry.paragraphIds.add(preferred.paragraphId);
2133
+ return preferred;
2134
+ }
2135
+ for(let attempt = 0; attempt < 8; attempt += 1){
2136
+ const identity = createDocumentParagraphIdentity();
2137
+ if (!registry.paragraphIds.has(identity.paragraphId)) {
2138
+ registry.paragraphIds.add(identity.paragraphId);
2139
+ return identity;
2140
+ }
2141
+ }
2142
+ return sequentialDocumentParagraphIdentity(registry);
2143
+ }
2144
+ function createDocumentParagraphIdentity() {
2145
+ return {
2146
+ paragraphId: randomDocumentParagraphId(),
2147
+ textId: randomDocumentParagraphId()
2148
+ };
2149
+ }
2150
+ function sequentialDocumentParagraphIdentity(registry) {
2151
+ for(let value = 1; value <= MAX_PARAGRAPH_ID; value += 1){
2152
+ const paragraphId = formatDocumentParagraphId(value);
2153
+ if (!registry.paragraphIds.has(paragraphId)) {
2154
+ registry.paragraphIds.add(paragraphId);
2155
+ return {
2156
+ paragraphId,
2157
+ textId: randomDocumentParagraphId()
2158
+ };
2159
+ }
2160
+ }
2161
+ throw new Error('No unique Word paragraph identity is available.');
2162
+ }
2163
+ function nextDocumentParagraphTextId(value) {
2164
+ const current = normalizeDocumentParagraphId(value);
2165
+ if (!current) return randomDocumentParagraphId();
2166
+ const number = Number.parseInt(current, 16);
2167
+ return formatDocumentParagraphId(number >= MAX_PARAGRAPH_ID ? 1 : number + 1);
2168
+ }
2169
+ function randomDocumentParagraphId() {
2170
+ let value = 0;
2171
+ const cryptoApi = globalThis.crypto;
2172
+ if ('function' == typeof cryptoApi?.getRandomValues) {
2173
+ const values = new Uint32Array(1);
2174
+ cryptoApi.getRandomValues(values);
2175
+ value = values[0] ?? 0;
2176
+ } else if ('function' == typeof cryptoApi?.randomUUID) value = Number.parseInt(cryptoApi.randomUUID().replaceAll('-', '').slice(0, 8), 16);
2177
+ if (!value) {
2178
+ fallbackIdentitySequence += 1;
2179
+ value = stableIdentityHash(`${Date.now()}:${Math.random()}:${fallbackIdentitySequence}`);
2180
+ }
2181
+ return formatDocumentParagraphId(value || fallbackIdentitySequence || 1);
2182
+ }
2183
+ function stableIdentityHash(value) {
2184
+ let hash = 0x811c9dc5;
2185
+ for(let index = 0; index < value.length; index += 1){
2186
+ hash ^= value.charCodeAt(index);
2187
+ hash = Math.imul(hash, 0x01000193);
2188
+ }
2189
+ return hash >>> 0 || 1;
2190
+ }
2191
+ function formatDocumentParagraphId(value) {
2192
+ return (value >>> 0 & MAX_PARAGRAPH_ID || 1).toString(16).toUpperCase().padStart(8, '0');
2193
+ }
2194
+ function sameDocumentParagraphIdentity(source, identity) {
2195
+ return normalizeDocumentParagraphId(source.paragraphId) === identity.paragraphId && normalizeDocumentParagraphId(source.textId) === identity.textId;
2196
+ }
2197
+ function transactionMapping(transactions) {
2198
+ const mapping = new Mapping();
2199
+ for (const transaction of transactions)mapping.appendMapping(transaction.mapping);
2200
+ return mapping;
2201
+ }
2202
+ function collectWorkDocumentOutline(document) {
2203
+ const items = [];
2204
+ const hierarchy = [];
2205
+ document.descendants((node, position)=>{
2206
+ const level = workDocumentOutlineLevel(node);
2207
+ if (null === level) return;
2208
+ while((hierarchy.at(-1)?.level ?? 0) >= level)hierarchy.pop();
2209
+ const parent = hierarchy.at(-1);
2210
+ const from = position + 1;
2211
+ const paragraphId = normalizeDocumentParagraphId(node.attrs.paragraphId);
2212
+ const item = {
2213
+ id: paragraphId ? `heading-${paragraphId.toLowerCase()}` : `heading-${position}`,
2214
+ text: normalizedDocumentHeadingText(node.textContent),
2215
+ level,
2216
+ depth: hierarchy.length,
2217
+ from,
2218
+ to: from + node.content.size,
2219
+ ...parent ? {
2220
+ parentId: parent.id
2221
+ } : {}
2222
+ };
2223
+ items.push(item);
2224
+ hierarchy.push(item);
2225
+ });
2226
+ return items.map((item, index)=>({
2227
+ ...item,
2228
+ hasChildren: (items[index + 1]?.depth ?? -1) > item.depth
2229
+ }));
2230
+ }
2231
+ function workDocumentOutlineLevel(node) {
2232
+ if ('heading' === node.type.name) return documentHeadingLevel(node.attrs.level);
2233
+ if ('paragraph' !== node.type.name) return null;
2234
+ const value = node.attrs.outlineLevel;
2235
+ if (null == value || '' === value) return null;
2236
+ const outlineLevel = Number(value);
2237
+ return Number.isInteger(outlineLevel) && outlineLevel >= 0 && outlineLevel <= 8 ? outlineLevel + 1 : null;
2238
+ }
2239
+ function currentWorkDocumentOutlineItem(items, position) {
2240
+ let current = null;
2241
+ for (const item of items){
2242
+ if (item.from > position) break;
2243
+ current = item;
2244
+ }
2245
+ return current;
2246
+ }
2247
+ function visibleWorkDocumentOutlineItems(items, collapsedIds, rawQuery) {
2248
+ const query = normalizedDocumentOutlineQuery(rawQuery);
2249
+ if (query) return items.filter((item)=>normalizedDocumentOutlineQuery(item.text).includes(query));
2250
+ const visible = [];
2251
+ let hiddenBelowDepth = null;
2252
+ for (const item of items){
2253
+ if (null !== hiddenBelowDepth && item.depth <= hiddenBelowDepth) hiddenBelowDepth = null;
2254
+ if (null === hiddenBelowDepth) {
2255
+ visible.push(item);
2256
+ if (item.hasChildren && collapsedIds.has(item.id)) hiddenBelowDepth = item.depth;
2257
+ }
2258
+ }
2259
+ return visible;
2260
+ }
2261
+ function documentHeadingLevel(value) {
2262
+ return 'number' == typeof value && Number.isInteger(value) && value >= 1 && value <= 6 ? value : 1;
2263
+ }
2264
+ function normalizedDocumentHeadingText(value) {
2265
+ return value.replace(/\s+/g, ' ').trim() || '未命名标题';
2266
+ }
2267
+ function normalizedDocumentOutlineQuery(value) {
2268
+ return value.normalize('NFKC').trim().toLocaleLowerCase();
2269
+ }
2270
+ const DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS = {
2271
+ minLevel: 1,
2272
+ maxLevel: 3,
2273
+ hyperlinks: true,
2274
+ showPageNumbers: true,
2275
+ rightAlignPageNumbers: true,
2276
+ leader: 'dot'
2277
+ };
2278
+ const MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES = 512;
2279
+ const TABLE_OF_CONTENTS_SELECTOR = '[data-document-table-of-contents]';
2280
+ const MAX_TABLE_OF_CONTENTS_TITLE_LENGTH = 512;
2281
+ const TABLE_OF_CONTENTS_ID_PATTERN = /^[a-z0-9][a-z0-9._:-]{0,127}$/i;
2282
+ const TABLE_OF_CONTENTS_TARGET_PATTERN = /^heading-[a-z0-9._:-]{1,128}$/i;
2283
+ function normalizeDocumentTableOfContentsOptions(source) {
2284
+ const minLevel = boundedLevel(source?.minLevel, 1);
2285
+ const maxLevel = Math.max(minLevel, boundedLevel(source?.maxLevel, Math.max(3, minLevel)));
2286
+ const showPageNumbers = source?.showPageNumbers !== false;
2287
+ return {
2288
+ minLevel,
2289
+ maxLevel,
2290
+ hyperlinks: source?.hyperlinks !== false,
2291
+ showPageNumbers,
2292
+ rightAlignPageNumbers: showPageNumbers && source?.rightAlignPageNumbers !== false,
2293
+ leader: tableOfContentsLeader(source?.leader) ?? 'dot'
2294
+ };
2295
+ }
2296
+ function buildDocumentTableOfContentsEntries(document, options, buildOptions = {}) {
2297
+ const normalized = normalizeDocumentTableOfContentsOptions(options);
2298
+ const outline = collectWorkDocumentOutline(document).filter((item)=>item.text.length > 0 && item.level >= normalized.minLevel && item.level <= normalized.maxLevel);
2299
+ const entries = outline.slice(0, MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES).map((item)=>tableOfContentsEntryFromOutline(document, item, buildOptions.resolveContext));
2300
+ return {
2301
+ entries,
2302
+ truncated: outline.length > MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES
2303
+ };
2304
+ }
2305
+ function documentTableOfContentsHtml(source) {
2306
+ const value = normalizeDocumentTableOfContentsValue(source);
2307
+ const options = value.options;
2308
+ const rows = value.entries.length ? value.entries.map((entry)=>tableOfContentsEntryHtml(entry, options)) : [
2309
+ '<li class="work-document-table-of-contents-empty">没有符合级别范围的标题</li>'
2310
+ ];
2311
+ const status = value.truncated ? `仅显示前 ${MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES} 项` : `${value.entries.length} 项`;
2312
+ return [
2313
+ `<div data-document-table-of-contents="true" data-toc-id="${escapeHtmlAttribute(value.id)}" data-toc-min-level="${options.minLevel}" data-toc-max-level="${options.maxLevel}" data-toc-hyperlinks="${String(options.hyperlinks)}" data-toc-show-page-numbers="${String(options.showPageNumbers)}" data-toc-right-align-page-numbers="${String(options.rightAlignPageNumbers)}" data-toc-leader="${options.leader}" data-toc-entries="${escapeHtmlAttribute(JSON.stringify(value.entries))}" data-toc-truncated="${String(value.truncated)}" class="work-document-table-of-contents" contenteditable="false" aria-label="目录">`,
2314
+ '<div class="work-document-table-of-contents-header"><strong>目录</strong>',
2315
+ `<span>${status}</span></div>`,
2316
+ '<ol class="work-document-table-of-contents-list">',
2317
+ ...rows,
2318
+ '</ol></div>'
2319
+ ].join('');
2320
+ }
2321
+ function normalizeDocumentTableOfContentsHtml(source) {
2322
+ const document = new DOMParser().parseFromString(source, 'text/html');
2323
+ const usedIds = new Set();
2324
+ for (const [index, element] of Array.from(document.body.querySelectorAll(TABLE_OF_CONTENTS_SELECTOR)).entries()){
2325
+ const value = documentTableOfContentsValueFromElement(element, index + 1);
2326
+ value.id = uniqueTableOfContentsId(value.id, index + 1, usedIds);
2327
+ const replacement = document.createRange().createContextualFragment(documentTableOfContentsHtml(value));
2328
+ element.replaceWith(replacement);
2329
+ }
2330
+ return document.body.innerHTML;
2331
+ }
2332
+ function documentTableOfContentsValueFromElement(element, index = 1) {
2333
+ const entries = parseTableOfContentsEntries(element.dataset.tocEntries);
2334
+ return normalizeDocumentTableOfContentsValue({
2335
+ id: validTableOfContentsId(element.dataset.tocId) ?? `toc-${index}`,
2336
+ options: {
2337
+ minLevel: Number(element.dataset.tocMinLevel),
2338
+ maxLevel: Number(element.dataset.tocMaxLevel),
2339
+ hyperlinks: 'false' !== element.dataset.tocHyperlinks,
2340
+ showPageNumbers: 'false' !== element.dataset.tocShowPageNumbers,
2341
+ rightAlignPageNumbers: 'false' !== element.dataset.tocRightAlignPageNumbers,
2342
+ leader: tableOfContentsLeader(element.dataset.tocLeader) ?? 'dot'
2343
+ },
2344
+ entries,
2345
+ truncated: 'true' === element.dataset.tocTruncated
2346
+ });
2347
+ }
2348
+ function parseDocumentTableOfContentsInstruction(instruction) {
2349
+ const command = /^\s*TOC\b/i.exec(instruction);
2350
+ if (!command) return {
2351
+ supported: false,
2352
+ reason: 'not-table-of-contents'
2353
+ };
2354
+ const source = instruction.slice(command[0].length);
2355
+ const switches = new Map();
2356
+ const matcher = /\\([a-z])(?:\s+("([^"]*)"|([^\\\s]+)))?/gi;
2357
+ let cursor = 0;
2358
+ for(let match = matcher.exec(source); match; match = matcher.exec(source)){
2359
+ if (source.slice(cursor, match.index).trim()) return {
2360
+ supported: false,
2361
+ reason: 'invalid-instruction'
2362
+ };
2363
+ const name = match[1]?.toLowerCase() ?? '';
2364
+ if (!name || switches.has(name)) return {
2365
+ supported: false,
2366
+ reason: 'invalid-instruction'
2367
+ };
2368
+ switches.set(name, match[3] ?? match[4] ?? null);
2369
+ cursor = matcher.lastIndex;
2370
+ }
2371
+ if (source.slice(cursor).trim()) return {
2372
+ supported: false,
2373
+ reason: 'invalid-instruction'
2374
+ };
2375
+ for (const name of switches.keys())if (![
2376
+ 'o',
2377
+ 'h',
2378
+ 'z',
2379
+ 'u',
2380
+ 'n',
2381
+ 'p'
2382
+ ].includes(name)) return {
2383
+ supported: false,
2384
+ reason: 'unsupported-switch'
2385
+ };
2386
+ const range = switches.has('o') ? parseTableOfContentsRange(switches.get('o')) : {
2387
+ minLevel: 1,
2388
+ maxLevel: 3
2389
+ };
2390
+ if (!range) return {
2391
+ supported: false,
2392
+ reason: 'invalid-level-range'
2393
+ };
2394
+ const pageRange = switches.has('n') ? parseOptionalTableOfContentsRange(switches.get('n')) : null;
2395
+ if (switches.has('n') && void 0 === pageRange) return {
2396
+ supported: false,
2397
+ reason: 'invalid-level-range'
2398
+ };
2399
+ if (pageRange && (pageRange.minLevel !== range.minLevel || pageRange.maxLevel !== range.maxLevel)) return {
2400
+ supported: false,
2401
+ reason: 'unsupported-page-range'
2402
+ };
2403
+ const separator = switches.get('p');
2404
+ if (switches.has('p') && (null == separator || separator.trim())) return {
2405
+ supported: false,
2406
+ reason: 'unsupported-separator'
2407
+ };
2408
+ const showPageNumbers = !switches.has('n');
2409
+ const rightAlignPageNumbers = showPageNumbers && !switches.has('p');
2410
+ return {
2411
+ supported: true,
2412
+ options: {
2413
+ ...range,
2414
+ hyperlinks: switches.has('h'),
2415
+ showPageNumbers,
2416
+ rightAlignPageNumbers,
2417
+ leader: rightAlignPageNumbers ? 'dot' : 'none'
2418
+ }
2419
+ };
2420
+ }
2421
+ function tableOfContentsLeader(value) {
2422
+ return 'dot' === value || 'dash' === value || 'underline' === value || 'none' === value ? value : null;
2423
+ }
2424
+ function normalizeDocumentTableOfContentsValue(source) {
2425
+ return {
2426
+ id: validTableOfContentsId(source.id) ?? 'document-table-of-contents',
2427
+ options: normalizeDocumentTableOfContentsOptions(source.options),
2428
+ entries: normalizeTableOfContentsEntries(source.entries),
2429
+ truncated: Boolean(source.truncated)
2430
+ };
2431
+ }
2432
+ function tableOfContentsEntryFromOutline(document, item, resolveContext) {
2433
+ return {
2434
+ targetId: item.id,
2435
+ title: item.text.slice(0, MAX_TABLE_OF_CONTENTS_TITLE_LENGTH),
2436
+ level: item.level,
2437
+ pageNumber: positiveInteger(resolveContext?.(item.from)?.pageNumber) ?? fallbackDocumentPageNumber(document, item.from)
2438
+ };
2439
+ }
2440
+ function fallbackDocumentPageNumber(document, position) {
2441
+ let pageNumber = 1;
2442
+ document.descendants((node, offset)=>{
2443
+ if (offset >= position) return false;
2444
+ if ('pageBreak' === node.type.name) pageNumber += 1;
2445
+ return true;
2446
+ });
2447
+ return pageNumber;
2448
+ }
2449
+ function tableOfContentsEntryHtml(entry, options) {
2450
+ const title = escapeHtml(entry.title);
2451
+ const targetId = escapeHtmlAttribute(entry.targetId);
2452
+ const label = options.hyperlinks ? `<a href="#${targetId}" data-toc-target="${targetId}" tabindex="-1">${title}</a>` : `<span>${title}</span>`;
2453
+ const page = options.showPageNumbers ? `<span class="work-document-table-of-contents-page">${entry.pageNumber}</span>` : '';
2454
+ return `<li data-toc-target="${targetId}" data-toc-level="${entry.level}" style="--work-toc-level:${entry.level}">${label}<i aria-hidden="true"></i>${page}</li>`;
2455
+ }
2456
+ function parseTableOfContentsEntries(source) {
2457
+ if (!source) return [];
2458
+ try {
2459
+ const parsed = JSON.parse(source);
2460
+ return Array.isArray(parsed) ? normalizeTableOfContentsEntries(parsed) : [];
2461
+ } catch {
2462
+ return [];
2463
+ }
2464
+ }
2465
+ function normalizeTableOfContentsEntries(source) {
2466
+ const entries = [];
2467
+ for (const value of source.slice(0, MAX_DOCUMENT_TABLE_OF_CONTENTS_ENTRIES)){
2468
+ if (!value || 'object' != typeof value) continue;
2469
+ const candidate = value;
2470
+ const targetId = 'string' == typeof candidate.targetId ? candidate.targetId.trim() : '';
2471
+ const title = 'string' == typeof candidate.title ? candidate.title.replace(/\s+/g, ' ').trim() : '';
2472
+ const level = boundedLevel(candidate.level, 0);
2473
+ const pageNumber = positiveInteger(candidate.pageNumber);
2474
+ if (TABLE_OF_CONTENTS_TARGET_PATTERN.test(targetId) && title && level && pageNumber) entries.push({
2475
+ targetId,
2476
+ title: title.slice(0, MAX_TABLE_OF_CONTENTS_TITLE_LENGTH),
2477
+ level,
2478
+ pageNumber
2479
+ });
2480
+ }
2481
+ return entries;
2482
+ }
2483
+ function parseTableOfContentsRange(value) {
2484
+ if (null == value) return null;
2485
+ const match = /^([1-9])-([1-9])$/.exec(value.trim());
2486
+ if (!match) return null;
2487
+ const minLevel = Number(match[1]);
2488
+ const maxLevel = Number(match[2]);
2489
+ return minLevel <= maxLevel ? {
2490
+ minLevel,
2491
+ maxLevel
2492
+ } : null;
2493
+ }
2494
+ function parseOptionalTableOfContentsRange(value) {
2495
+ if (null === value) return null;
2496
+ return parseTableOfContentsRange(value) ?? void 0;
2497
+ }
2498
+ function boundedLevel(value, fallback) {
2499
+ const number = Number(value);
2500
+ return Number.isInteger(number) && number >= 1 && number <= 9 ? number : fallback;
2501
+ }
2502
+ function positiveInteger(value) {
2503
+ const number = Number(value);
2504
+ return Number.isSafeInteger(number) && number > 0 ? Math.min(999999, number) : null;
2505
+ }
2506
+ function validTableOfContentsId(value) {
2507
+ return 'string' == typeof value && TABLE_OF_CONTENTS_ID_PATTERN.test(value) ? value : null;
2508
+ }
2509
+ function uniqueTableOfContentsId(source, index, usedIds) {
2510
+ if (!usedIds.has(source)) {
2511
+ usedIds.add(source);
2512
+ return source;
2513
+ }
2514
+ let suffix = index;
2515
+ while(usedIds.has(`document-table-of-contents-${suffix}`))suffix += 1;
2516
+ const id = `document-table-of-contents-${suffix}`;
2517
+ usedIds.add(id);
2518
+ return id;
2519
+ }
2520
+ function escapeHtml(value) {
2521
+ return value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
2522
+ }
2523
+ function escapeHtmlAttribute(value) {
2524
+ return escapeHtml(value).replaceAll('"', '&quot;').replaceAll("'", '&#39;');
2525
+ }
974
2526
  const WORK_TEMPLATES = [
975
2527
  {
976
2528
  id: 'blank-document',
@@ -986,6 +2538,13 @@ const WORK_TEMPLATES = [
986
2538
  description: '目标、范围、里程碑与风险',
987
2539
  accent: '#536de2'
988
2540
  },
2541
+ {
2542
+ id: 'table-of-contents',
2543
+ kind: 'document',
2544
+ name: '可更新目录',
2545
+ description: '标题级别、超链接、页码、前导符与原生 DOCX 往返',
2546
+ accent: '#315f9f'
2547
+ },
989
2548
  {
990
2549
  id: 'text-effects',
991
2550
  kind: 'document',
@@ -1000,6 +2559,20 @@ const WORK_TEMPLATES = [
1000
2559
  description: '原生线型、颜色、宽度、间距与阴影',
1001
2560
  accent: '#4472c4'
1002
2561
  },
2562
+ {
2563
+ id: 'run-shading',
2564
+ kind: 'document',
2565
+ name: '字符底纹',
2566
+ description: '原生图案、前景色、背景色与显式重置',
2567
+ accent: '#70ad47'
2568
+ },
2569
+ {
2570
+ id: 'proofing-languages',
2571
+ kind: 'document',
2572
+ name: '校对语言',
2573
+ description: '拉丁、东亚、双向文字与校对排除',
2574
+ accent: '#2f6fed'
2575
+ },
1003
2576
  {
1004
2577
  id: 'blank-markdown',
1005
2578
  kind: 'markdown',
@@ -1021,6 +2594,13 @@ const WORK_TEMPLATES = [
1021
2594
  description: '目标进度与预算跟踪',
1022
2595
  accent: '#168f72'
1023
2596
  },
2597
+ {
2598
+ id: 'data-validation',
2599
+ kind: 'spreadsheet',
2600
+ name: '数据验证',
2601
+ description: '下拉列表、输入提示与错误警告',
2602
+ accent: '#13795b'
2603
+ },
1024
2604
  {
1025
2605
  id: 'blank-presentation',
1026
2606
  kind: 'presentation',
@@ -1058,9 +2638,13 @@ function createWorkId(prefix) {
1058
2638
  function initialTitle(templateId, kind) {
1059
2639
  const titles = {
1060
2640
  'project-brief': '新项目方案',
2641
+ 'table-of-contents': '可更新目录示例',
1061
2642
  'text-effects': '文字效果示例',
1062
2643
  'run-borders': '字符边框示例',
2644
+ 'run-shading': '字符底纹示例',
2645
+ 'proofing-languages': '校对语言示例',
1063
2646
  'quarterly-plan': '季度执行计划',
2647
+ 'data-validation': '数据验证示例',
1064
2648
  'strategy-deck': '业务策略汇报'
1065
2649
  };
1066
2650
  if (titles[templateId]) return titles[templateId];
@@ -1075,6 +2659,50 @@ function contentForTemplate(templateId) {
1075
2659
  pageSize: 'a4',
1076
2660
  html: "<h1>新项目方案</h1><p><strong>负责人:</strong>项目团队  <strong>更新日期:</strong>今天</p><blockquote><p>用一句话说明这项工作的目标,以及完成后会带来什么变化。</p></blockquote><h2>背景与目标</h2><p>描述当前情况、核心问题和可衡量的成功标准。</p><h2>工作范围</h2><ul><li><p>需要完成的关键交付物</p></li><li><p>明确不在本期范围内的事项</p></li></ul><h2>里程碑</h2><ol><li><p>方案确认</p></li><li><p>执行与评审</p></li><li><p>交付与复盘</p></li></ol><h2>风险与决策</h2><p>记录尚未解决的问题、依赖和决策负责人。</p>"
1077
2661
  };
2662
+ if ('table-of-contents' === templateId) return {
2663
+ type: 'document',
2664
+ pageSize: 'a4',
2665
+ html: [
2666
+ documentTableOfContentsHtml({
2667
+ id: 'playground-table-of-contents',
2668
+ options: {
2669
+ minLevel: 1,
2670
+ maxLevel: 3,
2671
+ hyperlinks: true,
2672
+ showPageNumbers: true,
2673
+ rightAlignPageNumbers: true,
2674
+ leader: 'dot'
2675
+ },
2676
+ entries: [
2677
+ {
2678
+ targetId: 'heading-00001001',
2679
+ title: '项目概述',
2680
+ level: 1,
2681
+ pageNumber: 1
2682
+ },
2683
+ {
2684
+ targetId: 'heading-00001002',
2685
+ title: '目标与范围',
2686
+ level: 2,
2687
+ pageNumber: 1
2688
+ },
2689
+ {
2690
+ targetId: 'heading-00001003',
2691
+ title: '实施计划',
2692
+ level: 1,
2693
+ pageNumber: 2
2694
+ }
2695
+ ]
2696
+ }),
2697
+ '<h1 data-office-paragraph-id="00001001" data-office-paragraph-text-id="00002001">项目概述</h1>',
2698
+ '<p>目录是一个可选择、不可直接改写的结构化块。请从“引用”选项卡自定义或更新它。</p>',
2699
+ '<h2 data-office-paragraph-id="00001002" data-office-paragraph-text-id="00002002">目标与范围</h2>',
2700
+ '<p>修改标题文字后,使用“更新目录”同步标题与当前分页页码。</p>',
2701
+ '<hr class="work-page-break" data-page-break="true">',
2702
+ '<h1 data-office-paragraph-id="00001003" data-office-paragraph-text-id="00002003">实施计划</h1>',
2703
+ '<p>导出 DOCX 后仍保留原生 TOC 域、缓存目录项、超链接和前导符。</p>'
2704
+ ].join('')
2705
+ };
1078
2706
  if ('text-effects' === templateId) return {
1079
2707
  type: 'document',
1080
2708
  pageSize: 'a4',
@@ -1124,10 +2752,89 @@ function contentForTemplate(templateId) {
1124
2752
  }, '阴影与框架字符边框')}</p>`
1125
2753
  ].join('')
1126
2754
  };
2755
+ if ('run-shading' === templateId) return {
2756
+ type: 'document',
2757
+ pageSize: 'a4',
2758
+ html: [
2759
+ '<h1>原生字符底纹</h1>',
2760
+ '<p>选择任一示例并打开字体高级设置,可以编辑完整的原生图案、前景色、背景色,或写入显式无底纹重置。</p>',
2761
+ '<h2>基本填充</h2>',
2762
+ `<p>${runShadingTemplateSpan({
2763
+ pattern: 'clear',
2764
+ fill: {
2765
+ value: '#fff2cc'
2766
+ }
2767
+ }, '清除图案使用背景色')}</p>`,
2768
+ `<p>${runShadingTemplateSpan({
2769
+ pattern: 'solid',
2770
+ color: {
2771
+ value: '#4472c4'
2772
+ }
2773
+ }, '实心图案使用前景色')}</p>`,
2774
+ '<h2>图案与密度</h2>',
2775
+ `<p>${runShadingTemplateSpan({
2776
+ pattern: 'diagCross',
2777
+ color: {
2778
+ value: '#c00000'
2779
+ },
2780
+ fill: {
2781
+ value: '#fce4d6'
2782
+ }
2783
+ }, '对角交叉字符底纹')}</p>`,
2784
+ `<p>${runShadingTemplateSpan({
2785
+ pattern: 'pct25',
2786
+ color: {
2787
+ value: '#4472c4'
2788
+ },
2789
+ fill: {
2790
+ value: '#ddebf7'
2791
+ }
2792
+ }, '25% 字符底纹')}</p>`,
2793
+ `<p>${runShadingTemplateSpan({
2794
+ pattern: 'thinHorzStripe',
2795
+ color: {
2796
+ value: '#70ad47'
2797
+ },
2798
+ fill: {
2799
+ value: '#e2f0d9'
2800
+ }
2801
+ }, '细水平条纹字符底纹')}</p>`
2802
+ ].join('')
2803
+ };
2804
+ if ('proofing-languages' === templateId) {
2805
+ const languages = {
2806
+ latin: 'en-US',
2807
+ eastAsia: 'zh-CN',
2808
+ bidi: 'ar-SA'
2809
+ };
2810
+ return {
2811
+ type: 'document',
2812
+ pageSize: 'a4',
2813
+ html: [
2814
+ '<h1>原生校对语言</h1>',
2815
+ '<p>在“审阅”选项卡中打开“设置校对语言”,可以独立编辑拉丁、东亚和双向文字语言,并决定文字是否参与拼写与语法检查。</p>',
2816
+ '<h2>按文字系统设置</h2>',
2817
+ `<p>${proofingLanguageTemplateSpan(languages, false, 'ascii', 'English proofing language')}</p>`,
2818
+ `<p>${proofingLanguageTemplateSpan(languages, false, 'eastAsia', '简体中文校对语言')}</p>`,
2819
+ `<p dir="rtl">${proofingLanguageTemplateSpan(languages, false, 'complexScript', 'لغة التدقيق العربية')}</p>`,
2820
+ '<h2>校对行为</h2>',
2821
+ `<p>${proofingLanguageTemplateSpan({
2822
+ latin: 'en-GB'
2823
+ }, false, 'ascii', 'This text participates in proofing.')}</p>`,
2824
+ `<p>${proofingLanguageTemplateSpan({
2825
+ latin: 'x-none'
2826
+ }, true, 'ascii', 'A3S-API-v2: this product identifier is excluded from proofing.')}</p>`
2827
+ ].join('')
2828
+ };
2829
+ }
1127
2830
  if ('quarterly-plan' === templateId) return {
1128
2831
  type: 'spreadsheet',
1129
2832
  sheets: quarterlyPlanSheets()
1130
2833
  };
2834
+ if ('data-validation' === templateId) return {
2835
+ type: 'spreadsheet',
2836
+ sheets: dataValidationTemplateSheets()
2837
+ };
1131
2838
  if ('strategy-deck' === templateId) return strategyPresentation();
1132
2839
  if ('blank-spreadsheet' === templateId) return {
1133
2840
  type: 'spreadsheet',
@@ -1155,6 +2862,14 @@ function runBorderTemplateSpan(border, text) {
1155
2862
  const attributes = documentRunBorderDomAttributes(border);
1156
2863
  return `<span ${DOCUMENT_RUN_BORDER_ATTRIBUTE}='${attributes[DOCUMENT_RUN_BORDER_ATTRIBUTE]}' style="${attributes.style}">${text}</span>`;
1157
2864
  }
2865
+ function runShadingTemplateSpan(shading, text) {
2866
+ const attributes = documentRunShadingDomAttributes(shading);
2867
+ return `<span ${DOCUMENT_RUN_SHADING_ATTRIBUTE}='${attributes[DOCUMENT_RUN_SHADING_ATTRIBUTE]}' style="${attributes.style}">${text}</span>`;
2868
+ }
2869
+ function proofingLanguageTemplateSpan(languages, noProof, slot, text) {
2870
+ const attributes = documentProofingDomAttributes(languages, noProof, slot);
2871
+ return `<span ${Object.entries(attributes).map(([name, value])=>`${name}='${value}'`).join(' ')}>${text}</span>`;
2872
+ }
1158
2873
  function blankSheet() {
1159
2874
  return {
1160
2875
  id: createWorkId('sheet'),
@@ -1270,6 +2985,229 @@ function quarterlyPlanSheets() {
1270
2985
  }
1271
2986
  ];
1272
2987
  }
2988
+ function dataValidationTemplateSheets() {
2989
+ const inputs = emptyMatrix(24, 8);
2990
+ [
2991
+ 'Task',
2992
+ 'State',
2993
+ 'Due date',
2994
+ 'Priority',
2995
+ 'Owner'
2996
+ ].forEach((value, column)=>{
2997
+ inputs[0][column] = headerCell(value);
2998
+ });
2999
+ const rows = [
3000
+ [
3001
+ 'Confirm requirements',
3002
+ 'Ready',
3003
+ '2026-09-05',
3004
+ 2,
3005
+ 'Avery'
3006
+ ],
3007
+ [
3008
+ 'Review integration',
3009
+ 'In review',
3010
+ '2026-09-12',
3011
+ 3,
3012
+ 'Morgan'
3013
+ ],
3014
+ [
3015
+ 'Resolve blockers',
3016
+ 'Blocked',
3017
+ '2026-09-18',
3018
+ 5,
3019
+ 'Riley'
3020
+ ],
3021
+ [
3022
+ 'Publish preview',
3023
+ 'Ready',
3024
+ '2026-09-24',
3025
+ 1,
3026
+ 'Jordan'
3027
+ ],
3028
+ [
3029
+ 'Ship release',
3030
+ 'In review',
3031
+ '2026-09-30',
3032
+ 4,
3033
+ 'Taylor'
3034
+ ]
3035
+ ];
3036
+ rows.forEach((row, rowIndex)=>{
3037
+ row.forEach((value, columnIndex)=>{
3038
+ inputs[rowIndex + 1][columnIndex] = styledCell(value, {
3039
+ bg: rowIndex % 2 ? '#f4faf7' : '#ffffff'
3040
+ });
3041
+ });
3042
+ });
3043
+ return [
3044
+ {
3045
+ id: createWorkId('sheet'),
3046
+ name: 'Inputs',
3047
+ status: 1,
3048
+ order: 0,
3049
+ row: 24,
3050
+ column: 8,
3051
+ data: inputs,
3052
+ dataValidationRanges: [
3053
+ {
3054
+ ranges: [
3055
+ {
3056
+ row: [
3057
+ 1,
3058
+ 5
3059
+ ],
3060
+ column: [
3061
+ 1,
3062
+ 1
3063
+ ]
3064
+ }
3065
+ ],
3066
+ item: dataValidationTemplateItem({
3067
+ type: 'dropdown',
3068
+ rangeTxt: 'B2:B6',
3069
+ value1: "'Lists'!A1:A3",
3070
+ allowBlank: false,
3071
+ showDropdownArrow: true,
3072
+ errorStyle: 'stop',
3073
+ errorTitle: 'Invalid state',
3074
+ errorMessage: 'Choose a state from the list.',
3075
+ hintShow: true,
3076
+ hintTitle: 'Workflow state',
3077
+ hintValue: 'Choose Ready, Blocked, or In review.'
3078
+ })
3079
+ },
3080
+ {
3081
+ ranges: [
3082
+ {
3083
+ row: [
3084
+ 1,
3085
+ 5
3086
+ ],
3087
+ column: [
3088
+ 2,
3089
+ 2
3090
+ ]
3091
+ }
3092
+ ],
3093
+ item: dataValidationTemplateItem({
3094
+ type: 'date',
3095
+ type2: 'between',
3096
+ rangeTxt: 'C2:C6',
3097
+ value1: '2026-01-01',
3098
+ value2: '2026-12-31',
3099
+ errorStyle: 'information',
3100
+ errorTitle: 'Date outside 2026',
3101
+ errorMessage: 'Enter a date in calendar year 2026.',
3102
+ hintShow: true,
3103
+ hintTitle: 'Due date',
3104
+ hintValue: 'Use a date between 2026-01-01 and 2026-12-31.'
3105
+ })
3106
+ },
3107
+ {
3108
+ ranges: [
3109
+ {
3110
+ row: [
3111
+ 1,
3112
+ 5
3113
+ ],
3114
+ column: [
3115
+ 3,
3116
+ 3
3117
+ ]
3118
+ }
3119
+ ],
3120
+ item: dataValidationTemplateItem({
3121
+ type: 'number_integer',
3122
+ type2: 'between',
3123
+ rangeTxt: 'D2:D6',
3124
+ value1: '1',
3125
+ value2: '5',
3126
+ allowBlank: false,
3127
+ errorStyle: 'warning',
3128
+ errorTitle: 'Priority outside range',
3129
+ errorMessage: 'Enter a whole number from 1 through 5.',
3130
+ hintShow: true,
3131
+ hintTitle: 'Priority',
3132
+ hintValue: '1 is highest priority; 5 is lowest.'
3133
+ })
3134
+ }
3135
+ ],
3136
+ luckysheet_select_save: [
3137
+ {
3138
+ row: [
3139
+ 1,
3140
+ 5
3141
+ ],
3142
+ column: [
3143
+ 1,
3144
+ 1
3145
+ ],
3146
+ row_focus: 1,
3147
+ column_focus: 1
3148
+ }
3149
+ ],
3150
+ config: {
3151
+ columnlen: {
3152
+ 0: 190,
3153
+ 1: 110,
3154
+ 2: 118,
3155
+ 3: 84,
3156
+ 4: 104
3157
+ },
3158
+ rowlen: {
3159
+ 0: 30
3160
+ }
3161
+ }
3162
+ },
3163
+ {
3164
+ id: createWorkId('sheet'),
3165
+ name: 'Lists',
3166
+ status: 0,
3167
+ order: 1,
3168
+ row: 12,
3169
+ column: 3,
3170
+ data: [
3171
+ [
3172
+ styledCell('Ready')
3173
+ ],
3174
+ [
3175
+ styledCell('Blocked')
3176
+ ],
3177
+ [
3178
+ styledCell('In review')
3179
+ ]
3180
+ ],
3181
+ config: {
3182
+ columnlen: {
3183
+ 0: 120
3184
+ }
3185
+ }
3186
+ }
3187
+ ];
3188
+ }
3189
+ function dataValidationTemplateItem(overrides) {
3190
+ return {
3191
+ type: 'dropdown',
3192
+ type2: '',
3193
+ rangeTxt: '',
3194
+ value1: '',
3195
+ value2: '',
3196
+ validity: '',
3197
+ remote: false,
3198
+ allowBlank: true,
3199
+ showDropdownArrow: true,
3200
+ prohibitInput: true,
3201
+ errorStyle: 'stop',
3202
+ errorTitle: '',
3203
+ errorMessage: '',
3204
+ hintShow: false,
3205
+ hintTitle: '',
3206
+ hintValue: '',
3207
+ checked: false,
3208
+ ...overrides
3209
+ };
3210
+ }
1273
3211
  function emptyMatrix(rows, columns) {
1274
3212
  return Array.from({
1275
3213
  length: rows
@@ -1507,4 +3445,4 @@ new TextEncoder();
1507
3445
  function isOfficeKernelSpreadsheetError(value) {
1508
3446
  return 'string' == typeof value && spreadsheetErrors.has(value);
1509
3447
  }
1510
- export { DOCUMENT_PARAGRAPH_BORDERS_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_RUN_BORDER_ATTRIBUTE, DOCUMENT_RUN_BORDER_STYLES, DocxThemePatchCollector, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OoxmlPackage, WORK_TEMPLATES as officeTemplates, attribute, bytesToDataUrl, childPath, contentTypeForPart, createWorkArtifact as createArtifact, createWorkId as createOfficeId, decodeXmlBytes, descendants, directChild, directChildren, documentBorderPresentation, documentParagraphBordersDomAttributes, documentRunBorderDomAttributes, documentRunBorderIsVisible, firstDescendant, isDocumentParagraphArtBorderStyle, isOfficeKernelSpreadsheetError, normalizeCssColor, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentRunBorder, parseDocumentParagraphBorders, parseDocumentParagraphBordersElement, parseDocumentRunBorder, parseDocumentRunBorderElement, parseDocxThemeReference, parseXml, patchDocxThemeReferences, resolvePartTarget, serializeDocumentParagraphBorders, serializeDocumentRunBorder, serializeDocxThemeReference, serializeUtf8Xml, xmlContainsAnyElement, xmlNamespacePrefix };
3448
+ export { DEFAULT_DOCUMENT_TABLE_OF_CONTENTS_OPTIONS, DOCUMENT_HIGHLIGHT_ATTRIBUTE, DOCUMENT_NO_PROOF_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDERS_ATTRIBUTE, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_PARAGRAPH_ID_ATTRIBUTE, DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE, DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE, DOCUMENT_RUN_BORDER_ATTRIBUTE, DOCUMENT_RUN_BORDER_STYLES, DOCUMENT_RUN_SHADING_ATTRIBUTE, DOCUMENT_SCRIPT_FONTS_ATTRIBUTE, DOCUMENT_SCRIPT_FONT_SLOT_ATTRIBUTE, DocumentParagraphIdentity, DocxThemePatchCollector, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, OoxmlPackage, WORK_TEMPLATES as officeTemplates, applyDocumentParagraphIdentityToElement, attribute, buildDocumentTableOfContentsEntries, bytesToDataUrl, childPath, collectWorkDocumentOutline, contentTypeForPart, createDocumentParagraphIdentity, createDocumentParagraphIdentityRegistry, createWorkArtifact as createArtifact, createWorkId as createOfficeId, cssDocumentFontFamily, currentWorkDocumentOutlineItem, decodeXmlBytes, descendants, directChild, directChildren, documentBorderPresentation, documentFontNameFromCssFamily, documentHasIntegrityFeature, documentHighlightCssColor, documentHighlightDomAttributes, documentHighlightForCssColor, documentHighlightFromDocxValue, documentHighlightFromElement, documentNoProofFromElement, documentParagraphBordersDomAttributes, documentParagraphIdentityFromElement, documentParagraphShadingDomAttributes, documentProofingDomAttributes, documentProofingLanguagesFromElement, documentRunBorderDomAttributes, documentRunBorderIsVisible, documentRunShadingDomAttributes, documentScriptFontDirectFamily, documentScriptFontFallbackSlots, documentScriptFontFamily, documentScriptFontFamilyForRendering, documentScriptFontSegments, documentScriptFontSlotFromElement, documentScriptFontSlotFromHint, documentScriptFontsDomAttributes, documentScriptFontsForAllText, documentScriptFontsFromElement, documentTableOfContentsHtml, documentTableOfContentsValueFromElement, firstDescendant, isDocumentParagraphArtBorderStyle, isOfficeKernelSpreadsheetError, normalizeCssColor, normalizeDocumentFontName, normalizeDocumentHighlight, normalizeDocumentLanguageTag, normalizeDocumentNoProof, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentParagraphId, normalizeDocumentParagraphIdentity, normalizeDocumentProofingLanguages, normalizeDocumentRunBorder, normalizeDocumentRunShading, normalizeDocumentScriptFontHint, normalizeDocumentScriptFontSlot, normalizeDocumentScriptFonts, normalizeDocumentTableOfContentsHtml, normalizeDocumentTableOfContentsOptions, normalizeDocumentTableOfContentsValue, normalizeDocumentThemeFont, parseDocumentParagraphBorders, parseDocumentParagraphBordersElement, parseDocumentParagraphShading, parseDocumentParagraphShadingElement, parseDocumentProofingLanguages, parseDocumentRunBorder, parseDocumentRunBorderElement, parseDocumentRunShading, parseDocumentRunShadingElement, parseDocumentScriptFonts, parseDocumentTableOfContentsInstruction, parseDocxThemeReference, parseXml, patchDocumentProofingLanguages, patchDocumentScriptFonts, patchDocxThemeReferences, primeDocumentIntegrityFeatures, resolvePartTarget, serializeDocumentParagraphBorders, serializeDocumentParagraphShading, serializeDocumentProofingLanguages, serializeDocumentRunBorder, serializeDocumentRunShading, serializeDocumentScriptFonts, serializeDocxThemeReference, serializeUtf8Xml, uniqueDocumentParagraphIdentity, visibleWorkDocumentOutlineItems, workDocumentOutlineLevel, work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS, xmlContainsAnyElement, xmlNamespacePrefix };