ooxml-ui 0.31.0 → 1.1.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 (115) hide show
  1. package/README.md +16 -0
  2. package/custom-elements.json +10 -0
  3. package/dist/{chunk-OXKWNNNJ.js → chunk-3FPW7M6U.js} +1 -1
  4. package/dist/{chunk-XDUYS4KK.js → chunk-BEN3453I.js} +1 -1
  5. package/dist/{chunk-HZ422LTR.js → chunk-BOX43CZD.js} +1 -0
  6. package/dist/{chunk-3GE2NHNG.js → chunk-KVKKXRL7.js} +121 -83
  7. package/dist/{chunk-2QW4QE56.js → chunk-M5DTJSOV.js} +105 -70
  8. package/dist/{chunk-ZV2Z4IWH.js → chunk-USDLALB5.js} +4 -1
  9. package/dist/{chunk-RAZAJMHK.js → chunk-ZU7GX4SY.js} +4 -4
  10. package/dist/controls.js +4 -4
  11. package/dist/docx/hard-break-command.d.ts +1 -3
  12. package/dist/docx/link-commands.d.ts +4 -15
  13. package/dist/docx/localization-strings.d.ts +1 -1
  14. package/dist/docx/localization.d.ts +0 -1
  15. package/dist/docx/note-editor.d.ts +3 -2
  16. package/dist/docx/run-styles.d.ts +1 -1
  17. package/dist/docx/schema.d.ts +1 -1
  18. package/dist/docx/toggle-commands.d.ts +2 -8
  19. package/dist/docx.js +118 -321
  20. package/dist/form/gradient-direction-gallery.d.ts +19 -0
  21. package/dist/form/gradient-gallery-preview.d.ts +3 -0
  22. package/dist/form/gradient-preset-gallery.d.ts +16 -0
  23. package/dist/form/gradient-stop-track.d.ts +20 -0
  24. package/dist/form/number-range.d.ts +12 -0
  25. package/dist/icons.d.ts.map +1 -1
  26. package/dist/icons.js +1 -1
  27. package/dist/index.js +7 -7
  28. package/dist/menu/menu-button.d.ts +10 -0
  29. package/dist/menu/menu-button.d.ts.map +1 -1
  30. package/dist/pptx/{chart-3d-view-scene-IANLDFIE.mjs → chart-3d-view-scene-2KRQ5667.mjs} +2 -2
  31. package/dist/pptx/{chart-3d-view-scene-3DK5TUBZ.cjs → chart-3d-view-scene-36DMZWZ3.cjs} +37 -37
  32. package/dist/pptx/{chunk-C42ZL35K.mjs → chunk-ADOC5JLI.mjs} +1 -1
  33. package/dist/pptx/{chunk-QM4FGZG4.cjs → chunk-AIL3BNZS.cjs} +31 -131
  34. package/dist/pptx/{chunk-WLETAW3T.cjs → chunk-CJU4P5FT.cjs} +33 -13
  35. package/dist/pptx/{chunk-6SCK57RJ.cjs → chunk-KPZWYF44.cjs} +220 -342
  36. package/dist/pptx/{chunk-XQZWZMGZ.cjs → chunk-SM3CWDIQ.cjs} +7 -17
  37. package/dist/pptx/{chunk-JSBGBVBH.mjs → chunk-VRFNAF3Q.mjs} +7 -17
  38. package/dist/pptx/{chunk-EVGSFPUV.mjs → chunk-Y2W4SZER.mjs} +71 -202
  39. package/dist/pptx/{chunk-7JEMQW6R.mjs → chunk-YARCML7O.mjs} +11 -122
  40. package/dist/pptx/{chunk-OHE5UXST.cjs → chunk-YHA6XAB3.cjs} +1 -1
  41. package/dist/pptx/{chunk-X2F6PA2D.mjs → chunk-YOGDIDPB.mjs} +22 -3
  42. package/dist/pptx/dom/index.cjs +238 -238
  43. package/dist/pptx/dom/index.mjs +8 -8
  44. package/dist/pptx/export/html2canvas-clone.cjs +2 -2
  45. package/dist/pptx/export/html2canvas-clone.mjs +1 -1
  46. package/dist/pptx/i18n/index.cjs +6 -6
  47. package/dist/pptx/i18n/index.mjs +1 -1
  48. package/dist/pptx/i18n/translator.d.ts.map +1 -1
  49. package/dist/pptx/index.cjs +3006 -2990
  50. package/dist/pptx/index.mjs +5 -5
  51. package/dist/pptx/render/chart-combo-stock.cjs +3 -3
  52. package/dist/pptx/render/chart-combo-stock.mjs +1 -1
  53. package/dist/pptx/render/chart-manual-layout.d.ts +2 -20
  54. package/dist/pptx/render/chart-manual-layout.d.ts.map +1 -1
  55. package/dist/pptx/render/chart-overlays.cjs +7 -7
  56. package/dist/pptx/render/chart-overlays.mjs +1 -1
  57. package/dist/pptx/render/chart-surface-treemap.cjs +4 -4
  58. package/dist/pptx/render/chart-surface-treemap.mjs +1 -1
  59. package/dist/pptx/render/chart-svg-def-types.d.ts +6 -1
  60. package/dist/pptx/render/chart-svg-def-types.d.ts.map +1 -1
  61. package/dist/pptx/render/chart-view-model-dom-helpers.d.ts +1 -1
  62. package/dist/pptx/render/chart-view-model-dom-helpers.d.ts.map +1 -1
  63. package/dist/pptx/render/chart-view-model.cjs +41 -41
  64. package/dist/pptx/render/chart-view-model.mjs +1 -1
  65. package/dist/pptx/render/chart-waterfall-map.cjs +6 -6
  66. package/dist/pptx/render/chart-waterfall-map.mjs +1 -1
  67. package/dist/pptx/render/connector-elbow-geometry.d.ts +7 -43
  68. package/dist/pptx/render/connector-elbow-geometry.d.ts.map +1 -1
  69. package/dist/pptx/render/element-interaction.d.ts +1 -1
  70. package/dist/pptx/render/element-interaction.d.ts.map +1 -1
  71. package/dist/pptx/render/gradient-picker.d.ts.map +1 -1
  72. package/dist/pptx/render/index.d.ts +2 -0
  73. package/dist/pptx/render/index.d.ts.map +1 -1
  74. package/dist/pptx/render/path-gradient-rect.d.ts +1 -75
  75. package/dist/pptx/render/path-gradient-rect.d.ts.map +1 -1
  76. package/dist/pptx/render/rotate-handle-placement.d.ts +1 -27
  77. package/dist/pptx/render/rotate-handle-placement.d.ts.map +1 -1
  78. package/dist/pptx/render/rotation-drag.d.ts +1 -7
  79. package/dist/pptx/render/rotation-drag.d.ts.map +1 -1
  80. package/dist/pptx/render/viewer-root-options.d.ts +46 -0
  81. package/dist/pptx/render/viewer-root-options.d.ts.map +1 -0
  82. package/dist/pptx/web-components/registration-contract.d.ts.map +1 -1
  83. package/dist/presence.js +2 -2
  84. package/dist/registry.d.ts +2 -0
  85. package/dist/registry.d.ts.map +1 -1
  86. package/dist/smartart.js +2 -2
  87. package/dist/teams/app/files-panel.d.ts +8 -3
  88. package/dist/teams/app/teams-app.d.ts +1 -0
  89. package/dist/teams/app/teams-settings.d.ts +6 -0
  90. package/dist/teams.js +5 -5
  91. package/dist/visio/render-fill.d.ts +2 -1
  92. package/dist/visio/render-svg.d.ts +2 -0
  93. package/dist/visio/ribbon-action.d.ts +8 -1
  94. package/dist/visio/ribbon-parts.d.ts +2 -1
  95. package/dist/visio/ribbon-router.d.ts +4 -2
  96. package/dist/visio/viewer-commands.d.ts +3 -3
  97. package/dist/visio/viewer-draw-tool.d.ts +16 -6
  98. package/dist/visio/viewer-handle-events.d.ts +19 -0
  99. package/dist/visio/viewer-line-endpoints.d.ts +14 -0
  100. package/dist/visio/viewer-rotation-handle.d.ts +14 -0
  101. package/dist/visio/viewer-rotation-preview.d.ts +7 -0
  102. package/dist/visio.js +742 -90
  103. package/dist/xlsx/chart-area-pane.d.ts +9 -0
  104. package/dist/xlsx/chart-fill-binding.d.ts +23 -0
  105. package/dist/xlsx/chart-gradient-preview.d.ts +8 -0
  106. package/dist/xlsx/chart-series-fill.d.ts +2 -1
  107. package/dist/xlsx/chart-series-gradient-type.d.ts +9 -0
  108. package/dist/xlsx/chart-series-gradient.d.ts +8 -0
  109. package/dist/xlsx/chart-series-pane.d.ts +2 -1
  110. package/dist/xlsx/chart-series-range-preview.d.ts +7 -0
  111. package/dist/xlsx/chart-series-transparency.d.ts +2 -1
  112. package/dist/xlsx/grid/measure.d.ts +5 -0
  113. package/dist/xlsx/grid/styles.d.ts +1 -1
  114. package/dist/xlsx.js +965 -105
  115. package/package.json +3 -3
package/dist/docx.js CHANGED
@@ -1,13 +1,14 @@
1
- import { defineSmartArt } from './chunk-XDUYS4KK.js';
1
+ import { defineSmartArt } from './chunk-BEN3453I.js';
2
2
  import { shadcnBridge } from './chunk-X7RINDJQ.js';
3
- import { createRibbonOverflow, defineRibbon, defineDialog, defineSearchField, defineSwitch, defineTitleBar, defineBackstage, defineStatusBar, defineZoomSlider, defineContextMenu, runKeyTips, assignKeyTips } from './chunk-2QW4QE56.js';
4
- import { registerIcon } from './chunk-HZ422LTR.js';
5
- import './chunk-OXKWNNNJ.js';
6
- import './chunk-ZV2Z4IWH.js';
3
+ import { createRibbonOverflow, defineRibbon, defineDialog, defineSearchField, defineSwitch, defineTitleBar, defineBackstage, defineStatusBar, defineZoomSlider, defineContextMenu, runKeyTips, assignKeyTips } from './chunk-M5DTJSOV.js';
4
+ import { registerIcon } from './chunk-BOX43CZD.js';
5
+ import './chunk-3FPW7M6U.js';
6
+ import './chunk-USDLALB5.js';
7
7
  import './chunk-JFJXBYRD.js';
8
- import { resolveRunFormatting, createDocument, saveDocx, sectionsFromLayout, sectionLayoutJson, sectionsOf, pageSizeOf, columnPreset, applyPageSetup, withSection, computeListLabels, numberNotesInOrder, tocEntries, tableOfFiguresInstruction, findTableOfContents, ensureListDefinition, resolveNumberingLevel, equalColumnDraft, readColumnDraft, PAGE_SIZE_OPTIONS, PAGE_SIZES, readPageSetup, isRunHiddenForReview, resolveTableStyleFormatting, resolveParagraphFormatting, displayListLabel, setTitlePage, setLineNumbering, setVerticalAlign, setPageNumbering, ST_NumberFormat, unequalColumnPreset, setColumns, setOrientation, setPageSize, setMargins, lineSpacingLabel, formatNoteNumber, reviewDocumentFormatting, reviewFormattingWarnings, listRevisions, plainText, tocHyperlinks, DEFAULT_TOC_INSTRUCTION, tocBookmarks, buildTableOfContents, tocCaptionLabel, twips as twips$1, signedTwips, formatListNumber, columnTextWidth, validColumnDraft, validatePageSetup, presetOf, LIGATURE_VALUES, isLigatures, reviewRunFormatting, reviewParagraphFormatting, resolveThemeColorReference, lineSpacingValue, transformCase, DEFAULT_TABLE_BORDERS, parseLineSpacingValue, twipsAttr, twipsFromPixels, headingLevel, isValidLanguageTag, WORD, isHeadingListKind, fieldName, lineSpacingOptions, changeColumnWidth, changeColumnGap, createListDefinition, linkStylesToList, headingListLevels, documentStats } from 'ooxml-core/docx';
8
+ import { normalizeLocale, SUPPORTED_OFFICE_LOCALES, interpolate } from 'ooxml-core/i18n';
9
+ import { createDocument, saveDocx, sectionsFromLayout, sectionLayoutJson, sectionsOf, pageSizeOf, columnPreset, applyPageSetup, withSection, computeListLabels, numberNotesInOrder, tocEntries, tableOfFiguresInstruction, findTableOfContents, ensureListDefinition, resolveNumberingLevel, equalColumnDraft, readColumnDraft, PAGE_SIZE_OPTIONS, PAGE_SIZES, readPageSetup, isRunHiddenForReview, resolveTableStyleFormatting, resolveParagraphFormatting, displayListLabel, setTitlePage, setLineNumbering, setVerticalAlign, setPageNumbering, ST_NumberFormat, unequalColumnPreset, setColumns, setOrientation, setPageSize, setMargins, lineSpacingLabel, formatNoteNumber, reviewDocumentFormatting, reviewFormattingWarnings, listRevisions, plainText, tocHyperlinks, DEFAULT_TOC_INSTRUCTION, tocBookmarks, buildTableOfContents, tocCaptionLabel, isFieldLocked, twips as twips$1, signedTwips, formatListNumber, columnTextWidth, validColumnDraft, validatePageSetup, presetOf, LIGATURE_VALUES, isLigatures, reviewRunFormatting, resolveRunFormatting, reviewParagraphFormatting, resolveThemeColorReference, lineSpacingValue, isStHighlightColor, transformCase, DEFAULT_TABLE_BORDERS, parseLineSpacingValue, twipsAttr, twipsFromPixels, headingLevel, isValidLanguageTag, WORD, isHeadingListKind, fieldName, lineSpacingOptions, halfPointsFromPoints, changeColumnWidth, changeColumnGap, createListDefinition, linkStylesToList, headingListLevels, documentStats } from 'ooxml-core/docx';
9
10
  import { Schema, DOMSerializer, Fragment } from 'prosemirror-model';
10
- import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, tableCellStyle, tableStyle, expectDefined, paragraphBoxCss, themeToCssVars, lightTheme, darkTheme, appendInlineNode, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, restoreSectionParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, sectionPartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, countWords, fieldGuardPlugin, trackChangesPlugin, wordYjsPresencePlugin, placementClass, removeCommentAnchor, deleteComment, addComment, toggleTrackChanges, goToNextChange, goToPreviousChange, rejectAllChanges, acceptAllChanges, rejectChangeAtCursor, acceptChangeAtCursor, goToComment, sameJson, sameRuns, PARAGRAPH_KEEP_KEYS, paragraphFromAttrs, parseBordersJson, isNavigableHref, wordYjsPluginKey, setReviewRecordingPreferences, nodeNumbering, paragraphFormattingRevision, inlineNodeRun, formattingRevision, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, ligatureCss as ligatureCss$1, wordYjsRedo, wordYjsUndo, runToInlineNodes as runToInlineNodes$1, backstageFocus, wordHighlightColors, ligatureStyle, swatchColor, cssBorderSide, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
11
+ import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, hardBreakNodeSpec, commentHistoryAttributes, tableCellStyle, tableStyle, createToggleFormat, expectDefined, paragraphBoxCss, themeToCssVars, lightTheme, darkTheme, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, restoreSectionParts, commentThreadsFromDoc, restoreNoteParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, sectionPartsJson, NotePartsStep, notePartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, countWords, fieldGuardPlugin, trackChangesPlugin, wordYjsPresencePlugin, placementClass, removeCommentThread, removeCommentAnchor, deleteComment, updateCommentThreads, addComment, toggleTrackChanges, goToNextChange, goToPreviousChange, rejectAllChanges, acceptAllChanges, rejectChangeAtCursor, acceptChangeAtCursor, goToComment, appendInlineNode, sameJson, sameRuns, PARAGRAPH_KEEP_KEYS, paragraphFromAttrs, parseBordersJson, isNavigableHref, wordYjsPluginKey, setReviewRecordingPreferences, nodeNumbering, paragraphFormattingRevision, inlineNodeRun, formattingRevision, insertWordHardBreak, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, removeWordLink, fieldResultRanges, wordLinkRangeAt, ligatureCss as ligatureCss$1, wordYjsRedo, wordYjsUndo, runToInlineNodes as runToInlineNodes$1, backstageFocus, applyRunFormattingPatch, clearDirectRunFormatting, applyWordLink, ligatureStyle, wordHighlightColors, swatchColor, cssBorderSide, deleteFieldSelection, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
11
12
  export { CollaborationAuthority, CollaborationClient, RIBBON_ACTION_IDS, RIBBON_ACTION_LABELS, createCollaborationIdGenerator, darkTheme, isRibbonActionId, lightTheme, normalizeRibbonActions, repairCollaborativeDocumentIds, themeToCssVars } from 'ooxml-core/docx/ui';
12
13
  import { parseOmml, convertOmmlToLatex, convertOmmlToMathMl } from 'ooxml-core/math';
13
14
  import { PluginKey, EditorState, Plugin, NodeSelection, TextSelection, Selection } from 'prosemirror-state';
@@ -15,10 +16,10 @@ import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
15
16
  import { loadDocument } from 'ooxml-core/docx/load';
16
17
  import { closeHistory, undo, redo, history } from 'prosemirror-history';
17
18
  import { layoutDocumentModel, pageNumbers, createFakeMeasurer, ligatureCss, cssFontStack, pageNumberValues, sectionPageCounts, headerFooterForPage, tokenizeRun, paragraphFloats, floatPosition, placeTab, DEFAULT_FONT_SIZE_PT, fieldDisplayText } from 'ooxml-core/docx/layout';
18
- import { chainCommands, baseKeymap, toggleMark, selectAll, deleteSelection } from 'prosemirror-commands';
19
19
  import { sendableSteps, getVersion } from 'prosemirror-collab';
20
20
  import { sanitizeColor, sanitizeUserName, SequenceTracker, isValidId, classifyVersion, validateDisplayName } from 'ooxml-core/collab';
21
21
  import { keymap } from 'prosemirror-keymap';
22
+ import { chainCommands, baseKeymap, selectAll } from 'prosemirror-commands';
22
23
 
23
24
  // src/docx/locales/columns.ts
24
25
  var enColumns = {
@@ -3949,30 +3950,17 @@ var zhCN = {
3949
3950
 
3950
3951
  // src/docx/localization-strings.ts
3951
3952
  var strings = { en, fr, de, es, "zh-CN": zhCN };
3952
- var EDITOR_LOCALES = ["en", "fr", "de", "es", "zh-CN"];
3953
+ var EDITOR_LOCALES = SUPPORTED_OFFICE_LOCALES;
3953
3954
 
3954
3955
  // src/docx/localization.ts
3955
3956
  function normalizeEditorLocale(value) {
3956
- const parts = (value ?? "").trim().toLowerCase().split(/[-_]/);
3957
- switch (parts[0]) {
3958
- case "fr":
3959
- case "de":
3960
- case "es":
3961
- return parts[0];
3962
- case "zh":
3963
- return parts.some((part) => ["hant", "tw", "hk", "mo"].includes(part)) ? "en" : "zh-CN";
3964
- default:
3965
- return "en";
3966
- }
3957
+ return normalizeLocale(value, EDITOR_LOCALES, "en");
3967
3958
  }
3968
3959
  function translate(locale, key2) {
3969
3960
  return strings[locale][key2] ?? strings.en[key2] ?? key2;
3970
3961
  }
3971
3962
  function translateTemplate(locale, key2, values2) {
3972
- return translate(locale, key2).replace(
3973
- /\{(\w+)\}/g,
3974
- (match, name) => name in values2 ? String(values2[name]) : match
3975
- );
3963
+ return interpolate(translate(locale, key2), values2);
3976
3964
  }
3977
3965
  function translateDynamic(locale, text) {
3978
3966
  if (locale === "en") return text;
@@ -4182,7 +4170,9 @@ var schema = new Schema({
4182
4170
  endnoteNumFmt: { default: null },
4183
4171
  /** Section layout (no header/footer content) as JSON, so page setup is undoable. */
4184
4172
  sections: { default: null },
4185
- sectionParts: { default: null }
4173
+ sectionParts: { default: null },
4174
+ noteParts: { default: null },
4175
+ ...commentHistoryAttributes
4186
4176
  }
4187
4177
  },
4188
4178
  paragraph: {
@@ -4282,15 +4272,7 @@ var schema = new Schema({
4282
4272
  ]
4283
4273
  },
4284
4274
  text: { group: "inline" },
4285
- hardBreak: {
4286
- group: "inline",
4287
- inline: true,
4288
- atom: true,
4289
- selectable: false,
4290
- leafText: () => "\n",
4291
- parseDOM: [{ tag: "br" }],
4292
- toDOM: () => ["br"]
4293
- },
4275
+ hardBreak: hardBreakNodeSpec,
4294
4276
  pageBreak: pageBreakNodeSpec,
4295
4277
  noteReference: noteReferenceNodeSpec,
4296
4278
  fieldMarker: fieldMarkerNodeSpec,
@@ -4634,6 +4616,8 @@ function modelToDoc(model) {
4634
4616
  marginLeft: model.page.marginLeft,
4635
4617
  sections: model.sections ? sectionLayoutJson(model.sections) : null,
4636
4618
  sectionParts: sectionPartsJson(model.sections),
4619
+ noteParts: notePartsJson(model),
4620
+ commentThreads: JSON.stringify(model.comments ?? []),
4637
4621
  evenAndOddHeaders: Boolean(model.evenAndOddHeaders),
4638
4622
  trackChanges: Boolean(model.trackChanges),
4639
4623
  trackFormatting: model.trackFormatting !== false,
@@ -4722,6 +4706,9 @@ function docToModel(doc, prior) {
4722
4706
  });
4723
4707
  const {
4724
4708
  sections: priorSections,
4709
+ footnotes: priorFootnotes,
4710
+ endnotes: priorEndnotes,
4711
+ comments: priorComments,
4725
4712
  evenAndOddHeaders: _evenOdd,
4726
4713
  trackChanges: _trackChanges,
4727
4714
  trackFormatting: _trackFormatting,
@@ -4732,8 +4719,14 @@ function docToModel(doc, prior) {
4732
4719
  } = prior;
4733
4720
  const sectionLayout = typeof doc.attrs.sections === "string" ? sectionsFromLayout(doc.attrs.sections, priorSections, blocks) : keepHeaderFooterSections(priorSections, blocks, doc).sections;
4734
4721
  const sections = typeof doc.attrs.sectionParts === "string" && sectionLayout ? restoreSectionParts(sectionLayout, doc.attrs.sectionParts, blocks) : sectionLayout;
4722
+ const threads = commentThreadsFromDoc(doc);
4735
4723
  return {
4736
4724
  ...rest,
4725
+ ...threads === void 0 ? priorComments !== void 0 ? { comments: priorComments } : {} : threads.length ? { comments: threads } : {},
4726
+ ...restoreNoteParts(doc.attrs.noteParts, {
4727
+ ...priorFootnotes ? { footnotes: priorFootnotes } : {},
4728
+ ...priorEndnotes ? { endnotes: priorEndnotes } : {}
4729
+ }),
4737
4730
  blocks,
4738
4731
  ...doc.attrs.evenAndOddHeaders ? { evenAndOddHeaders: true } : {},
4739
4732
  trackChanges: Boolean(doc.attrs.trackChanges),
@@ -7776,7 +7769,7 @@ function runStylesPlugin(getModel, getMode = () => "all") {
7776
7769
  const paragraphStyleId = displayParagraph(paragraph2, mode).value.style;
7777
7770
  let hasScale = false;
7778
7771
  paragraph2.forEach((child, offset) => {
7779
- if (!child.isText) return;
7772
+ if (!child.isInline || child.type.name === "equation") return;
7780
7773
  const current2 = runOf(child);
7781
7774
  if (!current2) return;
7782
7775
  const projected = reviewRunFormatting(current2, mode);
@@ -7794,6 +7787,18 @@ function runStylesPlugin(getModel, getMode = () => "all") {
7794
7787
  ...projected.error ? { "data-review-format-error": projected.error } : {}
7795
7788
  } : {};
7796
7789
  const hidden = resolved.vanish === true;
7790
+ if (!child.isText) {
7791
+ decorations2.push(
7792
+ Decoration.node(start + offset, start + offset + child.nodeSize, {
7793
+ style: `${runFormattingCss(resolved, model.theme)};${reviewRunCss(resolved)}`,
7794
+ ...run.language ? { lang: run.language } : {},
7795
+ ...run.rtl !== void 0 ? { dir: run.rtl ? "rtl" : "ltr" } : {},
7796
+ ...projected.error ? { "data-review-format-error": projected.error } : {},
7797
+ ...hidden ? { class: "dve-hidden-text" } : {}
7798
+ })
7799
+ );
7800
+ return;
7801
+ }
7797
7802
  const segments = scaledSegments(
7798
7803
  child.text,
7799
7804
  resolved,
@@ -7878,8 +7883,8 @@ function effectiveFont(state, text, paragraph2) {
7878
7883
  if (!run || !model) {
7879
7884
  const font = text.marks.find((mark) => mark.type === schema.marks.font);
7880
7885
  return {
7881
- family: String(font?.attrs.family ?? DEFAULT_FAMILY),
7882
- size: Number(font?.attrs.size ?? DEFAULT_SIZE)
7886
+ family: String(run?.fontFamily ?? font?.attrs.family ?? DEFAULT_FAMILY),
7887
+ size: Number(run?.fontSize ?? font?.attrs.size ?? DEFAULT_SIZE)
7883
7888
  };
7884
7889
  }
7885
7890
  const resolved = resolveRunFormatting(run, {
@@ -7907,7 +7912,7 @@ function syncFontControls(toolbar, state) {
7907
7912
  } else {
7908
7913
  let found = false;
7909
7914
  doc.nodesBetween(selection.from, selection.to, (node, _pos, parent) => {
7910
- if (!node.isText || !parent) return;
7915
+ if (!node.isInline || node.type.name === "equation" || !parent) return;
7911
7916
  found = true;
7912
7917
  add(node, parent);
7913
7918
  });
@@ -7933,7 +7938,7 @@ function selectionScript(state) {
7933
7938
  };
7934
7939
  if (!state.selection.empty)
7935
7940
  state.doc.nodesBetween(state.selection.from, state.selection.to, (node, _pos, parent) => {
7936
- if (node.isText && parent) add(node, parent);
7941
+ if (node.isInline && node.type.name !== "equation" && parent) add(node, parent);
7937
7942
  });
7938
7943
  if (!values2.size)
7939
7944
  add(
@@ -7942,62 +7947,26 @@ function selectionScript(state) {
7942
7947
  );
7943
7948
  return values2.size === 1 ? [...values2][0] : null;
7944
7949
  }
7945
-
7946
- // src/docx/inline-commands.ts
7947
- function setInlineMark(view, type, attrs) {
7948
- if (!view.editable) return;
7949
- const { state } = view;
7950
- const { from: from2, to, empty } = state.selection;
7951
- const mark = attrs ? type.create(attrs) : void 0;
7952
- if (empty) {
7953
- const marks2 = (state.storedMarks ?? state.selection.$from.marks()).filter(
7954
- (item) => item.type !== type
7955
- );
7956
- view.dispatch(state.tr.setStoredMarks(mark ? [...marks2, mark] : marks2));
7957
- } else {
7958
- const transaction = state.tr.removeMark(from2, to, type);
7959
- view.dispatch(mark ? transaction.addMark(from2, to, mark) : transaction);
7960
- }
7961
- }
7962
7950
  function applyHighlight(view, color) {
7963
- if (color !== "none" && !Object.hasOwn(wordHighlightColors, color)) return;
7964
- setInlineMark(view, schema.marks.highlight, color === "none" ? void 0 : { color });
7951
+ if (!isStHighlightColor(color)) return;
7952
+ applyRunFormattingPatch({ highlight: color === "none" ? void 0 : color })(
7953
+ view.state,
7954
+ view.dispatch,
7955
+ view
7956
+ );
7965
7957
  }
7966
7958
  function toggleVerticalAlign(view, value) {
7967
7959
  applyVerticalAlign(view, selectionScript(view.state) === value ? "baseline" : value);
7968
7960
  }
7969
7961
  function applyVerticalAlign(view, value) {
7970
- setInlineMark(view, schema.marks.verticalAlign, { value });
7962
+ applyRunFormattingPatch({ verticalAlign: value })(view.state, view.dispatch, view);
7971
7963
  }
7972
7964
  function applyFont(view, key2, value) {
7973
- const attr = key2 === "family" ? "family" : key2 === "size" ? "size" : "color";
7974
- const mark = schema.marks.font;
7975
- const nextValue = key2 === "size" ? Number(value) : value;
7976
- const { state } = view;
7977
- if (state.selection.empty) {
7978
- const marks2 = state.storedMarks || state.selection.$from.marks();
7979
- const existing = marks2.find((item) => item.type === mark);
7980
- const type = mark.create({ ...existing?.attrs, [attr]: nextValue });
7981
- view.dispatch(state.tr.setStoredMarks([...marks2.filter((item) => item.type !== mark), type]));
7982
- return;
7983
- }
7984
- let transaction = state.tr;
7985
- state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
7986
- if (!node.isText) return;
7987
- const start = Math.max(pos, state.selection.from);
7988
- const end = Math.min(pos + node.nodeSize, state.selection.to);
7989
- const existing = node.marks.find((item) => item.type === mark);
7990
- const type = mark.create({ ...existing?.attrs, [attr]: nextValue });
7991
- transaction = transaction.removeMark(start, end, mark).addMark(start, end, type);
7992
- });
7993
- view.dispatch(transaction);
7965
+ const patch = key2 === "family" ? { fontFamily: value } : key2 === "size" ? { fontSize: Number(value) } : { color: value };
7966
+ applyRunFormattingPatch(patch)(view.state, view.dispatch, view);
7994
7967
  }
7995
7968
  function clearFormatting(view) {
7996
- const { state } = view;
7997
- let transaction = state.tr;
7998
- for (const mark of Object.values(schema.marks))
7999
- transaction = transaction.removeMark(state.selection.from, state.selection.to, mark);
8000
- view.dispatch(transaction.setStoredMarks([]));
7969
+ clearDirectRunFormatting(view.state, view.dispatch, view);
8001
7970
  }
8002
7971
  var tableId = 0;
8003
7972
  var MAX_TABLE_ROWS = 100;
@@ -8089,84 +8058,7 @@ function applyPageStyles(paper, model, zoom) {
8089
8058
  else paper.style.removeProperty("--dve-page-color");
8090
8059
  paper.style.hyphens = model.autoHyphenation ? "auto" : "";
8091
8060
  }
8092
- function selectedText(state) {
8093
- const pieces = [];
8094
- const { from: from2, to } = state.selection;
8095
- state.doc.nodesBetween(from2, to, (node, pos, parent) => {
8096
- if (!node.isText) return true;
8097
- pieces.push({
8098
- from: Math.max(pos, from2),
8099
- to: Math.min(pos + node.nodeSize, to),
8100
- node,
8101
- paragraphStyle: parent?.attrs.style || void 0
8102
- });
8103
- return false;
8104
- });
8105
- return pieces;
8106
- }
8107
- function isOn(state, piece, key2) {
8108
- const runs = [];
8109
- appendInlineNode(runs, piece.node);
8110
- const run = runs[0];
8111
- if (!run) return false;
8112
- if (run[key2] !== void 0) return Boolean(run[key2]);
8113
- const model = styleModelOf(state);
8114
- if (!model) return false;
8115
- return Boolean(
8116
- resolveRunFormatting(run, {
8117
- runCatalog: model.characterStyles,
8118
- paragraphCatalog: model.paragraphStyles,
8119
- paragraphStyleId: piece.paragraphStyle
8120
- })[key2]
8121
- );
8122
- }
8123
- function setExplicitOff(tr, piece, key2, off) {
8124
- const type = schema.marks.runProperties;
8125
- const current2 = type.isInSet(piece.node.marks);
8126
- const props = { ...current2?.attrs.props ?? {} };
8127
- if (off) props[key2] = false;
8128
- else delete props[key2];
8129
- tr.removeMark(piece.from, piece.to, type);
8130
- if (Object.keys(props).length) tr.addMark(piece.from, piece.to, type.create({ props }));
8131
- }
8132
- function toggleFormat(key2) {
8133
- const markType = schema.marks[key2];
8134
- const plain = toggleMark(markType);
8135
- return (state, dispatch) => {
8136
- if (state.selection.empty) return plain(state, dispatch);
8137
- const pieces = selectedText(state);
8138
- if (!pieces.length) return plain(state, dispatch);
8139
- const allOn = pieces.every((piece) => isOn(state, piece, key2));
8140
- if (!dispatch) return true;
8141
- const tr = state.tr;
8142
- for (const piece of pieces) {
8143
- if (allOn) {
8144
- tr.removeMark(piece.from, piece.to, markType);
8145
- const withoutMark2 = {
8146
- ...piece,
8147
- node: piece.node.mark(markType.removeFromSet(piece.node.marks))
8148
- };
8149
- setExplicitOff(tr, withoutMark2, key2, false);
8150
- const inherited = isOn(
8151
- state,
8152
- {
8153
- ...withoutMark2,
8154
- node: withoutMark2.node.mark(
8155
- schema.marks.runProperties.removeFromSet(withoutMark2.node.marks)
8156
- )
8157
- },
8158
- key2
8159
- );
8160
- if (inherited) setExplicitOff(tr, withoutMark2, key2, true);
8161
- } else {
8162
- setExplicitOff(tr, piece, key2, false);
8163
- tr.addMark(piece.from, piece.to, markType.create());
8164
- }
8165
- }
8166
- dispatch(tr.scrollIntoView());
8167
- return true;
8168
- };
8169
- }
8061
+ var toggleFormat = createToggleFormat(schema, styleModelOf);
8170
8062
 
8171
8063
  // src/docx/font-format-batch.ts
8172
8064
  function batchFontFormat(view, apply) {
@@ -8190,8 +8082,6 @@ function batchFontFormat(view, apply) {
8190
8082
  if (scroll) combined.scrollIntoView();
8191
8083
  if (combined.steps.length || combined.storedMarksSet) view.dispatch(combined);
8192
8084
  }
8193
-
8194
- // src/docx/font-format.ts
8195
8085
  var FIELDS = [
8196
8086
  "family",
8197
8087
  "size",
@@ -8259,7 +8149,8 @@ function formatsOf(state) {
8259
8149
  formats.push(formatOf(state, schema.text("x", marks2), selection.$from.parent));
8260
8150
  } else {
8261
8151
  doc.nodesBetween(selection.from, selection.to, (node, _pos, parent) => {
8262
- if (node.isText && parent) formats.push(formatOf(state, node, parent));
8152
+ if (node.isInline && node.type.name !== "equation" && parent)
8153
+ formats.push(formatOf(state, node, parent));
8263
8154
  });
8264
8155
  if (!formats.length)
8265
8156
  formats.push(
@@ -8291,33 +8182,7 @@ function setToggle(view, key2, desired) {
8291
8182
  }
8292
8183
  }
8293
8184
  function patchExtraProps(view, patch) {
8294
- const type = schema.marks.runProperties;
8295
- const next = (marks2) => {
8296
- const existing = type.isInSet(marks2);
8297
- const props = { ...existing?.attrs.props ?? {} };
8298
- for (const [key2, value] of Object.entries(patch))
8299
- if (value === void 0) delete props[key2];
8300
- else props[key2] = value;
8301
- const others = marks2.filter((mark) => mark.type !== type);
8302
- return Object.keys(props).length ? [...others, type.create({ props })] : others;
8303
- };
8304
- const { state } = view;
8305
- if (state.selection.empty) {
8306
- view.dispatch(
8307
- state.tr.setStoredMarks(next(state.storedMarks ?? state.selection.$from.marks()))
8308
- );
8309
- return;
8310
- }
8311
- const tr = state.tr;
8312
- state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
8313
- if (!node.isText) return;
8314
- const from2 = Math.max(pos, state.selection.from);
8315
- const to = Math.min(pos + node.nodeSize, state.selection.to);
8316
- tr.removeMark(from2, to, type);
8317
- const wanted = type.isInSet(next(node.marks));
8318
- if (wanted) tr.addMark(from2, to, wanted);
8319
- });
8320
- view.dispatch(tr);
8185
+ applyRunFormattingPatch(patch)(view.state, view.dispatch, view);
8321
8186
  }
8322
8187
  function applyFontFormat(view, changes) {
8323
8188
  if (!view.editable) return;
@@ -8350,14 +8215,14 @@ function applyFontFields(view, changes) {
8350
8215
  if (changes.smallCaps !== void 0) extras.smallCaps = changes.smallCaps;
8351
8216
  if (changes.caps !== void 0) extras.caps = changes.caps;
8352
8217
  if (changes.hidden !== void 0) extras.vanish = changes.hidden;
8353
- if (changes.spacing !== void 0)
8354
- extras.characterSpacingTwips = Math.round(changes.spacing * 20);
8218
+ if (changes.spacing !== void 0 && Number.isFinite(changes.spacing))
8219
+ extras.characterSpacingTwips = signedTwips(Math.round(changes.spacing * 20));
8355
8220
  if (changes.scale !== void 0 && Number.isInteger(changes.scale) && changes.scale >= 0 && changes.scale <= 600)
8356
8221
  extras.textScalePercent = changes.scale;
8357
8222
  if (changes.position !== void 0 && Number.isFinite(changes.position))
8358
- extras.positionHalfPoints = Math.sign(changes.position) * Math.round(Math.abs(changes.position) * 2);
8223
+ extras.positionHalfPoints = halfPointsFromPoints(changes.position);
8359
8224
  if (changes.kerning !== void 0 && Number.isFinite(changes.kerning) && changes.kerning >= 0)
8360
- extras.kerningHalfPoints = Math.round(changes.kerning * 2);
8225
+ extras.kerningHalfPoints = halfPointsFromPoints(changes.kerning);
8361
8226
  if (Object.keys(extras).length) patchExtraProps(view, extras);
8362
8227
  }
8363
8228
 
@@ -9876,32 +9741,6 @@ var REFERENCE = /^\s*(REF|PAGEREF)\s+("[^"]+"|\S+)(.*)$/i;
9876
9741
  function plainSwitches(rest) {
9877
9742
  return !/\\/.test(rest.replace(/\\h\b/gi, "").replace(/\\\*\s+\S+/g, ""));
9878
9743
  }
9879
- function fieldRuns(doc) {
9880
- const runs = [];
9881
- doc.descendants((node, pos) => {
9882
- if (node.type.name !== "paragraph") return true;
9883
- let open;
9884
- node.forEach((child, offset) => {
9885
- const mark = child.isText ? child.marks.find((item) => item.type === schema.marks.field) : void 0;
9886
- const start = pos + 1 + offset;
9887
- if (mark && open?.mark.eq(mark)) {
9888
- open.to = start + child.nodeSize;
9889
- open.text += child.text ?? "";
9890
- } else if (mark) {
9891
- open = {
9892
- from: start,
9893
- to: start + child.nodeSize,
9894
- mark,
9895
- text: child.text ?? "",
9896
- marks: child.marks
9897
- };
9898
- runs.push(open);
9899
- } else open = void 0;
9900
- });
9901
- return false;
9902
- });
9903
- return runs;
9904
- }
9905
9744
  function bookmarkTargets(doc) {
9906
9745
  const targets = /* @__PURE__ */ new Map();
9907
9746
  doc.descendants((node) => {
@@ -9930,12 +9769,13 @@ function updateFields(view, pageOf) {
9930
9769
  }
9931
9770
  function refreshFieldResults(tr, pageOf, captionsOnly = false) {
9932
9771
  for (const label of new Set(
9933
- fieldRuns(tr.doc).map((run) => seqLabelOf(schema.text("x", [run.mark]))).filter((label2) => label2 !== void 0).map((label2) => label2.toLowerCase())
9772
+ fieldResultRanges(tr.doc).map((run) => seqLabelOf(schema.text("x", [run.mark]))).filter((label2) => label2 !== void 0).map((label2) => label2.toLowerCase())
9934
9773
  ))
9935
9774
  renumberCaptions(tr, label);
9936
9775
  const targets = bookmarkTargets(tr.doc);
9937
9776
  const changes = [];
9938
- for (const run of fieldRuns(tr.doc)) {
9777
+ for (const run of fieldResultRanges(tr.doc)) {
9778
+ if (isFieldLocked(inlineNodeRun(schema.text("x", run.marks)))) continue;
9939
9779
  const match = REFERENCE.exec(String(run.mark.attrs.instr ?? ""));
9940
9780
  if (!match || !plainSwitches(match[3] ?? "")) continue;
9941
9781
  const target = targets.get((match[2] ?? "").replace(/^"|"$/g, ""));
@@ -9971,6 +9811,7 @@ function renumberCaptions(tr, label) {
9971
9811
  });
9972
9812
  for (let index = fields.length - 1; index >= 0; index--) {
9973
9813
  const { from: from2, to, node } = fields[index];
9814
+ if (isFieldLocked(inlineNodeRun(node))) continue;
9974
9815
  if (node.text !== String(index + 1))
9975
9816
  tr.replaceWith(from2, to, schema.text(String(index + 1), node.marks));
9976
9817
  }
@@ -14667,23 +14508,15 @@ function refreshStoryPreviews(model, sectionIndex, elements, mode, decorate) {
14667
14508
  slot2.querySelector(".dve-header-footer-body"),
14668
14509
  effectiveHeaderFooter(model, sectionIndex, kind, slot2.dataset.slot)?.blocks
14669
14510
  );
14670
- const notes = [...model.footnotes ?? [], ...model.endnotes ?? []];
14671
- for (const item of elements.notes?.querySelectorAll("[data-docx-note-id]") ?? [])
14511
+ for (const item of elements.notes?.querySelectorAll("[data-docx-note-id]") ?? []) {
14512
+ const notes = item.dataset.docxNoteKind === "endnote" ? model.endnotes : model.footnotes;
14672
14513
  refresh(
14673
14514
  item.querySelector(".dve-note-body"),
14674
- notes.find((note) => note.id === item.dataset.docxNoteId)?.blocks
14515
+ notes?.find((note) => note.id === item.dataset.docxNoteId)?.blocks
14675
14516
  );
14517
+ }
14676
14518
  }
14677
14519
 
14678
- // src/docx/hard-break-command.ts
14679
- var insertHardBreak = (state, dispatch, view) => {
14680
- if (view && !view.editable) return false;
14681
- if (!dispatch) return true;
14682
- const transaction = state.tr.replaceSelectionWith(schema.nodes.hardBreak.create(), true).scrollIntoView();
14683
- dispatch(transaction);
14684
- return true;
14685
- };
14686
-
14687
14520
  // src/docx/page-break-command.ts
14688
14521
  function insertBreakCommand(kind) {
14689
14522
  return (state, dispatch, view) => {
@@ -14820,7 +14653,7 @@ var editorBindings = {
14820
14653
  "Mod-b": marks.bold,
14821
14654
  "Mod-i": marks.italic,
14822
14655
  "Mod-u": marks.underline,
14823
- "Shift-Enter": insertHardBreak,
14656
+ "Shift-Enter": insertWordHardBreak,
14824
14657
  Enter: chainCommands(
14825
14658
  exitListOnEmptyEnter,
14826
14659
  expectDefined(baseKeymap.Enter, "the base Enter command")
@@ -14998,6 +14831,7 @@ function noteList(notes, kind, numFmt, blocks, model) {
14998
14831
  for (const { note, number } of numbered) {
14999
14832
  const item = document.createElement("li");
15000
14833
  item.dataset.docxNoteId = note.id;
14834
+ item.dataset.docxNoteKind = kind;
15001
14835
  item.value = number;
15002
14836
  const marker = document.createElement("span");
15003
14837
  marker.className = "dve-note-marker";
@@ -15071,19 +14905,21 @@ function withMark(blocks, mark) {
15071
14905
  function attachNoteEditing(root, options) {
15072
14906
  for (const item of root.querySelectorAll("li[data-docx-note-id]")) {
15073
14907
  const id = item.dataset.docxNoteId;
14908
+ const kind = item.dataset.docxNoteKind;
14909
+ if (kind !== "footnote" && kind !== "endnote") continue;
15074
14910
  const body = item.querySelector(".dve-note-body");
15075
14911
  if (!body) continue;
15076
14912
  item.title = translateUiText(root, "Double-click to edit");
15077
14913
  item.addEventListener("dblclick", () => {
15078
14914
  if (!options.editable() || item.classList.contains("dve-header-footer-editing")) return;
15079
- const note = options.note(id);
14915
+ const note = options.note(kind, id);
15080
14916
  if (!note) return;
15081
14917
  const { editable: editable2, mark } = withoutMark(note.blocks);
15082
14918
  openBlocksEditor(
15083
14919
  item,
15084
14920
  body,
15085
14921
  editable2,
15086
- (blocks) => options.change(id, withMark(blocks, mark)),
14922
+ (blocks) => options.change(kind, id, withMark(blocks, mark)),
15087
14923
  options.editor
15088
14924
  );
15089
14925
  });
@@ -15125,7 +14961,9 @@ function insertNote(view, model, kind) {
15125
14961
  number: 1,
15126
14962
  format: JSON.stringify(formatting)
15127
14963
  });
15128
- view.dispatch(view.state.tr.replaceSelectionWith(reference, false).scrollIntoView());
14964
+ view.dispatch(
14965
+ view.state.tr.replaceSelectionWith(reference, false).setDocAttribute("noteParts", notePartsJson(next)).scrollIntoView()
14966
+ );
15129
14967
  return { model: next, id };
15130
14968
  }
15131
14969
  function noteNumberingPlugin() {
@@ -15354,13 +15192,13 @@ var PartsController = class {
15354
15192
  });
15355
15193
  if (this.notesEl)
15356
15194
  attachNoteEditing(this.notesEl, {
15357
- note: (id) => {
15195
+ note: (kind, id) => {
15358
15196
  const current2 = this.host.model();
15359
- return [...current2.footnotes ?? [], ...current2.endnotes ?? []].find(
15197
+ return current2[kind === "footnote" ? "footnotes" : "endnotes"]?.find(
15360
15198
  (note) => note.id === id
15361
15199
  );
15362
15200
  },
15363
- change: (id, blocks) => this.updateNote(id, blocks),
15201
+ change: (kind, id, blocks) => this.updateNote(kind, id, blocks),
15364
15202
  editable: editable2,
15365
15203
  editor: this.editorOptions()
15366
15204
  });
@@ -15389,9 +15227,7 @@ var PartsController = class {
15389
15227
  insertNote(kind, canvas, paper) {
15390
15228
  const view = this.host.view();
15391
15229
  if (!view?.editable || !this.host.canEditOutsideBody()) return;
15392
- const { model, id } = insertNote(view, this.host.model(), kind);
15393
- const key2 = kind === "footnote" ? "footnotes" : "endnotes";
15394
- this.host.setModel({ ...this.host.model(), [key2]: model[key2] });
15230
+ const { id } = insertNote(view, this.host.model(), kind);
15395
15231
  this.render(canvas, paper);
15396
15232
  const item = this.notesEl?.querySelector(
15397
15233
  `.dve-notes-${kind} li[data-docx-note-id="${id}"]`
@@ -15401,15 +15237,19 @@ var PartsController = class {
15401
15237
  this.host.edited();
15402
15238
  }
15403
15239
  /** Replaces one footnote's or endnote's blocks. */
15404
- updateNote(id, blocks) {
15240
+ updateNote(kind, id, blocks) {
15241
+ const view = this.host.view();
15242
+ if (!view?.editable || !this.host.canEditOutsideBody()) return;
15405
15243
  const replace = (notes) => notes.map((note) => note.id === id ? { ...note, blocks: structuredClone(blocks) } : note);
15406
15244
  const model = this.host.model();
15407
- this.host.setModel({
15245
+ const key2 = kind === "footnote" ? "footnotes" : "endnotes";
15246
+ const next = {
15408
15247
  ...model,
15409
- ...model.footnotes && { footnotes: replace(model.footnotes) },
15410
- ...model.endnotes && { endnotes: replace(model.endnotes) }
15411
- });
15412
- this.host.edited();
15248
+ ...model[key2] && { [key2]: replace(model[key2]) }
15249
+ };
15250
+ view.dispatch(
15251
+ view.state.tr.step(new NotePartsStep(notePartsJson(next))).setMeta(HEADER_FOOTER_INPUT, true)
15252
+ );
15413
15253
  }
15414
15254
  /** Applies header/footer edits to every section slot that shares the edited part. */
15415
15255
  updateHeaderFooter(kind, slot2, blocks) {
@@ -15781,28 +15621,7 @@ var PageController = class {
15781
15621
  this.host.printLayout()?.print(this.host.model(), (message) => emit(this.host.element, "document-warning", message));
15782
15622
  }
15783
15623
  };
15784
- function linkRangeAt(view, pos) {
15785
- const $pos = view.state.doc.resolve(pos);
15786
- const items = [];
15787
- let cursor = $pos.start();
15788
- $pos.parent.forEach((child) => {
15789
- const link = child.marks.find((item) => item.type === schema.marks.link);
15790
- items.push({ from: cursor, to: cursor + child.nodeSize, ...link && { link } });
15791
- cursor += child.nodeSize;
15792
- });
15793
- let index = items.findIndex((item) => item.link && item.from <= pos && pos < item.to);
15794
- if (index < 0) index = items.findIndex((item) => item.link && item.from < pos && pos <= item.to);
15795
- if (index < 0) return void 0;
15796
- const mark = items[index]?.link;
15797
- if (!mark) return void 0;
15798
- let start = index;
15799
- let end = index;
15800
- while (start > 0 && items[start - 1]?.link?.eq(mark)) start--;
15801
- while (end < items.length - 1 && items[end + 1]?.link?.eq(mark)) end++;
15802
- const first = items[start];
15803
- const last = items[end];
15804
- return first && last ? { from: first.from, to: last.to, mark } : void 0;
15805
- }
15624
+ var linkRangeAt = (view, pos) => wordLinkRangeAt(view.state, pos);
15806
15625
  function linkAtSelection(view) {
15807
15626
  const range = linkRangeAt(view, view.state.selection.from);
15808
15627
  if (!range) return void 0;
@@ -15814,43 +15633,10 @@ function linkAtSelection(view) {
15814
15633
  };
15815
15634
  }
15816
15635
  function applyLink(view, target, displayText) {
15817
- if (!target.href && !target.anchor) return false;
15818
- if (target.href && !isNavigableHref(target.href))
15819
- throw new Error("Links must start with http://, https:// or mailto:.");
15820
- const mark = schema.marks.link.create({
15821
- href: target.href ?? null,
15822
- anchor: target.anchor ?? null,
15823
- tooltip: target.tooltip || null
15824
- });
15825
- const { state } = view;
15826
- const { from: from2, to, empty } = state.selection;
15827
- const tr = state.tr;
15828
- if (!empty) tr.removeMark(from2, to, schema.marks.link).addMark(from2, to, mark);
15829
- else {
15830
- const existing = linkRangeAt(view, from2);
15831
- if (existing)
15832
- tr.removeMark(existing.from, existing.to, schema.marks.link).addMark(
15833
- existing.from,
15834
- existing.to,
15835
- mark
15836
- );
15837
- else {
15838
- const text = displayText || target.href || target.anchor;
15839
- tr.insert(
15840
- from2,
15841
- schema.text(text, [...state.storedMarks ?? state.selection.$from.marks(), mark])
15842
- );
15843
- }
15844
- }
15845
- view.dispatch(tr.scrollIntoView());
15846
- return true;
15636
+ return applyWordLink(target, displayText)(view.state, view.dispatch, view);
15847
15637
  }
15848
15638
  function removeLink(view) {
15849
- const { from: from2, to, empty } = view.state.selection;
15850
- const range = empty ? linkRangeAt(view, from2) : { from: from2, to };
15851
- if (!range) return false;
15852
- view.dispatch(view.state.tr.removeMark(range.from, range.to, schema.marks.link));
15853
- return true;
15639
+ return removeWordLink(view.state, view.dispatch, view);
15854
15640
  }
15855
15641
  function goToBookmark2(view, name) {
15856
15642
  let target = -1;
@@ -16612,30 +16398,38 @@ var EditorCore = class {
16612
16398
  }
16613
16399
  if (remote) transaction.setMeta(REMOTE_TRANSACTION_META, true);
16614
16400
  const previousParts = view.state.doc.attrs.sectionParts;
16615
- const applied = view.state.applyTransaction(transaction).state;
16401
+ const previousNotes = view.state.doc.attrs.noteParts;
16402
+ const previousComments = view.state.doc.attrs.commentThreads;
16403
+ const result = view.state.applyTransaction(transaction);
16404
+ const applied = result.state;
16405
+ const docChanged = !applied.doc.eq(view.state.doc);
16406
+ remote ||= Boolean(
16407
+ this.collab.yjs && !transaction.docChanged && result.transactions.some(isWordYjsRemoteTransaction)
16408
+ );
16616
16409
  if (applied === view.state) {
16617
16410
  view.updateState(applied);
16618
16411
  return;
16619
16412
  }
16620
- const repaired = remote || !transaction.docChanged ? null : this.collab.active ? repairCollaborativeDocumentIds(
16413
+ const repaired = remote || !docChanged ? null : this.collab.active ? repairCollaborativeDocumentIds(
16621
16414
  applied,
16622
16415
  this.collab.client?.clientId ?? String(this.collab.yjs.session.clientId),
16623
16416
  this.collab.ids
16624
16417
  ) : assignMissingParagraphIds(applied);
16625
16418
  view.updateState(repaired ? applied.apply(repaired) : applied);
16626
- if (transaction.docChanged) {
16419
+ if (docChanged) {
16627
16420
  this.model = docToModel(view.state.doc, this.model);
16421
+ if (previousComments !== view.state.doc.attrs.commentThreads)
16422
+ this.shell.review?.commentsPanel.refresh();
16628
16423
  this.pages.refreshPageStyles();
16629
16424
  this.pages.relayout();
16630
16425
  this.shell.chrome?.setSaveState("dirty");
16631
16426
  this.notifyChange();
16632
- if (previousParts !== view.state.doc.attrs.sectionParts && !transaction.getMeta(HEADER_FOOTER_INPUT))
16427
+ if ((previousParts !== view.state.doc.attrs.sectionParts || previousNotes !== view.state.doc.attrs.noteParts) && !transaction.getMeta(HEADER_FOOTER_INPUT))
16633
16428
  this.parts.render(this.shell.canvas, this.shell.paper, true);
16634
16429
  }
16635
16430
  this.refreshControls();
16636
- if (transaction.docChanged || remote) this.scheduleCollaborationSend();
16637
- if (transaction.docChanged || transaction.selectionSet || remote)
16638
- this.collab.presence?.schedule();
16431
+ if (docChanged || remote) this.scheduleCollaborationSend();
16432
+ if (docChanged || transaction.selectionSet || remote) this.collab.presence?.schedule();
16639
16433
  }
16640
16434
  refreshControls() {
16641
16435
  this.parts.syncSection(this.shell.canvas, this.shell.paper);
@@ -17879,10 +17673,13 @@ var ReviewController = class {
17879
17673
  if (view) yjs.comments.delete(view, id);
17880
17674
  return;
17881
17675
  }
17676
+ if (view && removeCommentThread(view, id)) return;
17882
17677
  if (view) removeCommentAnchor(view, id);
17883
17678
  this.updateComments(deleteComment(this.host.getModel().comments ?? [], id));
17884
17679
  }
17885
17680
  updateComments(next) {
17681
+ const view = this.host.getView();
17682
+ if (view && updateCommentThreads(view, next)) return;
17886
17683
  this.host.setModel({ ...this.host.getModel(), comments: next });
17887
17684
  this.host.notifyChange();
17888
17685
  this.host.refresh();
@@ -17902,7 +17699,8 @@ var ReviewController = class {
17902
17699
  text,
17903
17700
  this.host.getCollaborationIds()
17904
17701
  );
17905
- if (comment) this.updateComments([...this.host.getModel().comments ?? [], comment]);
17702
+ if (comment && commentThreadsFromDoc(view.state.doc) === void 0)
17703
+ this.updateComments([...this.host.getModel().comments ?? [], comment]);
17906
17704
  }
17907
17705
  handleReview(key2) {
17908
17706
  if (key2 === "trackChanges") {
@@ -18936,9 +18734,8 @@ async function copyOrCut(view, op) {
18936
18734
  return false;
18937
18735
  }
18938
18736
  if (op === "cut" && !view.isDestroyed && view.editable && view.state.doc.eq(doc) && view.state.selection.eq(selection))
18939
- deleteSelection(
18940
- view.state,
18941
- (transaction) => view.dispatch(transaction.setMeta("uiEvent", "cut"))
18737
+ view.dispatch(
18738
+ (deleteFieldSelection(view.state) ?? view.state.tr.deleteSelection()).scrollIntoView().setMeta("uiEvent", "cut")
18942
18739
  );
18943
18740
  return true;
18944
18741
  }