@a3s-lab/office 0.26.0 → 0.27.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 (81) hide show
  1. package/README.md +75 -2
  2. package/dist/0~4595.js +16 -2
  3. package/dist/0~5093.js +463 -201
  4. package/dist/0~6090.js +77 -77
  5. package/dist/{0~2805.js → 0~7043.js} +305 -2
  6. package/dist/0~document-editor.js +2451 -985
  7. package/dist/0~spreadsheet-editor.js +1324 -378
  8. package/dist/0~work-docx-export.js +492 -10
  9. package/dist/0~work-docx-import.js +171 -98
  10. package/dist/0~work-office-diagnostics.js +198 -4
  11. package/dist/{164.js → 1544.js} +1083 -785
  12. package/dist/4104.js +145 -29
  13. package/dist/6282.js +1774 -384
  14. package/dist/core.js +1 -1
  15. package/dist/index.js +1 -1
  16. package/dist/internal/features/work/editors/document-command-catalog.d.ts +102 -0
  17. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +83 -0
  18. package/dist/internal/features/work/editors/document-font-dialog-script-font-model.d.ts +18 -0
  19. package/dist/internal/features/work/editors/document-font-dialog.d.ts +9 -0
  20. package/dist/internal/features/work/editors/document-home-ribbon.d.ts +2 -1
  21. package/dist/internal/features/work/editors/document-page-chrome-editor.d.ts +6 -0
  22. package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
  23. package/dist/internal/features/work/editors/document-strike-ribbon.d.ts +7 -0
  24. package/dist/internal/features/work/editors/document-text-case-ribbon.d.ts +4 -0
  25. package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
  26. package/dist/internal/features/work/editors/document-underline-ribbon.d.ts +9 -0
  27. package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +1 -0
  28. package/dist/internal/features/work/editors/spreadsheet-cell-fill-format.d.ts +11 -0
  29. package/dist/internal/features/work/editors/spreadsheet-cell-format.d.ts +2 -1
  30. package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog-model.d.ts +13 -2
  31. package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-panel.d.ts +13 -0
  32. package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-preview.d.ts +6 -0
  33. package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +1 -1
  34. package/dist/internal/features/work/editors/work-office-chrome.d.ts +9 -1
  35. package/dist/internal/features/work/work-document-character-formatting.d.ts +16 -1
  36. package/dist/internal/features/work/work-document-character-position.d.ts +9 -0
  37. package/dist/internal/features/work/work-document-character-scale.d.ts +8 -0
  38. package/dist/internal/features/work/work-document-character-spacing.d.ts +8 -0
  39. package/dist/internal/features/work/work-document-emphasis.d.ts +7 -0
  40. package/dist/internal/features/work/work-document-equations.d.ts +2 -1
  41. package/dist/internal/features/work/work-document-format-changes.d.ts +16 -2
  42. package/dist/internal/features/work/work-document-hidden-text.d.ts +5 -0
  43. package/dist/internal/features/work/work-document-kerning.d.ts +10 -0
  44. package/dist/internal/features/work/work-document-script-font-extension.d.ts +2 -0
  45. package/dist/internal/features/work/work-document-script-fonts.d.ts +51 -0
  46. package/dist/internal/features/work/work-document-strike.d.ts +21 -0
  47. package/dist/internal/features/work/work-document-text-case.d.ts +10 -0
  48. package/dist/internal/features/work/work-document-underline.d.ts +37 -0
  49. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +12 -0
  50. package/dist/internal/features/work/work-docx-character-position.d.ts +2 -0
  51. package/dist/internal/features/work/work-docx-character-scale.d.ts +2 -0
  52. package/dist/internal/features/work/work-docx-character-spacing.d.ts +4 -0
  53. package/dist/internal/features/work/work-docx-emphasis-diagnostics.d.ts +3 -0
  54. package/dist/internal/features/work/work-docx-emphasis.d.ts +14 -0
  55. package/dist/internal/features/work/work-docx-hidden-text-diagnostics.d.ts +3 -0
  56. package/dist/internal/features/work/work-docx-hidden-text-export.d.ts +16 -0
  57. package/dist/internal/features/work/work-docx-hidden-text.d.ts +11 -0
  58. package/dist/internal/features/work/work-docx-kerning-diagnostics.d.ts +3 -0
  59. package/dist/internal/features/work/work-docx-kerning.d.ts +14 -0
  60. package/dist/internal/features/work/work-docx-run-fonts-diagnostics.d.ts +3 -0
  61. package/dist/internal/features/work/work-docx-run-fonts-export.d.ts +14 -0
  62. package/dist/internal/features/work/work-docx-run-fonts.d.ts +13 -0
  63. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +23 -2
  64. package/dist/internal/features/work/work-docx-run-script-font-import.d.ts +9 -0
  65. package/dist/internal/features/work/work-docx-strike.d.ts +8 -0
  66. package/dist/internal/features/work/work-docx-theme-reference.d.ts +1 -1
  67. package/dist/internal/features/work/work-docx-twips.d.ts +6 -0
  68. package/dist/internal/features/work/work-docx-underline.d.ts +3 -0
  69. package/dist/internal/features/work/work-spreadsheet-gradient-fill-canvas.d.ts +10 -0
  70. package/dist/internal/features/work/work-spreadsheet-native-fill-canvas.d.ts +8 -0
  71. package/dist/internal/features/work/work-spreadsheet-pattern-fill-canvas.d.ts +8 -0
  72. package/dist/internal/features/work/work-xlsx-cell-style-origin.d.ts +2 -1
  73. package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +3 -0
  74. package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +4 -0
  75. package/dist/internal/features/work/work-xlsx-gradient-fill.d.ts +31 -0
  76. package/dist/internal/features/work/work-xlsx-native-fill.d.ts +17 -0
  77. package/dist/internal/features/work/work-xlsx-pattern-fill.d.ts +21 -0
  78. package/dist/office-kernel.wasm +0 -0
  79. package/dist/styles.css +770 -80
  80. package/docs/latest/en/browser-editor-architecture.md +10 -0
  81. package/package.json +32 -1
package/dist/0~6090.js CHANGED
@@ -696,6 +696,83 @@ function adjacentDocumentTabStop(current, direction, excludedRoot) {
696
696
  const index = tabStops.indexOf(current);
697
697
  return index < 0 ? null : tabStops[index + direction] ?? null;
698
698
  }
699
+ const OFFICE_MENU_NAVIGATION_KEYS = [
700
+ 'ArrowDown',
701
+ 'ArrowUp',
702
+ 'Home',
703
+ 'End'
704
+ ];
705
+ const OFFICE_GRID_MENU_NAVIGATION_KEYS = [
706
+ ...OFFICE_MENU_NAVIGATION_KEYS,
707
+ 'ArrowLeft',
708
+ 'ArrowRight'
709
+ ];
710
+ const OFFICE_MENU_BUTTON_SELECTOR = 'button[role="menuitem"]:not(:disabled), button[role="menuitemradio"]:not(:disabled), button[role="menuitemcheckbox"]:not(:disabled)';
711
+ function moveOfficeMenuFocus(event) {
712
+ if (!OFFICE_MENU_NAVIGATION_KEYS.includes(event.key)) return false;
713
+ const buttons = officeMenuButtons(event.currentTarget);
714
+ if (!buttons.length) return false;
715
+ event.preventDefault();
716
+ const current = buttons.indexOf(document.activeElement);
717
+ const next = 'Home' === event.key ? 0 : 'End' === event.key ? buttons.length - 1 : 'ArrowDown' === event.key ? (current + 1 + buttons.length) % buttons.length : (current - 1 + buttons.length) % buttons.length;
718
+ buttons[next]?.focus();
719
+ return true;
720
+ }
721
+ function moveOfficeGridMenuFocus(event, columns) {
722
+ if (!OFFICE_GRID_MENU_NAVIGATION_KEYS.includes(event.key)) return false;
723
+ const buttons = officeMenuButtons(event.currentTarget);
724
+ if (!buttons.length) return false;
725
+ event.preventDefault();
726
+ const currentButton = document.activeElement;
727
+ const current = Math.max(0, buttons.indexOf(currentButton));
728
+ if ('Home' === event.key || 'End' === event.key) {
729
+ buttons['Home' === event.key ? 0 : buttons.length - 1]?.focus();
730
+ return true;
731
+ }
732
+ if ('ArrowLeft' === event.key || 'ArrowRight' === event.key) {
733
+ const delta = 'ArrowRight' === event.key ? 1 : -1;
734
+ buttons[(current + delta + buttons.length) % buttons.length]?.focus();
735
+ return true;
736
+ }
737
+ const groups = [
738
+ ...event.currentTarget.querySelectorAll('[data-office-menu-grid]')
739
+ ];
740
+ const groupIndex = groups.findIndex((group)=>group.contains(currentButton));
741
+ if (groupIndex < 0) {
742
+ const delta = 'ArrowDown' === event.key ? columns : -columns;
743
+ buttons[(current + delta + buttons.length) % buttons.length]?.focus();
744
+ return true;
745
+ }
746
+ const groupButtons = officeMenuButtons(groups[groupIndex]);
747
+ const localIndex = Math.max(0, groupButtons.indexOf(currentButton));
748
+ const column = localIndex % columns;
749
+ if ('ArrowDown' === event.key) {
750
+ const nextRow = localIndex - column + columns;
751
+ if (nextRow < groupButtons.length) {
752
+ groupButtons[Math.min(nextRow + column, groupButtons.length - 1)]?.focus();
753
+ return true;
754
+ }
755
+ const nextGroup = groups[(groupIndex + 1) % groups.length];
756
+ const nextButtons = officeMenuButtons(nextGroup);
757
+ nextButtons[Math.min(column, nextButtons.length - 1)]?.focus();
758
+ return true;
759
+ }
760
+ const previousRow = localIndex - column - columns;
761
+ if (previousRow >= 0) {
762
+ groupButtons[previousRow + column]?.focus();
763
+ return true;
764
+ }
765
+ const previousGroup = groups[(groupIndex - 1 + groups.length) % groups.length];
766
+ const previousButtons = officeMenuButtons(previousGroup);
767
+ const previousRowStart = Math.floor((previousButtons.length - 1) / columns) * columns;
768
+ previousButtons[Math.min(previousRowStart + column, previousButtons.length - 1)]?.focus();
769
+ return true;
770
+ }
771
+ function officeMenuButtons(root) {
772
+ return [
773
+ ...root.querySelectorAll(OFFICE_MENU_BUTTON_SELECTOR)
774
+ ];
775
+ }
699
776
  const PRESENCE_COLORS = [
700
777
  '#1d4ed8',
701
778
  '#6d28d9',
@@ -1230,83 +1307,6 @@ function presenceLocationLabel(participant) {
1230
1307
  return `第 ${location.pageIndex + 1} 页`;
1231
1308
  }
1232
1309
  }
1233
- const OFFICE_MENU_NAVIGATION_KEYS = [
1234
- 'ArrowDown',
1235
- 'ArrowUp',
1236
- 'Home',
1237
- 'End'
1238
- ];
1239
- const OFFICE_GRID_MENU_NAVIGATION_KEYS = [
1240
- ...OFFICE_MENU_NAVIGATION_KEYS,
1241
- 'ArrowLeft',
1242
- 'ArrowRight'
1243
- ];
1244
- const OFFICE_MENU_BUTTON_SELECTOR = 'button[role="menuitem"]:not(:disabled), button[role="menuitemradio"]:not(:disabled), button[role="menuitemcheckbox"]:not(:disabled)';
1245
- function moveOfficeMenuFocus(event) {
1246
- if (!OFFICE_MENU_NAVIGATION_KEYS.includes(event.key)) return false;
1247
- const buttons = officeMenuButtons(event.currentTarget);
1248
- if (!buttons.length) return false;
1249
- event.preventDefault();
1250
- const current = buttons.indexOf(document.activeElement);
1251
- const next = 'Home' === event.key ? 0 : 'End' === event.key ? buttons.length - 1 : 'ArrowDown' === event.key ? (current + 1 + buttons.length) % buttons.length : (current - 1 + buttons.length) % buttons.length;
1252
- buttons[next]?.focus();
1253
- return true;
1254
- }
1255
- function moveOfficeGridMenuFocus(event, columns) {
1256
- if (!OFFICE_GRID_MENU_NAVIGATION_KEYS.includes(event.key)) return false;
1257
- const buttons = officeMenuButtons(event.currentTarget);
1258
- if (!buttons.length) return false;
1259
- event.preventDefault();
1260
- const currentButton = document.activeElement;
1261
- const current = Math.max(0, buttons.indexOf(currentButton));
1262
- if ('Home' === event.key || 'End' === event.key) {
1263
- buttons['Home' === event.key ? 0 : buttons.length - 1]?.focus();
1264
- return true;
1265
- }
1266
- if ('ArrowLeft' === event.key || 'ArrowRight' === event.key) {
1267
- const delta = 'ArrowRight' === event.key ? 1 : -1;
1268
- buttons[(current + delta + buttons.length) % buttons.length]?.focus();
1269
- return true;
1270
- }
1271
- const groups = [
1272
- ...event.currentTarget.querySelectorAll('[data-office-menu-grid]')
1273
- ];
1274
- const groupIndex = groups.findIndex((group)=>group.contains(currentButton));
1275
- if (groupIndex < 0) {
1276
- const delta = 'ArrowDown' === event.key ? columns : -columns;
1277
- buttons[(current + delta + buttons.length) % buttons.length]?.focus();
1278
- return true;
1279
- }
1280
- const groupButtons = officeMenuButtons(groups[groupIndex]);
1281
- const localIndex = Math.max(0, groupButtons.indexOf(currentButton));
1282
- const column = localIndex % columns;
1283
- if ('ArrowDown' === event.key) {
1284
- const nextRow = localIndex - column + columns;
1285
- if (nextRow < groupButtons.length) {
1286
- groupButtons[Math.min(nextRow + column, groupButtons.length - 1)]?.focus();
1287
- return true;
1288
- }
1289
- const nextGroup = groups[(groupIndex + 1) % groups.length];
1290
- const nextButtons = officeMenuButtons(nextGroup);
1291
- nextButtons[Math.min(column, nextButtons.length - 1)]?.focus();
1292
- return true;
1293
- }
1294
- const previousRow = localIndex - column - columns;
1295
- if (previousRow >= 0) {
1296
- groupButtons[previousRow + column]?.focus();
1297
- return true;
1298
- }
1299
- const previousGroup = groups[(groupIndex - 1 + groups.length) % groups.length];
1300
- const previousButtons = officeMenuButtons(previousGroup);
1301
- const previousRowStart = Math.floor((previousButtons.length - 1) / columns) * columns;
1302
- previousButtons[Math.min(previousRowStart + column, previousButtons.length - 1)]?.focus();
1303
- return true;
1304
- }
1305
- function officeMenuButtons(root) {
1306
- return [
1307
- ...root.querySelectorAll(OFFICE_MENU_BUTTON_SELECTOR)
1308
- ];
1309
- }
1310
1310
  function stepOfficeZoom(zoom, direction, { minimum = 50, maximum = 200, step = 10 } = {}) {
1311
1311
  const delta = 'in' === direction ? step : -step;
1312
1312
  return Math.min(maximum, Math.max(minimum, Math.round(zoom + delta)));
@@ -1,6 +1,6 @@
1
1
  import jszip from "jszip";
2
2
  import { serializeUtf8Xml, directChildren, xmlNamespacePrefix, parseXml, firstDescendant, decodeXmlBytes, directChild, descendants, attribute as work_ooxml_package_attribute } from "./5184.js";
3
- import { createDocumentBibliography, documentCitationStyle, documentCitationStyleDetails, normalizeDocumentTabStops } from "./6282.js";
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';
6
6
  const OFFICE_RELATIONSHIPS_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
@@ -708,6 +708,309 @@ 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
+ const STRICT_WORDPROCESSING_NAMESPACE = 'http://purl.oclc.org/ooxml/wordprocessingml/main';
712
+ const UNIVERSAL_TWIP_RATIOS = {
713
+ mm: [
714
+ 7200n,
715
+ 127n
716
+ ],
717
+ cm: [
718
+ 72000n,
719
+ 127n
720
+ ],
721
+ in: [
722
+ 1440n,
723
+ 1n
724
+ ],
725
+ pt: [
726
+ 20n,
727
+ 1n
728
+ ],
729
+ pc: [
730
+ 240n,
731
+ 1n
732
+ ],
733
+ pi: [
734
+ 240n,
735
+ 1n
736
+ ]
737
+ };
738
+ const UNIVERSAL_HALF_POINT_RATIOS = {
739
+ mm: [
740
+ 720n,
741
+ 127n
742
+ ],
743
+ cm: [
744
+ 7200n,
745
+ 127n
746
+ ],
747
+ in: [
748
+ 144n,
749
+ 1n
750
+ ],
751
+ pt: [
752
+ 2n,
753
+ 1n
754
+ ],
755
+ pc: [
756
+ 24n,
757
+ 1n
758
+ ],
759
+ pi: [
760
+ 24n,
761
+ 1n
762
+ ]
763
+ };
764
+ function parseDocxTwipsMeasure(source, options) {
765
+ const integer = parseBoundedDocxInteger(source, {
766
+ minimum: options.minimum,
767
+ maximum: options.maximum,
768
+ signed: options.signed
769
+ });
770
+ if (null !== integer) return integer;
771
+ return options.strict ? parseStrictUniversalMeasure(source, UNIVERSAL_TWIP_RATIOS, options) : null;
772
+ }
773
+ function parseDocxHalfPointsMeasure(source, options) {
774
+ const integer = parseBoundedDocxInteger(source, {
775
+ minimum: options.minimum,
776
+ maximum: options.maximum,
777
+ signed: options.signed
778
+ });
779
+ if (null !== integer) return integer;
780
+ return options.strict ? parseStrictUniversalMeasure(source, UNIVERSAL_HALF_POINT_RATIOS, options) : null;
781
+ }
782
+ function parseBoundedDocxInteger(source, options) {
783
+ if (source.length > 32) return null;
784
+ const pattern = options.signed ? /^[+-]?\d+$/u : /^\+?\d+$/u;
785
+ if (!pattern.test(source)) return null;
786
+ const value = Number(source);
787
+ return Number.isSafeInteger(value) && value >= options.minimum && value <= options.maximum ? Object.is(value, -0) ? 0 : value : null;
788
+ }
789
+ function parseStrictUniversalMeasure(source, conversions, options) {
790
+ if (source.length > 64) return null;
791
+ const match = /^(-?)(\d+)(?:\.(\d+))?(mm|cm|in|pt|pc|pi)$/u.exec(source);
792
+ if (!match) return null;
793
+ const [, sign, whole = '', fraction = '', unit = ''] = match;
794
+ if (!options.signed && sign) return null;
795
+ const conversion = conversions[unit];
796
+ if (!conversion) return null;
797
+ const denominator = 10n ** BigInt(fraction.length) * conversion[1];
798
+ const numerator = BigInt(`${whole}${fraction}`) * conversion[0] * (sign ? -1n : 1n);
799
+ if (numerator % denominator !== 0n) return null;
800
+ const units = numerator / denominator;
801
+ if (units < BigInt(options.minimum) || units > BigInt(options.maximum)) return null;
802
+ return Number(units);
803
+ }
804
+ function docxCharacterScaleValue(value) {
805
+ return normalizeDocumentCharacterScalePercent(value) ?? void 0;
806
+ }
807
+ function docxCharacterScalePercentFromProperties(properties) {
808
+ if (!properties) return;
809
+ const localMatches = directChildren(properties, 'w');
810
+ const scales = localMatches.filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
811
+ if (1 !== localMatches.length || 1 !== scales.length) return;
812
+ const scale = scales[0];
813
+ if (directChildren(scale).length || Array.from(scale.childNodes).some((node)=>(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.CDATA_SECTION_NODE) && Boolean(node.textContent?.trim()))) return;
814
+ const attributes = Array.from(scale.attributes).filter((attribute)=>xmlAttributeNamespace(scale, attribute) !== XMLNS_NAMESPACE && 'xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:'));
815
+ if (!attributes.length) return 100;
816
+ if (1 !== attributes.length || 'val' !== xmlAttributeLocalName(attributes[0]) || !DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(scale, attributes[0]) ?? '')) return;
817
+ return parseBoundedDocxInteger(attributes[0].value.trim(), {
818
+ minimum: 1,
819
+ maximum: 600,
820
+ signed: false
821
+ }) ?? void 0;
822
+ }
823
+ function docxCharacterPositionValue(value) {
824
+ const position = normalizeDocumentCharacterPositionHalfPoints(value);
825
+ return null === position ? void 0 : String(position);
826
+ }
827
+ function docxCharacterPositionHalfPointsFromProperties(properties) {
828
+ if (!properties) return;
829
+ const localMatches = directChildren(properties, 'position');
830
+ const positions = localMatches.filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
831
+ if (1 !== localMatches.length || 1 !== positions.length) return;
832
+ const position = positions[0];
833
+ if (directChildren(position).length || Array.from(position.childNodes).some((node)=>(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.CDATA_SECTION_NODE) && Boolean(node.textContent?.trim()))) return;
834
+ const attributes = Array.from(position.attributes).filter((attribute)=>xmlAttributeNamespace(position, attribute) !== XMLNS_NAMESPACE && 'xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:'));
835
+ if (1 !== attributes.length || 'val' !== xmlAttributeLocalName(attributes[0]) || !DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(position, attributes[0]) ?? '')) return;
836
+ return parseDocxHalfPointsMeasure(attributes[0].value.trim(), {
837
+ minimum: -3168,
838
+ maximum: 3168,
839
+ signed: true,
840
+ strict: position.namespaceURI === STRICT_WORDPROCESSING_NAMESPACE
841
+ }) ?? void 0;
842
+ }
843
+ const DOCX_EXPLICIT_ZERO_CHARACTER_SPACING_SENTINEL = 31681;
844
+ const CHARACTER_SPACING_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
845
+ function docxCharacterSpacingValue(value) {
846
+ const spacing = normalizeDocumentCharacterSpacingTwips(value);
847
+ if (null === spacing) return;
848
+ return 0 === spacing ? DOCX_EXPLICIT_ZERO_CHARACTER_SPACING_SENTINEL : spacing;
849
+ }
850
+ function docxCharacterSpacingTwipsFromProperties(properties) {
851
+ if (!properties) return;
852
+ const spacing = directChildren(properties, 'spacing').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
853
+ if (1 !== spacing.length) return;
854
+ return normalizeDocumentCharacterSpacingTwips(wordValue(spacing[0])) ?? void 0;
855
+ }
856
+ async function patchDocxExplicitZeroCharacterSpacing(buffer) {
857
+ const archive = await jszip.loadAsync(buffer);
858
+ let replacements = 0;
859
+ for (const entry of Object.values(archive.files)){
860
+ if (entry.dir || !CHARACTER_SPACING_PART_PATTERN.test(entry.name)) continue;
861
+ const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
862
+ let changed = false;
863
+ for (const spacing of descendants(document, 'spacing'))if (DOCX_WORDPROCESSING_NAMESPACES.has(spacing.namespaceURI ?? '') && wordValue(spacing) === String(DOCX_EXPLICIT_ZERO_CHARACTER_SPACING_SENTINEL)) {
864
+ setWordValue(spacing, '0');
865
+ replacements += 1;
866
+ changed = true;
867
+ }
868
+ if (changed) archive.file(entry.name, serializeUtf8Xml(document));
869
+ }
870
+ if (!replacements) throw new Error('Generated DOCX explicit-zero character spacing was not emitted.');
871
+ return archive.generateAsync({
872
+ type: 'arraybuffer'
873
+ });
874
+ }
875
+ function wordValue(element) {
876
+ const values = Array.from(element.attributes).filter((item)=>'val' === xmlAttributeLocalName(item) && DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(element, item) ?? ''));
877
+ return 1 === values.length ? values[0].value : null;
878
+ }
879
+ function setWordValue(element, value) {
880
+ const existing = Array.from(element.attributes).find((candidate)=>'val' === candidate.localName && DOCX_WORDPROCESSING_NAMESPACES.has(candidate.namespaceURI ?? ''));
881
+ const namespace = element.namespaceURI ?? '';
882
+ const prefix = element.prefix || 'w';
883
+ if (existing) element.setAttributeNS(existing.namespaceURI, existing.name, value);
884
+ else element.setAttributeNS(namespace, `${prefix}:val`, value);
885
+ }
886
+ const DOCX_EXPLICIT_ZERO_KERNING_THRESHOLD_SENTINEL = 3278;
887
+ const KERNING_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
888
+ function docxKerningThresholdValue(value) {
889
+ const threshold = normalizeDocumentKerningThresholdHalfPoints(value);
890
+ if (null === threshold) return;
891
+ return 0 === threshold ? DOCX_EXPLICIT_ZERO_KERNING_THRESHOLD_SENTINEL : threshold;
892
+ }
893
+ function docxKerningThresholdHalfPointsFromProperties(properties) {
894
+ const inspection = inspectDocxKerningThresholdHalfPoints(properties);
895
+ return 'valid' === inspection.status ? inspection.value : void 0;
896
+ }
897
+ function resolveDocxKerningThresholdHalfPoints(propertySources) {
898
+ let threshold;
899
+ for (const properties of propertySources){
900
+ const candidate = docxKerningThresholdHalfPointsFromProperties(properties);
901
+ if (void 0 !== candidate) threshold = candidate;
902
+ }
903
+ return threshold;
904
+ }
905
+ function inspectDocxKerningThresholdHalfPoints(properties) {
906
+ if (!properties) return {
907
+ status: 'absent'
908
+ };
909
+ const localMatches = directChildren(properties, 'kern');
910
+ if (!localMatches.length) return {
911
+ status: 'absent'
912
+ };
913
+ const nativeMatches = localMatches.filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
914
+ if (1 !== localMatches.length || 1 !== nativeMatches.length) return {
915
+ status: 'invalid'
916
+ };
917
+ const kerning = nativeMatches[0];
918
+ if (directChildren(kerning).length || Array.from(kerning.childNodes).some((node)=>(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.CDATA_SECTION_NODE) && Boolean(node.textContent?.trim()))) return {
919
+ status: 'invalid'
920
+ };
921
+ const attributes = Array.from(kerning.attributes).filter((attribute)=>xmlAttributeNamespace(kerning, attribute) !== XMLNS_NAMESPACE && 'xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:'));
922
+ if (1 !== attributes.length || 'val' !== xmlAttributeLocalName(attributes[0]) || !DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(kerning, attributes[0]) ?? '')) return {
923
+ status: 'invalid'
924
+ };
925
+ const value = parseBoundedDocxInteger(attributes[0].value.trim(), {
926
+ minimum: 0,
927
+ maximum: 3277,
928
+ signed: false
929
+ });
930
+ return null === value ? {
931
+ status: 'invalid'
932
+ } : {
933
+ status: 'valid',
934
+ value
935
+ };
936
+ }
937
+ async function patchDocxExplicitZeroKerningThresholds(buffer) {
938
+ const archive = await jszip.loadAsync(buffer);
939
+ let replacements = 0;
940
+ for (const entry of Object.values(archive.files)){
941
+ if (entry.dir || !KERNING_PART_PATTERN.test(entry.name)) continue;
942
+ const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
943
+ let changed = false;
944
+ for (const kerning of descendants(document, 'kern'))if (DOCX_WORDPROCESSING_NAMESPACES.has(kerning.namespaceURI ?? '') && work_docx_kerning_wordValue(kerning) === String(DOCX_EXPLICIT_ZERO_KERNING_THRESHOLD_SENTINEL)) {
945
+ work_docx_kerning_setWordValue(kerning, '0');
946
+ replacements += 1;
947
+ changed = true;
948
+ }
949
+ if (changed) archive.file(entry.name, serializeUtf8Xml(document));
950
+ }
951
+ if (!replacements) throw new Error('Generated DOCX explicit-zero kerning was not emitted.');
952
+ return archive.generateAsync({
953
+ type: 'arraybuffer'
954
+ });
955
+ }
956
+ function work_docx_kerning_wordValue(element) {
957
+ const values = Array.from(element.attributes).filter((attribute)=>'val' === xmlAttributeLocalName(attribute) && DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(element, attribute) ?? ''));
958
+ return 1 === values.length ? values[0].value : null;
959
+ }
960
+ function work_docx_kerning_setWordValue(element, value) {
961
+ const existing = Array.from(element.attributes).find((attribute)=>'val' === xmlAttributeLocalName(attribute) && DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(element, attribute) ?? ''));
962
+ const namespace = element.namespaceURI ?? '';
963
+ const prefix = element.prefix || 'w';
964
+ if (existing) existing.value = value;
965
+ else element.setAttributeNS(namespace, `${prefix}:val`, value);
966
+ }
967
+ function docxEmphasisMarkFromProperties(properties) {
968
+ const inspection = inspectDocxEmphasisMark(properties);
969
+ return 'valid' === inspection.status ? inspection.value : void 0;
970
+ }
971
+ function resolveDocxEmphasisMark(propertySources) {
972
+ let emphasisMark;
973
+ for (const properties of propertySources){
974
+ const candidate = docxEmphasisMarkFromProperties(properties);
975
+ if (void 0 !== candidate) emphasisMark = candidate;
976
+ }
977
+ return emphasisMark;
978
+ }
979
+ function inspectDocxEmphasisMark(properties) {
980
+ if (!properties) return {
981
+ status: 'absent'
982
+ };
983
+ const localMatches = directChildren(properties, 'em');
984
+ if (!localMatches.length) return {
985
+ status: 'absent'
986
+ };
987
+ const nativeMatches = localMatches.filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
988
+ if (1 !== localMatches.length || 1 !== nativeMatches.length) return {
989
+ status: 'invalid'
990
+ };
991
+ const emphasis = nativeMatches[0];
992
+ if (directChildren(emphasis).length || Array.from(emphasis.childNodes).some((node)=>(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.CDATA_SECTION_NODE) && Boolean(node.textContent?.trim()))) return {
993
+ status: 'invalid'
994
+ };
995
+ const attributes = Array.from(emphasis.attributes).filter((attribute)=>xmlAttributeNamespace(emphasis, attribute) !== XMLNS_NAMESPACE && 'xmlns' !== attribute.name && !attribute.name.startsWith('xmlns:'));
996
+ if (1 !== attributes.length || 'val' !== xmlAttributeLocalName(attributes[0]) || !DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(emphasis, attributes[0]) ?? '')) return {
997
+ status: 'invalid'
998
+ };
999
+ const value = normalizeDocumentEmphasisMark(attributes[0].value);
1000
+ return null === value ? {
1001
+ status: 'invalid'
1002
+ } : {
1003
+ status: 'valid',
1004
+ value
1005
+ };
1006
+ }
1007
+ function docxEmphasisMarkRunOptions(value) {
1008
+ const emphasisMark = normalizeDocumentEmphasisMark(value);
1009
+ if (!emphasisMark) return;
1010
+ return {
1011
+ type: emphasisMark
1012
+ };
1013
+ }
711
1014
  function paragraphAlignment(element, docx) {
712
1015
  const alignment = element.style.textAlign;
713
1016
  if ('center' === alignment) return docx.AlignmentType.CENTER;
@@ -1276,4 +1579,4 @@ function hexFactor(value) {
1276
1579
  function isDocxThemeResolver(source) {
1277
1580
  return Boolean(source && 'colors' in source && source.colors instanceof Map && 'fonts' in source && source.fonts instanceof Map);
1278
1581
  }
1279
- export { DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, DOCX_WORDPROCESSING_NAMESPACES, DocxParagraphDefaultCollapsedPatchCollector, XMLNS_NAMESPACE, XML_NAMESPACE, assertXmlRoot, cloneXmlElement, createDocxThemeResolver, cssColorToHex, cssFontFamily, cssFontSize, dataBoolean, docxThemeColor, docxThemeFont, domDirection, hasNonWhitespaceXmlText, mergeDocxIgnorableExtensions, mergeDocxIgnorableExtensionsAtPairs, paragraphAlignment, paragraphBidirectional, paragraphDirectionOptions, paragraphIndent, paragraphPaginationOptions, paragraphSpacingOptions, paragraphTabStops, parseDocxColorSchemeMappingElement, parseDocxParagraphDefaultCollapsed, patchDocxBibliography, patchDocxParagraphDefaultCollapsed, readDocxBibliography, resolveDocxThemeResolver, xmlAttributeLocalName, xmlAttributeNamespace, xmlDeclaredPrefix, xmlNamespaceUri };
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 };