@a3s-lab/office 0.37.4 → 0.38.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 (33) hide show
  1. package/README.md +10 -1
  2. package/dist/{0~4808.js → 0~5024.js} +150 -2
  3. package/dist/0~7240.js +26 -4
  4. package/dist/0~document-editor.js +455 -13
  5. package/dist/0~spreadsheet-editor.js +52 -36
  6. package/dist/0~work-docx-export.js +215 -18
  7. package/dist/0~work-docx-import.js +4 -2
  8. package/dist/0~work-office-diagnostics.js +57 -1
  9. package/dist/4174.js +313 -112
  10. package/dist/5416.js +56 -44
  11. package/dist/core.js +56 -10
  12. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +5 -4
  13. package/dist/internal/features/work/editors/document-font-dialog-opentype-model.d.ts +53 -0
  14. package/dist/internal/features/work/editors/document-font-dialog-script-font-model.d.ts +5 -0
  15. package/dist/internal/features/work/editors/spreadsheet-auto-filter-menu.d.ts +2 -2
  16. package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +3 -3
  17. package/dist/internal/features/work/editors/spreadsheet-date-time-command.d.ts +2 -1
  18. package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +2 -2
  19. package/dist/internal/features/work/editors/spreadsheet-filter-reconciliation.d.ts +3 -2
  20. package/dist/internal/features/work/work-document-equations.d.ts +4 -3
  21. package/dist/internal/features/work/work-document-format-changes.d.ts +2 -0
  22. package/dist/internal/features/work/work-document-opentype.d.ts +39 -0
  23. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +1 -0
  24. package/dist/internal/features/work/work-docx-opentype-diagnostics.d.ts +3 -0
  25. package/dist/internal/features/work/work-docx-opentype-export.d.ts +19 -0
  26. package/dist/internal/features/work/work-docx-opentype-import.d.ts +8 -0
  27. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +2 -0
  28. package/dist/internal/features/work/work-spreadsheet-dynamic-filter.d.ts +3 -2
  29. package/dist/internal/features/work/work-types.d.ts +3 -0
  30. package/dist/office-kernel.wasm +0 -0
  31. package/dist/styles.css +7 -3
  32. package/docs/latest/en/browser-editor-architecture.md +4 -2
  33. package/package.json +6 -1
@@ -4516,19 +4516,21 @@ function spreadsheetSortColumnLabel(column) {
4516
4516
  }
4517
4517
  ]).replace(/\d+$/, '');
4518
4518
  }
4519
- function reconcileSpreadsheetFiltersAfterFortune(sheets, sourceSheets, operations = []) {
4519
+ function reconcileSpreadsheetFiltersAfterFortune(sheets, sourceSheets, operations = [], context = {
4520
+ now: new Date()
4521
+ }) {
4520
4522
  const coordinates = spreadsheetCellOperationCoordinates(operations);
4521
4523
  return sheets.map((sheet, index)=>{
4522
4524
  const source = spreadsheet_filter_reconciliation_sourceSheet(sheet, sourceSheets, index);
4523
4525
  if (!source || !spreadsheetSheetHasCriteria(source) || !spreadsheetFilterReconciliationIsBounded(source) || !spreadsheetFilterRangesWereEdited(source, operations, coordinates)) return sheet;
4524
- const previousTableOwnedRows = spreadsheetTableFilterOwnedRows(source);
4526
+ const previousTableOwnedRows = spreadsheetTableFilterOwnedRows(source, context);
4525
4527
  const manuallyHiddenRows = workSpreadsheetAutoFilterManuallyHiddenRows(source);
4526
4528
  for (const row of previousTableOwnedRows)manuallyHiddenRows.delete(row);
4527
4529
  let next = sheet;
4528
- if (normalizedWorkSpreadsheetAutoFilterRange(sheet.filter_select) && workSpreadsheetAutoFilterCriteriaEntries(source).length) next = workSpreadsheetSheetWithReappliedAutoFilterCriteria(sheet, source, manuallyHiddenRows);
4530
+ if (normalizedWorkSpreadsheetAutoFilterRange(sheet.filter_select) && workSpreadsheetAutoFilterCriteriaEntries(source).length) next = workSpreadsheetSheetWithReappliedAutoFilterCriteria(sheet, source, manuallyHiddenRows, context);
4529
4531
  const hiddenRows = new Set(manuallyHiddenRows);
4530
4532
  for (const row of workSpreadsheetAutoFilterOwnedRows(next))hiddenRows.add(row);
4531
- for (const row of spreadsheetTableFilterOwnedRows(next))hiddenRows.add(row);
4533
+ for (const row of spreadsheetTableFilterOwnedRows(next, context))hiddenRows.add(row);
4532
4534
  const rowhidden = Object.fromEntries([
4533
4535
  ...hiddenRows
4534
4536
  ].sort(compareSpreadsheetRowKeys).map((row)=>[
@@ -4544,26 +4546,28 @@ function reconcileSpreadsheetFiltersAfterFortune(sheets, sourceSheets, operation
4544
4546
  };
4545
4547
  });
4546
4548
  }
4547
- function reconcileSpreadsheetFiltersAfterSort(sheet, source, range, sourceIndexes) {
4549
+ function reconcileSpreadsheetFiltersAfterSort(sheet, source, range, sourceIndexes, context = {
4550
+ now: new Date()
4551
+ }) {
4548
4552
  if (!spreadsheetFilterReconciliationIsBounded(source) || !spreadsheetSortSourceIndexesAreValid(range, sourceIndexes)) return null;
4549
4553
  const reconciled = reconcileSpreadsheetFiltersAfterFortune([
4550
4554
  sheet
4551
4555
  ], [
4552
4556
  source
4553
- ])[0];
4557
+ ], [], context)[0];
4554
4558
  if (!reconciled) return null;
4555
4559
  let filter = reconciled.filter;
4556
4560
  const autoFilter = normalizedWorkSpreadsheetAutoFilterRange(source.filter_select);
4557
4561
  if (autoFilter && autoFilter.row[0] === range.row[0] && autoFilter.row[1] === range.row[1] && autoFilter.column[0] === range.column[0] && autoFilter.column[1] === range.column[1]) filter = spreadsheetFilterWithRemappedOpaqueEntries(reconciled, source, range, sourceIndexes);
4558
4562
  const manuallyHiddenRows = workSpreadsheetAutoFilterManuallyHiddenRows(source);
4559
- for (const row of spreadsheetTableFilterOwnedRows(source))manuallyHiddenRows.delete(row);
4563
+ for (const row of spreadsheetTableFilterOwnedRows(source, context))manuallyHiddenRows.delete(row);
4560
4564
  const withFilter = {
4561
4565
  ...reconciled,
4562
4566
  filter
4563
4567
  };
4564
4568
  const hiddenRows = new Set(manuallyHiddenRows);
4565
4569
  for (const row of workSpreadsheetAutoFilterOwnedRows(withFilter))hiddenRows.add(row);
4566
- for (const row of spreadsheetTableFilterOwnedRows(withFilter))hiddenRows.add(row);
4570
+ for (const row of spreadsheetTableFilterOwnedRows(withFilter, context))hiddenRows.add(row);
4567
4571
  const rowhidden = Object.fromEntries([
4568
4572
  ...hiddenRows
4569
4573
  ].sort(compareSpreadsheetRowKeys).map((row)=>[
@@ -4645,13 +4649,13 @@ function spreadsheetFilterRanges(sheet) {
4645
4649
  }
4646
4650
  return ranges;
4647
4651
  }
4648
- function spreadsheetTableFilterOwnedRows(sheet) {
4652
+ function spreadsheetTableFilterOwnedRows(sheet, context) {
4649
4653
  const hidden = new Set();
4650
4654
  for (const table of sheet.tables ?? []){
4651
4655
  const range = spreadsheetTableFilterRange(table);
4652
4656
  if (range) for (const filter of table.filters){
4653
4657
  const column = range.column[0] + filter.column;
4654
- const rowhidden = workSpreadsheetFilterHiddenRows(sheet, range, column, filter.criteria);
4658
+ const rowhidden = workSpreadsheetFilterHiddenRows(sheet, range, column, filter.criteria, context);
4655
4659
  for (const row of Object.keys(rowhidden ?? {}))hidden.add(row);
4656
4660
  }
4657
4661
  }
@@ -5348,8 +5352,12 @@ function recordSpreadsheetProjectionMeasure(start, end, detail) {
5348
5352
  });
5349
5353
  } catch {}
5350
5354
  }
5351
- function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = []) {
5355
+ function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = [], dateSystem = '1900') {
5352
5356
  const startedAt = spreadsheetProjectionNow();
5357
+ const filterContext = {
5358
+ dateSystem,
5359
+ now: new Date()
5360
+ };
5353
5361
  const incremental = projectSpreadsheetSheetsFromFortuneOperations(sheets, sourceSheets, operations);
5354
5362
  if (incremental) {
5355
5363
  recordSpreadsheetControlledProjectionMeasure(startedAt, spreadsheetProjectionNow(), {
@@ -5357,7 +5365,7 @@ function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = []) {
5357
5365
  incremental: true,
5358
5366
  operationCount: operations.length
5359
5367
  });
5360
- return reconcileSpreadsheetFiltersAfterFortune(reconcileSpreadsheetTablesAfterFortune(incremental.sheets, sourceSheets, operations), sourceSheets, operations);
5368
+ return reconcileSpreadsheetFiltersAfterFortune(reconcileSpreadsheetTablesAfterFortune(incremental.sheets, sourceSheets, operations), sourceSheets, operations, filterContext);
5361
5369
  }
5362
5370
  const operationCoordinatesBySheet = spreadsheetCellOperationCoordinates(operations);
5363
5371
  const projected = sheets.map((sheet, index)=>{
@@ -5399,7 +5407,7 @@ function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = []) {
5399
5407
  incremental: false,
5400
5408
  operationCount: operations.length
5401
5409
  });
5402
- return reconcileSpreadsheetFiltersAfterFortune(reconcileSpreadsheetTablesAfterFortune(projected, sourceSheets, operations), sourceSheets, operations);
5410
+ return reconcileSpreadsheetFiltersAfterFortune(reconcileSpreadsheetTablesAfterFortune(projected, sourceSheets, operations), sourceSheets, operations, filterContext);
5403
5411
  }
5404
5412
  function recordSpreadsheetControlledProjectionMeasure(start, end, detail) {
5405
5413
  try {
@@ -5929,18 +5937,18 @@ function toggleSpreadsheetAutoFilter(content, sheetId, selection) {
5929
5937
  function spreadsheetAutoFilterCriteria(sheet, column) {
5930
5938
  return workSpreadsheetAutoFilterCriteria(sheet, column);
5931
5939
  }
5932
- function spreadsheetAutoFilterColumnIsNumeric(sheet, range, column) {
5933
- return spreadsheetAutoFilterColumnProfile(sheet, range, column).numeric;
5940
+ function spreadsheetAutoFilterColumnIsNumeric(sheet, range, column, dateSystem = '1900') {
5941
+ return spreadsheetAutoFilterColumnProfile(sheet, range, column, dateSystem).numeric;
5934
5942
  }
5935
- function spreadsheetAutoFilterColumnIsDate(sheet, range, column) {
5936
- return spreadsheetAutoFilterColumnProfile(sheet, range, column).date;
5943
+ function spreadsheetAutoFilterColumnIsDate(sheet, range, column, dateSystem = '1900') {
5944
+ return spreadsheetAutoFilterColumnProfile(sheet, range, column, dateSystem).date;
5937
5945
  }
5938
- function spreadsheetAutoFilterColumnProfile(sheet, range, column) {
5946
+ function spreadsheetAutoFilterColumnProfile(sheet, range, column, dateSystem) {
5939
5947
  if (!Number.isSafeInteger(column) || column < range.column[0] || column > range.column[1]) return {
5940
5948
  date: false,
5941
5949
  numeric: false
5942
5950
  };
5943
- const key = `${range.row[0]}:${range.row[1]}:${column}`;
5951
+ const key = `${dateSystem}:${range.row[0]}:${range.row[1]}:${column}`;
5944
5952
  const cached = spreadsheetAutoFilterColumnProfileCache.get(sheet)?.get(key);
5945
5953
  if (cached) return cached;
5946
5954
  const cellAt = spreadsheetSheetCellReader(sheet);
@@ -5949,7 +5957,7 @@ function spreadsheetAutoFilterColumnProfile(sheet, range, column) {
5949
5957
  const cell = cellAt(row, column);
5950
5958
  const value = cell?.v ?? cell?.m;
5951
5959
  if (null == value || '' === value) continue;
5952
- const valueKind = workSpreadsheetCellIsDate(cell) ? 'date' : 'number' == typeof value && Number.isFinite(value) ? 'numeric' : null;
5960
+ const valueKind = workSpreadsheetCellIsDate(cell, dateSystem) ? 'date' : 'number' == typeof value && Number.isFinite(value) ? 'numeric' : null;
5953
5961
  if (!valueKind || null !== columnKind && columnKind !== valueKind) {
5954
5962
  columnKind = null;
5955
5963
  break;
@@ -5969,7 +5977,10 @@ function applySpreadsheetAutoFilterCriteria(content, sheetId, column, criteria,
5969
5977
  const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
5970
5978
  const sheet = content.sheets[sheetIndex];
5971
5979
  if (!sheet) return null;
5972
- const nextSheet = workSpreadsheetSheetWithAutoFilterCriteria(sheet, column, criteria, context);
5980
+ const nextSheet = workSpreadsheetSheetWithAutoFilterCriteria(sheet, column, criteria, {
5981
+ dateSystem: content.dateSystem,
5982
+ now: context?.now ?? new Date()
5983
+ });
5973
5984
  if (!nextSheet) return null;
5974
5985
  const sheets = [
5975
5986
  ...content.sheets
@@ -8529,13 +8540,15 @@ function clampSpreadsheetDataValidationFocus(value, range) {
8529
8540
  const MILLISECONDS_PER_DAY = 86400000;
8530
8541
  const MINUTES_PER_DAY = 1440;
8531
8542
  const EXCEL_1900_EPOCH_UTC = Date.UTC(1899, 11, 30);
8532
- function spreadsheetDateTimeEntry(kind, now) {
8543
+ const EXCEL_1904_EPOCH_UTC = Date.UTC(1904, 0, 1);
8544
+ function spreadsheetDateTimeEntry(kind, now, dateSystem = '1900') {
8533
8545
  if (!Number.isFinite(now.getTime())) return null;
8534
8546
  if ('date' === kind) {
8535
8547
  const year = now.getFullYear();
8536
8548
  const month = now.getMonth();
8537
8549
  const day = now.getDate();
8538
- const value = (Date.UTC(year, month, day) - EXCEL_1900_EPOCH_UTC) / MILLISECONDS_PER_DAY;
8550
+ const epoch = '1904' === dateSystem ? EXCEL_1904_EPOCH_UTC : EXCEL_1900_EPOCH_UTC;
8551
+ const value = (Date.UTC(year, month, day) - epoch) / MILLISECONDS_PER_DAY;
8539
8552
  if (!Number.isFinite(value)) return null;
8540
8553
  return {
8541
8554
  format: {
@@ -8576,7 +8589,7 @@ function createSpreadsheetDateTimeExtension() {
8576
8589
  function insertCurrentSpreadsheetDateTime(context, kind) {
8577
8590
  if (!isSpreadsheetDateTimeKind(kind)) return false;
8578
8591
  const target = spreadsheetDateTimeTarget(context);
8579
- const entry = spreadsheetDateTimeEntry(kind, new Date());
8592
+ const entry = spreadsheetDateTimeEntry(kind, new Date(), context.content.dateSystem);
8580
8593
  if (!target || !entry || !context.workbook) return false;
8581
8594
  try {
8582
8595
  context.workbook.batchCallApis([
@@ -10369,7 +10382,10 @@ function applySpreadsheetSort(context, request) {
10369
10382
  if (!result.ok) return false;
10370
10383
  if (owned && spreadsheetSortRequiresFilterReconciliation(sheet, owned)) {
10371
10384
  const sorted = spreadsheetSheetWithSortedRange(sheet, validation.request.range, result.rows);
10372
- const reconciled = reconcileSpreadsheetFiltersAfterSort(sorted, sheet, validation.request.range, result.sourceIndexes);
10385
+ const reconciled = reconcileSpreadsheetFiltersAfterSort(sorted, sheet, validation.request.range, result.sourceIndexes, {
10386
+ dateSystem: context.content.dateSystem,
10387
+ now: new Date()
10388
+ });
10373
10389
  if (!reconciled) return false;
10374
10390
  context.onChange({
10375
10391
  ...context.content,
@@ -23509,7 +23525,7 @@ const SPREADSHEET_AUTO_FILTER_MENU_ITEMS = [
23509
23525
  '|',
23510
23526
  'filter-by-value'
23511
23527
  ];
23512
- function enhanceSpreadsheetAutoFilterSurface(container, sheet, invoker) {
23528
+ function enhanceSpreadsheetAutoFilterSurface(container, sheet, invoker, dateSystem = '1900') {
23513
23529
  const range = sheet?.filter_select;
23514
23530
  const startRow = range?.row?.[0];
23515
23531
  const startColumn = range?.column?.[0];
@@ -23556,14 +23572,14 @@ function enhanceSpreadsheetAutoFilterSurface(container, sheet, invoker) {
23556
23572
  action.setAttribute('aria-haspopup', 'dialog');
23557
23573
  }
23558
23574
  }
23559
- synchronizeSpreadsheetAutoFilterRankAction(menu, sheet, trigger);
23575
+ synchronizeSpreadsheetAutoFilterRankAction(menu, sheet, trigger, dateSystem);
23560
23576
  return menu;
23561
23577
  }
23562
- function synchronizeSpreadsheetAutoFilterRankAction(menu, sheet, trigger) {
23578
+ function synchronizeSpreadsheetAutoFilterRankAction(menu, sheet, trigger, dateSystem) {
23563
23579
  const existing = menu.querySelector('[data-a3s-auto-filter-rank]');
23564
23580
  const range = normalizedWorkSpreadsheetAutoFilterRange(sheet?.filter_select);
23565
23581
  const column = Number(trigger?.dataset.filterColumn);
23566
- const numeric = Boolean(sheet && range && Number.isSafeInteger(column) && spreadsheetAutoFilterColumnIsNumeric(sheet, range, column));
23582
+ const numeric = Boolean(sheet && range && Number.isSafeInteger(column) && spreadsheetAutoFilterColumnIsNumeric(sheet, range, column, dateSystem));
23567
23583
  if (!numeric) return void existing?.remove();
23568
23584
  if (existing) {
23569
23585
  existing.dataset.filterColumn = String(column);
@@ -24291,7 +24307,7 @@ function useSpreadsheetAutoFilter({ canvasRef, commandsRef, content, editable, m
24291
24307
  const column = spreadsheetAutoFilterHeaderColumn(activeSheet, currentSpreadsheetAutoFilterSelection(selectionRef.current, workbookRef.current));
24292
24308
  const startColumn = activeSheet?.filter_select?.column?.[0];
24293
24309
  if (!container || null === column || !Number.isFinite(startColumn)) return false;
24294
- enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current);
24310
+ enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current, contentRef.current.dateSystem);
24295
24311
  const triggers = [
24296
24312
  ...container.querySelectorAll('.luckysheet-filter-options')
24297
24313
  ];
@@ -24300,7 +24316,7 @@ function useSpreadsheetAutoFilter({ canvasRef, commandsRef, content, editable, m
24300
24316
  keyboardInvokerRef.current = trigger;
24301
24317
  restoreInvokerFocusRef.current = true;
24302
24318
  trigger.click();
24303
- enhanceSpreadsheetAutoFilterSurface(container, activeSheet, trigger);
24319
+ enhanceSpreadsheetAutoFilterSurface(container, activeSheet, trigger, contentRef.current.dateSystem);
24304
24320
  focusSpreadsheetAutoFilterMenu(container);
24305
24321
  return true;
24306
24322
  }, [
@@ -24328,11 +24344,11 @@ function useSpreadsheetAutoFilter({ canvasRef, commandsRef, content, editable, m
24328
24344
  column,
24329
24345
  columnLabel: spreadsheetAutoFilterColumnLabel(activeSheet, range.row[0], column),
24330
24346
  criteria,
24331
- date: spreadsheetAutoFilterColumnIsDate(activeSheet, range, column),
24347
+ date: spreadsheetAutoFilterColumnIsDate(activeSheet, range, column, contentRef.current.dateSystem),
24332
24348
  filterRange: range,
24333
24349
  hasActiveFilter: Object.hasOwn(activeSheet.filter ?? {}, key),
24334
24350
  invoker,
24335
- numeric: spreadsheetAutoFilterColumnIsNumeric(activeSheet, range, column),
24351
+ numeric: spreadsheetAutoFilterColumnIsNumeric(activeSheet, range, column, contentRef.current.dateSystem),
24336
24352
  sheetId: activeSheet.id ?? sheetIdRef.current,
24337
24353
  sheetName: activeSheet.name
24338
24354
  };
@@ -24354,7 +24370,7 @@ function useSpreadsheetAutoFilter({ canvasRef, commandsRef, content, editable, m
24354
24370
  if (!container || !editable) return;
24355
24371
  const enhance = ()=>{
24356
24372
  const activeSheet = contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current);
24357
- const menu = enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current);
24373
+ const menu = enhanceSpreadsheetAutoFilterSurface(container, activeSheet, keyboardInvokerRef.current, contentRef.current.dateSystem);
24358
24374
  const menuOpen = Boolean(menu);
24359
24375
  if (menuWasOpenRef.current && !menuOpen && restoreInvokerFocusRef.current) {
24360
24376
  const invoker = keyboardInvokerRef.current;
@@ -24389,7 +24405,7 @@ function useSpreadsheetAutoFilter({ canvasRef, commandsRef, content, editable, m
24389
24405
  keyboardInvokerRef.current = trigger;
24390
24406
  restoreInvokerFocusRef.current = true;
24391
24407
  trigger.click();
24392
- enhanceSpreadsheetAutoFilterSurface(container, contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current), trigger);
24408
+ enhanceSpreadsheetAutoFilterSurface(container, contentRef.current.sheets.find((candidate)=>candidate.id === sheetIdRef.current), trigger, contentRef.current.dateSystem);
24393
24409
  focusSpreadsheetAutoFilterMenu(container);
24394
24410
  return;
24395
24411
  }
@@ -30136,7 +30152,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
30136
30152
  if (ignoreChangeDuringExternalSync(matchesRenderedWorkbook)) return;
30137
30153
  const hasPendingResultPatches = calculation.hasPendingResultPatches();
30138
30154
  if (previewRef.current || matchesRenderedWorkbook && !hasPendingResultPatches) return;
30139
- const controlledSheets = spreadsheetSheetsFromFortune(sheets, contentRef.current.sheets, operations);
30155
+ const controlledSheets = spreadsheetSheetsFromFortune(sheets, contentRef.current.sheets, operations, contentRef.current.dateSystem);
30140
30156
  const withCharts = reconcileSpreadsheetChartPreviews(contentRef.current, controlledSheets);
30141
30157
  const next = reconcileSpreadsheetPivots(contentRef.current, withCharts.sheets);
30142
30158
  const isHistoryNoop = sameSpreadsheetHistoryContent(contentRef.current, next);
@@ -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, 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 "./4174.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, serializeDocumentOpenTypeFeatures, normalizeDocumentImageIdentity, normalizeDocumentStrikeStyle, normalizeTableColor, normalizeDocumentOpenTypeFeatures, documentCitationTags, docxDocumentFieldKind, documentTableBordersFromElement, documentSections, wrapsBesideImage, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentKerningThresholdHalfPoints, defaultDocumentImageWrapContour, parseDocumentOpenTypeFeatures, normalizeDocumentPaperSource, DOCUMENT_LEGACY_TEXT_OUTLINE_ATTRIBUTE, documentEquationFromElement, documentLegacyTextEffectsFromElement, parseDocumentCharacterFormatting, documentUnderlineFormattingFromElement, DOCUMENT_LEGACY_TEXT_SHADOW_ATTRIBUTE, normalizeDocumentEquation, parseDocumentParagraphFormatting, documentOpenTypeFeaturesFromElement, normalizeDocumentBookmarkNativeId, documentTableRowIdentityFromElement, DOCUMENT_PAGE_MARGIN_KEYS, uniqueDocumentImageIdentity, documentHiddenTextFromElement, collectDocumentNotes, documentImageLayoutFromElement, documentPageHorizontalMarginTwips, DOCUMENT_OPEN_TYPE_ATTRIBUTE, documentPageGeometryForLayout, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, documentCharacterScalePercentFromElement, normalizeDocumentPageMargins, normalizeDocumentLegacyTextEffect, documentNoteKind } from "./4174.js";
3
3
  import { normalizeDocumentRunBorder, parseDocumentScriptFonts, normalizeDocumentIndexesHtml, parseXml, parseDocumentRunShading, applyDocumentParagraphIdentityToElement, DOCUMENT_RUN_SHADING_ATTRIBUTE, documentScriptFontSlotFromElement, DOCUMENT_HIGHLIGHT_ATTRIBUTE, parseDocxThemeReference, 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, documentIndexValueFromElement, descendants, resolvePartTarget, documentProofingLanguagesFromElement, documentScriptFontFamily, parseDocumentRunShadingElement, parseDocumentProofingLanguages, documentHighlightFromElement, parseDocumentParagraphBordersElement, DOCUMENT_RUN_BORDER_ATTRIBUTE, parseDocumentRunBorderElement, xmlNamespacePrefix, documentScriptFontSlotFromHint, documentNoProofFromElement, documentScriptFontsFromElement, normalizeDocumentRunShading, documentIndexEntryFromElement, directChild, normalizeDocumentScriptFontSlot, patchDocxThemeReferences, parseDocumentParagraphShadingElement, documentFontNameFromCssFamily } from "./4121.js";
4
4
  import { assignDocxNoteIds, patchDocxPageColor, normalizeDocxCommentId, assignDocxCommentThreads } from "./0~4980.js";
5
- import { paragraphTabStops, mergeDocxIgnorableExtensionsAtPairs, patchDocxBibliography, docxKerningThresholdValue, docxCharacterPositionValue, documentIndexInstruction, docxCharacterScaleValue, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, paragraphAlignment, xmlNamespaceUri, paragraphSpacingOptions, docxEmphasisMarkRunOptions, documentIndexEntryInstruction, hasNonWhitespaceXmlText, patchDocxExplicitZeroCharacterSpacing, cloneXmlElement, cssColorToHex, xmlDeclaredPrefix, assertXmlRoot, DOCX_WORDPROCESSING_NAMESPACES, paragraphIndent, domDirection, xmlAttributeNamespace, paragraphBidirectional, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, mergeDocxIgnorableExtensions, DocxParagraphDefaultCollapsedPatchCollector, dataBoolean, patchDocxParagraphDefaultCollapsed, patchDocxExplicitZeroKerningThresholds, parseDocxColorSchemeMappingElement, paragraphPaginationOptions, DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, documentProofingLanguageDocxOptions, xmlAttributeLocalName, cssFontSize, paragraphDirectionOptions, cssFontFamily, docxCharacterSpacingValue } from "./0~4808.js";
5
+ import { paragraphTabStops, mergeDocxIgnorableExtensionsAtPairs, DOCX_WORD_2010_NAMESPACE, docxKerningThresholdValue, patchDocxBibliography, documentIndexInstruction, docxCharacterScaleValue, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, paragraphAlignment, xmlNamespaceUri, paragraphSpacingOptions, docxCharacterPositionValue, documentIndexEntryInstruction, docxEmphasisMarkRunOptions, hasNonWhitespaceXmlText, patchDocxExplicitZeroCharacterSpacing, cloneXmlElement, cssColorToHex, xmlDeclaredPrefix, assertXmlRoot, DOCX_WORDPROCESSING_NAMESPACES, paragraphIndent, domDirection, xmlAttributeNamespace, paragraphBidirectional, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, mergeDocxIgnorableExtensions, DocxParagraphDefaultCollapsedPatchCollector, dataBoolean, patchDocxParagraphDefaultCollapsed, patchDocxExplicitZeroKerningThresholds, parseDocxColorSchemeMappingElement, paragraphPaginationOptions, DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, documentProofingLanguageDocxOptions, xmlAttributeLocalName, cssFontSize, paragraphDirectionOptions, cssFontFamily, docxCharacterSpacingValue } from "./0~5024.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 {
@@ -2660,6 +2660,174 @@ function work_docx_run_shading_export_setWordAttribute(document, element, name,
2660
2660
  const prefix = element.prefix ?? xmlNamespacePrefix(document.documentElement, namespace) ?? 'w';
2661
2661
  element.setAttributeNS(namespace, `${prefix}:${name}`, value);
2662
2662
  }
2663
+ const work_docx_opentype_export_MARKUP_COMPATIBILITY_NAMESPACE = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
2664
+ const OPEN_TYPE_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i;
2665
+ const OPEN_TYPE_PROPERTY_ORDER = [
2666
+ 'ligatures',
2667
+ 'numForm',
2668
+ 'numSpacing',
2669
+ 'stylisticSets',
2670
+ 'cntxtAlts'
2671
+ ];
2672
+ class DocxOpenTypePatchCollector {
2673
+ patches = [];
2674
+ nextMarker = 1;
2675
+ occupied;
2676
+ patchesByMarker = new Map();
2677
+ markersByFeaturesAndStyle = new Map();
2678
+ constructor(source){
2679
+ this.occupied = source;
2680
+ }
2681
+ marker(value, inheritedStyle) {
2682
+ const features = normalizeDocumentOpenTypeFeatures(value);
2683
+ if (!features) throw new Error('Document contains invalid OpenType typography.');
2684
+ const style = this.originalStyle(inheritedStyle);
2685
+ const serialized = serializeDocumentOpenTypeFeatures(features);
2686
+ if (!serialized) throw new Error('Document contains invalid OpenType typography.');
2687
+ const key = JSON.stringify([
2688
+ serialized,
2689
+ style ?? null
2690
+ ]);
2691
+ const existing = this.markersByFeaturesAndStyle.get(key);
2692
+ if (existing) return existing;
2693
+ let marker = '';
2694
+ do {
2695
+ marker = `A3SOfficeOpenType${String(this.nextMarker).padStart(8, '0')}`;
2696
+ this.nextMarker += 1;
2697
+ }while (this.occupied.includes(marker) || this.patches.some((patch)=>patch.marker === marker))
2698
+ const patch = {
2699
+ marker,
2700
+ features,
2701
+ ...style ? {
2702
+ style
2703
+ } : {}
2704
+ };
2705
+ this.patches.push(patch);
2706
+ this.patchesByMarker.set(marker, patch);
2707
+ this.markersByFeaturesAndStyle.set(key, marker);
2708
+ return marker;
2709
+ }
2710
+ lookup(marker) {
2711
+ return marker ? this.patchesByMarker.get(marker) : void 0;
2712
+ }
2713
+ originalStyle(style) {
2714
+ let current = style;
2715
+ const seen = new Set();
2716
+ while(current && !seen.has(current)){
2717
+ seen.add(current);
2718
+ const patch = this.patchesByMarker.get(current);
2719
+ if (!patch) break;
2720
+ current = patch.style;
2721
+ }
2722
+ return current;
2723
+ }
2724
+ }
2725
+ async function patchDocxOpenTypeFeatures(buffer, patches) {
2726
+ if (!patches.length) return buffer;
2727
+ const byMarker = validatedPatches(patches);
2728
+ const archive = await jszip.loadAsync(buffer);
2729
+ const applied = new Set();
2730
+ for (const entry of Object.values(archive.files)){
2731
+ if (entry.dir || !OPEN_TYPE_PART_PATTERN.test(entry.name)) continue;
2732
+ const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
2733
+ let changed = false;
2734
+ for (const properties of descendants(document, 'rPr')){
2735
+ if (!DOCX_WORDPROCESSING_NAMESPACES.has(properties.namespaceURI ?? '')) continue;
2736
+ const markerStyles = directChildren(properties, 'rStyle').filter((style)=>{
2737
+ if (!DOCX_WORDPROCESSING_NAMESPACES.has(style.namespaceURI ?? '')) return false;
2738
+ const marker = work_docx_opentype_export_wordValue(style);
2739
+ return null !== marker && byMarker.has(marker);
2740
+ });
2741
+ if (!markerStyles.length) continue;
2742
+ if (1 !== markerStyles.length) throw new Error('Generated DOCX OpenType marker is duplicated in one run.');
2743
+ const marker = work_docx_opentype_export_wordValue(markerStyles[0]);
2744
+ const patch = marker ? byMarker.get(marker) : void 0;
2745
+ if (marker && patch) {
2746
+ if (directChildren(properties).some((child)=>child.namespaceURI === DOCX_WORD_2010_NAMESPACE && OPEN_TYPE_PROPERTY_ORDER.includes(child.localName))) throw new Error('Generated DOCX OpenType marker unexpectedly has a native value.');
2747
+ if (patch.style) work_docx_opentype_export_setWordValue(markerStyles[0], patch.style);
2748
+ else markerStyles[0].remove();
2749
+ appendDocxOpenTypeProperties(document, properties, patch.features);
2750
+ applied.add(marker);
2751
+ changed = true;
2752
+ }
2753
+ }
2754
+ if (changed) archive.file(entry.name, serializeUtf8Xml(document));
2755
+ }
2756
+ const missing = patches.filter((patch)=>!applied.has(patch.marker));
2757
+ if (missing.length) throw new Error(`DOCX OpenType markers were not emitted: ${missing.map((patch)=>patch.marker).join(', ')}.`);
2758
+ return archive.generateAsync({
2759
+ type: 'arraybuffer'
2760
+ });
2761
+ }
2762
+ function validatedPatches(patches) {
2763
+ const result = new Map();
2764
+ for (const patch of patches){
2765
+ const features = normalizeDocumentOpenTypeFeatures(patch.features);
2766
+ if (!patch.marker || !features || result.has(patch.marker)) throw new Error('Document contains invalid OpenType patches.');
2767
+ result.set(patch.marker, {
2768
+ ...patch,
2769
+ features
2770
+ });
2771
+ }
2772
+ return result;
2773
+ }
2774
+ function appendDocxOpenTypeProperties(document, properties, source) {
2775
+ const features = normalizeDocumentOpenTypeFeatures(source);
2776
+ if (!features) throw new Error('Document contains invalid OpenType typography.');
2777
+ const prefix = work_docx_opentype_export_ensureWord2010Prefix(document.documentElement);
2778
+ if (void 0 !== features.ligatures) properties.append(valuedElement(document, prefix, 'ligatures', features.ligatures));
2779
+ if (void 0 !== features.numberForm) properties.append(valuedElement(document, prefix, 'numForm', features.numberForm));
2780
+ if (void 0 !== features.numberSpacing) properties.append(valuedElement(document, prefix, 'numSpacing', features.numberSpacing));
2781
+ if (void 0 !== features.stylisticSets) {
2782
+ const stylisticSets = word2010Element(document, prefix, 'stylisticSets');
2783
+ for (const id of features.stylisticSets)stylisticSets.append(valuedElement(document, prefix, 'styleSet', String(id), 'id'));
2784
+ properties.append(stylisticSets);
2785
+ }
2786
+ if (void 0 !== features.contextualAlternates) properties.append(valuedElement(document, prefix, 'cntxtAlts', features.contextualAlternates ? '1' : '0'));
2787
+ }
2788
+ function valuedElement(document, prefix, name, value, attribute = 'val') {
2789
+ const element = word2010Element(document, prefix, name);
2790
+ element.setAttributeNS(DOCX_WORD_2010_NAMESPACE, `${prefix}:${attribute}`, value);
2791
+ return element;
2792
+ }
2793
+ function word2010Element(document, prefix, name) {
2794
+ return document.createElementNS(DOCX_WORD_2010_NAMESPACE, `${prefix}:${name}`);
2795
+ }
2796
+ function work_docx_opentype_export_ensureWord2010Prefix(root) {
2797
+ const existing = Array.from(root.attributes).find((attribute)=>attribute.namespaceURI === work_docx_settings_xml_XMLNS_NAMESPACE && attribute.value === DOCX_WORD_2010_NAMESPACE);
2798
+ const prefix = existing?.localName ?? availablePrefix(root, 'w14');
2799
+ if (!existing) root.setAttributeNS(work_docx_settings_xml_XMLNS_NAMESPACE, `xmlns:${prefix}`, DOCX_WORD_2010_NAMESPACE);
2800
+ ensureIgnorable(root, prefix);
2801
+ return prefix;
2802
+ }
2803
+ function availablePrefix(root, preferred) {
2804
+ let index = 0;
2805
+ while(true){
2806
+ const prefix = index ? `${preferred}${index}` : preferred;
2807
+ const occupied = Array.from(root.attributes).some((attribute)=>attribute.namespaceURI === work_docx_settings_xml_XMLNS_NAMESPACE && attribute.localName === prefix);
2808
+ if (!occupied) return prefix;
2809
+ index += 1;
2810
+ }
2811
+ }
2812
+ function ensureIgnorable(root, word2010Prefix) {
2813
+ const existingPrefix = Array.from(root.attributes).find((attribute)=>attribute.namespaceURI === work_docx_settings_xml_XMLNS_NAMESPACE && attribute.value === work_docx_opentype_export_MARKUP_COMPATIBILITY_NAMESPACE)?.localName;
2814
+ const prefix = existingPrefix ?? availablePrefix(root, 'mc');
2815
+ if (!existingPrefix) root.setAttributeNS(work_docx_settings_xml_XMLNS_NAMESPACE, `xmlns:${prefix}`, work_docx_opentype_export_MARKUP_COMPATIBILITY_NAMESPACE);
2816
+ const value = root.getAttributeNS(work_docx_opentype_export_MARKUP_COMPATIBILITY_NAMESPACE, 'Ignorable');
2817
+ const tokens = value?.trim().split(/\s+/).filter(Boolean) ?? [];
2818
+ if (!tokens.includes(word2010Prefix)) tokens.push(word2010Prefix);
2819
+ root.setAttributeNS(work_docx_opentype_export_MARKUP_COMPATIBILITY_NAMESPACE, `${prefix}:Ignorable`, tokens.join(' '));
2820
+ }
2821
+ function work_docx_opentype_export_wordValue(element) {
2822
+ const values = Array.from(element.attributes).filter((attribute)=>'val' === xmlAttributeLocalName(attribute) && DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(element, attribute) ?? ''));
2823
+ return 1 === values.length ? values[0].value : null;
2824
+ }
2825
+ function work_docx_opentype_export_setWordValue(element, value) {
2826
+ const namespace = element.namespaceURI ?? '';
2827
+ const prefix = element.prefix || 'w';
2828
+ for (const attribute of Array.from(element.attributes))if ('val' === xmlAttributeLocalName(attribute) && DOCX_WORDPROCESSING_NAMESPACES.has(xmlAttributeNamespace(element, attribute) ?? '')) element.removeAttributeNode(attribute);
2829
+ element.setAttributeNS(namespace, `${prefix}:val`, value);
2830
+ }
2663
2831
  const MAX_RUN_FORMATTING_CHANGE_PATCHES = 65536;
2664
2832
  const RUN_FORMATTING_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
2665
2833
  class DocxRunFormattingChangePatchCollector {
@@ -2805,6 +2973,11 @@ function appendFormattingProperties(document, properties, namespace, prefix, ser
2805
2973
  appendVerticalAlignProperty(document, properties, namespace, prefix, byType);
2806
2974
  appendEmphasisMarkProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2807
2975
  appendProofingLanguagesProperty(document, properties, namespace, prefix, byType.get('textStyle'));
2976
+ appendOpenTypeProperties(document, properties, byType.get('textStyle'));
2977
+ }
2978
+ function appendOpenTypeProperties(document, properties, mark) {
2979
+ const features = parseDocumentOpenTypeFeatures(mark?.attrs?.openTypeFeatures);
2980
+ if (features) appendDocxOpenTypeProperties(document, properties, features);
2808
2981
  }
2809
2982
  function appendNoProofProperty(document, properties, namespace, prefix, mark) {
2810
2983
  const noProof = normalizeDocumentNoProof(mark?.attrs?.noProof);
@@ -5271,12 +5444,12 @@ function work_docx_note_comment_hyperlink_relationships_removeNamespacedAttribut
5271
5444
  function setNamespacedAttribute(element, root, namespace, preferredPrefix, localName, value) {
5272
5445
  let prefix = xmlDeclaredPrefix(element, namespace) ?? xmlDeclaredPrefix(root, namespace);
5273
5446
  if (!prefix) {
5274
- prefix = availablePrefix(root, preferredPrefix);
5447
+ prefix = work_docx_note_comment_hyperlink_relationships_availablePrefix(root, preferredPrefix);
5275
5448
  root.setAttributeNS(work_docx_settings_xml_XMLNS_NAMESPACE, `xmlns:${prefix}`, namespace);
5276
5449
  }
5277
5450
  element.setAttributeNS(namespace, `${prefix}:${localName}`, value);
5278
5451
  }
5279
- function availablePrefix(root, preferred) {
5452
+ function work_docx_note_comment_hyperlink_relationships_availablePrefix(root, preferred) {
5280
5453
  if (!xmlNamespaceUri(root, preferred)) return preferred;
5281
5454
  let index = 1;
5282
5455
  while(xmlNamespaceUri(root, `${preferred}${index}`))index += 1;
@@ -8424,11 +8597,13 @@ async function createDocxBlob(content, sourcePackage) {
8424
8597
  runFontPatches: new DocxRunFontsPatchCollector(JSON.stringify(normalizedContent)),
8425
8598
  hiddenTextPatches: new DocxHiddenTextPatchCollector(JSON.stringify(normalizedContent)),
8426
8599
  legacyTextEffectsPatches: new DocxLegacyTextEffectsPatchCollector(JSON.stringify(normalizedContent)),
8600
+ openTypePatches: new DocxOpenTypePatchCollector(JSON.stringify(normalizedContent)),
8427
8601
  runBorderPatches: new DocxRunBorderPatchCollector(JSON.stringify(normalizedContent)),
8428
8602
  usedRunBorderMarkers: new Set(),
8429
8603
  runShadingPatches: new DocxRunShadingPatchCollector(JSON.stringify(normalizedContent)),
8430
8604
  usedRunShadingMarkers: new Set(),
8431
8605
  usedNativeTextEffectMarkers: new Set(),
8606
+ usedOpenTypeMarkers: new Set(),
8432
8607
  paragraphFormattingChangePatches: new DocxParagraphFormattingChangePatchCollector(),
8433
8608
  tableOfContentsPatches: new DocxTableOfContentsPatchCollector(),
8434
8609
  indexPatches: new DocxIndexPatchCollector(),
@@ -8483,7 +8658,8 @@ async function createDocxBlob(content, sourcePackage) {
8483
8658
  const characterSpacingPatched = noteContext.hasExplicitZeroCharacterSpacing ? await patchDocxExplicitZeroCharacterSpacing(await packed.arrayBuffer()) : await packed.arrayBuffer();
8484
8659
  const kerningPatched = noteContext.hasExplicitZeroKerningThreshold ? await patchDocxExplicitZeroKerningThresholds(characterSpacingPatched) : characterSpacingPatched;
8485
8660
  const runFontsPatched = await patchDocxRunFonts(kerningPatched, noteContext.runFontPatches.patches);
8486
- const hiddenTextPatched = await patchDocxHiddenText(runFontsPatched, noteContext.hiddenTextPatches.patches.filter((patch)=>noteContext.usedNativeTextEffectMarkers.has(patch.marker)));
8661
+ const openTypePatched = await patchDocxOpenTypeFeatures(runFontsPatched, noteContext.openTypePatches.patches.filter((patch)=>noteContext.usedOpenTypeMarkers.has(patch.marker)));
8662
+ const hiddenTextPatched = await patchDocxHiddenText(openTypePatched, noteContext.hiddenTextPatches.patches.filter((patch)=>noteContext.usedNativeTextEffectMarkers.has(patch.marker)));
8487
8663
  const legacyTextEffectsPatched = await patchDocxLegacyTextEffects(hiddenTextPatched, noteContext.legacyTextEffectsPatches.patches.filter((patch)=>noteContext.usedNativeTextEffectMarkers.has(patch.marker)));
8488
8664
  const runBordersPatched = await patchDocxRunBorders(legacyTextEffectsPatched, noteContext.runBorderPatches.patches.filter((patch)=>noteContext.usedRunBorderMarkers.has(patch.marker)));
8489
8665
  const runShadingPatched = await patchDocxRunShading(runBordersPatched, noteContext.runShadingPatches.patches.filter((patch)=>noteContext.usedRunShadingMarkers.has(patch.marker)));
@@ -8516,13 +8692,20 @@ async function createDocxBlob(content, sourcePackage) {
8516
8692
  type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
8517
8693
  });
8518
8694
  }
8519
- function docxNativeTextEffectState(style, context) {
8695
+ function docxRunStyleState(style, context) {
8520
8696
  let current = style;
8521
8697
  let hiddenText;
8698
+ let openTypeFeatures;
8522
8699
  const legacyTextEffects = {};
8523
8700
  const seen = new Set();
8524
8701
  while(current && !seen.has(current)){
8525
8702
  seen.add(current);
8703
+ const openTypePatch = context.openTypePatches.lookup(current);
8704
+ if (openTypePatch) {
8705
+ openTypeFeatures ??= openTypePatch.features;
8706
+ current = openTypePatch.style;
8707
+ continue;
8708
+ }
8526
8709
  const hiddenPatch = context.hiddenTextPatches.lookup(current);
8527
8710
  if (hiddenPatch) {
8528
8711
  hiddenText ??= hiddenPatch.value;
@@ -8547,14 +8730,23 @@ function docxNativeTextEffectState(style, context) {
8547
8730
  ...void 0 !== hiddenText ? {
8548
8731
  hiddenText
8549
8732
  } : {},
8733
+ ...openTypeFeatures ? {
8734
+ openTypeFeatures
8735
+ } : {},
8550
8736
  legacyTextEffects
8551
8737
  };
8552
8738
  }
8553
- function markDocxNativeTextEffectStyleUsed(style, context) {
8739
+ function markDocxRunStyleMarkersUsed(style, context) {
8554
8740
  let current = style;
8555
8741
  const seen = new Set();
8556
8742
  while(current && !seen.has(current)){
8557
8743
  seen.add(current);
8744
+ const openTypePatch = context.openTypePatches.lookup(current);
8745
+ if (openTypePatch) {
8746
+ context.usedOpenTypeMarkers.add(current);
8747
+ current = openTypePatch.style;
8748
+ continue;
8749
+ }
8558
8750
  const hiddenPatch = context.hiddenTextPatches.lookup(current);
8559
8751
  if (hiddenPatch) {
8560
8752
  context.usedNativeTextEffectMarkers.add(current);
@@ -8751,7 +8943,7 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8751
8943
  const visit = async (node, inherited = {}, revision)=>{
8752
8944
  if (node.nodeType === Node.TEXT_NODE) {
8753
8945
  if (!node.textContent) return [];
8754
- markDocxNativeTextEffectStyleUsed(inherited.style, noteContext);
8946
+ markDocxRunStyleMarkersUsed(inherited.style, noteContext);
8755
8947
  markDocxRunBorderUsed(inherited.border, noteContext);
8756
8948
  markDocxRunShadingUsed(inherited.shading, noteContext);
8757
8949
  if (revision?.kind === 'insertion') return [
@@ -8843,6 +9035,9 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8843
9035
  const hasExplicitNoProof = 'span' === tag && node.hasAttribute(DOCUMENT_NO_PROOF_ATTRIBUTE);
8844
9036
  const explicitNoProof = hasExplicitNoProof ? documentNoProofFromElement(node) : null;
8845
9037
  if (hasExplicitNoProof && null === explicitNoProof) throw new Error('Document contains invalid proofing state.');
9038
+ const hasExplicitOpenType = 'span' === tag && node.hasAttribute(DOCUMENT_OPEN_TYPE_ATTRIBUTE);
9039
+ const explicitOpenType = hasExplicitOpenType ? documentOpenTypeFeaturesFromElement(node) : null;
9040
+ if (hasExplicitOpenType && !explicitOpenType) throw new Error('Document contains invalid OpenType typography.');
8846
9041
  const hasExplicitLegacyTextEffects = 'span' === tag && [
8847
9042
  DOCUMENT_LEGACY_TEXT_OUTLINE_ATTRIBUTE,
8848
9043
  DOCUMENT_LEGACY_TEXT_SHADOW_ATTRIBUTE,
@@ -8863,18 +9058,20 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8863
9058
  const position = null === explicitCharacterPosition ? inherited.position : docxCharacterPositionValue(explicitCharacterPosition);
8864
9059
  const emphasisMark = null === explicitEmphasisMark ? inherited.emphasisMark : docxEmphasisMarkRunOptions(explicitEmphasisMark);
8865
9060
  const textCaseOptions = docxTextCaseRunOptions(explicitTextCase, inherited);
8866
- const inheritedNativeTextEffects = docxNativeTextEffectState(inherited.style, noteContext);
9061
+ const inheritedRunStyle = docxRunStyleState(inherited.style, noteContext);
8867
9062
  const legacyTextEffects = {
8868
- ...inheritedNativeTextEffects.legacyTextEffects,
9063
+ ...inheritedRunStyle.legacyTextEffects,
8869
9064
  ...explicitLegacyTextEffects ?? {}
8870
9065
  };
8871
9066
  if (documentLegacyTextEffectsConflict(legacyTextEffects)) throw new Error('Document contains conflicting legacy text effects.');
8872
- const hiddenText = null === explicitHiddenText ? inheritedNativeTextEffects.hiddenText : explicitHiddenText;
8873
- let nativeTextEffectStyle = inherited.style;
8874
- if (hasExplicitLegacyTextEffects || null !== explicitHiddenText) {
8875
- nativeTextEffectStyle = inheritedNativeTextEffects.baseStyle;
8876
- if (Object.keys(legacyTextEffects).length) nativeTextEffectStyle = noteContext.legacyTextEffectsPatches.marker(legacyTextEffects, nativeTextEffectStyle);
8877
- if (void 0 !== hiddenText) nativeTextEffectStyle = noteContext.hiddenTextPatches.marker(hiddenText, nativeTextEffectStyle);
9067
+ const hiddenText = null === explicitHiddenText ? inheritedRunStyle.hiddenText : explicitHiddenText;
9068
+ const openTypeFeatures = hasExplicitOpenType ? explicitOpenType ?? void 0 : inheritedRunStyle.openTypeFeatures;
9069
+ let runStyle = inherited.style;
9070
+ if (hasExplicitLegacyTextEffects || null !== explicitHiddenText || hasExplicitOpenType) {
9071
+ runStyle = inheritedRunStyle.baseStyle;
9072
+ if (Object.keys(legacyTextEffects).length) runStyle = noteContext.legacyTextEffectsPatches.marker(legacyTextEffects, runStyle);
9073
+ if (void 0 !== hiddenText) runStyle = noteContext.hiddenTextPatches.marker(hiddenText, runStyle);
9074
+ if (openTypeFeatures) runStyle = noteContext.openTypePatches.marker(openTypeFeatures, runStyle);
8878
9075
  }
8879
9076
  const underline = docxUnderlineRunOptions(node, inherited.underline, noteContext.themePatches);
8880
9077
  const strike = docxStrikeRunOptions(node, inherited);
@@ -8884,7 +9081,7 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8884
9081
  const noProof = hasExplicitNoProof ? explicitNoProof ?? false : inherited.noProof;
8885
9082
  const style = {
8886
9083
  ...inherited,
8887
- style: nativeTextEffectStyle,
9084
+ style: runStyle,
8888
9085
  bold: inherited.bold || 'strong' === tag || 'b' === tag,
8889
9086
  italics: inherited.italics || 'em' === tag || 'i' === tag,
8890
9087
  underline,
@@ -8913,7 +9110,7 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
8913
9110
  ...textCaseOptions
8914
9111
  };
8915
9112
  if ('br' === tag) {
8916
- markDocxNativeTextEffectStyleUsed(style.style, noteContext);
9113
+ markDocxRunStyleMarkersUsed(style.style, noteContext);
8917
9114
  markDocxRunBorderUsed(style.border, noteContext);
8918
9115
  markDocxRunShadingUsed(style.shading, noteContext);
8919
9116
  return [