ooxml-ui 0.31.0 → 1.0.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 (96) hide show
  1. package/README.md +14 -0
  2. package/custom-elements.json +10 -0
  3. package/dist/{chunk-RAZAJMHK.js → chunk-4QQASR5A.js} +2 -2
  4. package/dist/{chunk-HZ422LTR.js → chunk-BOX43CZD.js} +1 -0
  5. package/dist/{chunk-3GE2NHNG.js → chunk-FLHM5Q4O.js} +119 -81
  6. package/dist/{chunk-2QW4QE56.js → chunk-T3HB5LMH.js} +103 -68
  7. package/dist/controls.js +2 -2
  8. package/dist/docx/hard-break-command.d.ts +1 -3
  9. package/dist/docx/link-commands.d.ts +4 -15
  10. package/dist/docx/note-editor.d.ts +3 -2
  11. package/dist/docx/run-styles.d.ts +1 -1
  12. package/dist/docx/schema.d.ts +1 -1
  13. package/dist/docx/toggle-commands.d.ts +2 -8
  14. package/dist/docx.js +109 -302
  15. package/dist/form/gradient-direction-gallery.d.ts +19 -0
  16. package/dist/form/gradient-gallery-preview.d.ts +3 -0
  17. package/dist/form/gradient-preset-gallery.d.ts +16 -0
  18. package/dist/form/gradient-stop-track.d.ts +20 -0
  19. package/dist/form/number-range.d.ts +12 -0
  20. package/dist/icons.d.ts.map +1 -1
  21. package/dist/icons.js +1 -1
  22. package/dist/index.js +4 -4
  23. package/dist/menu/menu-button.d.ts +10 -0
  24. package/dist/menu/menu-button.d.ts.map +1 -1
  25. package/dist/pptx/{chart-3d-view-scene-IANLDFIE.mjs → chart-3d-view-scene-2KRQ5667.mjs} +2 -2
  26. package/dist/pptx/{chart-3d-view-scene-3DK5TUBZ.cjs → chart-3d-view-scene-36DMZWZ3.cjs} +37 -37
  27. package/dist/pptx/{chunk-C42ZL35K.mjs → chunk-ADOC5JLI.mjs} +1 -1
  28. package/dist/pptx/{chunk-QM4FGZG4.cjs → chunk-AIL3BNZS.cjs} +31 -131
  29. package/dist/pptx/{chunk-WLETAW3T.cjs → chunk-CJU4P5FT.cjs} +33 -13
  30. package/dist/pptx/{chunk-6SCK57RJ.cjs → chunk-FEFQTZDM.cjs} +158 -245
  31. package/dist/pptx/{chunk-EVGSFPUV.mjs → chunk-XWE5GSE7.mjs} +16 -109
  32. package/dist/pptx/{chunk-7JEMQW6R.mjs → chunk-YARCML7O.mjs} +11 -122
  33. package/dist/pptx/{chunk-OHE5UXST.cjs → chunk-YHA6XAB3.cjs} +1 -1
  34. package/dist/pptx/{chunk-X2F6PA2D.mjs → chunk-YOGDIDPB.mjs} +22 -3
  35. package/dist/pptx/dom/index.cjs +235 -235
  36. package/dist/pptx/dom/index.mjs +6 -6
  37. package/dist/pptx/export/html2canvas-clone.cjs +2 -2
  38. package/dist/pptx/export/html2canvas-clone.mjs +1 -1
  39. package/dist/pptx/index.cjs +2993 -2989
  40. package/dist/pptx/index.mjs +4 -4
  41. package/dist/pptx/render/chart-combo-stock.cjs +3 -3
  42. package/dist/pptx/render/chart-combo-stock.mjs +1 -1
  43. package/dist/pptx/render/chart-manual-layout.d.ts +2 -20
  44. package/dist/pptx/render/chart-manual-layout.d.ts.map +1 -1
  45. package/dist/pptx/render/chart-overlays.cjs +7 -7
  46. package/dist/pptx/render/chart-overlays.mjs +1 -1
  47. package/dist/pptx/render/chart-surface-treemap.cjs +4 -4
  48. package/dist/pptx/render/chart-surface-treemap.mjs +1 -1
  49. package/dist/pptx/render/chart-svg-def-types.d.ts +6 -1
  50. package/dist/pptx/render/chart-svg-def-types.d.ts.map +1 -1
  51. package/dist/pptx/render/chart-view-model-dom-helpers.d.ts +1 -1
  52. package/dist/pptx/render/chart-view-model-dom-helpers.d.ts.map +1 -1
  53. package/dist/pptx/render/chart-view-model.cjs +41 -41
  54. package/dist/pptx/render/chart-view-model.mjs +1 -1
  55. package/dist/pptx/render/chart-waterfall-map.cjs +6 -6
  56. package/dist/pptx/render/chart-waterfall-map.mjs +1 -1
  57. package/dist/pptx/render/element-interaction.d.ts +1 -1
  58. package/dist/pptx/render/element-interaction.d.ts.map +1 -1
  59. package/dist/pptx/render/gradient-picker.d.ts.map +1 -1
  60. package/dist/pptx/render/index.d.ts +1 -0
  61. package/dist/pptx/render/index.d.ts.map +1 -1
  62. package/dist/pptx/render/path-gradient-rect.d.ts +1 -75
  63. package/dist/pptx/render/path-gradient-rect.d.ts.map +1 -1
  64. package/dist/pptx/render/rotate-handle-placement.d.ts +1 -27
  65. package/dist/pptx/render/rotate-handle-placement.d.ts.map +1 -1
  66. package/dist/pptx/render/rotation-drag.d.ts +1 -7
  67. package/dist/pptx/render/rotation-drag.d.ts.map +1 -1
  68. package/dist/teams/app/files-panel.d.ts +8 -3
  69. package/dist/teams/app/teams-app.d.ts +1 -0
  70. package/dist/teams/app/teams-settings.d.ts +6 -0
  71. package/dist/teams.js +3 -3
  72. package/dist/visio/render-fill.d.ts +2 -1
  73. package/dist/visio/render-svg.d.ts +2 -0
  74. package/dist/visio/ribbon-action.d.ts +8 -1
  75. package/dist/visio/ribbon-parts.d.ts +2 -1
  76. package/dist/visio/ribbon-router.d.ts +4 -2
  77. package/dist/visio/viewer-commands.d.ts +3 -3
  78. package/dist/visio/viewer-draw-tool.d.ts +16 -6
  79. package/dist/visio/viewer-handle-events.d.ts +19 -0
  80. package/dist/visio/viewer-line-endpoints.d.ts +14 -0
  81. package/dist/visio/viewer-rotation-handle.d.ts +14 -0
  82. package/dist/visio/viewer-rotation-preview.d.ts +7 -0
  83. package/dist/visio.js +734 -88
  84. package/dist/xlsx/chart-area-pane.d.ts +9 -0
  85. package/dist/xlsx/chart-fill-binding.d.ts +23 -0
  86. package/dist/xlsx/chart-gradient-preview.d.ts +8 -0
  87. package/dist/xlsx/chart-series-fill.d.ts +2 -1
  88. package/dist/xlsx/chart-series-gradient-type.d.ts +9 -0
  89. package/dist/xlsx/chart-series-gradient.d.ts +8 -0
  90. package/dist/xlsx/chart-series-pane.d.ts +2 -1
  91. package/dist/xlsx/chart-series-range-preview.d.ts +7 -0
  92. package/dist/xlsx/chart-series-transparency.d.ts +2 -1
  93. package/dist/xlsx/grid/measure.d.ts +5 -0
  94. package/dist/xlsx/grid/styles.d.ts +1 -1
  95. package/dist/xlsx.js +962 -102
  96. package/package.json +2 -2
package/dist/docx.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { defineSmartArt } from './chunk-XDUYS4KK.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';
3
+ import { createRibbonOverflow, defineRibbon, defineDialog, defineSearchField, defineSwitch, defineTitleBar, defineBackstage, defineStatusBar, defineZoomSlider, defineContextMenu, runKeyTips, assignKeyTips } from './chunk-T3HB5LMH.js';
4
+ import { registerIcon } from './chunk-BOX43CZD.js';
5
5
  import './chunk-OXKWNNNJ.js';
6
6
  import './chunk-ZV2Z4IWH.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 { 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, 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
9
  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';
10
+ 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
11
  export { CollaborationAuthority, CollaborationClient, RIBBON_ACTION_IDS, RIBBON_ACTION_LABELS, createCollaborationIdGenerator, darkTheme, isRibbonActionId, lightTheme, normalizeRibbonActions, repairCollaborativeDocumentIds, themeToCssVars } from 'ooxml-core/docx/ui';
12
12
  import { parseOmml, convertOmmlToLatex, convertOmmlToMathMl } from 'ooxml-core/math';
13
13
  import { PluginKey, EditorState, Plugin, NodeSelection, TextSelection, Selection } from 'prosemirror-state';
@@ -15,10 +15,10 @@ import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
15
15
  import { loadDocument } from 'ooxml-core/docx/load';
16
16
  import { closeHistory, undo, redo, history } from 'prosemirror-history';
17
17
  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
18
  import { sendableSteps, getVersion } from 'prosemirror-collab';
20
19
  import { sanitizeColor, sanitizeUserName, SequenceTracker, isValidId, classifyVersion, validateDisplayName } from 'ooxml-core/collab';
21
20
  import { keymap } from 'prosemirror-keymap';
21
+ import { chainCommands, baseKeymap, selectAll } from 'prosemirror-commands';
22
22
 
23
23
  // src/docx/locales/columns.ts
24
24
  var enColumns = {
@@ -4182,7 +4182,9 @@ var schema = new Schema({
4182
4182
  endnoteNumFmt: { default: null },
4183
4183
  /** Section layout (no header/footer content) as JSON, so page setup is undoable. */
4184
4184
  sections: { default: null },
4185
- sectionParts: { default: null }
4185
+ sectionParts: { default: null },
4186
+ noteParts: { default: null },
4187
+ ...commentHistoryAttributes
4186
4188
  }
4187
4189
  },
4188
4190
  paragraph: {
@@ -4282,15 +4284,7 @@ var schema = new Schema({
4282
4284
  ]
4283
4285
  },
4284
4286
  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
- },
4287
+ hardBreak: hardBreakNodeSpec,
4294
4288
  pageBreak: pageBreakNodeSpec,
4295
4289
  noteReference: noteReferenceNodeSpec,
4296
4290
  fieldMarker: fieldMarkerNodeSpec,
@@ -4634,6 +4628,8 @@ function modelToDoc(model) {
4634
4628
  marginLeft: model.page.marginLeft,
4635
4629
  sections: model.sections ? sectionLayoutJson(model.sections) : null,
4636
4630
  sectionParts: sectionPartsJson(model.sections),
4631
+ noteParts: notePartsJson(model),
4632
+ commentThreads: JSON.stringify(model.comments ?? []),
4637
4633
  evenAndOddHeaders: Boolean(model.evenAndOddHeaders),
4638
4634
  trackChanges: Boolean(model.trackChanges),
4639
4635
  trackFormatting: model.trackFormatting !== false,
@@ -4722,6 +4718,9 @@ function docToModel(doc, prior) {
4722
4718
  });
4723
4719
  const {
4724
4720
  sections: priorSections,
4721
+ footnotes: priorFootnotes,
4722
+ endnotes: priorEndnotes,
4723
+ comments: priorComments,
4725
4724
  evenAndOddHeaders: _evenOdd,
4726
4725
  trackChanges: _trackChanges,
4727
4726
  trackFormatting: _trackFormatting,
@@ -4732,8 +4731,14 @@ function docToModel(doc, prior) {
4732
4731
  } = prior;
4733
4732
  const sectionLayout = typeof doc.attrs.sections === "string" ? sectionsFromLayout(doc.attrs.sections, priorSections, blocks) : keepHeaderFooterSections(priorSections, blocks, doc).sections;
4734
4733
  const sections = typeof doc.attrs.sectionParts === "string" && sectionLayout ? restoreSectionParts(sectionLayout, doc.attrs.sectionParts, blocks) : sectionLayout;
4734
+ const threads = commentThreadsFromDoc(doc);
4735
4735
  return {
4736
4736
  ...rest,
4737
+ ...threads === void 0 ? priorComments !== void 0 ? { comments: priorComments } : {} : threads.length ? { comments: threads } : {},
4738
+ ...restoreNoteParts(doc.attrs.noteParts, {
4739
+ ...priorFootnotes ? { footnotes: priorFootnotes } : {},
4740
+ ...priorEndnotes ? { endnotes: priorEndnotes } : {}
4741
+ }),
4737
4742
  blocks,
4738
4743
  ...doc.attrs.evenAndOddHeaders ? { evenAndOddHeaders: true } : {},
4739
4744
  trackChanges: Boolean(doc.attrs.trackChanges),
@@ -7776,7 +7781,7 @@ function runStylesPlugin(getModel, getMode = () => "all") {
7776
7781
  const paragraphStyleId = displayParagraph(paragraph2, mode).value.style;
7777
7782
  let hasScale = false;
7778
7783
  paragraph2.forEach((child, offset) => {
7779
- if (!child.isText) return;
7784
+ if (!child.isInline || child.type.name === "equation") return;
7780
7785
  const current2 = runOf(child);
7781
7786
  if (!current2) return;
7782
7787
  const projected = reviewRunFormatting(current2, mode);
@@ -7794,6 +7799,18 @@ function runStylesPlugin(getModel, getMode = () => "all") {
7794
7799
  ...projected.error ? { "data-review-format-error": projected.error } : {}
7795
7800
  } : {};
7796
7801
  const hidden = resolved.vanish === true;
7802
+ if (!child.isText) {
7803
+ decorations2.push(
7804
+ Decoration.node(start + offset, start + offset + child.nodeSize, {
7805
+ style: `${runFormattingCss(resolved, model.theme)};${reviewRunCss(resolved)}`,
7806
+ ...run.language ? { lang: run.language } : {},
7807
+ ...run.rtl !== void 0 ? { dir: run.rtl ? "rtl" : "ltr" } : {},
7808
+ ...projected.error ? { "data-review-format-error": projected.error } : {},
7809
+ ...hidden ? { class: "dve-hidden-text" } : {}
7810
+ })
7811
+ );
7812
+ return;
7813
+ }
7797
7814
  const segments = scaledSegments(
7798
7815
  child.text,
7799
7816
  resolved,
@@ -7878,8 +7895,8 @@ function effectiveFont(state, text, paragraph2) {
7878
7895
  if (!run || !model) {
7879
7896
  const font = text.marks.find((mark) => mark.type === schema.marks.font);
7880
7897
  return {
7881
- family: String(font?.attrs.family ?? DEFAULT_FAMILY),
7882
- size: Number(font?.attrs.size ?? DEFAULT_SIZE)
7898
+ family: String(run?.fontFamily ?? font?.attrs.family ?? DEFAULT_FAMILY),
7899
+ size: Number(run?.fontSize ?? font?.attrs.size ?? DEFAULT_SIZE)
7883
7900
  };
7884
7901
  }
7885
7902
  const resolved = resolveRunFormatting(run, {
@@ -7907,7 +7924,7 @@ function syncFontControls(toolbar, state) {
7907
7924
  } else {
7908
7925
  let found = false;
7909
7926
  doc.nodesBetween(selection.from, selection.to, (node, _pos, parent) => {
7910
- if (!node.isText || !parent) return;
7927
+ if (!node.isInline || node.type.name === "equation" || !parent) return;
7911
7928
  found = true;
7912
7929
  add(node, parent);
7913
7930
  });
@@ -7933,7 +7950,7 @@ function selectionScript(state) {
7933
7950
  };
7934
7951
  if (!state.selection.empty)
7935
7952
  state.doc.nodesBetween(state.selection.from, state.selection.to, (node, _pos, parent) => {
7936
- if (node.isText && parent) add(node, parent);
7953
+ if (node.isInline && node.type.name !== "equation" && parent) add(node, parent);
7937
7954
  });
7938
7955
  if (!values2.size)
7939
7956
  add(
@@ -7942,62 +7959,26 @@ function selectionScript(state) {
7942
7959
  );
7943
7960
  return values2.size === 1 ? [...values2][0] : null;
7944
7961
  }
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
7962
  function applyHighlight(view, color) {
7963
- if (color !== "none" && !Object.hasOwn(wordHighlightColors, color)) return;
7964
- setInlineMark(view, schema.marks.highlight, color === "none" ? void 0 : { color });
7963
+ if (!isStHighlightColor(color)) return;
7964
+ applyRunFormattingPatch({ highlight: color === "none" ? void 0 : color })(
7965
+ view.state,
7966
+ view.dispatch,
7967
+ view
7968
+ );
7965
7969
  }
7966
7970
  function toggleVerticalAlign(view, value) {
7967
7971
  applyVerticalAlign(view, selectionScript(view.state) === value ? "baseline" : value);
7968
7972
  }
7969
7973
  function applyVerticalAlign(view, value) {
7970
- setInlineMark(view, schema.marks.verticalAlign, { value });
7974
+ applyRunFormattingPatch({ verticalAlign: value })(view.state, view.dispatch, view);
7971
7975
  }
7972
7976
  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);
7977
+ const patch = key2 === "family" ? { fontFamily: value } : key2 === "size" ? { fontSize: Number(value) } : { color: value };
7978
+ applyRunFormattingPatch(patch)(view.state, view.dispatch, view);
7994
7979
  }
7995
7980
  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([]));
7981
+ clearDirectRunFormatting(view.state, view.dispatch, view);
8001
7982
  }
8002
7983
  var tableId = 0;
8003
7984
  var MAX_TABLE_ROWS = 100;
@@ -8089,84 +8070,7 @@ function applyPageStyles(paper, model, zoom) {
8089
8070
  else paper.style.removeProperty("--dve-page-color");
8090
8071
  paper.style.hyphens = model.autoHyphenation ? "auto" : "";
8091
8072
  }
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
- }
8073
+ var toggleFormat = createToggleFormat(schema, styleModelOf);
8170
8074
 
8171
8075
  // src/docx/font-format-batch.ts
8172
8076
  function batchFontFormat(view, apply) {
@@ -8190,8 +8094,6 @@ function batchFontFormat(view, apply) {
8190
8094
  if (scroll) combined.scrollIntoView();
8191
8095
  if (combined.steps.length || combined.storedMarksSet) view.dispatch(combined);
8192
8096
  }
8193
-
8194
- // src/docx/font-format.ts
8195
8097
  var FIELDS = [
8196
8098
  "family",
8197
8099
  "size",
@@ -8259,7 +8161,8 @@ function formatsOf(state) {
8259
8161
  formats.push(formatOf(state, schema.text("x", marks2), selection.$from.parent));
8260
8162
  } else {
8261
8163
  doc.nodesBetween(selection.from, selection.to, (node, _pos, parent) => {
8262
- if (node.isText && parent) formats.push(formatOf(state, node, parent));
8164
+ if (node.isInline && node.type.name !== "equation" && parent)
8165
+ formats.push(formatOf(state, node, parent));
8263
8166
  });
8264
8167
  if (!formats.length)
8265
8168
  formats.push(
@@ -8291,33 +8194,7 @@ function setToggle(view, key2, desired) {
8291
8194
  }
8292
8195
  }
8293
8196
  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);
8197
+ applyRunFormattingPatch(patch)(view.state, view.dispatch, view);
8321
8198
  }
8322
8199
  function applyFontFormat(view, changes) {
8323
8200
  if (!view.editable) return;
@@ -8350,14 +8227,14 @@ function applyFontFields(view, changes) {
8350
8227
  if (changes.smallCaps !== void 0) extras.smallCaps = changes.smallCaps;
8351
8228
  if (changes.caps !== void 0) extras.caps = changes.caps;
8352
8229
  if (changes.hidden !== void 0) extras.vanish = changes.hidden;
8353
- if (changes.spacing !== void 0)
8354
- extras.characterSpacingTwips = Math.round(changes.spacing * 20);
8230
+ if (changes.spacing !== void 0 && Number.isFinite(changes.spacing))
8231
+ extras.characterSpacingTwips = signedTwips(Math.round(changes.spacing * 20));
8355
8232
  if (changes.scale !== void 0 && Number.isInteger(changes.scale) && changes.scale >= 0 && changes.scale <= 600)
8356
8233
  extras.textScalePercent = changes.scale;
8357
8234
  if (changes.position !== void 0 && Number.isFinite(changes.position))
8358
- extras.positionHalfPoints = Math.sign(changes.position) * Math.round(Math.abs(changes.position) * 2);
8235
+ extras.positionHalfPoints = halfPointsFromPoints(changes.position);
8359
8236
  if (changes.kerning !== void 0 && Number.isFinite(changes.kerning) && changes.kerning >= 0)
8360
- extras.kerningHalfPoints = Math.round(changes.kerning * 2);
8237
+ extras.kerningHalfPoints = halfPointsFromPoints(changes.kerning);
8361
8238
  if (Object.keys(extras).length) patchExtraProps(view, extras);
8362
8239
  }
8363
8240
 
@@ -9876,32 +9753,6 @@ var REFERENCE = /^\s*(REF|PAGEREF)\s+("[^"]+"|\S+)(.*)$/i;
9876
9753
  function plainSwitches(rest) {
9877
9754
  return !/\\/.test(rest.replace(/\\h\b/gi, "").replace(/\\\*\s+\S+/g, ""));
9878
9755
  }
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
9756
  function bookmarkTargets(doc) {
9906
9757
  const targets = /* @__PURE__ */ new Map();
9907
9758
  doc.descendants((node) => {
@@ -9930,12 +9781,12 @@ function updateFields(view, pageOf) {
9930
9781
  }
9931
9782
  function refreshFieldResults(tr, pageOf, captionsOnly = false) {
9932
9783
  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())
9784
+ fieldResultRanges(tr.doc).map((run) => seqLabelOf(schema.text("x", [run.mark]))).filter((label2) => label2 !== void 0).map((label2) => label2.toLowerCase())
9934
9785
  ))
9935
9786
  renumberCaptions(tr, label);
9936
9787
  const targets = bookmarkTargets(tr.doc);
9937
9788
  const changes = [];
9938
- for (const run of fieldRuns(tr.doc)) {
9789
+ for (const run of fieldResultRanges(tr.doc)) {
9939
9790
  const match = REFERENCE.exec(String(run.mark.attrs.instr ?? ""));
9940
9791
  if (!match || !plainSwitches(match[3] ?? "")) continue;
9941
9792
  const target = targets.get((match[2] ?? "").replace(/^"|"$/g, ""));
@@ -14667,23 +14518,15 @@ function refreshStoryPreviews(model, sectionIndex, elements, mode, decorate) {
14667
14518
  slot2.querySelector(".dve-header-footer-body"),
14668
14519
  effectiveHeaderFooter(model, sectionIndex, kind, slot2.dataset.slot)?.blocks
14669
14520
  );
14670
- const notes = [...model.footnotes ?? [], ...model.endnotes ?? []];
14671
- for (const item of elements.notes?.querySelectorAll("[data-docx-note-id]") ?? [])
14521
+ for (const item of elements.notes?.querySelectorAll("[data-docx-note-id]") ?? []) {
14522
+ const notes = item.dataset.docxNoteKind === "endnote" ? model.endnotes : model.footnotes;
14672
14523
  refresh(
14673
14524
  item.querySelector(".dve-note-body"),
14674
- notes.find((note) => note.id === item.dataset.docxNoteId)?.blocks
14525
+ notes?.find((note) => note.id === item.dataset.docxNoteId)?.blocks
14675
14526
  );
14527
+ }
14676
14528
  }
14677
14529
 
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
14530
  // src/docx/page-break-command.ts
14688
14531
  function insertBreakCommand(kind) {
14689
14532
  return (state, dispatch, view) => {
@@ -14820,7 +14663,7 @@ var editorBindings = {
14820
14663
  "Mod-b": marks.bold,
14821
14664
  "Mod-i": marks.italic,
14822
14665
  "Mod-u": marks.underline,
14823
- "Shift-Enter": insertHardBreak,
14666
+ "Shift-Enter": insertWordHardBreak,
14824
14667
  Enter: chainCommands(
14825
14668
  exitListOnEmptyEnter,
14826
14669
  expectDefined(baseKeymap.Enter, "the base Enter command")
@@ -14998,6 +14841,7 @@ function noteList(notes, kind, numFmt, blocks, model) {
14998
14841
  for (const { note, number } of numbered) {
14999
14842
  const item = document.createElement("li");
15000
14843
  item.dataset.docxNoteId = note.id;
14844
+ item.dataset.docxNoteKind = kind;
15001
14845
  item.value = number;
15002
14846
  const marker = document.createElement("span");
15003
14847
  marker.className = "dve-note-marker";
@@ -15071,19 +14915,21 @@ function withMark(blocks, mark) {
15071
14915
  function attachNoteEditing(root, options) {
15072
14916
  for (const item of root.querySelectorAll("li[data-docx-note-id]")) {
15073
14917
  const id = item.dataset.docxNoteId;
14918
+ const kind = item.dataset.docxNoteKind;
14919
+ if (kind !== "footnote" && kind !== "endnote") continue;
15074
14920
  const body = item.querySelector(".dve-note-body");
15075
14921
  if (!body) continue;
15076
14922
  item.title = translateUiText(root, "Double-click to edit");
15077
14923
  item.addEventListener("dblclick", () => {
15078
14924
  if (!options.editable() || item.classList.contains("dve-header-footer-editing")) return;
15079
- const note = options.note(id);
14925
+ const note = options.note(kind, id);
15080
14926
  if (!note) return;
15081
14927
  const { editable: editable2, mark } = withoutMark(note.blocks);
15082
14928
  openBlocksEditor(
15083
14929
  item,
15084
14930
  body,
15085
14931
  editable2,
15086
- (blocks) => options.change(id, withMark(blocks, mark)),
14932
+ (blocks) => options.change(kind, id, withMark(blocks, mark)),
15087
14933
  options.editor
15088
14934
  );
15089
14935
  });
@@ -15125,7 +14971,9 @@ function insertNote(view, model, kind) {
15125
14971
  number: 1,
15126
14972
  format: JSON.stringify(formatting)
15127
14973
  });
15128
- view.dispatch(view.state.tr.replaceSelectionWith(reference, false).scrollIntoView());
14974
+ view.dispatch(
14975
+ view.state.tr.replaceSelectionWith(reference, false).setDocAttribute("noteParts", notePartsJson(next)).scrollIntoView()
14976
+ );
15129
14977
  return { model: next, id };
15130
14978
  }
15131
14979
  function noteNumberingPlugin() {
@@ -15354,13 +15202,13 @@ var PartsController = class {
15354
15202
  });
15355
15203
  if (this.notesEl)
15356
15204
  attachNoteEditing(this.notesEl, {
15357
- note: (id) => {
15205
+ note: (kind, id) => {
15358
15206
  const current2 = this.host.model();
15359
- return [...current2.footnotes ?? [], ...current2.endnotes ?? []].find(
15207
+ return current2[kind === "footnote" ? "footnotes" : "endnotes"]?.find(
15360
15208
  (note) => note.id === id
15361
15209
  );
15362
15210
  },
15363
- change: (id, blocks) => this.updateNote(id, blocks),
15211
+ change: (kind, id, blocks) => this.updateNote(kind, id, blocks),
15364
15212
  editable: editable2,
15365
15213
  editor: this.editorOptions()
15366
15214
  });
@@ -15389,9 +15237,7 @@ var PartsController = class {
15389
15237
  insertNote(kind, canvas, paper) {
15390
15238
  const view = this.host.view();
15391
15239
  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] });
15240
+ const { id } = insertNote(view, this.host.model(), kind);
15395
15241
  this.render(canvas, paper);
15396
15242
  const item = this.notesEl?.querySelector(
15397
15243
  `.dve-notes-${kind} li[data-docx-note-id="${id}"]`
@@ -15401,15 +15247,19 @@ var PartsController = class {
15401
15247
  this.host.edited();
15402
15248
  }
15403
15249
  /** Replaces one footnote's or endnote's blocks. */
15404
- updateNote(id, blocks) {
15250
+ updateNote(kind, id, blocks) {
15251
+ const view = this.host.view();
15252
+ if (!view?.editable || !this.host.canEditOutsideBody()) return;
15405
15253
  const replace = (notes) => notes.map((note) => note.id === id ? { ...note, blocks: structuredClone(blocks) } : note);
15406
15254
  const model = this.host.model();
15407
- this.host.setModel({
15255
+ const key2 = kind === "footnote" ? "footnotes" : "endnotes";
15256
+ const next = {
15408
15257
  ...model,
15409
- ...model.footnotes && { footnotes: replace(model.footnotes) },
15410
- ...model.endnotes && { endnotes: replace(model.endnotes) }
15411
- });
15412
- this.host.edited();
15258
+ ...model[key2] && { [key2]: replace(model[key2]) }
15259
+ };
15260
+ view.dispatch(
15261
+ view.state.tr.step(new NotePartsStep(notePartsJson(next))).setMeta(HEADER_FOOTER_INPUT, true)
15262
+ );
15413
15263
  }
15414
15264
  /** Applies header/footer edits to every section slot that shares the edited part. */
15415
15265
  updateHeaderFooter(kind, slot2, blocks) {
@@ -15781,28 +15631,7 @@ var PageController = class {
15781
15631
  this.host.printLayout()?.print(this.host.model(), (message) => emit(this.host.element, "document-warning", message));
15782
15632
  }
15783
15633
  };
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
- }
15634
+ var linkRangeAt = (view, pos) => wordLinkRangeAt(view.state, pos);
15806
15635
  function linkAtSelection(view) {
15807
15636
  const range = linkRangeAt(view, view.state.selection.from);
15808
15637
  if (!range) return void 0;
@@ -15814,43 +15643,10 @@ function linkAtSelection(view) {
15814
15643
  };
15815
15644
  }
15816
15645
  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;
15646
+ return applyWordLink(target, displayText)(view.state, view.dispatch, view);
15847
15647
  }
15848
15648
  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;
15649
+ return removeWordLink(view.state, view.dispatch, view);
15854
15650
  }
15855
15651
  function goToBookmark2(view, name) {
15856
15652
  let target = -1;
@@ -16612,30 +16408,38 @@ var EditorCore = class {
16612
16408
  }
16613
16409
  if (remote) transaction.setMeta(REMOTE_TRANSACTION_META, true);
16614
16410
  const previousParts = view.state.doc.attrs.sectionParts;
16615
- const applied = view.state.applyTransaction(transaction).state;
16411
+ const previousNotes = view.state.doc.attrs.noteParts;
16412
+ const previousComments = view.state.doc.attrs.commentThreads;
16413
+ const result = view.state.applyTransaction(transaction);
16414
+ const applied = result.state;
16415
+ const docChanged = !applied.doc.eq(view.state.doc);
16416
+ remote ||= Boolean(
16417
+ this.collab.yjs && !transaction.docChanged && result.transactions.some(isWordYjsRemoteTransaction)
16418
+ );
16616
16419
  if (applied === view.state) {
16617
16420
  view.updateState(applied);
16618
16421
  return;
16619
16422
  }
16620
- const repaired = remote || !transaction.docChanged ? null : this.collab.active ? repairCollaborativeDocumentIds(
16423
+ const repaired = remote || !docChanged ? null : this.collab.active ? repairCollaborativeDocumentIds(
16621
16424
  applied,
16622
16425
  this.collab.client?.clientId ?? String(this.collab.yjs.session.clientId),
16623
16426
  this.collab.ids
16624
16427
  ) : assignMissingParagraphIds(applied);
16625
16428
  view.updateState(repaired ? applied.apply(repaired) : applied);
16626
- if (transaction.docChanged) {
16429
+ if (docChanged) {
16627
16430
  this.model = docToModel(view.state.doc, this.model);
16431
+ if (previousComments !== view.state.doc.attrs.commentThreads)
16432
+ this.shell.review?.commentsPanel.refresh();
16628
16433
  this.pages.refreshPageStyles();
16629
16434
  this.pages.relayout();
16630
16435
  this.shell.chrome?.setSaveState("dirty");
16631
16436
  this.notifyChange();
16632
- if (previousParts !== view.state.doc.attrs.sectionParts && !transaction.getMeta(HEADER_FOOTER_INPUT))
16437
+ if ((previousParts !== view.state.doc.attrs.sectionParts || previousNotes !== view.state.doc.attrs.noteParts) && !transaction.getMeta(HEADER_FOOTER_INPUT))
16633
16438
  this.parts.render(this.shell.canvas, this.shell.paper, true);
16634
16439
  }
16635
16440
  this.refreshControls();
16636
- if (transaction.docChanged || remote) this.scheduleCollaborationSend();
16637
- if (transaction.docChanged || transaction.selectionSet || remote)
16638
- this.collab.presence?.schedule();
16441
+ if (docChanged || remote) this.scheduleCollaborationSend();
16442
+ if (docChanged || transaction.selectionSet || remote) this.collab.presence?.schedule();
16639
16443
  }
16640
16444
  refreshControls() {
16641
16445
  this.parts.syncSection(this.shell.canvas, this.shell.paper);
@@ -17879,10 +17683,13 @@ var ReviewController = class {
17879
17683
  if (view) yjs.comments.delete(view, id);
17880
17684
  return;
17881
17685
  }
17686
+ if (view && removeCommentThread(view, id)) return;
17882
17687
  if (view) removeCommentAnchor(view, id);
17883
17688
  this.updateComments(deleteComment(this.host.getModel().comments ?? [], id));
17884
17689
  }
17885
17690
  updateComments(next) {
17691
+ const view = this.host.getView();
17692
+ if (view && updateCommentThreads(view, next)) return;
17886
17693
  this.host.setModel({ ...this.host.getModel(), comments: next });
17887
17694
  this.host.notifyChange();
17888
17695
  this.host.refresh();
@@ -17902,7 +17709,8 @@ var ReviewController = class {
17902
17709
  text,
17903
17710
  this.host.getCollaborationIds()
17904
17711
  );
17905
- if (comment) this.updateComments([...this.host.getModel().comments ?? [], comment]);
17712
+ if (comment && commentThreadsFromDoc(view.state.doc) === void 0)
17713
+ this.updateComments([...this.host.getModel().comments ?? [], comment]);
17906
17714
  }
17907
17715
  handleReview(key2) {
17908
17716
  if (key2 === "trackChanges") {
@@ -18936,9 +18744,8 @@ async function copyOrCut(view, op) {
18936
18744
  return false;
18937
18745
  }
18938
18746
  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"))
18747
+ view.dispatch(
18748
+ (deleteFieldSelection(view.state) ?? view.state.tr.deleteSelection()).scrollIntoView().setMeta("uiEvent", "cut")
18942
18749
  );
18943
18750
  return true;
18944
18751
  }