@harbour-enterprises/superdoc 0.28.0-next.12 → 0.28.0-next.14

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 (27) hide show
  1. package/dist/chunks/{PdfViewer-BsJq49rR.es.js → PdfViewer-C5N8ds3O.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-D8L8mpOs.cjs → PdfViewer-CTJIldpN.cjs} +1 -1
  3. package/dist/chunks/{index-BNr0wgOU-j0xGZdr7.es.js → index-BNr0wgOU-Bj1k6CCB.es.js} +1 -1
  4. package/dist/chunks/{index-BNr0wgOU-Bg5kSvF0.cjs → index-BNr0wgOU-DGdWV9Iz.cjs} +1 -1
  5. package/dist/chunks/{index-x4srxOl3.cjs → index-C2zCd-ai.cjs} +2 -2
  6. package/dist/chunks/{index-ByV1n--x.es.js → index-DOIFo7ao.es.js} +2 -2
  7. package/dist/chunks/{super-editor.es-C0LbO3l0.es.js → super-editor.es-CSyQAFrJ.es.js} +505 -89
  8. package/dist/chunks/{super-editor.es-CANt5-KH.cjs → super-editor.es-DAO9OQ4k.cjs} +505 -89
  9. package/dist/core/types/index.d.ts.map +1 -1
  10. package/dist/super-editor/ai-writer.es.js +1 -1
  11. package/dist/super-editor/chunks/{editor-BwNyV6ke.js → editor-DSQC1des.js} +504 -88
  12. package/dist/super-editor/chunks/{toolbar-Bx1rJX7n.js → toolbar-Dq-rYRTG.js} +1 -1
  13. package/dist/super-editor/editor.es.js +1 -1
  14. package/dist/super-editor/super-editor/src/core/helpers/rangeUtils.d.ts +2 -0
  15. package/dist/super-editor/super-editor/src/extensions/field-annotation/FieldAnnotationPlugin.d.ts +5 -1
  16. package/dist/super-editor/super-editor/src/extensions/image/imageHelpers/imagePositionPlugin.d.ts +2 -0
  17. package/dist/super-editor/super-editor/src/extensions/list-item/helpers/listItemTypography.d.ts +5 -0
  18. package/dist/super-editor/super-editor/src/extensions/list-item/helpers/styledListMarkerPlugin.d.ts +11 -2
  19. package/dist/super-editor/super-editor.es.js +3 -3
  20. package/dist/super-editor/toolbar.es.js +2 -2
  21. package/dist/super-editor.cjs +1 -1
  22. package/dist/super-editor.es.js +1 -1
  23. package/dist/superdoc.cjs +2 -2
  24. package/dist/superdoc.es.js +2 -2
  25. package/dist/superdoc.umd.js +504 -88
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -49996,17 +49996,7 @@ const TrackChangesBasePlugin = () => {
49996
49996
  },
49997
49997
  apply(tr, oldState, prevEditorState, newEditorState) {
49998
49998
  const meta = tr.getMeta(TrackChangesBasePluginKey);
49999
- if (!meta) {
50000
- return {
50001
- ...oldState,
50002
- decorations: getTrackChangesDecorations(
50003
- newEditorState,
50004
- oldState.onlyOriginalShown,
50005
- oldState.onlyModifiedShown
50006
- )
50007
- };
50008
- }
50009
- if (meta.type === "TRACK_CHANGES_ENABLE") {
49999
+ if (meta && meta.type === "TRACK_CHANGES_ENABLE") {
50010
50000
  return {
50011
50001
  ...oldState,
50012
50002
  isTrackChangesActive: meta.value === true,
@@ -50017,7 +50007,7 @@ const TrackChangesBasePlugin = () => {
50017
50007
  )
50018
50008
  };
50019
50009
  }
50020
- if (meta.type === "SHOW_ONLY_ORIGINAL") {
50010
+ if (meta && meta.type === "SHOW_ONLY_ORIGINAL") {
50021
50011
  return {
50022
50012
  ...oldState,
50023
50013
  onlyOriginalShown: meta.value === true,
@@ -50025,7 +50015,7 @@ const TrackChangesBasePlugin = () => {
50025
50015
  decorations: getTrackChangesDecorations(newEditorState, meta.value === true, false)
50026
50016
  };
50027
50017
  }
50028
- if (meta.type === "SHOW_ONLY_MODIFIED") {
50018
+ if (meta && meta.type === "SHOW_ONLY_MODIFIED") {
50029
50019
  return {
50030
50020
  ...oldState,
50031
50021
  onlyOriginalShown: false,
@@ -50033,6 +50023,31 @@ const TrackChangesBasePlugin = () => {
50033
50023
  decorations: getTrackChangesDecorations(newEditorState, false, meta.value === true)
50034
50024
  };
50035
50025
  }
50026
+ if (!tr.docChanged) {
50027
+ return oldState;
50028
+ }
50029
+ if (!meta) {
50030
+ let mightAffectTrackChanges = false;
50031
+ tr.steps.forEach((step) => {
50032
+ if (step.slice || step.from !== step.to) {
50033
+ mightAffectTrackChanges = true;
50034
+ }
50035
+ });
50036
+ if (mightAffectTrackChanges) {
50037
+ return {
50038
+ ...oldState,
50039
+ decorations: getTrackChangesDecorations(
50040
+ newEditorState,
50041
+ oldState.onlyOriginalShown,
50042
+ oldState.onlyModifiedShown
50043
+ )
50044
+ };
50045
+ }
50046
+ return {
50047
+ ...oldState,
50048
+ decorations: oldState.decorations.map(tr.mapping, tr.doc)
50049
+ };
50050
+ }
50036
50051
  return {
50037
50052
  ...oldState,
50038
50053
  decorations: getTrackChangesDecorations(
@@ -50787,6 +50802,7 @@ const CommentsPlugin = Extension.create({
50787
50802
  view() {
50788
50803
  let prevDoc;
50789
50804
  let prevActiveThreadId;
50805
+ let prevAllCommentPositions = {};
50790
50806
  return {
50791
50807
  update(view) {
50792
50808
  const { state: state2 } = view;
@@ -50797,16 +50813,19 @@ const CommentsPlugin = Extension.create({
50797
50813
  if (meta?.type === "setActiveComment" || meta?.forceUpdate) {
50798
50814
  shouldUpdate = true;
50799
50815
  }
50800
- if (prevDoc && !prevDoc.eq(doc2)) shouldUpdate = true;
50801
- if (prevActiveThreadId !== currentActiveThreadId) {
50816
+ const docChanged = prevDoc && !prevDoc.eq(doc2);
50817
+ if (docChanged) shouldUpdate = true;
50818
+ const activeThreadChanged = prevActiveThreadId !== currentActiveThreadId;
50819
+ if (activeThreadChanged) {
50802
50820
  shouldUpdate = true;
50803
50821
  prevActiveThreadId = currentActiveThreadId;
50804
50822
  }
50823
+ const onlyActiveThreadChanged = !docChanged && activeThreadChanged;
50805
50824
  if (!shouldUpdate) return;
50806
50825
  prevDoc = doc2;
50807
50826
  shouldUpdate = false;
50808
50827
  const decorations = [];
50809
- const allCommentPositions = {};
50828
+ const allCommentPositions = onlyActiveThreadChanged ? prevAllCommentPositions : {};
50810
50829
  doc2.descendants((node, pos) => {
50811
50830
  const { marks = [] } = node;
50812
50831
  const commentMarks = marks.filter((mark) => mark.type.name === CommentMarkName);
@@ -50814,14 +50833,16 @@ const CommentsPlugin = Extension.create({
50814
50833
  commentMarks.forEach((commentMark) => {
50815
50834
  const { attrs } = commentMark;
50816
50835
  const threadId = attrs.commentId || attrs.importedId;
50817
- const currentBounds = view.coordsAtPos(pos);
50818
- updatePosition({
50819
- allCommentPositions,
50820
- threadId,
50821
- pos,
50822
- currentBounds,
50823
- node
50824
- });
50836
+ if (!onlyActiveThreadChanged) {
50837
+ const currentBounds = view.coordsAtPos(pos);
50838
+ updatePosition({
50839
+ allCommentPositions,
50840
+ threadId,
50841
+ pos,
50842
+ currentBounds,
50843
+ node
50844
+ });
50845
+ }
50825
50846
  const isInternal = attrs.internal;
50826
50847
  if (!hasActive) hasActive = currentActiveThreadId === threadId;
50827
50848
  let color = getHighlightColor({
@@ -50844,20 +50865,22 @@ const CommentsPlugin = Extension.create({
50844
50865
  to: pos + node.nodeSize
50845
50866
  });
50846
50867
  if (trackedChangeMark) {
50847
- const currentBounds = view.coordsAtPos(pos);
50848
- const { id } = trackedChangeMark.mark.attrs;
50849
- updatePosition({
50850
- allCommentPositions,
50851
- threadId: id,
50852
- pos,
50853
- currentBounds,
50854
- node
50855
- });
50856
- const isActiveTrackedChange = currentActiveThreadId === id;
50868
+ if (!onlyActiveThreadChanged) {
50869
+ const currentBounds = view.coordsAtPos(pos);
50870
+ const { id } = trackedChangeMark.mark.attrs;
50871
+ updatePosition({
50872
+ allCommentPositions,
50873
+ threadId: id,
50874
+ pos,
50875
+ currentBounds,
50876
+ node
50877
+ });
50878
+ }
50879
+ const isActiveTrackedChange = currentActiveThreadId === trackedChangeMark.mark.attrs.id;
50857
50880
  if (isActiveTrackedChange) {
50858
50881
  const trackedChangeDeco = Decoration.inline(pos, pos + node.nodeSize, {
50859
50882
  style: `border-width: 2px;`,
50860
- "data-thread-id": id,
50883
+ "data-thread-id": trackedChangeMark.mark.attrs.id,
50861
50884
  class: "sd-editor-tracked-change-highlight"
50862
50885
  });
50863
50886
  decorations.push(trackedChangeDeco);
@@ -50875,7 +50898,13 @@ const CommentsPlugin = Extension.create({
50875
50898
  });
50876
50899
  view.dispatch(tr2);
50877
50900
  }
50878
- editor.emit("comment-positions", { allCommentPositions });
50901
+ if (!onlyActiveThreadChanged) {
50902
+ const positionsChanged = hasPositionsChanged(prevAllCommentPositions, allCommentPositions);
50903
+ if (positionsChanged) {
50904
+ prevAllCommentPositions = allCommentPositions;
50905
+ editor.emit("comment-positions", { allCommentPositions });
50906
+ }
50907
+ }
50879
50908
  }
50880
50909
  };
50881
50910
  }
@@ -50883,6 +50912,19 @@ const CommentsPlugin = Extension.create({
50883
50912
  return [commentsPlugin];
50884
50913
  }
50885
50914
  });
50915
+ const hasPositionsChanged = (prevPositions, currPositions) => {
50916
+ const prevKeys = Object.keys(prevPositions);
50917
+ const currKeys = Object.keys(currPositions);
50918
+ if (prevKeys.length !== currKeys.length) return true;
50919
+ for (const key2 of currKeys) {
50920
+ const prev = prevPositions[key2];
50921
+ const curr = currPositions[key2];
50922
+ if (!prev || prev.top !== curr.top || prev.left !== curr.left) {
50923
+ return true;
50924
+ }
50925
+ }
50926
+ return false;
50927
+ };
50886
50928
  const getActiveCommentId = (doc2, selection) => {
50887
50929
  if (!selection) return;
50888
50930
  const { $from, $to } = selection;
@@ -53649,7 +53691,7 @@ const _Editor = class _Editor2 extends EventEmitter$1 {
53649
53691
  { default: remarkStringify },
53650
53692
  { default: remarkGfm }
53651
53693
  ] = await Promise.all([
53652
- Promise.resolve().then(() => require("./index-BNr0wgOU-Bg5kSvF0.cjs")),
53694
+ Promise.resolve().then(() => require("./index-BNr0wgOU-DGdWV9Iz.cjs")),
53653
53695
  Promise.resolve().then(() => require("./index-DRCvimau-H4Ck3S9a.cjs")),
53654
53696
  Promise.resolve().then(() => require("./index-C_x_N6Uh-Db3CUJMX.cjs")),
53655
53697
  Promise.resolve().then(() => require("./index-D_sWOSiG-BtDZzJ6I.cjs")),
@@ -58087,8 +58129,36 @@ const createLinkedStylesPlugin = (editor) => {
58087
58129
  if (!editor.converter || editor.options.mode !== "docx") return { ...prev };
58088
58130
  let decorations = prev.decorations || DecorationSet.empty;
58089
58131
  if (tr.docChanged) {
58090
- const styles = LinkedStylesPluginKey.getState(editor.state).styles;
58091
- decorations = generateDecorations(newEditorState, styles);
58132
+ let mightAffectStyles = false;
58133
+ const styleRelatedMarks = /* @__PURE__ */ new Set(["textStyle", "bold", "italic", "underline", "strike"]);
58134
+ tr.steps.forEach((step) => {
58135
+ if (step.slice) {
58136
+ step.slice.content.descendants((node) => {
58137
+ if (node.attrs?.styleId) {
58138
+ mightAffectStyles = true;
58139
+ return false;
58140
+ }
58141
+ if (node.marks.length > 0) {
58142
+ const hasStyleMarks = node.marks.some((mark) => styleRelatedMarks.has(mark.type.name));
58143
+ if (hasStyleMarks) {
58144
+ mightAffectStyles = true;
58145
+ return false;
58146
+ }
58147
+ }
58148
+ });
58149
+ }
58150
+ if (step.jsonID === "addMark" || step.jsonID === "removeMark") {
58151
+ if (step.mark && styleRelatedMarks.has(step.mark.type.name)) {
58152
+ mightAffectStyles = true;
58153
+ }
58154
+ }
58155
+ });
58156
+ if (mightAffectStyles) {
58157
+ const styles = LinkedStylesPluginKey.getState(editor.state).styles;
58158
+ decorations = generateDecorations(newEditorState, styles);
58159
+ } else {
58160
+ decorations = decorations.map(tr.mapping, tr.doc);
58161
+ }
58092
58162
  }
58093
58163
  return { ...prev, decorations };
58094
58164
  }
@@ -58401,6 +58471,12 @@ function parseFontFamilyFromRunProperties(listRunProperties) {
58401
58471
  const eastAsia = listRunProperties?.["w:eastAsia"];
58402
58472
  return ascii || hAnsi || eastAsia || null;
58403
58473
  }
58474
+ const computedStylesCache = /* @__PURE__ */ new WeakMap();
58475
+ function clearComputedStyleCache(domNode) {
58476
+ if (domNode) {
58477
+ computedStylesCache.delete(domNode);
58478
+ }
58479
+ }
58404
58480
  function readNodeViewStyles(view) {
58405
58481
  const fallback = { fontSize: null, fontFamily: null, lineHeight: null };
58406
58482
  if (!view?.dom) return fallback;
@@ -58410,13 +58486,27 @@ function readNodeViewStyles(view) {
58410
58486
  lineHeight: view.dom.style?.lineHeight || null
58411
58487
  };
58412
58488
  if (inline.fontSize && inline.fontFamily && inline.lineHeight) return inline;
58489
+ if (computedStylesCache.has(view.dom)) {
58490
+ const cached = computedStylesCache.get(view.dom);
58491
+ return {
58492
+ fontSize: inline.fontSize || cached.fontSize,
58493
+ fontFamily: inline.fontFamily || cached.fontFamily,
58494
+ lineHeight: inline.lineHeight || cached.lineHeight
58495
+ };
58496
+ }
58413
58497
  const globalWindow = typeof window !== "undefined" ? window : void 0;
58414
58498
  if (globalWindow?.getComputedStyle) {
58415
58499
  const computed2 = globalWindow.getComputedStyle(view.dom);
58500
+ const computedStyles = {
58501
+ fontSize: computed2.fontSize,
58502
+ fontFamily: computed2.fontFamily,
58503
+ lineHeight: computed2.lineHeight
58504
+ };
58505
+ computedStylesCache.set(view.dom, computedStyles);
58416
58506
  return {
58417
- fontSize: inline.fontSize || computed2.fontSize,
58418
- fontFamily: inline.fontFamily || computed2.fontFamily,
58419
- lineHeight: inline.lineHeight || computed2.lineHeight
58507
+ fontSize: inline.fontSize || computedStyles.fontSize,
58508
+ fontFamily: inline.fontFamily || computedStyles.fontFamily,
58509
+ lineHeight: inline.lineHeight || computedStyles.lineHeight
58420
58510
  };
58421
58511
  }
58422
58512
  return inline;
@@ -58630,9 +58720,14 @@ class ListItemNodeView {
58630
58720
  });
58631
58721
  }
58632
58722
  update(node, decorations) {
58723
+ const prevNode = this.node;
58633
58724
  this.node = node;
58634
58725
  this.decorations = decorations;
58635
58726
  this.invalidateResolvedPos();
58727
+ const stylingAttrsChanged = !prevNode || prevNode.attrs.styleId !== node.attrs.styleId || prevNode.attrs.numId !== node.attrs.numId || prevNode.attrs.level !== node.attrs.level;
58728
+ if (stylingAttrsChanged) {
58729
+ clearComputedStyleCache(this.dom);
58730
+ }
58636
58731
  const { fontSize: fontSize2, fontFamily: fontFamily2, lineHeight: lineHeight2 } = resolveListItemTypography({
58637
58732
  node,
58638
58733
  pos: this.getResolvedPos(),
@@ -58643,11 +58738,15 @@ class ListItemNodeView {
58643
58738
  this.dom.style.fontSize = fontSize2;
58644
58739
  this.dom.style.fontFamily = fontFamily2 || "inherit";
58645
58740
  this.dom.style.lineHeight = lineHeight2 || "";
58646
- this.refreshIndentStyling();
58741
+ const attrsChanged = stylingAttrsChanged || prevNode?.attrs.indent !== node.attrs.indent;
58742
+ if (attrsChanged) {
58743
+ this.refreshIndentStyling();
58744
+ }
58647
58745
  }
58648
58746
  destroy() {
58649
58747
  activeListItemNodeViews.delete(this);
58650
58748
  this.numberingDOM.removeEventListener("click", this.handleNumberingClick);
58749
+ clearComputedStyleCache(this.dom);
58651
58750
  const caf = typeof globalThis !== "undefined" ? globalThis.cancelAnimationFrame : void 0;
58652
58751
  if (this._pendingIndentRefresh != null && typeof caf === "function") {
58653
58752
  caf(this._pendingIndentRefresh);
@@ -58766,8 +58865,11 @@ function calculateMarkerWidth(dom, numberingDOM, editor, { withPadding = true }
58766
58865
  if (!markerText.trim()) return 0;
58767
58866
  try {
58768
58867
  if (editor?.options?.isHeadless) return 0;
58868
+ if (typeof globalThis.CanvasRenderingContext2D === "undefined") return 0;
58769
58869
  const canvas = document.createElement("canvas");
58870
+ if (typeof canvas.getContext !== "function") return 0;
58770
58871
  const context = canvas.getContext("2d");
58872
+ if (!context) return 0;
58771
58873
  const fontSizePx = fontSize2.includes("pt") ? Number.parseFloat(fontSize2) * POINT_TO_PIXEL_CONVERSION_FACTOR : Number.parseFloat(fontSize2);
58772
58874
  context.font = `${fontSizePx}px ${fontFamily2}`;
58773
58875
  const textWidth = context.measureText(markerText).width;
@@ -58786,7 +58888,9 @@ function orderedListSync(editor) {
58786
58888
  appendTransaction(transactions, oldState, newState) {
58787
58889
  if (transactions.every((tr2) => tr2.getMeta("y-sync$"))) return null;
58788
58890
  const updateNodeViews = transactions.some((tr2) => tr2.getMeta("updatedListItemNodeViews"));
58789
- if (updateNodeViews || !hasInitialized) refreshAllListItemNodeViews();
58891
+ if (updateNodeViews || !hasInitialized) {
58892
+ refreshAllListItemNodeViews();
58893
+ }
58790
58894
  const isFromPlugin = transactions.some((tr2) => tr2.getMeta("orderedListSync"));
58791
58895
  const docChanged = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
58792
58896
  if (isFromPlugin || !docChanged) {
@@ -58798,10 +58902,24 @@ function orderedListSync(editor) {
58798
58902
  const listMap = /* @__PURE__ */ new Map();
58799
58903
  const listInitialized = /* @__PURE__ */ new Map();
58800
58904
  const shouldProcess = transactions.some((tr2) => {
58905
+ if (tr2.getMeta("updateListSync")) return true;
58801
58906
  return tr2.steps.some((step) => {
58802
58907
  const stepJSON = step.toJSON();
58803
- const hasUpdateMeta = tr2.getMeta("updateListSync");
58804
- return hasUpdateMeta || stepJSON && stepJSON.slice && JSON.stringify(stepJSON).includes('"listItem"');
58908
+ if (step.slice?.content) {
58909
+ let hasListItem = false;
58910
+ step.slice.content.descendants((node) => {
58911
+ if (node.type.name === "listItem") {
58912
+ hasListItem = true;
58913
+ return false;
58914
+ }
58915
+ });
58916
+ if (hasListItem) return true;
58917
+ }
58918
+ if (stepJSON && stepJSON.slice) {
58919
+ const jsonStr = JSON.stringify(stepJSON);
58920
+ if (jsonStr.includes('"listItem"')) return true;
58921
+ }
58922
+ return false;
58805
58923
  });
58806
58924
  });
58807
58925
  if (!shouldProcess) return null;
@@ -59271,17 +59389,68 @@ const Paragraph = OxmlNode.create({
59271
59389
  },
59272
59390
  addPmPlugins() {
59273
59391
  const { view } = this.editor;
59392
+ const dropcapWidthCache = /* @__PURE__ */ new Map();
59393
+ const hasDropcapParagraph = (node) => node.type.name === "paragraph" && node.attrs.dropcap?.type === "margin";
59394
+ const invalidateCacheForRange = (from2, to) => {
59395
+ for (const [pos] of dropcapWidthCache) {
59396
+ if (pos >= from2 && pos <= to) {
59397
+ dropcapWidthCache.delete(pos);
59398
+ }
59399
+ }
59400
+ };
59274
59401
  const dropcapPlugin = new Plugin({
59275
59402
  name: "dropcapPlugin",
59276
59403
  key: new PluginKey("dropcapPlugin"),
59277
59404
  state: {
59278
59405
  init(_2, state2) {
59279
- let decorations = getDropcapDecorations(state2, view);
59406
+ const decorations = getDropcapDecorations(state2, view, dropcapWidthCache);
59280
59407
  return DecorationSet.create(state2.doc, decorations);
59281
59408
  },
59282
59409
  apply(tr, oldDecorationSet, oldState, newState) {
59283
59410
  if (!tr.docChanged) return oldDecorationSet;
59284
- const decorations = getDropcapDecorations(newState, view);
59411
+ let hasDropcaps = false;
59412
+ newState.doc.descendants((node) => {
59413
+ if (hasDropcapParagraph(node)) {
59414
+ hasDropcaps = true;
59415
+ return false;
59416
+ }
59417
+ });
59418
+ if (!hasDropcaps) {
59419
+ dropcapWidthCache.clear();
59420
+ return DecorationSet.empty;
59421
+ }
59422
+ let affectsDropcaps = false;
59423
+ tr.steps.forEach((step) => {
59424
+ if (step.slice?.content) {
59425
+ step.slice.content.descendants((node) => {
59426
+ if (hasDropcapParagraph(node)) {
59427
+ affectsDropcaps = true;
59428
+ return false;
59429
+ }
59430
+ });
59431
+ }
59432
+ if (step.jsonID === "replace" && step.from !== void 0 && step.to !== void 0) {
59433
+ try {
59434
+ oldState.doc.nodesBetween(step.from, step.to, (node) => {
59435
+ if (hasDropcapParagraph(node)) {
59436
+ affectsDropcaps = true;
59437
+ return false;
59438
+ }
59439
+ });
59440
+ } catch {
59441
+ affectsDropcaps = true;
59442
+ }
59443
+ }
59444
+ });
59445
+ if (!affectsDropcaps) {
59446
+ return oldDecorationSet.map(tr.mapping, tr.doc);
59447
+ }
59448
+ tr.steps.forEach((step) => {
59449
+ if (step.from !== void 0 && step.to !== void 0) {
59450
+ invalidateCacheForRange(step.from, step.to);
59451
+ }
59452
+ });
59453
+ const decorations = getDropcapDecorations(newState, view, dropcapWidthCache);
59285
59454
  return DecorationSet.create(newState.doc, decorations);
59286
59455
  }
59287
59456
  },
@@ -59294,12 +59463,12 @@ const Paragraph = OxmlNode.create({
59294
59463
  return [dropcapPlugin];
59295
59464
  }
59296
59465
  });
59297
- const getDropcapDecorations = (state2, view) => {
59298
- let decorations = [];
59466
+ const getDropcapDecorations = (state2, view, widthCache) => {
59467
+ const decorations = [];
59299
59468
  state2.doc.descendants((node, pos) => {
59300
59469
  if (node.type.name === "paragraph") {
59301
59470
  if (node.attrs.dropcap?.type === "margin") {
59302
- const width = getDropcapWidth(view, pos);
59471
+ const width = getDropcapWidth(view, pos, widthCache);
59303
59472
  decorations.push(Decoration.inline(pos, pos + node.nodeSize, { style: `margin-left: -${width}px;` }));
59304
59473
  }
59305
59474
  return false;
@@ -59307,12 +59476,17 @@ const getDropcapDecorations = (state2, view) => {
59307
59476
  });
59308
59477
  return decorations;
59309
59478
  };
59310
- function getDropcapWidth(view, pos) {
59479
+ function getDropcapWidth(view, pos, widthCache) {
59480
+ if (widthCache.has(pos)) {
59481
+ return widthCache.get(pos);
59482
+ }
59311
59483
  const domNode = view.nodeDOM(pos);
59312
59484
  if (domNode) {
59313
59485
  const range2 = document.createRange();
59314
59486
  range2.selectNodeContents(domNode);
59315
- return range2.getBoundingClientRect().width;
59487
+ const width = range2.getBoundingClientRect().width;
59488
+ widthCache.set(pos, width);
59489
+ return width;
59316
59490
  }
59317
59491
  return 0;
59318
59492
  }
@@ -59774,7 +59948,7 @@ const TabNode = Node$1.create({
59774
59948
  },
59775
59949
  addPmPlugins() {
59776
59950
  const { view, helpers: helpers2 } = this.editor;
59777
- const mergeRanges = (ranges) => {
59951
+ const mergeRanges2 = (ranges) => {
59778
59952
  if (ranges.length === 0) return [];
59779
59953
  const sorted = ranges.slice().sort((a, b2) => a[0] - b2[0]);
59780
59954
  const merged = [sorted[0]];
@@ -59847,7 +60021,7 @@ const TabNode = Node$1.create({
59847
60021
  if (rangesToRecalculate.length === 0) {
59848
60022
  return { decorations };
59849
60023
  }
59850
- const mergedRanges = mergeRanges(rangesToRecalculate);
60024
+ const mergedRanges = mergeRanges2(rangesToRecalculate);
59851
60025
  mergedRanges.forEach(([start2, end2]) => {
59852
60026
  const oldDecorations = decorations.find(start2, end2);
59853
60027
  decorations = decorations.remove(oldDecorations);
@@ -63750,6 +63924,29 @@ createAnnotation_fn = function({ displayLabel } = {}) {
63750
63924
  content
63751
63925
  };
63752
63926
  };
63927
+ const mergeRanges = (ranges) => {
63928
+ if (ranges.length === 0) return [];
63929
+ const sorted = [...ranges].sort((a, b2) => a[0] - b2[0]).map((range2) => [...range2]);
63930
+ const merged = [sorted[0]];
63931
+ for (let i = 1; i < sorted.length; i++) {
63932
+ const current = sorted[i];
63933
+ const lastMerged = merged[merged.length - 1];
63934
+ if (current[0] <= lastMerged[1]) {
63935
+ lastMerged[1] = Math.max(lastMerged[1], current[1]);
63936
+ } else {
63937
+ merged.push(current);
63938
+ }
63939
+ }
63940
+ return merged;
63941
+ };
63942
+ const clampRange = (start2, end2, docSize) => {
63943
+ const safeStart = Math.max(0, Math.min(start2, docSize));
63944
+ const safeEnd = Math.max(0, Math.min(end2, docSize));
63945
+ if (safeStart >= safeEnd) {
63946
+ return null;
63947
+ }
63948
+ return [safeStart, safeEnd];
63949
+ };
63753
63950
  const FieldAnnotationPlugin = (options = {}) => {
63754
63951
  let { editor, annotationClass: annotationClass2 } = options;
63755
63952
  return new Plugin({
@@ -63824,24 +64021,104 @@ const FieldAnnotationPlugin = (options = {}) => {
63824
64021
  },
63825
64022
  /// For y-prosemirror support.
63826
64023
  appendTransaction: (transactions, oldState, newState) => {
63827
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
64024
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
63828
64025
  if (!docChanges) {
63829
64026
  return;
63830
64027
  }
63831
- let { tr } = newState;
63832
- let changed = false;
63833
- let annotations = getAllFieldAnnotations(newState);
63834
- if (!annotations.length) {
63835
- return;
64028
+ const affectedRanges = [];
64029
+ let hasFieldAnnotationsInSlice = false;
64030
+ let hasSteps = false;
64031
+ transactions.forEach((transaction) => {
64032
+ if (!transaction.steps) return;
64033
+ hasSteps = true;
64034
+ transaction.steps.forEach((step) => {
64035
+ if (step.slice?.content) {
64036
+ step.slice.content.descendants((node) => {
64037
+ if (node.type.name === "fieldAnnotation") {
64038
+ hasFieldAnnotationsInSlice = true;
64039
+ return false;
64040
+ }
64041
+ });
64042
+ }
64043
+ if (typeof step.from === "number" && typeof step.to === "number") {
64044
+ const from2 = step.from;
64045
+ const to = step.from === step.to && step.slice?.size ? step.from + step.slice.size : step.to;
64046
+ affectedRanges.push([from2, to]);
64047
+ }
64048
+ });
64049
+ });
64050
+ if (hasSteps && !hasFieldAnnotationsInSlice && affectedRanges.length > 0) {
64051
+ const mergedRanges = mergeRanges(affectedRanges);
64052
+ let hasExistingAnnotations = false;
64053
+ for (const [start2, end2] of mergedRanges) {
64054
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
64055
+ if (!clampedRange) continue;
64056
+ const [validStart, validEnd] = clampedRange;
64057
+ try {
64058
+ newState.doc.nodesBetween(validStart, validEnd, (node) => {
64059
+ if (node.type.name === "fieldAnnotation") {
64060
+ hasExistingAnnotations = true;
64061
+ return false;
64062
+ }
64063
+ });
64064
+ } catch (error) {
64065
+ console.warn("FieldAnnotationPlugin: range check failed, assuming annotations exist", error);
64066
+ hasExistingAnnotations = true;
64067
+ break;
64068
+ }
64069
+ if (hasExistingAnnotations) break;
64070
+ }
64071
+ if (!hasExistingAnnotations) {
64072
+ return;
64073
+ }
63836
64074
  }
63837
- annotations.forEach(({ node, pos }) => {
63838
- let { marks } = node;
63839
- let currentNode = tr.doc.nodeAt(pos);
64075
+ const { tr } = newState;
64076
+ let changed = false;
64077
+ const removeMarksFromAnnotation = (node, pos) => {
64078
+ const { marks } = node;
64079
+ const currentNode = tr.doc.nodeAt(pos);
63840
64080
  if (marks.length > 0 && node.eq(currentNode)) {
63841
64081
  tr.removeMark(pos, pos + node.nodeSize, null);
63842
64082
  changed = true;
63843
64083
  }
63844
- });
64084
+ };
64085
+ if (affectedRanges.length > 0) {
64086
+ const mergedRanges = mergeRanges(affectedRanges);
64087
+ let shouldFallbackToFullScan = false;
64088
+ for (const [start2, end2] of mergedRanges) {
64089
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
64090
+ if (!clampedRange) continue;
64091
+ const [validStart, validEnd] = clampedRange;
64092
+ try {
64093
+ newState.doc.nodesBetween(validStart, validEnd, (node, pos) => {
64094
+ if (node.type.name === "fieldAnnotation") {
64095
+ removeMarksFromAnnotation(node, pos);
64096
+ }
64097
+ });
64098
+ } catch (error) {
64099
+ console.warn("FieldAnnotationPlugin: nodesBetween failed, falling back to full scan", error);
64100
+ shouldFallbackToFullScan = true;
64101
+ break;
64102
+ }
64103
+ }
64104
+ if (shouldFallbackToFullScan) {
64105
+ const annotations = getAllFieldAnnotations(newState);
64106
+ if (!annotations.length) {
64107
+ return changed ? tr : null;
64108
+ }
64109
+ annotations.forEach(({ node, pos }) => {
64110
+ removeMarksFromAnnotation(node, pos);
64111
+ });
64112
+ }
64113
+ } else {
64114
+ const annotations = getAllFieldAnnotations(newState);
64115
+ if (!annotations.length) {
64116
+ return;
64117
+ }
64118
+ annotations.forEach(({ node, pos }) => {
64119
+ removeMarksFromAnnotation(node, pos);
64120
+ });
64121
+ }
63845
64122
  return changed ? tr : null;
63846
64123
  }
63847
64124
  ///
@@ -65651,7 +65928,9 @@ const registerImages = async (foundImages, editor, view) => {
65651
65928
  }
65652
65929
  });
65653
65930
  };
65931
+ const stepHasSlice = (step) => "slice" in step && Boolean(step.slice);
65654
65932
  const ImagePositionPluginKey = new PluginKey("ImagePosition");
65933
+ const pageBreakPositionCache = /* @__PURE__ */ new WeakMap();
65655
65934
  const ImagePositionPlugin = ({ editor }) => {
65656
65935
  const { view } = editor;
65657
65936
  let shouldUpdate = false;
@@ -65664,6 +65943,20 @@ const ImagePositionPlugin = ({ editor }) => {
65664
65943
  },
65665
65944
  apply(tr, oldDecorationSet, oldState, newState) {
65666
65945
  if (!tr.docChanged && !shouldUpdate) return oldDecorationSet;
65946
+ let affectsImages = false;
65947
+ tr.steps.forEach((step) => {
65948
+ if (stepHasSlice(step)) {
65949
+ step.slice.content.descendants((node) => {
65950
+ if (node.type.name === "image" || node.attrs?.anchorData) {
65951
+ affectsImages = true;
65952
+ return false;
65953
+ }
65954
+ });
65955
+ }
65956
+ });
65957
+ if (!affectsImages && !shouldUpdate) {
65958
+ return oldDecorationSet.map(tr.mapping, tr.doc);
65959
+ }
65667
65960
  const decorations = getImagePositionDecorations(newState, view);
65668
65961
  shouldUpdate = false;
65669
65962
  return DecorationSet.create(newState.doc, decorations);
@@ -65693,6 +65986,16 @@ const ImagePositionPlugin = ({ editor }) => {
65693
65986
  };
65694
65987
  const getImagePositionDecorations = (state2, view) => {
65695
65988
  let decorations = [];
65989
+ let hasAnchoredImages = false;
65990
+ state2.doc.descendants((node) => {
65991
+ if (node.attrs?.anchorData) {
65992
+ hasAnchoredImages = true;
65993
+ return false;
65994
+ }
65995
+ });
65996
+ if (!hasAnchoredImages) {
65997
+ return decorations;
65998
+ }
65696
65999
  state2.doc.descendants((node, pos) => {
65697
66000
  if (node.attrs.anchorData) {
65698
66001
  let style2 = "";
@@ -65701,7 +66004,15 @@ const getImagePositionDecorations = (state2, view) => {
65701
66004
  const { size: size2, padding } = node.attrs;
65702
66005
  const pageBreak = findPreviousDomNodeWithClass(view, pos, "pagination-break-wrapper");
65703
66006
  if (pageBreak && vRelativeFrom === "margin" && alignH) {
65704
- const topPos = pageBreak?.offsetTop + pageBreak?.offsetHeight;
66007
+ let pageBreakPos = pageBreakPositionCache.get(pageBreak);
66008
+ if (!pageBreakPos) {
66009
+ pageBreakPos = {
66010
+ top: pageBreak.offsetTop,
66011
+ height: pageBreak.offsetHeight
66012
+ };
66013
+ pageBreakPositionCache.set(pageBreak, pageBreakPos);
66014
+ }
66015
+ const topPos = pageBreakPos.top + pageBreakPos.height;
65705
66016
  let horizontalAlignment = `${alignH}: 0;`;
65706
66017
  if (alignH === "center") horizontalAlignment = "left: 50%; transform: translateX(-50%);";
65707
66018
  style2 += vRelativeFrom === "margin" ? `position: absolute; top: ${topPos}px; ${horizontalAlignment}` : "";
@@ -67193,11 +67504,22 @@ const BlockNode = Extension.create({
67193
67504
  },
67194
67505
  addPmPlugins() {
67195
67506
  let hasInitialized = false;
67507
+ const assignBlockId = (tr, node, pos) => {
67508
+ tr.setNodeMarkup(
67509
+ pos,
67510
+ void 0,
67511
+ {
67512
+ ...node.attrs,
67513
+ sdBlockId: v4()
67514
+ },
67515
+ node.marks
67516
+ );
67517
+ };
67196
67518
  return [
67197
67519
  new Plugin({
67198
67520
  key: BlockNodePluginKey,
67199
67521
  appendTransaction: (transactions, oldState, newState) => {
67200
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
67522
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
67201
67523
  if (hasInitialized && !docChanges) {
67202
67524
  return;
67203
67525
  }
@@ -67206,21 +67528,87 @@ const BlockNode = Extension.create({
67206
67528
  }
67207
67529
  const { tr } = newState;
67208
67530
  let changed = false;
67209
- newState.doc.descendants((node, pos) => {
67210
- if (!nodeAllowsSdBlockIdAttr(node) || !nodeNeedsSdBlockId(node)) {
67211
- return;
67531
+ if (!hasInitialized) {
67532
+ newState.doc.descendants((node, pos) => {
67533
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
67534
+ assignBlockId(tr, node, pos);
67535
+ changed = true;
67536
+ }
67537
+ });
67538
+ } else {
67539
+ const rangesToCheck = [];
67540
+ let shouldFallbackToFullTraversal = false;
67541
+ transactions.forEach((transaction, txIndex) => {
67542
+ transaction.steps.forEach((step, stepIndex) => {
67543
+ if (!(step instanceof ReplaceStep)) return;
67544
+ const hasNewBlockNodes = step.slice?.content?.content?.some((node) => nodeAllowsSdBlockIdAttr(node));
67545
+ if (!hasNewBlockNodes) return;
67546
+ const stepMap = step.getMap();
67547
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
67548
+ if (newEnd <= newStart) {
67549
+ if (process$1$1.env.NODE_ENV === "development") {
67550
+ console.debug("Block node: invalid range in step map, falling back to full traversal");
67551
+ }
67552
+ shouldFallbackToFullTraversal = true;
67553
+ return;
67554
+ }
67555
+ let rangeStart = newStart;
67556
+ let rangeEnd = newEnd;
67557
+ for (let i = stepIndex + 1; i < transaction.steps.length; i++) {
67558
+ const laterStepMap = transaction.steps[i].getMap();
67559
+ rangeStart = laterStepMap.map(rangeStart, -1);
67560
+ rangeEnd = laterStepMap.map(rangeEnd, 1);
67561
+ }
67562
+ for (let i = txIndex + 1; i < transactions.length; i++) {
67563
+ const laterTx = transactions[i];
67564
+ rangeStart = laterTx.mapping.map(rangeStart, -1);
67565
+ rangeEnd = laterTx.mapping.map(rangeEnd, 1);
67566
+ }
67567
+ if (rangeEnd <= rangeStart) {
67568
+ if (process$1$1.env.NODE_ENV === "development") {
67569
+ console.debug("Block node: invalid range after mapping, falling back to full traversal");
67570
+ }
67571
+ shouldFallbackToFullTraversal = true;
67572
+ return;
67573
+ }
67574
+ rangesToCheck.push([rangeStart, rangeEnd]);
67575
+ });
67576
+ });
67577
+ });
67578
+ const mergedRanges = mergeRanges(rangesToCheck);
67579
+ for (const [start2, end2] of mergedRanges) {
67580
+ const docSize = newState.doc.content.size;
67581
+ const clampedRange = clampRange(start2, end2, docSize);
67582
+ if (!clampedRange) {
67583
+ if (process$1$1.env.NODE_ENV === "development") {
67584
+ console.debug("Block node: invalid range after clamping, falling back to full traversal");
67585
+ }
67586
+ shouldFallbackToFullTraversal = true;
67587
+ break;
67588
+ }
67589
+ const [safeStart, safeEnd] = clampedRange;
67590
+ try {
67591
+ newState.doc.nodesBetween(safeStart, safeEnd, (node, pos) => {
67592
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
67593
+ assignBlockId(tr, node, pos);
67594
+ changed = true;
67595
+ }
67596
+ });
67597
+ } catch (error) {
67598
+ console.warn("Block node plugin: nodesBetween failed, falling back to full traversal", error);
67599
+ shouldFallbackToFullTraversal = true;
67600
+ break;
67601
+ }
67212
67602
  }
67213
- tr.setNodeMarkup(
67214
- pos,
67215
- void 0,
67216
- {
67217
- ...node.attrs,
67218
- sdBlockId: v4()
67219
- },
67220
- node.marks
67221
- );
67222
- changed = true;
67223
- });
67603
+ if (shouldFallbackToFullTraversal) {
67604
+ newState.doc.descendants((node, pos) => {
67605
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
67606
+ assignBlockId(tr, node, pos);
67607
+ changed = true;
67608
+ }
67609
+ });
67610
+ }
67611
+ }
67224
67612
  if (changed && !hasInitialized) {
67225
67613
  hasInitialized = true;
67226
67614
  tr.setMeta("blockNodeInitialUpdate", true);
@@ -73696,8 +74084,8 @@ const PopoverPlugin = Extension.create({
73696
74084
  return {};
73697
74085
  },
73698
74086
  apply: (tr, value) => {
73699
- let newValue = { ...value };
73700
- if (tr.docChanged) {
74087
+ const newValue = { ...value };
74088
+ if (tr.docChanged || tr.selectionSet) {
73701
74089
  newValue.shouldUpdate = true;
73702
74090
  } else {
73703
74091
  newValue.shouldUpdate = false;
@@ -74952,6 +75340,8 @@ const Pagination = Extension.create({
74952
75340
  let shouldUpdate = false;
74953
75341
  let hasInitialized = false;
74954
75342
  let shouldInitialize = false;
75343
+ let paginationTimeout = null;
75344
+ const PAGINATION_DEBOUNCE_MS = 150;
74955
75345
  const paginationPlugin = new Plugin({
74956
75346
  key: PaginationPluginKey,
74957
75347
  state: {
@@ -74979,6 +75369,9 @@ const Pagination = Extension.create({
74979
75369
  shouldUpdate = true;
74980
75370
  shouldInitialize = meta.isReadyToInit;
74981
75371
  }
75372
+ if (meta && meta.skipPagination) {
75373
+ return { ...oldState };
75374
+ }
74982
75375
  const syncMeta = tr.getMeta("y-sync$");
74983
75376
  const listSyncMeta = tr.getMeta("orderedListSync");
74984
75377
  if (syncMeta && syncMeta.isChangeOrigin || listSyncMeta) {
@@ -75010,11 +75403,23 @@ const Pagination = Extension.create({
75010
75403
  shouldUpdate = false;
75011
75404
  return { ...oldState };
75012
75405
  }
75406
+ if (!isForceUpdate && hasInitialized && tr.docChanged) {
75407
+ let isMarkOnlyChange = true;
75408
+ tr.steps.forEach((step) => {
75409
+ if (step.jsonID !== "addMark" && step.jsonID !== "removeMark") {
75410
+ isMarkOnlyChange = false;
75411
+ }
75412
+ });
75413
+ if (isMarkOnlyChange) {
75414
+ shouldUpdate = false;
75415
+ return { ...oldState };
75416
+ }
75417
+ }
75013
75418
  shouldUpdate = true;
75014
75419
  if (isForceUpdate) shouldUpdate = true;
75015
75420
  return {
75016
75421
  ...oldState,
75017
- decorations: meta?.decorations?.map(tr.mapping, tr.doc) || DecorationSet.empty,
75422
+ decorations: meta?.decorations?.map(tr.mapping, tr.doc) || oldState.decorations.map(tr.mapping, tr.doc),
75018
75423
  isReadyToInit: shouldInitialize
75019
75424
  };
75020
75425
  }
@@ -75026,11 +75431,22 @@ const Pagination = Extension.create({
75026
75431
  update: (view) => {
75027
75432
  if (!PaginationPluginKey.getState(view.state)?.isEnabled) return;
75028
75433
  if (!shouldUpdate || isUpdating) return;
75029
- isUpdating = true;
75030
- hasInitialized = true;
75031
- performUpdate(editor, view, previousDecorations);
75032
- isUpdating = false;
75033
- shouldUpdate = false;
75434
+ const performPaginationUpdate = () => {
75435
+ if (!shouldUpdate) return;
75436
+ isUpdating = true;
75437
+ hasInitialized = true;
75438
+ performUpdate(editor, view, previousDecorations);
75439
+ isUpdating = false;
75440
+ shouldUpdate = false;
75441
+ };
75442
+ if (!hasInitialized) {
75443
+ performPaginationUpdate();
75444
+ return;
75445
+ }
75446
+ if (paginationTimeout) {
75447
+ clearTimeout(paginationTimeout);
75448
+ }
75449
+ paginationTimeout = setTimeout(performPaginationUpdate, PAGINATION_DEBOUNCE_MS);
75034
75450
  }
75035
75451
  };
75036
75452
  },