@a3s-lab/office 0.28.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 (69) hide show
  1. package/README.md +126 -3
  2. package/dist/0~1403.js +1 -1
  3. package/dist/0~4980.js +1 -1
  4. package/dist/0~7048.js +1 -1
  5. package/dist/{0~7043.js → 0~7231.js} +400 -242
  6. package/dist/{0~5093.js → 0~7360.js} +293 -53
  7. package/dist/0~7614.js +1 -1
  8. package/dist/0~document-editor.js +1535 -102
  9. package/dist/0~presentation-editor.js +1 -1
  10. package/dist/0~spreadsheet-editor.js +184 -36
  11. package/dist/0~work-docx-export.js +437 -11
  12. package/dist/0~work-docx-import.js +32 -7
  13. package/dist/0~work-office-diagnostics.js +170 -7
  14. package/dist/0~work-pptx-export.js +1 -1
  15. package/dist/0~work-pptx-import.js +1 -1
  16. package/dist/0~work-presentation-charts.js +1 -1
  17. package/dist/1544.js +14 -2
  18. package/dist/4104.js +31 -8
  19. package/dist/4121.js +3448 -0
  20. package/dist/6282.js +558 -1688
  21. package/dist/8715.js +1 -1
  22. package/dist/core.js +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/internal/features/work/editors/document-command-catalog.d.ts +27 -0
  25. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +8 -2
  26. package/dist/internal/features/work/editors/document-font-dialog-run-border-model.d.ts +24 -0
  27. package/dist/internal/features/work/editors/document-font-dialog-run-border-section.d.ts +10 -0
  28. package/dist/internal/features/work/editors/document-font-dialog-run-shading-model.d.ts +23 -0
  29. package/dist/internal/features/work/editors/document-font-dialog-run-shading-section.d.ts +8 -0
  30. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  31. package/dist/internal/features/work/editors/document-proofing-dialog-model.d.ts +22 -0
  32. package/dist/internal/features/work/editors/document-proofing-dialog.d.ts +7 -0
  33. package/dist/internal/features/work/editors/document-table-of-contents-dialog.d.ts +10 -0
  34. package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
  35. package/dist/internal/features/work/editors/spreadsheet-data-validation.d.ts +7 -1
  36. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +2 -0
  37. package/dist/internal/features/work/work-document-character-formatting.d.ts +12 -0
  38. package/dist/internal/features/work/work-document-format-changes.d.ts +7 -0
  39. package/dist/internal/features/work/work-document-highlight.d.ts +9 -0
  40. package/dist/internal/features/work/work-document-outline.d.ts +1 -0
  41. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +6 -0
  42. package/dist/internal/features/work/work-document-proofing.d.ts +19 -0
  43. package/dist/internal/features/work/work-document-run-border.d.ts +11 -0
  44. package/dist/internal/features/work/work-document-run-shading.d.ts +12 -0
  45. package/dist/internal/features/work/work-document-table-of-contents-node.d.ts +18 -0
  46. package/dist/internal/features/work/work-document-table-of-contents.d.ts +51 -0
  47. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +4 -0
  48. package/dist/internal/features/work/work-docx-field-instructions.d.ts +1 -1
  49. package/dist/internal/features/work/work-docx-import.d.ts +3 -1
  50. package/dist/internal/features/work/work-docx-proofing-diagnostics.d.ts +3 -0
  51. package/dist/internal/features/work/work-docx-proofing.d.ts +38 -0
  52. package/dist/internal/features/work/work-docx-run-border-diagnostics.d.ts +3 -0
  53. package/dist/internal/features/work/work-docx-run-border-export.d.ts +17 -0
  54. package/dist/internal/features/work/work-docx-run-border.d.ts +20 -0
  55. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +9 -0
  56. package/dist/internal/features/work/work-docx-run-shading-diagnostics.d.ts +3 -0
  57. package/dist/internal/features/work/work-docx-run-shading-export.d.ts +17 -0
  58. package/dist/internal/features/work/work-docx-run-shading.d.ts +20 -0
  59. package/dist/internal/features/work/work-docx-table-of-contents-export.d.ts +11 -0
  60. package/dist/internal/features/work/work-docx-table-of-contents-import.d.ts +15 -0
  61. package/dist/internal/features/work/work-spreadsheet-data-validation.d.ts +7 -0
  62. package/dist/internal/features/work/work-types.d.ts +9 -0
  63. package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -0
  64. package/dist/office-kernel.wasm +0 -0
  65. package/dist/styles.css +339 -1
  66. package/docs/latest/en/browser-editor-architecture.md +72 -1
  67. package/package.json +15 -2
  68. package/dist/5184.js +0 -662
  69. package/dist/9424.js +0 -16
@@ -1,8 +1,8 @@
1
1
  import jszip from "jszip";
2
- import { normalizeDocumentBookmarkName, normalizeDocumentEmphasisMark, DOCUMENT_STRIKE_STYLE_ATTRIBUTE, applyDocumentImageIdentityToElement, documentEmphasisMarkFromElement, DOCUMENT_PAGE_BORDER_EDGES, DOCUMENT_UNDERLINE_STYLE_ATTRIBUTE, documentScriptFontSlotFromElement, normalizeDocumentColumns, createDocumentImageIdentityRegistry, serializeDocumentScriptFonts, documentCharacterSpacingTwipsFromElement, uniqueDocumentParagraphIdentity, documentCharacterPositionHalfPointsFromElement, normalizeDocumentTableVerticalAlign, documentTableColumnPercentagesFromElement, normalizeDocumentTextCase, documentTableCellMarginOverridesFromElement, applyDocumentTableRowIdentityToElement, normalizeDocumentBookmarksHtml, documentImageIdentityFromElement, documentTableGeometryFromElement, normalizeDocumentTableRowHeightRule, normalizeDocumentScriptFonts, documentNoteKey, DOCUMENT_LEGACY_TEXT_EMBOSS_ATTRIBUTE, normalizeDocumentHiddenText, normalizeDocumentParagraphBorders, documentLegacyTextEffectsConflict, normalizeDocumentTableBorderWidth, normalizeDocumentCharacterSpacingTwips, normalizeDocumentParagraphId, documentStrikeFormattingFromElement, normalizeDocumentTableBorderStyle, normalizeDocumentBookmarkReferencesHtml, documentCitationInstruction, parseDocumentParagraphBordersElement, documentImageWrapContourFromElement, documentImagePositionFromElement, normalizeDocumentCharacterScalePercent, documentScriptFontsFromElement, normalizeDocumentUnderlineStyle, documentPageMarginsForLayout, normalizeDocumentPageChrome, normalizeDocumentImageLayer, documentFontNameFromCssFamily, documentBookmarkReferenceInstruction, documentImageCropFromElement, documentKerningThresholdHalfPointsFromElement, normalizeDocumentPageBorders, documentImageLayerFromElement, normalizeDocumentLegacyTextEffects, documentCaptionLabel, documentCaptionKind, applyDocumentParagraphIdentityToElement, DOCUMENT_LEGACY_TEXT_IMPRINT_ATTRIBUTE, isContourImageLayout, parseDocumentScriptFonts, normalizeDocumentStrikeStyle, parseDocxThemeReference, createDocumentParagraphIdentityRegistry, documentCitationTags, docxDocumentFieldKind, normalizeDocumentImageIdentity, normalizeTableColor, documentTableBordersFromElement, wrapsBesideImage, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentKerningThresholdHalfPoints, DocxThemePatchCollector, defaultDocumentImageWrapContour, documentSections, normalizeDocumentParagraphIdentity, normalizeDocumentPaperSource, DOCUMENT_LEGACY_TEXT_OUTLINE_ATTRIBUTE, documentEquationFromElement, DOCUMENT_PARAGRAPH_BORDER_EDGES, documentLegacyTextEffectsFromElement, parseDocumentCharacterFormatting, documentScriptFontFamily, documentParagraphIdentityFromElement, DOCUMENT_LEGACY_TEXT_SHADOW_ATTRIBUTE, normalizeDocumentEquation, documentUnderlineFormattingFromElement, normalizeDocumentBookmarkNativeId, patchDocxThemeReferences, DOCUMENT_PAGE_MARGIN_KEYS, uniqueDocumentImageIdentity, documentHiddenTextFromElement, parseDocumentParagraphShadingElement, documentImageLayoutFromElement, documentScriptFontSlotFromHint, parseDocumentParagraphFormatting, documentPageHorizontalMarginTwips, documentTableRowIdentityFromElement, collectDocumentNotes, documentPageGeometryForLayout, normalizeDocumentScriptFontSlot, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, documentCharacterScalePercentFromElement, normalizeDocumentPageMargins, normalizeDocumentLegacyTextEffect, documentNoteKind } from "./6282.js";
3
- import { serializeUtf8Xml, directChildren, xmlNamespacePrefix, parseXml, decodeXmlBytes, descendants, resolvePartTarget, directChild, attribute as work_ooxml_package_attribute } from "./5184.js";
2
+ import { normalizeDocumentBookmarkName, normalizeDocumentEmphasisMark, DOCUMENT_STRIKE_STYLE_ATTRIBUTE, applyDocumentImageIdentityToElement, documentEmphasisMarkFromElement, DOCUMENT_PAGE_BORDER_EDGES, DOCUMENT_UNDERLINE_STYLE_ATTRIBUTE, createDocumentImageIdentityRegistry, normalizeDocumentColumns, normalizeDocumentTableVerticalAlign, normalizeDocumentTextCase, documentCharacterSpacingTwipsFromElement, documentCharacterPositionHalfPointsFromElement, documentTableColumnPercentagesFromElement, documentTableCellMarginOverridesFromElement, applyDocumentTableRowIdentityToElement, normalizeDocumentBookmarksHtml, documentImageIdentityFromElement, documentTableGeometryFromElement, normalizeDocumentTableRowHeightRule, documentNoteKey, DOCUMENT_LEGACY_TEXT_EMBOSS_ATTRIBUTE, normalizeDocumentHiddenText, documentLegacyTextEffectsConflict, normalizeDocumentTableBorderWidth, normalizeDocumentCharacterSpacingTwips, documentStrikeFormattingFromElement, normalizeDocumentTableBorderStyle, normalizeDocumentBookmarkReferencesHtml, documentCitationInstruction, documentImageWrapContourFromElement, documentImagePositionFromElement, normalizeDocumentCharacterScalePercent, normalizeDocumentUnderlineStyle, normalizeDocumentPageChrome, documentPageMarginsForLayout, normalizeDocumentImageLayer, documentKerningThresholdHalfPointsFromElement, documentImageCropFromElement, documentBookmarkReferenceInstruction, normalizeDocumentPageBorders, documentImageLayerFromElement, normalizeDocumentLegacyTextEffects, documentCaptionLabel, documentCaptionKind, DOCUMENT_LEGACY_TEXT_IMPRINT_ATTRIBUTE, isContourImageLayout, normalizeDocumentImageIdentity, normalizeTableColor, normalizeDocumentStrikeStyle, documentTableBordersFromElement, documentSections, documentCitationTags, docxDocumentFieldKind, wrapsBesideImage, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentKerningThresholdHalfPoints, defaultDocumentImageWrapContour, normalizeDocumentPaperSource, DOCUMENT_LEGACY_TEXT_OUTLINE_ATTRIBUTE, documentEquationFromElement, documentLegacyTextEffectsFromElement, parseDocumentCharacterFormatting, documentUnderlineFormattingFromElement, DOCUMENT_LEGACY_TEXT_SHADOW_ATTRIBUTE, normalizeDocumentEquation, parseDocumentParagraphFormatting, documentTableRowIdentityFromElement, normalizeDocumentBookmarkNativeId, collectDocumentNotes, DOCUMENT_PAGE_MARGIN_KEYS, uniqueDocumentImageIdentity, documentHiddenTextFromElement, documentImageLayoutFromElement, documentPageHorizontalMarginTwips, documentPageGeometryForLayout, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, documentCharacterScalePercentFromElement, normalizeDocumentPageMargins, normalizeDocumentLegacyTextEffect, documentNoteKind } from "./6282.js";
3
+ import { normalizeDocumentRunBorder, parseDocumentScriptFonts, parseDocxThemeReference, parseXml, parseDocumentRunShading, applyDocumentParagraphIdentityToElement, DOCUMENT_RUN_SHADING_ATTRIBUTE, documentScriptFontSlotFromElement, DOCUMENT_HIGHLIGHT_ATTRIBUTE, serializeDocumentScriptFonts, attribute as work_ooxml_package_attribute, createDocumentParagraphIdentityRegistry, uniqueDocumentParagraphIdentity, DOCUMENT_NO_PROOF_ATTRIBUTE, documentHighlightForCssColor, directChildren, documentTableOfContentsValueFromElement, DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE, DocxThemePatchCollector, normalizeDocumentScriptFonts, normalizeDocumentParagraphIdentity, normalizeDocumentHighlight, normalizeDocumentParagraphBorders, serializeUtf8Xml, DOCUMENT_PARAGRAPH_BORDER_EDGES, parseDocumentRunBorder, normalizeDocumentNoProof, decodeXmlBytes, documentParagraphIdentityFromElement, normalizeDocumentParagraphId, documentScriptFontFamily, descendants, resolvePartTarget, documentProofingLanguagesFromElement, documentHighlightFromElement, parseDocumentRunShadingElement, parseDocumentProofingLanguages, patchDocxThemeReferences, parseDocumentParagraphBordersElement, DOCUMENT_RUN_BORDER_ATTRIBUTE, parseDocumentRunBorderElement, xmlNamespacePrefix, documentScriptFontSlotFromHint, documentNoProofFromElement, documentScriptFontsFromElement, normalizeDocumentRunShading, normalizeDocumentScriptFontSlot, directChild, parseDocumentParagraphShadingElement, documentFontNameFromCssFamily } from "./4121.js";
4
4
  import { assignDocxNoteIds, patchDocxPageColor, normalizeDocxCommentId, assignDocxCommentThreads } from "./0~4980.js";
5
- import { paragraphTabStops, mergeDocxIgnorableExtensionsAtPairs, patchDocxBibliography, docxKerningThresholdValue, docxCharacterPositionValue, docxCharacterScaleValue, docxEmphasisMarkRunOptions, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, paragraphAlignment, paragraphSpacingOptions, xmlNamespaceUri, hasNonWhitespaceXmlText, patchDocxExplicitZeroCharacterSpacing, cloneXmlElement, cssColorToHex, DocxParagraphDefaultCollapsedPatchCollector, assertXmlRoot, xmlDeclaredPrefix, paragraphIndent, domDirection, DOCX_WORDPROCESSING_NAMESPACES, paragraphBidirectional, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, patchDocxParagraphDefaultCollapsed, xmlAttributeNamespace, dataBoolean, mergeDocxIgnorableExtensions, patchDocxExplicitZeroKerningThresholds, parseDocxColorSchemeMappingElement, paragraphPaginationOptions, DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, xmlAttributeLocalName, cssFontSize, paragraphDirectionOptions, cssFontFamily, docxCharacterSpacingValue } from "./0~7043.js";
5
+ import { paragraphTabStops, mergeDocxIgnorableExtensionsAtPairs, patchDocxBibliography, docxKerningThresholdValue, docxCharacterPositionValue, docxCharacterScaleValue, docxEmphasisMarkRunOptions, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, paragraphAlignment, paragraphSpacingOptions, xmlNamespaceUri, hasNonWhitespaceXmlText, patchDocxExplicitZeroCharacterSpacing, cloneXmlElement, cssColorToHex, DocxParagraphDefaultCollapsedPatchCollector, assertXmlRoot, xmlDeclaredPrefix, paragraphIndent, domDirection, DOCX_WORDPROCESSING_NAMESPACES, paragraphBidirectional, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, patchDocxParagraphDefaultCollapsed, xmlAttributeNamespace, dataBoolean, mergeDocxIgnorableExtensions, patchDocxExplicitZeroKerningThresholds, parseDocxColorSchemeMappingElement, paragraphPaginationOptions, DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, documentProofingLanguageDocxOptions, xmlAttributeLocalName, cssFontSize, paragraphDirectionOptions, cssFontFamily, docxCharacterSpacingValue } from "./0~7231.js";
6
6
  import { normalizeDocumentHref } from "./0~work-document-links.js";
7
7
  const WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
8
8
  class DocxBookmarkPatchCollector {
@@ -2374,6 +2374,113 @@ function docxDocumentFieldRun(element, docx) {
2374
2374
  if (!docxDocumentFieldKind(instruction)) return new docx.TextRun(display);
2375
2375
  return new docx.SimpleField(instruction, display);
2376
2376
  }
2377
+ const work_docx_run_shading_export_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
2378
+ class DocxRunShadingPatchCollector {
2379
+ patches = [];
2380
+ nextMarker = 1;
2381
+ usedColors;
2382
+ constructor(sourceHtml){
2383
+ this.usedColors = work_docx_run_shading_export_sourceColors(sourceHtml);
2384
+ }
2385
+ marker(source) {
2386
+ const shading = normalizeDocumentRunShading(source);
2387
+ if (!shading) return null;
2388
+ let marker = '';
2389
+ do {
2390
+ const value = 0xd00000 + this.nextMarker;
2391
+ if (value > 0xdfffff) throw new Error('DOCX character shading marker space is exhausted.');
2392
+ marker = value.toString(16).padStart(6, '0').toUpperCase();
2393
+ this.nextMarker += 1;
2394
+ }while (this.usedColors.has(marker))
2395
+ this.usedColors.add(marker);
2396
+ this.patches.push({
2397
+ marker,
2398
+ shading
2399
+ });
2400
+ return marker;
2401
+ }
2402
+ hasMarker(value) {
2403
+ const marker = value?.toUpperCase();
2404
+ return Boolean(marker && this.patches.some((patch)=>patch.marker === marker));
2405
+ }
2406
+ }
2407
+ function documentRunShadingDocxOptions(source, collector) {
2408
+ const marker = collector.marker(source);
2409
+ return marker ? {
2410
+ shading: {
2411
+ type: 'clear',
2412
+ color: 'auto',
2413
+ fill: marker
2414
+ }
2415
+ } : {};
2416
+ }
2417
+ async function patchDocxRunShading(buffer, patches) {
2418
+ if (!patches.length) return buffer;
2419
+ const archive = await jszip.loadAsync(buffer);
2420
+ const byMarker = new Map(patches.map((patch)=>[
2421
+ patch.marker,
2422
+ patch
2423
+ ]));
2424
+ const applied = new Set();
2425
+ for (const entry of Object.values(archive.files)){
2426
+ if (entry.dir || !/^word\/(?:document|header\d+|footer\d+|footnotes|endnotes|comments)\.xml$/i.test(entry.name)) continue;
2427
+ const document = parseXml(await entry.async('text'), entry.name);
2428
+ let changed = false;
2429
+ for (const element of Array.from(document.getElementsByTagName('*'))){
2430
+ if ('shd' !== element.localName || element.namespaceURI !== work_docx_run_shading_export_WORD_NAMESPACE || element.parentElement?.localName !== 'rPr') continue;
2431
+ const marker = work_docx_run_shading_export_wordAttribute(element, 'fill')?.toUpperCase();
2432
+ const patch = marker ? byMarker.get(marker) : void 0;
2433
+ if (marker && patch) {
2434
+ replaceRunShadingAttributes(document, element, patch.shading);
2435
+ applied.add(marker);
2436
+ changed = true;
2437
+ }
2438
+ }
2439
+ if (changed) archive.file(entry.name, serializeUtf8Xml(document));
2440
+ }
2441
+ const missing = patches.filter((patch)=>!applied.has(patch.marker));
2442
+ if (missing.length) throw new Error(`Generated DOCX is missing ${missing.length} character shading marker(s).`);
2443
+ return archive.generateAsync({
2444
+ type: 'arraybuffer'
2445
+ });
2446
+ }
2447
+ function setDocxRunShadingAttributes(document, element, source) {
2448
+ const shading = normalizeDocumentRunShading(source);
2449
+ if (!shading) return false;
2450
+ work_docx_run_shading_export_setWordAttribute(document, element, 'val', shading.pattern);
2451
+ setShadingColorAttributes(document, element, shading.color, 'color');
2452
+ setShadingColorAttributes(document, element, shading.fill, 'fill');
2453
+ return true;
2454
+ }
2455
+ function replaceRunShadingAttributes(document, element, shading) {
2456
+ for (const attribute of Array.from(element.attributes))if ('xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:')) element.removeAttributeNode(attribute);
2457
+ element.replaceChildren();
2458
+ setDocxRunShadingAttributes(document, element, shading);
2459
+ }
2460
+ function setShadingColorAttributes(document, element, color, kind) {
2461
+ if (!color) return;
2462
+ work_docx_run_shading_export_setWordAttribute(document, element, kind, 'auto' === color.value ? 'auto' : color.value.slice(1).toUpperCase());
2463
+ if (!color.theme) return;
2464
+ const themeName = 'color' === kind ? 'themeColor' : 'themeFill';
2465
+ const tintName = 'color' === kind ? 'themeTint' : 'themeFillTint';
2466
+ const shadeName = 'color' === kind ? 'themeShade' : 'themeFillShade';
2467
+ work_docx_run_shading_export_setWordAttribute(document, element, themeName, color.theme.theme);
2468
+ if (color.theme.tint) work_docx_run_shading_export_setWordAttribute(document, element, tintName, color.theme.tint);
2469
+ if (color.theme.shade) work_docx_run_shading_export_setWordAttribute(document, element, shadeName, color.theme.shade);
2470
+ }
2471
+ function work_docx_run_shading_export_sourceColors(source) {
2472
+ const colors = new Set();
2473
+ for (const match of source.matchAll(/#([0-9a-f]{6})\b/gi))if (match[1]) colors.add(match[1].toUpperCase());
2474
+ return colors;
2475
+ }
2476
+ function work_docx_run_shading_export_wordAttribute(element, name) {
2477
+ return element.getAttributeNS(element.namespaceURI ?? work_docx_run_shading_export_WORD_NAMESPACE, name) ?? element.getAttribute(`${element.prefix ?? 'w'}:${name}`);
2478
+ }
2479
+ function work_docx_run_shading_export_setWordAttribute(document, element, name, value) {
2480
+ const namespace = element.namespaceURI ?? work_docx_run_shading_export_WORD_NAMESPACE;
2481
+ const prefix = element.prefix ?? xmlNamespacePrefix(document.documentElement, namespace) ?? 'w';
2482
+ element.setAttributeNS(namespace, `${prefix}:${name}`, value);
2483
+ }
2377
2484
  const MAX_RUN_FORMATTING_CHANGE_PATCHES = 65536;
2378
2485
  const RUN_FORMATTING_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
2379
2486
  class DocxRunFormattingChangePatchCollector {
@@ -2503,6 +2610,7 @@ function appendFormattingProperties(document, properties, namespace, prefix, ser
2503
2610
  appendTextCaseProperties(document, properties, namespace, prefix, byType.get('textStyle'));
2504
2611
  appendStrikeProperties(document, properties, namespace, prefix, byType.get('strike'));
2505
2612
  appendLegacyTextEffectsProperties(document, properties, namespace, prefix, byType.get('textStyle'));
2613
+ appendNoProofProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2506
2614
  appendSnapToGridProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2507
2615
  appendHiddenTextProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2508
2616
  appendColorProperty(document, properties, namespace, prefix, byType.get('textStyle'));
@@ -2511,10 +2619,54 @@ function appendFormattingProperties(document, properties, namespace, prefix, ser
2511
2619
  appendKerningThresholdProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2512
2620
  appendCharacterPositionProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2513
2621
  appendFontSizeProperties(document, properties, namespace, prefix, byType.get('textStyle'));
2514
- appendHighlightProperty(document, properties, namespace, prefix, byType.get('highlight'));
2622
+ appendHighlightProperty(document, properties, namespace, prefix, byType.get('highlight'), !parseDocumentRunShading(byType.get('textStyle')?.attrs?.runShading));
2515
2623
  appendUnderlineProperty(document, properties, namespace, prefix, byType.get('underline'));
2624
+ appendRunBorderProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2625
+ appendRunShadingProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2516
2626
  appendVerticalAlignProperty(document, properties, namespace, prefix, byType);
2517
2627
  appendEmphasisMarkProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2628
+ appendProofingLanguagesProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2629
+ }
2630
+ function appendNoProofProperty(document, properties, namespace, prefix, mark) {
2631
+ const noProof = normalizeDocumentNoProof(mark?.attrs?.noProof);
2632
+ if (null === noProof) return;
2633
+ if (noProof) properties.append(wordElement(document, namespace, prefix, 'noProof'));
2634
+ else appendValuedProperty(document, properties, namespace, prefix, 'noProof', '0');
2635
+ }
2636
+ function appendProofingLanguagesProperty(document, properties, namespace, prefix, mark) {
2637
+ const languages = parseDocumentProofingLanguages(mark?.attrs?.proofingLanguages);
2638
+ if (!languages) return;
2639
+ const element = wordElement(document, namespace, prefix, 'lang');
2640
+ if (languages.latin) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'val', languages.latin);
2641
+ if (languages.eastAsia) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'eastAsia', languages.eastAsia);
2642
+ if (languages.bidi) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'bidi', languages.bidi);
2643
+ properties.append(element);
2644
+ }
2645
+ function appendRunBorderProperty(document, properties, namespace, prefix, mark) {
2646
+ const border = parseDocumentRunBorder(mark?.attrs?.runBorder);
2647
+ if (!border) return;
2648
+ const element = wordElement(document, namespace, prefix, 'bdr');
2649
+ work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'val', border.style);
2650
+ if (border.color) {
2651
+ work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'color', 'auto' === border.color.value ? 'auto' : border.color.value.slice(1).toUpperCase());
2652
+ if (border.color.theme) {
2653
+ work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'themeColor', border.color.theme.theme);
2654
+ if (border.color.theme.tint) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'themeTint', border.color.theme.tint);
2655
+ if (border.color.theme.shade) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'themeShade', border.color.theme.shade);
2656
+ }
2657
+ }
2658
+ if (void 0 !== border.size) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'sz', String(border.size));
2659
+ if (void 0 !== border.space) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'space', String(border.space));
2660
+ if (void 0 !== border.shadow) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'shadow', border.shadow ? '1' : '0');
2661
+ if (void 0 !== border.frame) work_docx_format_change_export_setWordAttribute(element, namespace, prefix, 'frame', border.frame ? '1' : '0');
2662
+ properties.append(element);
2663
+ }
2664
+ function appendRunShadingProperty(document, properties, namespace, prefix, mark) {
2665
+ const shading = parseDocumentRunShading(mark?.attrs?.runShading);
2666
+ if (!shading) return;
2667
+ const element = wordElement(document, namespace, prefix, 'shd');
2668
+ if (!setDocxRunShadingAttributes(document, element, shading)) return;
2669
+ properties.append(element);
2518
2670
  }
2519
2671
  function appendLegacyTextEffectsProperties(document, properties, namespace, prefix, mark) {
2520
2672
  const effects = {};
@@ -2684,7 +2836,10 @@ function appendFontSizeProperties(document, properties, namespace, prefix, mark)
2684
2836
  appendValuedProperty(document, properties, namespace, prefix, 'sz', String(halfPoints));
2685
2837
  appendValuedProperty(document, properties, namespace, prefix, 'szCs', String(halfPoints));
2686
2838
  }
2687
- function appendHighlightProperty(document, properties, namespace, prefix, mark) {
2839
+ function appendHighlightProperty(document, properties, namespace, prefix, mark, allowFallbackShading) {
2840
+ const nativeHighlight = normalizeDocumentHighlight(mark?.attrs?.nativeHighlight) ?? documentHighlightForCssColor(mark?.attrs?.color);
2841
+ if (nativeHighlight) return void appendValuedProperty(document, properties, namespace, prefix, 'highlight', nativeHighlight);
2842
+ if (!allowFallbackShading) return;
2688
2843
  const fill = normalizedHex(mark?.attrs?.color);
2689
2844
  const theme = themeReference(mark?.attrs?.themeFill);
2690
2845
  if (!fill && !theme) return;
@@ -3951,6 +4106,127 @@ function docxBorderStyle(style, docx) {
3951
4106
  function docxColor(color) {
3952
4107
  return color.replace(/^#/, '').toUpperCase();
3953
4108
  }
4109
+ const work_docx_table_of_contents_export_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
4110
+ const work_docx_table_of_contents_export_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
4111
+ class DocxTableOfContentsPatchCollector {
4112
+ patches = [];
4113
+ add(element) {
4114
+ const value = documentTableOfContentsValueFromElement(element);
4115
+ const patch = {
4116
+ options: value.options,
4117
+ entries: value.entries
4118
+ };
4119
+ this.patches.push(patch);
4120
+ return patch;
4121
+ }
4122
+ }
4123
+ function docxTableOfContents(element, docx, collector) {
4124
+ const patch = collector.add(element);
4125
+ const options = patch.options;
4126
+ return new docx.TableOfContents('Table of Contents', {
4127
+ hyperlink: options.hyperlinks,
4128
+ headingStyleRange: `${options.minLevel}-${options.maxLevel}`,
4129
+ pageNumbersEntryLevelsRange: options.showPageNumbers ? void 0 : `${options.minLevel}-${options.maxLevel}`,
4130
+ entryAndPageNumberSeparator: options.showPageNumbers && !options.rightAlignPageNumbers ? ' ' : void 0,
4131
+ useAppliedParagraphOutlineLevel: true,
4132
+ hideTabAndPageNumbersInWebView: true,
4133
+ cachedEntries: patch.entries.map((entry)=>({
4134
+ title: entry.title,
4135
+ level: entry.level,
4136
+ page: options.showPageNumbers ? entry.pageNumber : void 0,
4137
+ href: options.hyperlinks ? entry.targetId : void 0
4138
+ }))
4139
+ });
4140
+ }
4141
+ async function patchDocxTableOfContents(buffer, patches) {
4142
+ if (!patches.length) return buffer;
4143
+ const archive = await jszip.loadAsync(buffer);
4144
+ const entry = archive.file('word/document.xml');
4145
+ if (!entry) return buffer;
4146
+ const document = parseXml(await entry.async('text'), 'generated DOCX word/document.xml');
4147
+ const tables = descendants(document, 'sdt').filter((element)=>descendants(element, 'instrText').some((instruction)=>/^\s*TOC\b/i.test(instruction.textContent ?? '')));
4148
+ if (tables.length !== patches.length) throw new Error(`Generated DOCX emitted ${tables.length} table(s) of contents for ${patches.length} source block(s).`);
4149
+ for (const [index, table] of tables.entries()){
4150
+ const patch = patches[index];
4151
+ if (patch) patchTableOfContents(document, table, patch.options);
4152
+ }
4153
+ addTableOfContentsBookmarks(document, patches);
4154
+ archive.file('word/document.xml', new XMLSerializer().serializeToString(document));
4155
+ return archive.generateAsync({
4156
+ type: 'arraybuffer'
4157
+ });
4158
+ }
4159
+ function patchTableOfContents(document, table, options) {
4160
+ for (const tabStop of descendants(table, 'tab')){
4161
+ if (tabStop.parentElement?.localName !== 'tabs') continue;
4162
+ const value = work_ooxml_package_attribute(tabStop, 'val');
4163
+ if ('right' !== value) continue;
4164
+ if (!options.showPageNumbers || !options.rightAlignPageNumbers) {
4165
+ const parent = tabStop.parentElement;
4166
+ tabStop.remove();
4167
+ if (parent && !directChildren(parent, 'tab').length) parent.remove();
4168
+ continue;
4169
+ }
4170
+ const leader = docxTableOfContentsLeader(options.leader);
4171
+ if (leader) work_docx_table_of_contents_export_setWordAttribute(document, tabStop, 'leader', leader);
4172
+ else removeWordAttribute(tabStop, 'leader');
4173
+ }
4174
+ if (options.showPageNumbers && options.rightAlignPageNumbers) return;
4175
+ for (const tab of descendants(table, 'tab')){
4176
+ if (tab.parentElement?.localName === 'tabs') continue;
4177
+ if (!options.showPageNumbers) {
4178
+ tab.remove();
4179
+ continue;
4180
+ }
4181
+ const text = document.createElementNS(work_docx_table_of_contents_export_WORD_NAMESPACE, work_docx_table_of_contents_export_wordQualifiedName(document.documentElement, 't'));
4182
+ text.setAttributeNS(work_docx_table_of_contents_export_XML_NAMESPACE, 'xml:space', 'preserve');
4183
+ text.textContent = ' ';
4184
+ tab.replaceWith(text);
4185
+ }
4186
+ }
4187
+ function addTableOfContentsBookmarks(document, patches) {
4188
+ const names = new Set(descendants(document, 'bookmarkStart').flatMap((bookmark)=>{
4189
+ const name = work_ooxml_package_attribute(bookmark, 'name')?.trim();
4190
+ return name ? [
4191
+ name
4192
+ ] : [];
4193
+ }));
4194
+ let nextId = Math.max(0, ...descendants(document, 'bookmarkStart').map((bookmark)=>Number(work_ooxml_package_attribute(bookmark, 'id') ?? 0))) + 1;
4195
+ const targets = new Set(patches.flatMap((patch)=>patch.options.hyperlinks ? patch.entries.map((candidate)=>candidate.targetId) : []));
4196
+ for (const target of targets){
4197
+ if (names.has(target)) continue;
4198
+ const paragraphId = /^heading-([0-9a-f]{8})$/i.exec(target)?.[1];
4199
+ if (!paragraphId) continue;
4200
+ const paragraph = descendants(document, 'p').find((candidate)=>work_ooxml_package_attribute(candidate, 'paraId')?.toLowerCase() === paragraphId.toLowerCase());
4201
+ if (!paragraph) continue;
4202
+ const start = document.createElementNS(work_docx_table_of_contents_export_WORD_NAMESPACE, work_docx_table_of_contents_export_wordQualifiedName(document.documentElement, 'bookmarkStart'));
4203
+ const end = document.createElementNS(work_docx_table_of_contents_export_WORD_NAMESPACE, work_docx_table_of_contents_export_wordQualifiedName(document.documentElement, 'bookmarkEnd'));
4204
+ work_docx_table_of_contents_export_setWordAttribute(document, start, 'id', String(nextId));
4205
+ work_docx_table_of_contents_export_setWordAttribute(document, start, 'name', target);
4206
+ work_docx_table_of_contents_export_setWordAttribute(document, end, 'id', String(nextId));
4207
+ nextId += 1;
4208
+ const properties = directChild(paragraph, 'pPr');
4209
+ paragraph.insertBefore(start, properties?.nextSibling ?? paragraph.firstChild);
4210
+ paragraph.append(end);
4211
+ names.add(target);
4212
+ }
4213
+ }
4214
+ function docxTableOfContentsLeader(value) {
4215
+ if ('dash' === value) return 'hyphen';
4216
+ if ('underline' === value) return 'underscore';
4217
+ if ('dot' === value) return 'dot';
4218
+ return null;
4219
+ }
4220
+ function work_docx_table_of_contents_export_setWordAttribute(document, element, localName, value) {
4221
+ removeWordAttribute(element, localName);
4222
+ element.setAttributeNS(work_docx_table_of_contents_export_WORD_NAMESPACE, work_docx_table_of_contents_export_wordQualifiedName(document.documentElement, localName), value);
4223
+ }
4224
+ function removeWordAttribute(element, localName) {
4225
+ for (const candidate of Array.from(element.attributes))if (candidate.localName === localName && (candidate.namespaceURI === work_docx_table_of_contents_export_WORD_NAMESPACE || !candidate.namespaceURI)) element.removeAttributeNode(candidate);
4226
+ }
4227
+ function work_docx_table_of_contents_export_wordQualifiedName(root, localName) {
4228
+ return `${xmlNamespacePrefix(root, work_docx_table_of_contents_export_WORD_NAMESPACE) ?? 'w'}:${localName}`;
4229
+ }
3954
4230
  const work_docx_table_sizing_export_TWIPS_PER_PIXEL = 15;
3955
4231
  function documentTableSizingDocxOptions(table, docx) {
3956
4232
  const geometry = documentTableGeometryFromElement(table);
@@ -7828,6 +8104,110 @@ function setWordFontAttribute(element, name, value) {
7828
8104
  const prefix = element.prefix || 'w';
7829
8105
  element.setAttributeNS(namespace, `${prefix}:${name}`, value);
7830
8106
  }
8107
+ const work_docx_run_border_export_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
8108
+ class DocxRunBorderPatchCollector {
8109
+ patches = [];
8110
+ nextMarker = 1;
8111
+ usedColors;
8112
+ constructor(sourceHtml){
8113
+ this.usedColors = work_docx_run_border_export_sourceColors(sourceHtml);
8114
+ }
8115
+ marker(source) {
8116
+ const border = normalizeDocumentRunBorder(source);
8117
+ if (!border) return null;
8118
+ let marker = '';
8119
+ do {
8120
+ const value = 0xc00000 + this.nextMarker;
8121
+ if (value > 0xcfffff) throw new Error('DOCX character border marker space is exhausted.');
8122
+ marker = value.toString(16).padStart(6, '0').toUpperCase();
8123
+ this.nextMarker += 1;
8124
+ }while (this.usedColors.has(marker))
8125
+ this.usedColors.add(marker);
8126
+ this.patches.push({
8127
+ marker,
8128
+ border
8129
+ });
8130
+ return marker;
8131
+ }
8132
+ hasMarker(value) {
8133
+ const marker = value?.toUpperCase();
8134
+ return Boolean(marker && this.patches.some((patch)=>patch.marker === marker));
8135
+ }
8136
+ }
8137
+ function documentRunBorderDocxOptions(source, collector) {
8138
+ const marker = collector.marker(source);
8139
+ return marker ? {
8140
+ border: {
8141
+ style: 'single',
8142
+ color: marker,
8143
+ size: 2,
8144
+ space: 0
8145
+ }
8146
+ } : {};
8147
+ }
8148
+ async function patchDocxRunBorders(buffer, patches) {
8149
+ if (!patches.length) return buffer;
8150
+ const archive = await jszip.loadAsync(buffer);
8151
+ const byMarker = new Map(patches.map((patch)=>[
8152
+ patch.marker,
8153
+ patch
8154
+ ]));
8155
+ const applied = new Set();
8156
+ for (const entry of Object.values(archive.files)){
8157
+ if (entry.dir || !/^word\/(?:document|header\d+|footer\d+|footnotes|endnotes|comments)\.xml$/i.test(entry.name)) continue;
8158
+ const document = parseXml(await entry.async('text'), entry.name);
8159
+ let changed = false;
8160
+ for (const element of Array.from(document.getElementsByTagName('*'))){
8161
+ if ('bdr' !== element.localName || element.namespaceURI !== work_docx_run_border_export_WORD_NAMESPACE || element.parentElement?.localName !== 'rPr') continue;
8162
+ const marker = work_docx_run_border_export_wordAttribute(element, 'color')?.toUpperCase();
8163
+ const patch = marker ? byMarker.get(marker) : void 0;
8164
+ if (marker && patch) {
8165
+ replaceRunBorderAttributes(document, element, patch.border);
8166
+ applied.add(marker);
8167
+ changed = true;
8168
+ }
8169
+ }
8170
+ if (changed) archive.file(entry.name, serializeUtf8Xml(document));
8171
+ }
8172
+ const missing = patches.filter((patch)=>!applied.has(patch.marker));
8173
+ if (missing.length) throw new Error(`Generated DOCX is missing ${missing.length} character border marker(s).`);
8174
+ return archive.generateAsync({
8175
+ type: 'arraybuffer'
8176
+ });
8177
+ }
8178
+ function setDocxRunBorderAttributes(document, element, border) {
8179
+ work_docx_run_border_export_setWordAttribute(document, element, 'val', border.style);
8180
+ const color = border.color;
8181
+ if (color) {
8182
+ work_docx_run_border_export_setWordAttribute(document, element, 'color', 'auto' === color.value ? 'auto' : color.value.slice(1).toUpperCase());
8183
+ if (color.theme) {
8184
+ work_docx_run_border_export_setWordAttribute(document, element, 'themeColor', color.theme.theme);
8185
+ if (color.theme.tint) work_docx_run_border_export_setWordAttribute(document, element, 'themeTint', color.theme.tint);
8186
+ if (color.theme.shade) work_docx_run_border_export_setWordAttribute(document, element, 'themeShade', color.theme.shade);
8187
+ }
8188
+ }
8189
+ if (void 0 !== border.size) work_docx_run_border_export_setWordAttribute(document, element, 'sz', String(border.size));
8190
+ if (void 0 !== border.space) work_docx_run_border_export_setWordAttribute(document, element, 'space', String(border.space));
8191
+ if (void 0 !== border.shadow) work_docx_run_border_export_setWordAttribute(document, element, 'shadow', border.shadow ? '1' : '0');
8192
+ if (void 0 !== border.frame) work_docx_run_border_export_setWordAttribute(document, element, 'frame', border.frame ? '1' : '0');
8193
+ }
8194
+ function replaceRunBorderAttributes(document, element, border) {
8195
+ for (const attribute of Array.from(element.attributes))if ('xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:')) element.removeAttributeNode(attribute);
8196
+ element.replaceChildren();
8197
+ setDocxRunBorderAttributes(document, element, border);
8198
+ }
8199
+ function work_docx_run_border_export_sourceColors(source) {
8200
+ const colors = new Set();
8201
+ for (const match of source.matchAll(/#([0-9a-f]{6})\b/gi))if (match[1]) colors.add(match[1].toUpperCase());
8202
+ return colors;
8203
+ }
8204
+ function work_docx_run_border_export_wordAttribute(element, name) {
8205
+ return element.getAttributeNS(work_docx_run_border_export_WORD_NAMESPACE, name) ?? element.getAttribute(`w:${name}`);
8206
+ }
8207
+ function work_docx_run_border_export_setWordAttribute(document, element, name, value) {
8208
+ const prefix = xmlNamespacePrefix(document.documentElement, work_docx_run_border_export_WORD_NAMESPACE) ?? 'w';
8209
+ element.setAttributeNS(work_docx_run_border_export_WORD_NAMESPACE, `${prefix}:${name}`, value);
8210
+ }
7831
8211
  async function createDocxBlob(content, sourcePackage) {
7832
8212
  const docx = await import("docx");
7833
8213
  const normalizedContent = {
@@ -7865,8 +8245,13 @@ async function createDocxBlob(content, sourcePackage) {
7865
8245
  runFontPatches: new DocxRunFontsPatchCollector(JSON.stringify(normalizedContent)),
7866
8246
  hiddenTextPatches: new DocxHiddenTextPatchCollector(JSON.stringify(normalizedContent)),
7867
8247
  legacyTextEffectsPatches: new DocxLegacyTextEffectsPatchCollector(JSON.stringify(normalizedContent)),
8248
+ runBorderPatches: new DocxRunBorderPatchCollector(JSON.stringify(normalizedContent)),
8249
+ usedRunBorderMarkers: new Set(),
8250
+ runShadingPatches: new DocxRunShadingPatchCollector(JSON.stringify(normalizedContent)),
8251
+ usedRunShadingMarkers: new Set(),
7868
8252
  usedNativeTextEffectMarkers: new Set(),
7869
8253
  paragraphFormattingChangePatches: new DocxParagraphFormattingChangePatchCollector(),
8254
+ tableOfContentsPatches: new DocxTableOfContentsPatchCollector(),
7870
8255
  hasExplicitZeroCharacterSpacing: false,
7871
8256
  hasExplicitZeroKerningThreshold: false
7872
8257
  };
@@ -7920,7 +8305,9 @@ async function createDocxBlob(content, sourcePackage) {
7920
8305
  const runFontsPatched = await patchDocxRunFonts(kerningPatched, noteContext.runFontPatches.patches);
7921
8306
  const hiddenTextPatched = await patchDocxHiddenText(runFontsPatched, noteContext.hiddenTextPatches.patches.filter((patch)=>noteContext.usedNativeTextEffectMarkers.has(patch.marker)));
7922
8307
  const legacyTextEffectsPatched = await patchDocxLegacyTextEffects(hiddenTextPatched, noteContext.legacyTextEffectsPatches.patches.filter((patch)=>noteContext.usedNativeTextEffectMarkers.has(patch.marker)));
7923
- const formattingChangesPatched = await patchDocxRunFormattingChanges(legacyTextEffectsPatched, noteContext.formattingChangePatches.patches);
8308
+ const runBordersPatched = await patchDocxRunBorders(legacyTextEffectsPatched, noteContext.runBorderPatches.patches.filter((patch)=>noteContext.usedRunBorderMarkers.has(patch.marker)));
8309
+ const runShadingPatched = await patchDocxRunShading(runBordersPatched, noteContext.runShadingPatches.patches.filter((patch)=>noteContext.usedRunShadingMarkers.has(patch.marker)));
8310
+ const formattingChangesPatched = await patchDocxRunFormattingChanges(runShadingPatched, noteContext.formattingChangePatches.patches);
7924
8311
  const noteImageRelationshipsPatched = await patchDocxNoteImageRelationships(formattingChangesPatched);
7925
8312
  const commentMetadataPatched = await patchDocxCommentMetadata(noteImageRelationshipsPatched, commentThreads);
7926
8313
  const numberingPatched = await patchDocxNumberingRestartRules(commentMetadataPatched, noteContext.numberingRestartRules);
@@ -7935,7 +8322,8 @@ async function createDocxBlob(content, sourcePackage) {
7935
8322
  const bookmarkPatched = await patchDocxBookmarks(imageIdentityPatched, noteContext.bookmarkPatches.patches);
7936
8323
  const paragraphDefaultCollapsedPatched = await patchDocxParagraphDefaultCollapsed(bookmarkPatched, noteContext.paragraphDefaultCollapsedPatches.patches);
7937
8324
  const paragraphIdentityPatched = await patchDocxParagraphIdentities(paragraphDefaultCollapsedPatched, noteContext.paragraphIdentityPatches.patches);
7938
- const paragraphFormattingChangesPatched = await patchDocxParagraphFormattingChanges(paragraphIdentityPatched, noteContext.paragraphFormattingChangePatches.patches);
8325
+ const tableOfContentsPatched = await patchDocxTableOfContents(paragraphIdentityPatched, noteContext.tableOfContentsPatches.patches);
8326
+ const paragraphFormattingChangesPatched = await patchDocxParagraphFormattingChanges(tableOfContentsPatched, noteContext.paragraphFormattingChangePatches.patches);
7939
8327
  const equationPatched = await patchDocxEquations(paragraphFormattingChangesPatched, noteContext.equationPatches.patches);
7940
8328
  const patched = await patchDocxPageColor(equationPatched, normalizedContent.pageColor);
7941
8329
  const preserved = sourcePackage ? await preserveDocxSourcePackage(patched, sourcePackage, {
@@ -8001,6 +8389,14 @@ function markDocxNativeTextEffectStyleUsed(style, context) {
8001
8389
  break;
8002
8390
  }
8003
8391
  }
8392
+ function markDocxRunBorderUsed(border, context) {
8393
+ const marker = border?.color?.toUpperCase();
8394
+ if (context.runBorderPatches.hasMarker(marker)) context.usedRunBorderMarkers.add(marker);
8395
+ }
8396
+ function markDocxRunShadingUsed(shading, context) {
8397
+ const marker = shading?.fill?.toUpperCase();
8398
+ if (context.runShadingPatches.hasMarker(marker)) context.usedRunShadingMarkers.add(marker);
8399
+ }
8004
8400
  function work_docx_export_sectionProperties(layout, docx) {
8005
8401
  const landscape = 'landscape' === layout.orientation;
8006
8402
  const dimensions = documentPageGeometryForLayout(layout);
@@ -8098,6 +8494,9 @@ async function blockToFileChildren(element, docx, noteContext) {
8098
8494
  if (element.hasAttribute('data-document-bibliography')) return [
8099
8495
  docxBibliographyParagraph(element, docx, paragraphBidirectional(element))
8100
8496
  ];
8497
+ if (element.hasAttribute('data-document-table-of-contents')) return [
8498
+ docxTableOfContents(element, docx, noteContext.tableOfContentsPatches)
8499
+ ];
8101
8500
  if (element.hasAttribute('data-document-caption')) return [
8102
8501
  docxCaptionParagraph(element, await paragraphRuns(element, docx, noteContext), docx, paragraphBidirectional(element))
8103
8502
  ];
@@ -8171,6 +8570,8 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8171
8570
  if (node.nodeType === Node.TEXT_NODE) {
8172
8571
  if (!node.textContent) return [];
8173
8572
  markDocxNativeTextEffectStyleUsed(inherited.style, noteContext);
8573
+ markDocxRunBorderUsed(inherited.border, noteContext);
8574
+ markDocxRunShadingUsed(inherited.shading, noteContext);
8174
8575
  if (revision?.kind === 'insertion') return [
8175
8576
  new docx.InsertedTextRun({
8176
8577
  ...inherited,
@@ -8228,19 +8629,32 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8228
8629
  const formattingChange = node.hasAttribute('data-document-change') && 'formatting' === node.dataset.changeKind ? noteContext.formattingChangePatches.register(node, docxRevisionId(node, noteContext)) : null;
8229
8630
  const commentBoundary = node.hasAttribute('data-document-comment') ? nextDocxCommentBoundary(node.dataset.commentId, noteContext) : null;
8230
8631
  const backgroundColor = cssColorToHex(node.style.backgroundColor);
8632
+ const hasExplicitRunShading = 'span' === tag && node.hasAttribute(DOCUMENT_RUN_SHADING_ATTRIBUTE);
8633
+ const explicitRunShading = hasExplicitRunShading ? parseDocumentRunShadingElement(node) : null;
8634
+ if (hasExplicitRunShading && !explicitRunShading) throw new Error('Document contains invalid character shading.');
8635
+ const hasHighlightSemantics = node.hasAttribute(DOCUMENT_HIGHLIGHT_ATTRIBUTE) || node.hasAttribute('data-color') || 'mark' === tag || Boolean(backgroundColor) && !hasExplicitRunShading;
8636
+ const explicitHighlight = hasHighlightSemantics ? documentHighlightFromElement(node) : null;
8231
8637
  const direction = domDirection(node);
8232
8638
  const resolvedColor = cssColorToHex(node.style.color) ?? inherited.color;
8233
8639
  const themeColorMarker = noteContext.themePatches.marker('color', parseDocxThemeReference(node.dataset.officeThemeColor), resolvedColor ? `#${resolvedColor}` : null);
8234
- const resolvedShading = backgroundColor ? {
8235
- fill: backgroundColor
8236
- } : inherited.shading;
8237
- const themeFillMarker = noteContext.themePatches.marker('fill', parseDocxThemeReference(node.dataset.officeThemeFill), resolvedShading?.fill ? `#${resolvedShading.fill}` : null);
8640
+ const runShading = explicitRunShading ? documentRunShadingDocxOptions(explicitRunShading, noteContext.runShadingPatches).shading : void 0;
8641
+ const customHighlightFill = hasHighlightSemantics && !explicitHighlight ? backgroundColor : null;
8642
+ const resolvedShading = runShading ?? (customHighlightFill ? {
8643
+ fill: customHighlightFill
8644
+ } : inherited.shading);
8645
+ const themeFillMarker = !runShading && customHighlightFill ? noteContext.themePatches.marker('fill', parseDocxThemeReference(node.dataset.officeThemeFill), `#${customHighlightFill}`) : null;
8238
8646
  const explicitTextCase = normalizeDocumentTextCase(node.dataset.officeTextCase);
8239
8647
  const explicitCharacterSpacing = documentCharacterSpacingTwipsFromElement(node);
8240
8648
  const explicitCharacterScale = documentCharacterScalePercentFromElement(node);
8241
8649
  const explicitKerningThreshold = documentKerningThresholdHalfPointsFromElement(node);
8242
8650
  const explicitEmphasisMark = documentEmphasisMarkFromElement(node);
8243
8651
  const explicitHiddenText = documentHiddenTextFromElement(node);
8652
+ const hasExplicitProofingLanguages = 'span' === tag && node.hasAttribute(DOCUMENT_PROOFING_LANGUAGES_ATTRIBUTE);
8653
+ const explicitProofingLanguages = hasExplicitProofingLanguages ? documentProofingLanguagesFromElement(node) : null;
8654
+ if (hasExplicitProofingLanguages && !explicitProofingLanguages) throw new Error('Document contains invalid proofing languages.');
8655
+ const hasExplicitNoProof = 'span' === tag && node.hasAttribute(DOCUMENT_NO_PROOF_ATTRIBUTE);
8656
+ const explicitNoProof = hasExplicitNoProof ? documentNoProofFromElement(node) : null;
8657
+ if (hasExplicitNoProof && null === explicitNoProof) throw new Error('Document contains invalid proofing state.');
8244
8658
  const hasExplicitLegacyTextEffects = 'span' === tag && [
8245
8659
  DOCUMENT_LEGACY_TEXT_OUTLINE_ATTRIBUTE,
8246
8660
  DOCUMENT_LEGACY_TEXT_SHADOW_ATTRIBUTE,
@@ -8250,6 +8664,9 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8250
8664
  const explicitLegacyTextEffects = hasExplicitLegacyTextEffects ? documentLegacyTextEffectsFromElement(node) : {};
8251
8665
  if (hasExplicitLegacyTextEffects && !explicitLegacyTextEffects) throw new Error('Document contains invalid legacy text effects.');
8252
8666
  const explicitCharacterPosition = documentCharacterPositionHalfPointsFromElement(node);
8667
+ const hasExplicitRunBorder = 'span' === tag && (node.hasAttribute(DOCUMENT_RUN_BORDER_ATTRIBUTE) || Boolean(node.style.borderStyle));
8668
+ const explicitRunBorder = hasExplicitRunBorder ? parseDocumentRunBorderElement(node) : null;
8669
+ if (hasExplicitRunBorder && !explicitRunBorder) throw new Error('Document contains an invalid character border.');
8253
8670
  if (0 === explicitCharacterSpacing) noteContext.hasExplicitZeroCharacterSpacing = true;
8254
8671
  if (0 === explicitKerningThreshold) noteContext.hasExplicitZeroKerningThreshold = true;
8255
8672
  const characterSpacing = null === explicitCharacterSpacing ? inherited.characterSpacing : docxCharacterSpacingValue(explicitCharacterSpacing);
@@ -8274,6 +8691,9 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8274
8691
  const underline = docxUnderlineRunOptions(node, inherited.underline, noteContext.themePatches);
8275
8692
  const strike = docxStrikeRunOptions(node, inherited);
8276
8693
  const scriptFontMarker = noteContext.runFontPatches.marker(documentScriptFontsFromElement(node), documentScriptFontSlotFromElement(node), node.style.fontFamily);
8694
+ const runBorder = explicitRunBorder ? documentRunBorderDocxOptions(explicitRunBorder, noteContext.runBorderPatches).border : inherited.border;
8695
+ const language = hasExplicitProofingLanguages ? documentProofingLanguageDocxOptions(explicitProofingLanguages) : inherited.language;
8696
+ const noProof = hasExplicitNoProof ? explicitNoProof ?? false : inherited.noProof;
8277
8697
  const style = {
8278
8698
  ...inherited,
8279
8699
  style: nativeTextEffectStyle,
@@ -8293,15 +8713,21 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8293
8713
  kern,
8294
8714
  position,
8295
8715
  emphasisMark,
8716
+ language,
8717
+ noProof,
8718
+ border: runBorder,
8296
8719
  shading: themeFillMarker ? {
8297
8720
  fill: themeFillMarker
8298
8721
  } : resolvedShading,
8722
+ highlight: hasHighlightSemantics ? explicitHighlight ?? (customHighlightFill ? 'none' : void 0) : inherited.highlight,
8299
8723
  snapToGrid: dataBoolean(node.dataset.officeWordSnapToGrid) ?? inherited.snapToGrid,
8300
8724
  rightToLeft: void 0 === direction ? inherited.rightToLeft : 'rtl' === direction,
8301
8725
  ...textCaseOptions
8302
8726
  };
8303
8727
  if ('br' === tag) {
8304
8728
  markDocxNativeTextEffectStyleUsed(style.style, noteContext);
8729
+ markDocxRunBorderUsed(style.border, noteContext);
8730
+ markDocxRunShadingUsed(style.shading, noteContext);
8305
8731
  return [
8306
8732
  new docx.TextRun({
8307
8733
  ...style,