@a3s-lab/office 0.29.0 → 0.31.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 (61) hide show
  1. package/README.md +117 -3
  2. package/dist/{0~7043.js → 0~4808.js} +347 -2
  3. package/dist/0~5050.js +10 -1
  4. package/dist/{0~5093.js → 0~7240.js} +465 -55
  5. package/dist/0~document-editor.js +1694 -187
  6. package/dist/0~spreadsheet-editor.js +183 -34
  7. package/dist/0~work-docx-export.js +507 -31
  8. package/dist/0~work-docx-import.js +41 -7
  9. package/dist/0~work-office-diagnostics.js +146 -5
  10. package/dist/1544.js +13 -1
  11. package/dist/4104.js +29 -6
  12. package/dist/4121.js +2340 -1
  13. package/dist/6282.js +1072 -1148
  14. package/dist/internal/features/work/editors/document-command-catalog.d.ts +45 -0
  15. package/dist/internal/features/work/editors/document-dom-selection.d.ts +7 -0
  16. package/dist/internal/features/work/editors/document-editor-support.d.ts +1 -0
  17. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +5 -2
  18. package/dist/internal/features/work/editors/document-font-dialog-run-shading-model.d.ts +23 -0
  19. package/dist/internal/features/work/editors/document-font-dialog-run-shading-section.d.ts +8 -0
  20. package/dist/internal/features/work/editors/document-index-dialog.d.ts +10 -0
  21. package/dist/internal/features/work/editors/document-index-entry-dialog.d.ts +10 -0
  22. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  23. package/dist/internal/features/work/editors/document-proofing-dialog-model.d.ts +22 -0
  24. package/dist/internal/features/work/editors/document-proofing-dialog.d.ts +7 -0
  25. package/dist/internal/features/work/editors/document-references-ribbon.d.ts +19 -0
  26. package/dist/internal/features/work/editors/document-table-of-contents-dialog.d.ts +10 -0
  27. package/dist/internal/features/work/editors/document-toolbar.d.ts +6 -1
  28. package/dist/internal/features/work/editors/spreadsheet-data-validation.d.ts +7 -1
  29. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +5 -0
  30. package/dist/internal/features/work/work-document-character-formatting.d.ts +8 -0
  31. package/dist/internal/features/work/work-document-format-changes.d.ts +6 -0
  32. package/dist/internal/features/work/work-document-highlight.d.ts +9 -0
  33. package/dist/internal/features/work/work-document-index-fields.d.ts +19 -0
  34. package/dist/internal/features/work/work-document-index-nodes.d.ts +32 -0
  35. package/dist/internal/features/work/work-document-index.d.ts +63 -0
  36. package/dist/internal/features/work/work-document-outline.d.ts +1 -0
  37. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +6 -0
  38. package/dist/internal/features/work/work-document-proofing.d.ts +19 -0
  39. package/dist/internal/features/work/work-document-run-shading.d.ts +12 -0
  40. package/dist/internal/features/work/work-document-table-of-contents-node.d.ts +18 -0
  41. package/dist/internal/features/work/work-document-table-of-contents.d.ts +51 -0
  42. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +3 -0
  43. package/dist/internal/features/work/work-docx-field-instructions.d.ts +1 -1
  44. package/dist/internal/features/work/work-docx-import.d.ts +5 -1
  45. package/dist/internal/features/work/work-docx-index-export.d.ts +14 -0
  46. package/dist/internal/features/work/work-docx-index-import.d.ts +23 -0
  47. package/dist/internal/features/work/work-docx-proofing-diagnostics.d.ts +3 -0
  48. package/dist/internal/features/work/work-docx-proofing.d.ts +38 -0
  49. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +7 -0
  50. package/dist/internal/features/work/work-docx-run-shading-diagnostics.d.ts +3 -0
  51. package/dist/internal/features/work/work-docx-run-shading-export.d.ts +17 -0
  52. package/dist/internal/features/work/work-docx-run-shading.d.ts +20 -0
  53. package/dist/internal/features/work/work-docx-table-of-contents-export.d.ts +11 -0
  54. package/dist/internal/features/work/work-docx-table-of-contents-import.d.ts +15 -0
  55. package/dist/internal/features/work/work-spreadsheet-data-validation.d.ts +7 -0
  56. package/dist/internal/features/work/work-types.d.ts +9 -0
  57. package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -0
  58. package/dist/office-kernel.wasm +0 -0
  59. package/dist/styles.css +607 -4
  60. package/docs/latest/en/browser-editor-architecture.md +64 -1
  61. package/package.json +15 -2
package/README.md CHANGED
@@ -54,6 +54,24 @@ workflows, and a separate Rust automation plane.
54
54
  - **Automate deterministically** through the native CLI, standard MCP server,
55
55
  or packaged Office Skill.
56
56
 
57
+ ## Latest on `main`
58
+
59
+ The `0.31.0` release plus the current `main` branch expose these capabilities
60
+ as normal user-facing Playground templates, with matching implementation
61
+ detail in the documentation:
62
+
63
+ | Editor | Latest capability | Public entry |
64
+ | --- | --- | --- |
65
+ | Writer | Insert, customize, navigate, and explicitly refresh a typed Table of Contents with heading and native outline levels 1–9, hyperlinks, page numbers, alignment, four leader styles, and native DOCX `TOC` round trips | Playground **Latest capabilities → 可更新目录** · [Document reference](docs/latest/en/components/document.mdx#native-table-of-contents) |
66
+ | Writer | Mark primary and secondary index terms, cross-references, and bold/italic page numbers; insert, navigate, customize, and refresh a bounded native index with editable DOCX `XE` and `INDEX` round trips | Playground **Latest capabilities → 原生索引** · [Document reference](docs/latest/en/components/document.mdx#native-document-index) |
67
+ | Writer | Native character shading with exact `w:shd` patterns, foreground/background color identity, explicit resets, authoring, and DOCX reopen | Playground **Latest capabilities → 字符底纹** · [Document reference](docs/latest/en/components/document.mdx#native-character-shading) |
68
+ | Writer | Independent Latin, East Asian, and bidi proofing languages plus explicit `w:noProof` inclusion/exclusion | Playground **Latest capabilities → 校对语言** · [Document reference](docs/latest/en/components/document.mdx#native-proofing-languages) |
69
+ | Spreadsheet | Complete common Data Validation input, blank/dropdown, and Stop/Warning/Information error settings with native XLSX round trips | Playground **Latest capabilities → 数据验证** · [Spreadsheet reference](docs/latest/en/components/spreadsheet.mdx#data-validation) |
70
+
71
+ The same five entries remain available under **新建**. The highlighted strip
72
+ exists so a capability is discoverable from the first Playground viewport
73
+ instead of only through a deep documentation section or an `?e2e=` fixture.
74
+
57
75
  ## See it working
58
76
 
59
77
  The images below are committed visual-regression baselines from the real
@@ -110,11 +128,11 @@ baseline rather than one specific release.
110
128
 
111
129
  | Capability | A3S Office today | Traditional Office baseline |
112
130
  | --- | --- | --- |
113
- | Text, paragraphs, lists, and styles | **Supported** — structured editing, independent native ASCII, high ANSI, East Asian, and complex-script font slots with direct/theme identity, native all-caps and small-caps effects, exact DOCX character scale plus signed spacing, half-point kerning thresholds, all five native East Asian emphasis marks, native hidden text with explicit visible resets, native character borders with 25 visible line styles plus `nil` and `none`, direct or theme color, width, spacing, shadow, and frame semantics, four independent native outline/shadow/emboss/imprint effects with conflict-safe authoring, and baseline position in one advanced font dialog, all 18 native DOCX underline values with direct or theme color identity, independent native single/double strikethrough with explicit resets, formatting revisions, clipboard, format painter, and undo/redo | Mature authoring with a broader long-tail style and typography catalog |
131
+ | Text, paragraphs, lists, and styles | **Supported** — structured editing, independent native ASCII, high ANSI, East Asian, and complex-script font slots with direct/theme identity, independent Latin/East Asian/bidi proofing-language slots and explicit proofing inclusion/exclusion, native all-caps and small-caps effects, exact DOCX character scale plus signed spacing, half-point kerning thresholds, all five native East Asian emphasis marks, native hidden text with explicit visible resets, native character borders with 25 visible line styles plus `nil` and `none`, direct or theme color, width, spacing, shadow, and frame semantics, four independent native outline/shadow/emboss/imprint effects with conflict-safe authoring, and baseline position in one advanced font dialog, all 18 native DOCX underline values with direct or theme color identity, independent native single/double strikethrough with explicit resets, formatting revisions, clipboard, format painter, and undo/redo | Mature authoring with a broader long-tail style and typography catalog |
114
132
  | Page layout and rendering | **Partial** — sections, margins, page size, columns, headers/footers, fields, and live pagination | Desktop-grade pagination, print layout, and vector output |
115
133
  | Tables, pictures, and equations | **Partial** — rich table geometry, floating pictures, crop/wrap, and structured OMML | Broader drawings, text boxes, charts, WordArt, and SmartArt |
116
134
  | Comments, revisions, and collaboration | **Partial** — comments, suggestions, text/format revisions, decisions, Yjs presence, and host relay contracts | Full revision families plus integrated sharing and review services |
117
- | References and document generation | **Partial** — bookmarks, links, captions, cross-references, citations, notes, and common fields | TOC/index authoring, mail merge, compare/combine, and broader fields |
135
+ | References and document generation | **Partial** — typed Table of Contents and native index authoring/refresh, bookmarks, links, captions, cross-references, citations, notes, and common fields | Mail merge, compare/combine, tables of figures/authorities, and broader fields |
118
136
  | Ribbon and shortcuts | **Supported** — responsive Office-style ribbon and editor-scoped daily-writing shortcuts | Complete desktop shortcut and contextual-tool surface |
119
137
  | Very large documents | **Supported with boundaries** — bounded 100,000-block plain-document windows and measured edit/navigation budgets | Native-engine virtualization with device-dependent limits |
120
138
  | DOCX and PDF fidelity | **Partial** — source-aware DOCX preservation and live-layout raster PDF export | Broader legacy/OOXML compatibility and searchable vector PDF output |
@@ -127,7 +145,7 @@ baseline rather than one specific release.
127
145
  | Formatting and style rendering | **Partial** — native fonts, colors, borders, alignment, number formats, cell styles, all 17 native non-solid OOXML pattern fills, native linear/path XLSX gradients, and one Format Cells surface that authors none, solid, pattern, or gradient fills with exact geometry and 2–256 ordered stops; static date/time entry, contrast-safe font preview, native XLSX rich-text runs, selected-text font formatting, direct formula-bar/F2 insertion or deletion, and bounded authenticated formatted-HTML paste | Disjoint multi-edit rich-text authoring, broader themes, locale formats, and advanced style effects |
128
146
  | Ribbon and shortcuts | **Partial** — common Office-style Home/Data/View commands, grid-scoped shortcuts, and focused Font-dialog aliases | Larger command catalog and platform-specific accelerators |
129
147
  | Formulas and recalculation | **Partial** — dependency-aware calculation and common formula paths | Wider functions, arrays, volatile semantics, and calculation parity |
130
- | Tables, pivots, charts, and rules | **Partial** — native tables, pivots, charts, conditional formatting, and validation | Calculated columns, slicers, pivot charts, advanced rules, and analysis |
148
+ | Tables, pivots, charts, and rules | **Partial** — native tables, pivots, charts, conditional formatting, and common validation rules with complete input/error-setting authoring | Calculated columns, slicers, pivot charts, custom/dependent validation rules, advanced analysis, and broader browser alert flows |
131
149
  | Large worksheets | **Supported with boundaries** — maximum-dimension sparse import/editing and viewport-bounded Canvas painting | Highly optimized native grid with hardware-dependent limits |
132
150
  | Files and printing | **Partial** — XLS/XLSX/ODS/CSV import, XLSX export, and PDF output | Broader round trips, external data, print fidelity, and legacy conversion |
133
151
  | External data, macros, and specialist analysis | **Gap** — active macros are never executed; bounded models are still needed for data connections and solver-like tools | Established data, macro/add-in, scenario, and optimization ecosystems |
@@ -216,6 +234,34 @@ is requested. The complete gap inventory and exit evidence live in the
216
234
  undoable action. Safe inline DOCX fields round-trip natively, while nested,
217
235
  incomplete, cross-paragraph, deleted, or instructionless structures stay
218
236
  text and produce an explicit compatibility warning.
237
+ Writer Table of Contents blocks reuse the same heading outline and live
238
+ Worker/WASM page resolver instead of maintaining parallel heading or page
239
+ state. Insert, customize, and explicit refresh each commit one TipTap
240
+ transaction and one Undo record. Semantic headings and native outline-level
241
+ paragraphs cover levels 1–9; included items without a native paragraph
242
+ identity receive one in the same transaction so hyperlinks survive
243
+ structural edits. Page-number visibility and alignment,
244
+ dot/dash/underline/no leaders, and at most 512 cached entries remain typed in
245
+ the DOM. DOCX export writes a native `w:sdt`/`TOC` content control and live
246
+ field with cached entries; import accepts the common `\\o`, `\\h`, `\\z`,
247
+ `\\u`, full-range `\\n`, and space-separator `\\p` subset while diagnosing
248
+ lossy custom style mappings. The Playground's **可更新目录** template exposes
249
+ the complete flow.
250
+ Writer indexes use hidden, selectable inline entry atoms and a separate
251
+ selectable generated block. Primary terms, secondary terms, cross-references,
252
+ and bold/italic page-number intent remain typed; duplicate terms on the same
253
+ page merge while retaining every stable marker target. The live Worker/WASM
254
+ field resolver remains the only page-number source. Mark, edit, insert,
255
+ customize, and explicit all-index refresh each commit one TipTap transaction
256
+ and one Undo record. At most 2,048 markers contribute to at most 512 cached
257
+ rows, with explicit truncation beyond either bound. DOCX export writes
258
+ native `XE` simple fields and a real `w:sdt`/`INDEX` content control with cached
259
+ `Index1`/`Index2` rows, columns, cross-references, page emphasis, alignment,
260
+ and dot/dash/underline/no leaders. Import accepts the lossless common `XE`
261
+ `\\b`, `\\i`, and `\\t` plus `INDEX` `\\c`, `\\e`, and `\\r` subset;
262
+ unsupported switches remain diagnosed instead of approximated. The
263
+ Playground's **原生索引** template exposes marking, navigation, refresh,
264
+ export, and reopen.
219
265
  - **Framework choice** — React components, Vue 3 adapters, Custom Elements,
220
266
  and a framework-neutral Core API over the same engine.
221
267
  - **Responsive computation** — Lazy editor chunks, cancellable Workers,
@@ -577,6 +623,34 @@ Protection ranges, passwordless editable ranges, and conditional formatting
577
623
  also remain compact and round-trip through native XLSX records without
578
624
  allocating every covered cell.
579
625
 
626
+ ### Complete Spreadsheet data-validation settings
627
+
628
+ Data → Data Validation authors list, whole-number, decimal, date, and text-length
629
+ rules across one or more selected ranges. The same dialog now owns the complete
630
+ common input and error metadata: `allowBlank`, `showDropdownArrow`,
631
+ `hintTitle`, `hintValue`, `prohibitInput`, `errorStyle`, `errorTitle`, and
632
+ `errorMessage`. Titles are bounded to 32 Unicode code points, the input message
633
+ to 255, and the error message to 225. Disabling a message keeps its text so a
634
+ later re-enable does not discard the user's draft.
635
+
636
+ The mounted grid reads compact rules without expanding blank cells, honors
637
+ `allowBlank`, can hide the in-cell list arrow, shows the authored input title
638
+ and message, and uses the authored error title and message when rejecting an
639
+ invalid value. The current Fortune boundary still has one blocking browser
640
+ alert path whenever error alerts are enabled. `stop`, `warning`, and
641
+ `information` therefore round-trip as exact native file semantics, but the
642
+ browser does not yet reproduce the separate warning/information confirmation
643
+ branches of a desktop suite. Custom formulas and dependent lists also remain
644
+ explicit gaps.
645
+
646
+ XLSX import and export preserve `allowBlank`, `showErrorMessage`,
647
+ `showInputMessage`, `errorStyle`, `errorTitle`, `error`, `promptTitle`, and
648
+ `prompt`. The public `showDropdownArrow` name describes what users see, while
649
+ SpreadsheetML stores the inverse in `showDropDown`. On the public Playground
650
+ home page, choose **新建 → 数据验证** to inspect list, date, and priority
651
+ examples with all three alert styles. This is a normal user-facing template,
652
+ not an `?e2e=` fixture or a documentation-only example.
653
+
580
654
  Native XLSX pattern fills retain all 17 non-solid OOXML pattern identities plus
581
655
  their foreground and background RGB, theme, indexed, automatic, and tint color
582
656
  origins. Canvas draws them only for visible cells, behind text and below table
@@ -757,6 +831,44 @@ layout. Browser and PDF paint are bounded visual approximations; the OOXML
757
831
  semantics remain exact. The Playground's **字符边框** template exercises the
758
832
  complete authoring and one-step Undo path.
759
833
 
834
+ Native Writer character shading retains one exact `w:shd` value rather than a
835
+ flattened CSS fill. The typed model preserves every WordprocessingML pattern,
836
+ direct or automatic foreground/background colors, independent theme channels
837
+ with tint and shade, and explicit `nil`. Document defaults, paragraph and
838
+ character styles, conditional table styles, body, page chrome, notes,
839
+ formatting revisions, strict/transitional import, exact export, and reopen use
840
+ the same resolver. Invalid or spoofed leaves fail closed and are diagnosed.
841
+
842
+ The shared `Cmd/Ctrl+D` Advanced Font Settings dialog distinguishes mixed,
843
+ Follow style, explicit no-shading, and editable pattern/color states; changes
844
+ commit with Format Painter and one-step Undo semantics. The DOM stores bounded
845
+ JSON in `data-office-run-shading`, while CSS projects patterns without changing
846
+ line geometry, so eligible content stays on the Worker/WASM path. Native
847
+ `w:highlight` remains independent and takes display precedence without
848
+ clobbering shading. The Playground's **字符底纹** template demonstrates the
849
+ complete flow.
850
+
851
+ Native Writer proofing languages retain the three independent WordprocessingML
852
+ `w:lang` slots: Latin `w:val`, East Asian `w:eastAsia`, and bidi `w:bidi`.
853
+ Native `w:noProof` remains an independent three-state property: inherited,
854
+ explicitly checked with `w:val="false"`, or excluded from proofing. The Review
855
+ ribbon's **设置校对语言** dialog accepts bounded BCP 47 language tags, keeps
856
+ untouched mixed slots unchanged, exposes Follow style for each slot, and applies
857
+ the touched language and proofing-state fields through one transaction and one
858
+ Undo record. The same contract is available while editing headers and footers.
859
+
860
+ Document defaults, paragraph and character styles, body text, headers,
861
+ footers, footnotes, endnotes, formatting revisions, strict/transitional DOCX
862
+ import, exact export, and reopen share the closed model. Malformed, duplicated,
863
+ misplaced, namespace-spoofed, nested, text-bearing, extra-attribute, invalid-tag,
864
+ or invalid on/off input fails closed and appears in compatibility diagnostics.
865
+ The DOM stores canonical JSON in `data-office-proofing-languages`, stores an
866
+ explicit Boolean in `data-office-no-proof`, and projects the effective `lang`
867
+ and `spellcheck` attributes without claiming a bundled dictionary or grammar
868
+ service. Valid effective languages also reach the Worker/WASM text-layout run
869
+ and RustyBuzz shaping buffer. The Playground's **校对语言** template demonstrates
870
+ Latin, East Asian, bidi, explicitly checked, and excluded states.
871
+
760
872
  Supported native OMML equations now survive as bounded structured objects in
761
873
  the document body, headers, footers, footnotes, and endnotes. Inline and display
762
874
  math, Unicode runs with literal/normal-text semantics, math script/style,
@@ -1457,6 +1569,8 @@ without hard-coded return URLs.
1457
1569
 
1458
1570
  - [Live Playground](https://a3s-lab.github.io/Office/)
1459
1571
  - [Documentation center](https://a3s-lab.github.io/Office/docs/)
1572
+ - [A3S Office 0.31.0 documentation](https://a3s-lab.github.io/Office/docs/0.31.0/)
1573
+ - [A3S Office 0.30.0 documentation](https://a3s-lab.github.io/Office/docs/0.30.0/)
1460
1574
  - [A3S Office 0.29.0 documentation](https://a3s-lab.github.io/Office/docs/0.29.0/)
1461
1575
  - [A3S Office 0.28.0 documentation](https://a3s-lab.github.io/Office/docs/0.28.0/)
1462
1576
  - [A3S Office 0.27.0 documentation](https://a3s-lab.github.io/Office/docs/0.27.0/)
@@ -1,5 +1,5 @@
1
1
  import jszip from "jszip";
2
- import { serializeUtf8Xml, directChildren, xmlNamespacePrefix, parseXml, firstDescendant, decodeXmlBytes, directChild, descendants, attribute as work_ooxml_package_attribute } from "./4121.js";
2
+ import { normalizeDocumentIndexEntryDraft, serializeUtf8Xml, directChildren, xmlNamespacePrefix, normalizeDocumentLanguageTag, parseXml, firstDescendant, decodeXmlBytes, directChild, descendants, normalizeDocumentProofingLanguages, attribute as work_ooxml_package_attribute, normalizeDocumentIndexOptions } from "./4121.js";
3
3
  import { normalizeDocumentEmphasisMark, normalizeDocumentCharacterScalePercent, documentCitationStyle, normalizeDocumentKerningThresholdHalfPoints, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentCharacterSpacingTwips, normalizeDocumentTabStops, createDocumentBibliography, documentCitationStyleDetails } from "./6282.js";
4
4
  const BIBLIOGRAPHY_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/bibliography';
5
5
  const CUSTOM_XML_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/customXml';
@@ -708,6 +708,193 @@ function isAllowedExtensionNamespace(namespace, context) {
708
708
  function isNamespacePrefix(value) {
709
709
  return /^[A-Za-z_][A-Za-z0-9_.-]*$/.test(value) && 'xml' !== value;
710
710
  }
711
+ function parseDocumentIndexEntryInstruction(instruction) {
712
+ const command = /^\s*XE\b/i.exec(instruction);
713
+ if (!command) return {
714
+ supported: false,
715
+ reason: 'not-index-entry'
716
+ };
717
+ const parsed = parseLeadingFieldValue(instruction.slice(command[0].length));
718
+ if (!parsed) return {
719
+ supported: false,
720
+ reason: 'invalid-instruction'
721
+ };
722
+ const switches = parseFieldSwitches(parsed.rest);
723
+ if (!switches) return {
724
+ supported: false,
725
+ reason: 'invalid-instruction'
726
+ };
727
+ for (const name of switches.keys())if (![
728
+ 'b',
729
+ 'i',
730
+ 't'
731
+ ].includes(name)) return {
732
+ supported: false,
733
+ reason: 'unsupported-switch'
734
+ };
735
+ const boldValue = valueSwitch(switches, 'b');
736
+ const italicValue = valueSwitch(switches, 'i');
737
+ if (null != boldValue || null != italicValue) return {
738
+ supported: false,
739
+ reason: 'invalid-instruction'
740
+ };
741
+ const crossReferenceValue = valueSwitch(switches, 't');
742
+ if (switches.has('t') && !crossReferenceValue) return {
743
+ supported: false,
744
+ reason: 'invalid-instruction'
745
+ };
746
+ const terms = splitIndexEntryTerms(parsed.value);
747
+ const value = normalizeDocumentIndexEntryDraft({
748
+ mainEntry: terms.mainEntry,
749
+ subEntry: terms.subEntry,
750
+ crossReference: crossReferenceValue?.replace(/^see\s+/i, '') ?? '',
751
+ pageBold: switches.has('b'),
752
+ pageItalic: switches.has('i')
753
+ });
754
+ return value ? {
755
+ supported: true,
756
+ value
757
+ } : {
758
+ supported: false,
759
+ reason: 'invalid-entry'
760
+ };
761
+ }
762
+ function documentIndexEntryInstruction(source) {
763
+ const value = normalizeDocumentIndexEntryDraft(source);
764
+ if (!value) throw new Error('Document index entry is invalid.');
765
+ const term = value.subEntry ? `${escapeFieldValue(value.mainEntry)}:${escapeFieldValue(value.subEntry)}` : escapeFieldValue(value.mainEntry);
766
+ const switches = [];
767
+ if (value.crossReference) switches.push(`\\t "See ${escapeFieldValue(value.crossReference)}"`);
768
+ else {
769
+ if (value.pageBold) switches.push('\\b');
770
+ if (value.pageItalic) switches.push('\\i');
771
+ }
772
+ return `XE "${term}"${switches.length ? ` ${switches.join(' ')}` : ''}`;
773
+ }
774
+ function parseDocumentIndexInstruction(instruction) {
775
+ const command = /^\s*INDEX\b/i.exec(instruction);
776
+ if (!command) return {
777
+ supported: false,
778
+ reason: 'not-index'
779
+ };
780
+ const switches = parseFieldSwitches(instruction.slice(command[0].length));
781
+ if (!switches) return {
782
+ supported: false,
783
+ reason: 'invalid-instruction'
784
+ };
785
+ for (const name of switches.keys())if (![
786
+ 'c',
787
+ 'e',
788
+ 'r'
789
+ ].includes(name)) return {
790
+ supported: false,
791
+ reason: 'unsupported-switch'
792
+ };
793
+ const columnsValue = valueSwitch(switches, 'c');
794
+ if (switches.has('c') && !/^[1-4]$/.test(columnsValue ?? '')) return {
795
+ supported: false,
796
+ reason: 'invalid-columns'
797
+ };
798
+ const separator = valueSwitch(switches, 'e');
799
+ if (switches.has('e') && void 0 === separator) return {
800
+ supported: false,
801
+ reason: 'invalid-instruction'
802
+ };
803
+ if (switches.has('r') && null !== valueSwitch(switches, 'r')) return {
804
+ supported: false,
805
+ reason: 'invalid-instruction'
806
+ };
807
+ return {
808
+ supported: true,
809
+ options: normalizeDocumentIndexOptions({
810
+ columns: columnsValue ? Number(columnsValue) : 1,
811
+ format: switches.has('r') ? 'run-in' : 'indented',
812
+ rightAlignPageNumbers: !switches.has('e'),
813
+ leader: switches.has('e') ? 'none' : 'dot'
814
+ })
815
+ };
816
+ }
817
+ function documentIndexInstruction(source) {
818
+ const options = normalizeDocumentIndexOptions(source);
819
+ const switches = options.columns > 1 ? [
820
+ `\\c "${options.columns}"`
821
+ ] : [];
822
+ if ('run-in' === options.format) switches.push('\\r');
823
+ if (!options.rightAlignPageNumbers) switches.push('\\e ", "');
824
+ return `INDEX${switches.length ? ` ${switches.join(' ')}` : ''}`;
825
+ }
826
+ function splitIndexEntryTerms(source) {
827
+ let escaped = false;
828
+ for(let index = 0; index < source.length; index += 1){
829
+ const character = source[index];
830
+ if (escaped) {
831
+ escaped = false;
832
+ continue;
833
+ }
834
+ if ('\\' === character) {
835
+ escaped = true;
836
+ continue;
837
+ }
838
+ if (':' === character) return {
839
+ mainEntry: unescapeFieldValue(source.slice(0, index)),
840
+ subEntry: unescapeFieldValue(source.slice(index + 1))
841
+ };
842
+ }
843
+ return {
844
+ mainEntry: unescapeFieldValue(source),
845
+ subEntry: ''
846
+ };
847
+ }
848
+ function parseLeadingFieldValue(source) {
849
+ const trimmed = source.trimStart();
850
+ if (!trimmed) return null;
851
+ if ('"' !== trimmed[0]) {
852
+ const match = /^([^\s\\]+)([\s\S]*)$/.exec(trimmed);
853
+ return match?.[1] ? {
854
+ value: match[1],
855
+ rest: match[2] ?? ''
856
+ } : null;
857
+ }
858
+ let escaped = false;
859
+ for(let index = 1; index < trimmed.length; index += 1){
860
+ const character = trimmed[index];
861
+ if (escaped) {
862
+ escaped = false;
863
+ continue;
864
+ }
865
+ if ('\\' === character) {
866
+ escaped = true;
867
+ continue;
868
+ }
869
+ if ('"' === character) return {
870
+ value: trimmed.slice(1, index),
871
+ rest: trimmed.slice(index + 1)
872
+ };
873
+ }
874
+ return null;
875
+ }
876
+ function parseFieldSwitches(source) {
877
+ const switches = new Map();
878
+ const matcher = /\\([a-z])(?:\s+("([^"\\]*(?:\\.[^"\\]*)*)"|([^\\\s]+)))?/gi;
879
+ let cursor = 0;
880
+ for(let match = matcher.exec(source); match; match = matcher.exec(source)){
881
+ if (source.slice(cursor, match.index).trim()) return null;
882
+ const name = match[1]?.toLowerCase();
883
+ if (!name || switches.has(name)) return null;
884
+ switches.set(name, unescapeFieldValue(match[3] ?? match[4] ?? '') || null);
885
+ cursor = matcher.lastIndex;
886
+ }
887
+ return source.slice(cursor).trim() ? null : switches;
888
+ }
889
+ function valueSwitch(switches, name) {
890
+ return switches.has(name) ? switches.get(name) : void 0;
891
+ }
892
+ function escapeFieldValue(value) {
893
+ return value.replaceAll('\\', '\\\\').replaceAll('"', '\\"').replaceAll(':', '\\:');
894
+ }
895
+ function unescapeFieldValue(value) {
896
+ return value.replace(/\\([\\":])/g, '$1');
897
+ }
711
898
  const STRICT_WORDPROCESSING_NAMESPACE = 'http://purl.oclc.org/ooxml/wordprocessingml/main';
712
899
  const UNIVERSAL_TWIP_RATIOS = {
713
900
  mm: [
@@ -1251,6 +1438,164 @@ function hexFactor(value) {
1251
1438
  function isDocxThemeResolver(source) {
1252
1439
  return Boolean(source && 'colors' in source && source.colors instanceof Map && 'fonts' in source && source.fonts instanceof Map);
1253
1440
  }
1441
+ const LANGUAGE_ATTRIBUTES = new Map([
1442
+ [
1443
+ 'val',
1444
+ 'latin'
1445
+ ],
1446
+ [
1447
+ 'eastAsia',
1448
+ 'eastAsia'
1449
+ ],
1450
+ [
1451
+ 'bidi',
1452
+ 'bidi'
1453
+ ]
1454
+ ]);
1455
+ function inspectDocxProofingLanguages(properties) {
1456
+ if (!properties) return {
1457
+ status: 'absent',
1458
+ spoofedCount: 0
1459
+ };
1460
+ const matches = directChildren(properties, 'lang');
1461
+ if (!matches.length) return {
1462
+ status: 'absent',
1463
+ spoofedCount: 0
1464
+ };
1465
+ const native = matches.filter((element)=>isWordElement(element));
1466
+ const spoofedCount = matches.length - native.length;
1467
+ if (1 !== matches.length || 1 !== native.length) return {
1468
+ status: 'invalid',
1469
+ spoofedCount
1470
+ };
1471
+ const element = native[0];
1472
+ if (!element || element.childNodes.length) return {
1473
+ status: 'invalid',
1474
+ spoofedCount
1475
+ };
1476
+ const languages = {};
1477
+ for (const attribute of Array.from(element.attributes)){
1478
+ if (work_docx_proofing_isNamespaceDeclaration(attribute)) continue;
1479
+ const name = wordAttributeLocalName(element, attribute);
1480
+ const slot = name ? LANGUAGE_ATTRIBUTES.get(name) : void 0;
1481
+ if (!slot) return {
1482
+ status: 'invalid',
1483
+ spoofedCount
1484
+ };
1485
+ const language = normalizeDocumentLanguageTag(attribute.value);
1486
+ if (!language) return {
1487
+ status: 'invalid',
1488
+ spoofedCount
1489
+ };
1490
+ languages[slot] = language;
1491
+ }
1492
+ return Object.keys(languages).length ? {
1493
+ status: 'valid',
1494
+ value: languages,
1495
+ spoofedCount
1496
+ } : {
1497
+ status: 'invalid',
1498
+ spoofedCount
1499
+ };
1500
+ }
1501
+ function inspectDocxNoProof(properties) {
1502
+ if (!properties) return {
1503
+ status: 'absent',
1504
+ spoofedCount: 0
1505
+ };
1506
+ const matches = directChildren(properties, 'noProof');
1507
+ if (!matches.length) return {
1508
+ status: 'absent',
1509
+ spoofedCount: 0
1510
+ };
1511
+ const native = matches.filter((element)=>isWordElement(element));
1512
+ const spoofedCount = matches.length - native.length;
1513
+ if (1 !== matches.length || 1 !== native.length) return {
1514
+ status: 'invalid',
1515
+ spoofedCount
1516
+ };
1517
+ const element = native[0];
1518
+ if (!element || element.childNodes.length) return {
1519
+ status: 'invalid',
1520
+ spoofedCount
1521
+ };
1522
+ const attributes = Array.from(element.attributes).filter((attribute)=>!work_docx_proofing_isNamespaceDeclaration(attribute));
1523
+ if (attributes.length > 1 || attributes.some((attribute)=>'val' !== wordAttributeLocalName(element, attribute))) return {
1524
+ status: 'invalid',
1525
+ spoofedCount
1526
+ };
1527
+ if (!attributes.length) return {
1528
+ status: 'valid',
1529
+ value: true,
1530
+ spoofedCount
1531
+ };
1532
+ const value = onOffValue(attributes[0]?.value);
1533
+ return void 0 === value ? {
1534
+ status: 'invalid',
1535
+ spoofedCount
1536
+ } : {
1537
+ status: 'valid',
1538
+ value,
1539
+ spoofedCount
1540
+ };
1541
+ }
1542
+ function resolveDocxProofing(propertySources) {
1543
+ let languages;
1544
+ let noProof;
1545
+ let invalidCount = 0;
1546
+ let spoofedCount = 0;
1547
+ for (const properties of propertySources){
1548
+ const languageInspection = inspectDocxProofingLanguages(properties);
1549
+ spoofedCount += languageInspection.spoofedCount;
1550
+ if ('valid' === languageInspection.status) languages = {
1551
+ ...languages,
1552
+ ...languageInspection.value
1553
+ };
1554
+ else if ('invalid' === languageInspection.status) invalidCount += 1;
1555
+ const noProofInspection = inspectDocxNoProof(properties);
1556
+ spoofedCount += noProofInspection.spoofedCount;
1557
+ if ('valid' === noProofInspection.status) noProof = noProofInspection.value;
1558
+ else if ('invalid' === noProofInspection.status) invalidCount += 1;
1559
+ }
1560
+ return {
1561
+ languages,
1562
+ noProof,
1563
+ invalidCount,
1564
+ spoofedCount
1565
+ };
1566
+ }
1567
+ function documentProofingLanguageDocxOptions(source) {
1568
+ const languages = normalizeDocumentProofingLanguages(source);
1569
+ if (!languages) return;
1570
+ return {
1571
+ ...languages.latin ? {
1572
+ value: languages.latin
1573
+ } : {},
1574
+ ...languages.eastAsia ? {
1575
+ eastAsia: languages.eastAsia
1576
+ } : {},
1577
+ ...languages.bidi ? {
1578
+ bidirectional: languages.bidi
1579
+ } : {}
1580
+ };
1581
+ }
1582
+ function isWordElement(element) {
1583
+ return DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? '');
1584
+ }
1585
+ function work_docx_proofing_isNamespaceDeclaration(attribute) {
1586
+ return 'xmlns' === attribute.name || 'xmlns' === attribute.prefix || 'http://www.w3.org/2000/xmlns/' === attribute.namespaceURI;
1587
+ }
1588
+ function wordAttributeLocalName(element, attribute) {
1589
+ if (attribute.namespaceURI === element.namespaceURI) return attribute.localName;
1590
+ const prefix = element.prefix ?? element.tagName.split(':')[0];
1591
+ const lexicalPrefix = prefix ? `${prefix}:` : '';
1592
+ return null === attribute.namespaceURI && lexicalPrefix && attribute.name.startsWith(lexicalPrefix) ? attribute.name.slice(lexicalPrefix.length) : null;
1593
+ }
1594
+ function onOffValue(source) {
1595
+ const value = source?.trim().toLowerCase();
1596
+ if ('1' === value || 'true' === value || 'on' === value) return true;
1597
+ if ('0' === value || 'false' === value || 'off' === value) return false;
1598
+ }
1254
1599
  function paragraphAlignment(element, docx) {
1255
1600
  const alignment = element.style.textAlign;
1256
1601
  if ('center' === alignment) return docx.AlignmentType.CENTER;
@@ -1579,4 +1924,4 @@ function isParagraphPartRoot(root, path) {
1579
1924
  const expected = /^word\/header\d*\.xml$/i.test(path) ? 'hdr' : /^word\/footer\d*\.xml$/i.test(path) ? 'ftr' : /^word\/footnotes\.xml$/i.test(path) ? 'footnotes' : /^word\/endnotes\.xml$/i.test(path) ? 'endnotes' : 'document';
1580
1925
  return root.localName === expected && DOCX_WORDPROCESSING_NAMESPACES.has(root.namespaceURI ?? '');
1581
1926
  }
1582
- export { DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, DOCX_WORDPROCESSING_NAMESPACES, DocxParagraphDefaultCollapsedPatchCollector, STRICT_WORDPROCESSING_NAMESPACE, XMLNS_NAMESPACE, XML_NAMESPACE, assertXmlRoot, cloneXmlElement, createDocxThemeResolver, cssColorToHex, cssFontFamily, cssFontSize, dataBoolean, docxCharacterPositionHalfPointsFromProperties, docxCharacterPositionValue, docxCharacterScalePercentFromProperties, docxCharacterScaleValue, docxCharacterSpacingTwipsFromProperties, docxCharacterSpacingValue, docxEmphasisMarkRunOptions, docxKerningThresholdValue, docxThemeColor, docxThemeFont, domDirection, hasNonWhitespaceXmlText, inspectDocxEmphasisMark, inspectDocxKerningThresholdHalfPoints, mergeDocxIgnorableExtensions, mergeDocxIgnorableExtensionsAtPairs, paragraphAlignment, paragraphBidirectional, paragraphDirectionOptions, paragraphIndent, paragraphPaginationOptions, paragraphSpacingOptions, paragraphTabStops, parseBoundedDocxInteger, parseDocxColorSchemeMappingElement, parseDocxParagraphDefaultCollapsed, parseDocxTwipsMeasure, patchDocxBibliography, patchDocxExplicitZeroCharacterSpacing, patchDocxExplicitZeroKerningThresholds, patchDocxParagraphDefaultCollapsed, readDocxBibliography, resolveDocxEmphasisMark, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver, xmlAttributeLocalName, xmlAttributeNamespace, xmlDeclaredPrefix, xmlNamespaceUri };
1927
+ export { DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, DOCX_WORDPROCESSING_NAMESPACES, DocxParagraphDefaultCollapsedPatchCollector, STRICT_WORDPROCESSING_NAMESPACE, XMLNS_NAMESPACE, XML_NAMESPACE, assertXmlRoot, cloneXmlElement, createDocxThemeResolver, cssColorToHex, cssFontFamily, cssFontSize, dataBoolean, documentIndexEntryInstruction, documentIndexInstruction, documentProofingLanguageDocxOptions, docxCharacterPositionHalfPointsFromProperties, docxCharacterPositionValue, docxCharacterScalePercentFromProperties, docxCharacterScaleValue, docxCharacterSpacingTwipsFromProperties, docxCharacterSpacingValue, docxEmphasisMarkRunOptions, docxKerningThresholdValue, docxThemeColor, docxThemeFont, domDirection, hasNonWhitespaceXmlText, inspectDocxEmphasisMark, inspectDocxKerningThresholdHalfPoints, inspectDocxNoProof, inspectDocxProofingLanguages, mergeDocxIgnorableExtensions, mergeDocxIgnorableExtensionsAtPairs, paragraphAlignment, paragraphBidirectional, paragraphDirectionOptions, paragraphIndent, paragraphPaginationOptions, paragraphSpacingOptions, paragraphTabStops, parseBoundedDocxInteger, parseDocumentIndexEntryInstruction, parseDocumentIndexInstruction, parseDocxColorSchemeMappingElement, parseDocxParagraphDefaultCollapsed, parseDocxTwipsMeasure, patchDocxBibliography, patchDocxExplicitZeroCharacterSpacing, patchDocxExplicitZeroKerningThresholds, patchDocxParagraphDefaultCollapsed, readDocxBibliography, resolveDocxEmphasisMark, resolveDocxKerningThresholdHalfPoints, resolveDocxProofing, resolveDocxThemeResolver, xmlAttributeLocalName, xmlAttributeNamespace, xmlDeclaredPrefix, xmlNamespaceUri };
package/dist/0~5050.js CHANGED
@@ -276,6 +276,15 @@ function documentCurrentPage(editor) {
276
276
  });
277
277
  return page;
278
278
  }
279
+ function documentHasRefreshableFields(editor) {
280
+ let found = false;
281
+ editor.state.doc.descendants((node)=>{
282
+ if ('documentField' !== node.type.name) return !found;
283
+ found = true;
284
+ return false;
285
+ });
286
+ return found;
287
+ }
279
288
  async function copyDocumentSelection(selection) {
280
289
  try {
281
290
  if (!navigator.clipboard?.writeText) throw new Error('Clipboard API is unavailable');
@@ -297,4 +306,4 @@ function mergeOfficeTiptapExtensions(editorName, builtInExtensions, additionalEx
297
306
  ...additionalExtensions
298
307
  ];
299
308
  }
300
- export { createWorkDocumentSelectionAction, createWorkDocumentSelectionSnapshot, customSelectionMenuItems, documentAgentMenuItems, documentCurrentPage, documentCustomSelectionMenuItems, documentPageCount, documentPlainTextAsHtml, mergeOfficeTiptapExtensions };
309
+ export { createWorkDocumentSelectionAction, createWorkDocumentSelectionSnapshot, customSelectionMenuItems, documentAgentMenuItems, documentCurrentPage, documentCustomSelectionMenuItems, documentHasRefreshableFields, documentPageCount, documentPlainTextAsHtml, mergeOfficeTiptapExtensions };