@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
@@ -57694,17 +57694,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
57694
57694
  },
57695
57695
  apply(tr, oldState, prevEditorState, newEditorState) {
57696
57696
  const meta2 = tr.getMeta(TrackChangesBasePluginKey);
57697
- if (!meta2) {
57698
- return {
57699
- ...oldState,
57700
- decorations: getTrackChangesDecorations(
57701
- newEditorState,
57702
- oldState.onlyOriginalShown,
57703
- oldState.onlyModifiedShown
57704
- )
57705
- };
57706
- }
57707
- if (meta2.type === "TRACK_CHANGES_ENABLE") {
57697
+ if (meta2 && meta2.type === "TRACK_CHANGES_ENABLE") {
57708
57698
  return {
57709
57699
  ...oldState,
57710
57700
  isTrackChangesActive: meta2.value === true,
@@ -57715,7 +57705,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
57715
57705
  )
57716
57706
  };
57717
57707
  }
57718
- if (meta2.type === "SHOW_ONLY_ORIGINAL") {
57708
+ if (meta2 && meta2.type === "SHOW_ONLY_ORIGINAL") {
57719
57709
  return {
57720
57710
  ...oldState,
57721
57711
  onlyOriginalShown: meta2.value === true,
@@ -57723,7 +57713,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
57723
57713
  decorations: getTrackChangesDecorations(newEditorState, meta2.value === true, false)
57724
57714
  };
57725
57715
  }
57726
- if (meta2.type === "SHOW_ONLY_MODIFIED") {
57716
+ if (meta2 && meta2.type === "SHOW_ONLY_MODIFIED") {
57727
57717
  return {
57728
57718
  ...oldState,
57729
57719
  onlyOriginalShown: false,
@@ -57731,6 +57721,31 @@ Please report this to https://github.com/markedjs/marked.`, e) {
57731
57721
  decorations: getTrackChangesDecorations(newEditorState, false, meta2.value === true)
57732
57722
  };
57733
57723
  }
57724
+ if (!tr.docChanged) {
57725
+ return oldState;
57726
+ }
57727
+ if (!meta2) {
57728
+ let mightAffectTrackChanges = false;
57729
+ tr.steps.forEach((step) => {
57730
+ if (step.slice || step.from !== step.to) {
57731
+ mightAffectTrackChanges = true;
57732
+ }
57733
+ });
57734
+ if (mightAffectTrackChanges) {
57735
+ return {
57736
+ ...oldState,
57737
+ decorations: getTrackChangesDecorations(
57738
+ newEditorState,
57739
+ oldState.onlyOriginalShown,
57740
+ oldState.onlyModifiedShown
57741
+ )
57742
+ };
57743
+ }
57744
+ return {
57745
+ ...oldState,
57746
+ decorations: oldState.decorations.map(tr.mapping, tr.doc)
57747
+ };
57748
+ }
57734
57749
  return {
57735
57750
  ...oldState,
57736
57751
  decorations: getTrackChangesDecorations(
@@ -58485,6 +58500,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58485
58500
  view() {
58486
58501
  let prevDoc;
58487
58502
  let prevActiveThreadId;
58503
+ let prevAllCommentPositions = {};
58488
58504
  return {
58489
58505
  update(view) {
58490
58506
  const { state: state2 } = view;
@@ -58495,16 +58511,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58495
58511
  if (meta2?.type === "setActiveComment" || meta2?.forceUpdate) {
58496
58512
  shouldUpdate = true;
58497
58513
  }
58498
- if (prevDoc && !prevDoc.eq(doc2)) shouldUpdate = true;
58499
- if (prevActiveThreadId !== currentActiveThreadId) {
58514
+ const docChanged = prevDoc && !prevDoc.eq(doc2);
58515
+ if (docChanged) shouldUpdate = true;
58516
+ const activeThreadChanged = prevActiveThreadId !== currentActiveThreadId;
58517
+ if (activeThreadChanged) {
58500
58518
  shouldUpdate = true;
58501
58519
  prevActiveThreadId = currentActiveThreadId;
58502
58520
  }
58521
+ const onlyActiveThreadChanged = !docChanged && activeThreadChanged;
58503
58522
  if (!shouldUpdate) return;
58504
58523
  prevDoc = doc2;
58505
58524
  shouldUpdate = false;
58506
58525
  const decorations = [];
58507
- const allCommentPositions = {};
58526
+ const allCommentPositions = onlyActiveThreadChanged ? prevAllCommentPositions : {};
58508
58527
  doc2.descendants((node2, pos) => {
58509
58528
  const { marks = [] } = node2;
58510
58529
  const commentMarks = marks.filter((mark2) => mark2.type.name === CommentMarkName);
@@ -58512,14 +58531,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58512
58531
  commentMarks.forEach((commentMark) => {
58513
58532
  const { attrs } = commentMark;
58514
58533
  const threadId = attrs.commentId || attrs.importedId;
58515
- const currentBounds = view.coordsAtPos(pos);
58516
- updatePosition({
58517
- allCommentPositions,
58518
- threadId,
58519
- pos,
58520
- currentBounds,
58521
- node: node2
58522
- });
58534
+ if (!onlyActiveThreadChanged) {
58535
+ const currentBounds = view.coordsAtPos(pos);
58536
+ updatePosition({
58537
+ allCommentPositions,
58538
+ threadId,
58539
+ pos,
58540
+ currentBounds,
58541
+ node: node2
58542
+ });
58543
+ }
58523
58544
  const isInternal = attrs.internal;
58524
58545
  if (!hasActive) hasActive = currentActiveThreadId === threadId;
58525
58546
  let color2 = getHighlightColor({
@@ -58542,20 +58563,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58542
58563
  to: pos + node2.nodeSize
58543
58564
  });
58544
58565
  if (trackedChangeMark) {
58545
- const currentBounds = view.coordsAtPos(pos);
58546
- const { id } = trackedChangeMark.mark.attrs;
58547
- updatePosition({
58548
- allCommentPositions,
58549
- threadId: id,
58550
- pos,
58551
- currentBounds,
58552
- node: node2
58553
- });
58554
- const isActiveTrackedChange = currentActiveThreadId === id;
58566
+ if (!onlyActiveThreadChanged) {
58567
+ const currentBounds = view.coordsAtPos(pos);
58568
+ const { id } = trackedChangeMark.mark.attrs;
58569
+ updatePosition({
58570
+ allCommentPositions,
58571
+ threadId: id,
58572
+ pos,
58573
+ currentBounds,
58574
+ node: node2
58575
+ });
58576
+ }
58577
+ const isActiveTrackedChange = currentActiveThreadId === trackedChangeMark.mark.attrs.id;
58555
58578
  if (isActiveTrackedChange) {
58556
58579
  const trackedChangeDeco = Decoration.inline(pos, pos + node2.nodeSize, {
58557
58580
  style: `border-width: 2px;`,
58558
- "data-thread-id": id,
58581
+ "data-thread-id": trackedChangeMark.mark.attrs.id,
58559
58582
  class: "sd-editor-tracked-change-highlight"
58560
58583
  });
58561
58584
  decorations.push(trackedChangeDeco);
@@ -58573,7 +58596,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58573
58596
  });
58574
58597
  view.dispatch(tr2);
58575
58598
  }
58576
- editor.emit("comment-positions", { allCommentPositions });
58599
+ if (!onlyActiveThreadChanged) {
58600
+ const positionsChanged = hasPositionsChanged(prevAllCommentPositions, allCommentPositions);
58601
+ if (positionsChanged) {
58602
+ prevAllCommentPositions = allCommentPositions;
58603
+ editor.emit("comment-positions", { allCommentPositions });
58604
+ }
58605
+ }
58577
58606
  }
58578
58607
  };
58579
58608
  }
@@ -58581,6 +58610,19 @@ Please report this to https://github.com/markedjs/marked.`, e) {
58581
58610
  return [commentsPlugin];
58582
58611
  }
58583
58612
  });
58613
+ const hasPositionsChanged = (prevPositions, currPositions) => {
58614
+ const prevKeys = Object.keys(prevPositions);
58615
+ const currKeys = Object.keys(currPositions);
58616
+ if (prevKeys.length !== currKeys.length) return true;
58617
+ for (const key2 of currKeys) {
58618
+ const prev = prevPositions[key2];
58619
+ const curr = currPositions[key2];
58620
+ if (!prev || prev.top !== curr.top || prev.left !== curr.left) {
58621
+ return true;
58622
+ }
58623
+ }
58624
+ return false;
58625
+ };
58584
58626
  const getActiveCommentId = (doc2, selection) => {
58585
58627
  if (!selection) return;
58586
58628
  const { $from, $to } = selection;
@@ -65785,8 +65827,36 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65785
65827
  if (!editor.converter || editor.options.mode !== "docx") return { ...prev };
65786
65828
  let decorations = prev.decorations || DecorationSet.empty;
65787
65829
  if (tr.docChanged) {
65788
- const styles = LinkedStylesPluginKey.getState(editor.state).styles;
65789
- decorations = generateDecorations(newEditorState, styles);
65830
+ let mightAffectStyles = false;
65831
+ const styleRelatedMarks = /* @__PURE__ */ new Set(["textStyle", "bold", "italic", "underline", "strike"]);
65832
+ tr.steps.forEach((step) => {
65833
+ if (step.slice) {
65834
+ step.slice.content.descendants((node2) => {
65835
+ if (node2.attrs?.styleId) {
65836
+ mightAffectStyles = true;
65837
+ return false;
65838
+ }
65839
+ if (node2.marks.length > 0) {
65840
+ const hasStyleMarks = node2.marks.some((mark2) => styleRelatedMarks.has(mark2.type.name));
65841
+ if (hasStyleMarks) {
65842
+ mightAffectStyles = true;
65843
+ return false;
65844
+ }
65845
+ }
65846
+ });
65847
+ }
65848
+ if (step.jsonID === "addMark" || step.jsonID === "removeMark") {
65849
+ if (step.mark && styleRelatedMarks.has(step.mark.type.name)) {
65850
+ mightAffectStyles = true;
65851
+ }
65852
+ }
65853
+ });
65854
+ if (mightAffectStyles) {
65855
+ const styles = LinkedStylesPluginKey.getState(editor.state).styles;
65856
+ decorations = generateDecorations(newEditorState, styles);
65857
+ } else {
65858
+ decorations = decorations.map(tr.mapping, tr.doc);
65859
+ }
65790
65860
  }
65791
65861
  return { ...prev, decorations };
65792
65862
  }
@@ -66099,6 +66169,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66099
66169
  const eastAsia = listRunProperties?.["w:eastAsia"];
66100
66170
  return ascii || hAnsi || eastAsia || null;
66101
66171
  }
66172
+ const computedStylesCache = /* @__PURE__ */ new WeakMap();
66173
+ function clearComputedStyleCache(domNode) {
66174
+ if (domNode) {
66175
+ computedStylesCache.delete(domNode);
66176
+ }
66177
+ }
66102
66178
  function readNodeViewStyles(view) {
66103
66179
  const fallback = { fontSize: null, fontFamily: null, lineHeight: null };
66104
66180
  if (!view?.dom) return fallback;
@@ -66108,13 +66184,27 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66108
66184
  lineHeight: view.dom.style?.lineHeight || null
66109
66185
  };
66110
66186
  if (inline.fontSize && inline.fontFamily && inline.lineHeight) return inline;
66187
+ if (computedStylesCache.has(view.dom)) {
66188
+ const cached = computedStylesCache.get(view.dom);
66189
+ return {
66190
+ fontSize: inline.fontSize || cached.fontSize,
66191
+ fontFamily: inline.fontFamily || cached.fontFamily,
66192
+ lineHeight: inline.lineHeight || cached.lineHeight
66193
+ };
66194
+ }
66111
66195
  const globalWindow = typeof window !== "undefined" ? window : void 0;
66112
66196
  if (globalWindow?.getComputedStyle) {
66113
66197
  const computed2 = globalWindow.getComputedStyle(view.dom);
66198
+ const computedStyles = {
66199
+ fontSize: computed2.fontSize,
66200
+ fontFamily: computed2.fontFamily,
66201
+ lineHeight: computed2.lineHeight
66202
+ };
66203
+ computedStylesCache.set(view.dom, computedStyles);
66114
66204
  return {
66115
- fontSize: inline.fontSize || computed2.fontSize,
66116
- fontFamily: inline.fontFamily || computed2.fontFamily,
66117
- lineHeight: inline.lineHeight || computed2.lineHeight
66205
+ fontSize: inline.fontSize || computedStyles.fontSize,
66206
+ fontFamily: inline.fontFamily || computedStyles.fontFamily,
66207
+ lineHeight: inline.lineHeight || computedStyles.lineHeight
66118
66208
  };
66119
66209
  }
66120
66210
  return inline;
@@ -66328,9 +66418,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66328
66418
  });
66329
66419
  }
66330
66420
  update(node2, decorations) {
66421
+ const prevNode = this.node;
66331
66422
  this.node = node2;
66332
66423
  this.decorations = decorations;
66333
66424
  this.invalidateResolvedPos();
66425
+ const stylingAttrsChanged = !prevNode || prevNode.attrs.styleId !== node2.attrs.styleId || prevNode.attrs.numId !== node2.attrs.numId || prevNode.attrs.level !== node2.attrs.level;
66426
+ if (stylingAttrsChanged) {
66427
+ clearComputedStyleCache(this.dom);
66428
+ }
66334
66429
  const { fontSize: fontSize2, fontFamily: fontFamily2, lineHeight: lineHeight2 } = resolveListItemTypography({
66335
66430
  node: node2,
66336
66431
  pos: this.getResolvedPos(),
@@ -66341,11 +66436,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66341
66436
  this.dom.style.fontSize = fontSize2;
66342
66437
  this.dom.style.fontFamily = fontFamily2 || "inherit";
66343
66438
  this.dom.style.lineHeight = lineHeight2 || "";
66344
- this.refreshIndentStyling();
66439
+ const attrsChanged = stylingAttrsChanged || prevNode?.attrs.indent !== node2.attrs.indent;
66440
+ if (attrsChanged) {
66441
+ this.refreshIndentStyling();
66442
+ }
66345
66443
  }
66346
66444
  destroy() {
66347
66445
  activeListItemNodeViews.delete(this);
66348
66446
  this.numberingDOM.removeEventListener("click", this.handleNumberingClick);
66447
+ clearComputedStyleCache(this.dom);
66349
66448
  const caf = typeof globalThis !== "undefined" ? globalThis.cancelAnimationFrame : void 0;
66350
66449
  if (this._pendingIndentRefresh != null && typeof caf === "function") {
66351
66450
  caf(this._pendingIndentRefresh);
@@ -66464,8 +66563,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66464
66563
  if (!markerText.trim()) return 0;
66465
66564
  try {
66466
66565
  if (editor?.options?.isHeadless) return 0;
66566
+ if (typeof globalThis.CanvasRenderingContext2D === "undefined") return 0;
66467
66567
  const canvas = document.createElement("canvas");
66568
+ if (typeof canvas.getContext !== "function") return 0;
66468
66569
  const context = canvas.getContext("2d");
66570
+ if (!context) return 0;
66469
66571
  const fontSizePx = fontSize2.includes("pt") ? Number.parseFloat(fontSize2) * POINT_TO_PIXEL_CONVERSION_FACTOR : Number.parseFloat(fontSize2);
66470
66572
  context.font = `${fontSizePx}px ${fontFamily2}`;
66471
66573
  const textWidth = context.measureText(markerText).width;
@@ -66484,7 +66586,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66484
66586
  appendTransaction(transactions, oldState, newState) {
66485
66587
  if (transactions.every((tr2) => tr2.getMeta("y-sync$"))) return null;
66486
66588
  const updateNodeViews = transactions.some((tr2) => tr2.getMeta("updatedListItemNodeViews"));
66487
- if (updateNodeViews || !hasInitialized) refreshAllListItemNodeViews();
66589
+ if (updateNodeViews || !hasInitialized) {
66590
+ refreshAllListItemNodeViews();
66591
+ }
66488
66592
  const isFromPlugin = transactions.some((tr2) => tr2.getMeta("orderedListSync"));
66489
66593
  const docChanged = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
66490
66594
  if (isFromPlugin || !docChanged) {
@@ -66496,10 +66600,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66496
66600
  const listMap = /* @__PURE__ */ new Map();
66497
66601
  const listInitialized = /* @__PURE__ */ new Map();
66498
66602
  const shouldProcess = transactions.some((tr2) => {
66603
+ if (tr2.getMeta("updateListSync")) return true;
66499
66604
  return tr2.steps.some((step) => {
66500
66605
  const stepJSON = step.toJSON();
66501
- const hasUpdateMeta = tr2.getMeta("updateListSync");
66502
- return hasUpdateMeta || stepJSON && stepJSON.slice && JSON.stringify(stepJSON).includes('"listItem"');
66606
+ if (step.slice?.content) {
66607
+ let hasListItem = false;
66608
+ step.slice.content.descendants((node2) => {
66609
+ if (node2.type.name === "listItem") {
66610
+ hasListItem = true;
66611
+ return false;
66612
+ }
66613
+ });
66614
+ if (hasListItem) return true;
66615
+ }
66616
+ if (stepJSON && stepJSON.slice) {
66617
+ const jsonStr = JSON.stringify(stepJSON);
66618
+ if (jsonStr.includes('"listItem"')) return true;
66619
+ }
66620
+ return false;
66503
66621
  });
66504
66622
  });
66505
66623
  if (!shouldProcess) return null;
@@ -66969,17 +67087,68 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66969
67087
  },
66970
67088
  addPmPlugins() {
66971
67089
  const { view } = this.editor;
67090
+ const dropcapWidthCache = /* @__PURE__ */ new Map();
67091
+ const hasDropcapParagraph = (node2) => node2.type.name === "paragraph" && node2.attrs.dropcap?.type === "margin";
67092
+ const invalidateCacheForRange = (from2, to) => {
67093
+ for (const [pos] of dropcapWidthCache) {
67094
+ if (pos >= from2 && pos <= to) {
67095
+ dropcapWidthCache.delete(pos);
67096
+ }
67097
+ }
67098
+ };
66972
67099
  const dropcapPlugin = new Plugin({
66973
67100
  name: "dropcapPlugin",
66974
67101
  key: new PluginKey("dropcapPlugin"),
66975
67102
  state: {
66976
67103
  init(_2, state2) {
66977
- let decorations = getDropcapDecorations(state2, view);
67104
+ const decorations = getDropcapDecorations(state2, view, dropcapWidthCache);
66978
67105
  return DecorationSet.create(state2.doc, decorations);
66979
67106
  },
66980
67107
  apply(tr, oldDecorationSet, oldState, newState) {
66981
67108
  if (!tr.docChanged) return oldDecorationSet;
66982
- const decorations = getDropcapDecorations(newState, view);
67109
+ let hasDropcaps = false;
67110
+ newState.doc.descendants((node2) => {
67111
+ if (hasDropcapParagraph(node2)) {
67112
+ hasDropcaps = true;
67113
+ return false;
67114
+ }
67115
+ });
67116
+ if (!hasDropcaps) {
67117
+ dropcapWidthCache.clear();
67118
+ return DecorationSet.empty;
67119
+ }
67120
+ let affectsDropcaps = false;
67121
+ tr.steps.forEach((step) => {
67122
+ if (step.slice?.content) {
67123
+ step.slice.content.descendants((node2) => {
67124
+ if (hasDropcapParagraph(node2)) {
67125
+ affectsDropcaps = true;
67126
+ return false;
67127
+ }
67128
+ });
67129
+ }
67130
+ if (step.jsonID === "replace" && step.from !== void 0 && step.to !== void 0) {
67131
+ try {
67132
+ oldState.doc.nodesBetween(step.from, step.to, (node2) => {
67133
+ if (hasDropcapParagraph(node2)) {
67134
+ affectsDropcaps = true;
67135
+ return false;
67136
+ }
67137
+ });
67138
+ } catch {
67139
+ affectsDropcaps = true;
67140
+ }
67141
+ }
67142
+ });
67143
+ if (!affectsDropcaps) {
67144
+ return oldDecorationSet.map(tr.mapping, tr.doc);
67145
+ }
67146
+ tr.steps.forEach((step) => {
67147
+ if (step.from !== void 0 && step.to !== void 0) {
67148
+ invalidateCacheForRange(step.from, step.to);
67149
+ }
67150
+ });
67151
+ const decorations = getDropcapDecorations(newState, view, dropcapWidthCache);
66983
67152
  return DecorationSet.create(newState.doc, decorations);
66984
67153
  }
66985
67154
  },
@@ -66992,12 +67161,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66992
67161
  return [dropcapPlugin];
66993
67162
  }
66994
67163
  });
66995
- const getDropcapDecorations = (state2, view) => {
66996
- let decorations = [];
67164
+ const getDropcapDecorations = (state2, view, widthCache) => {
67165
+ const decorations = [];
66997
67166
  state2.doc.descendants((node2, pos) => {
66998
67167
  if (node2.type.name === "paragraph") {
66999
67168
  if (node2.attrs.dropcap?.type === "margin") {
67000
- const width = getDropcapWidth(view, pos);
67169
+ const width = getDropcapWidth(view, pos, widthCache);
67001
67170
  decorations.push(Decoration.inline(pos, pos + node2.nodeSize, { style: `margin-left: -${width}px;` }));
67002
67171
  }
67003
67172
  return false;
@@ -67005,12 +67174,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67005
67174
  });
67006
67175
  return decorations;
67007
67176
  };
67008
- function getDropcapWidth(view, pos) {
67177
+ function getDropcapWidth(view, pos, widthCache) {
67178
+ if (widthCache.has(pos)) {
67179
+ return widthCache.get(pos);
67180
+ }
67009
67181
  const domNode = view.nodeDOM(pos);
67010
67182
  if (domNode) {
67011
67183
  const range2 = document.createRange();
67012
67184
  range2.selectNodeContents(domNode);
67013
- return range2.getBoundingClientRect().width;
67185
+ const width = range2.getBoundingClientRect().width;
67186
+ widthCache.set(pos, width);
67187
+ return width;
67014
67188
  }
67015
67189
  return 0;
67016
67190
  }
@@ -67472,7 +67646,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67472
67646
  },
67473
67647
  addPmPlugins() {
67474
67648
  const { view, helpers: helpers2 } = this.editor;
67475
- const mergeRanges = (ranges) => {
67649
+ const mergeRanges2 = (ranges) => {
67476
67650
  if (ranges.length === 0) return [];
67477
67651
  const sorted = ranges.slice().sort((a2, b2) => a2[0] - b2[0]);
67478
67652
  const merged = [sorted[0]];
@@ -67545,7 +67719,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
67545
67719
  if (rangesToRecalculate.length === 0) {
67546
67720
  return { decorations };
67547
67721
  }
67548
- const mergedRanges = mergeRanges(rangesToRecalculate);
67722
+ const mergedRanges = mergeRanges2(rangesToRecalculate);
67549
67723
  mergedRanges.forEach(([start2, end2]) => {
67550
67724
  const oldDecorations = decorations.find(start2, end2);
67551
67725
  decorations = decorations.remove(oldDecorations);
@@ -71448,6 +71622,29 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71448
71622
  content: content2
71449
71623
  };
71450
71624
  };
71625
+ const mergeRanges = (ranges) => {
71626
+ if (ranges.length === 0) return [];
71627
+ const sorted = [...ranges].sort((a2, b2) => a2[0] - b2[0]).map((range2) => [...range2]);
71628
+ const merged = [sorted[0]];
71629
+ for (let i2 = 1; i2 < sorted.length; i2++) {
71630
+ const current = sorted[i2];
71631
+ const lastMerged = merged[merged.length - 1];
71632
+ if (current[0] <= lastMerged[1]) {
71633
+ lastMerged[1] = Math.max(lastMerged[1], current[1]);
71634
+ } else {
71635
+ merged.push(current);
71636
+ }
71637
+ }
71638
+ return merged;
71639
+ };
71640
+ const clampRange = (start2, end2, docSize) => {
71641
+ const safeStart = Math.max(0, Math.min(start2, docSize));
71642
+ const safeEnd = Math.max(0, Math.min(end2, docSize));
71643
+ if (safeStart >= safeEnd) {
71644
+ return null;
71645
+ }
71646
+ return [safeStart, safeEnd];
71647
+ };
71451
71648
  const FieldAnnotationPlugin = (options = {}) => {
71452
71649
  let { editor, annotationClass: annotationClass2 } = options;
71453
71650
  return new Plugin({
@@ -71522,24 +71719,104 @@ Please report this to https://github.com/markedjs/marked.`, e) {
71522
71719
  },
71523
71720
  /// For y-prosemirror support.
71524
71721
  appendTransaction: (transactions, oldState, newState) => {
71525
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
71722
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
71526
71723
  if (!docChanges) {
71527
71724
  return;
71528
71725
  }
71529
- let { tr } = newState;
71530
- let changed = false;
71531
- let annotations = getAllFieldAnnotations(newState);
71532
- if (!annotations.length) {
71533
- return;
71726
+ const affectedRanges = [];
71727
+ let hasFieldAnnotationsInSlice = false;
71728
+ let hasSteps = false;
71729
+ transactions.forEach((transaction) => {
71730
+ if (!transaction.steps) return;
71731
+ hasSteps = true;
71732
+ transaction.steps.forEach((step) => {
71733
+ if (step.slice?.content) {
71734
+ step.slice.content.descendants((node2) => {
71735
+ if (node2.type.name === "fieldAnnotation") {
71736
+ hasFieldAnnotationsInSlice = true;
71737
+ return false;
71738
+ }
71739
+ });
71740
+ }
71741
+ if (typeof step.from === "number" && typeof step.to === "number") {
71742
+ const from2 = step.from;
71743
+ const to = step.from === step.to && step.slice?.size ? step.from + step.slice.size : step.to;
71744
+ affectedRanges.push([from2, to]);
71745
+ }
71746
+ });
71747
+ });
71748
+ if (hasSteps && !hasFieldAnnotationsInSlice && affectedRanges.length > 0) {
71749
+ const mergedRanges = mergeRanges(affectedRanges);
71750
+ let hasExistingAnnotations = false;
71751
+ for (const [start2, end2] of mergedRanges) {
71752
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
71753
+ if (!clampedRange) continue;
71754
+ const [validStart, validEnd] = clampedRange;
71755
+ try {
71756
+ newState.doc.nodesBetween(validStart, validEnd, (node2) => {
71757
+ if (node2.type.name === "fieldAnnotation") {
71758
+ hasExistingAnnotations = true;
71759
+ return false;
71760
+ }
71761
+ });
71762
+ } catch (error) {
71763
+ console.warn("FieldAnnotationPlugin: range check failed, assuming annotations exist", error);
71764
+ hasExistingAnnotations = true;
71765
+ break;
71766
+ }
71767
+ if (hasExistingAnnotations) break;
71768
+ }
71769
+ if (!hasExistingAnnotations) {
71770
+ return;
71771
+ }
71534
71772
  }
71535
- annotations.forEach(({ node: node2, pos }) => {
71536
- let { marks } = node2;
71537
- let currentNode = tr.doc.nodeAt(pos);
71773
+ const { tr } = newState;
71774
+ let changed = false;
71775
+ const removeMarksFromAnnotation = (node2, pos) => {
71776
+ const { marks } = node2;
71777
+ const currentNode = tr.doc.nodeAt(pos);
71538
71778
  if (marks.length > 0 && node2.eq(currentNode)) {
71539
71779
  tr.removeMark(pos, pos + node2.nodeSize, null);
71540
71780
  changed = true;
71541
71781
  }
71542
- });
71782
+ };
71783
+ if (affectedRanges.length > 0) {
71784
+ const mergedRanges = mergeRanges(affectedRanges);
71785
+ let shouldFallbackToFullScan = false;
71786
+ for (const [start2, end2] of mergedRanges) {
71787
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
71788
+ if (!clampedRange) continue;
71789
+ const [validStart, validEnd] = clampedRange;
71790
+ try {
71791
+ newState.doc.nodesBetween(validStart, validEnd, (node2, pos) => {
71792
+ if (node2.type.name === "fieldAnnotation") {
71793
+ removeMarksFromAnnotation(node2, pos);
71794
+ }
71795
+ });
71796
+ } catch (error) {
71797
+ console.warn("FieldAnnotationPlugin: nodesBetween failed, falling back to full scan", error);
71798
+ shouldFallbackToFullScan = true;
71799
+ break;
71800
+ }
71801
+ }
71802
+ if (shouldFallbackToFullScan) {
71803
+ const annotations = getAllFieldAnnotations(newState);
71804
+ if (!annotations.length) {
71805
+ return changed ? tr : null;
71806
+ }
71807
+ annotations.forEach(({ node: node2, pos }) => {
71808
+ removeMarksFromAnnotation(node2, pos);
71809
+ });
71810
+ }
71811
+ } else {
71812
+ const annotations = getAllFieldAnnotations(newState);
71813
+ if (!annotations.length) {
71814
+ return;
71815
+ }
71816
+ annotations.forEach(({ node: node2, pos }) => {
71817
+ removeMarksFromAnnotation(node2, pos);
71818
+ });
71819
+ }
71543
71820
  return changed ? tr : null;
71544
71821
  }
71545
71822
  ///
@@ -73349,7 +73626,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73349
73626
  }
73350
73627
  });
73351
73628
  };
73629
+ const stepHasSlice = (step) => "slice" in step && Boolean(step.slice);
73352
73630
  const ImagePositionPluginKey = new PluginKey("ImagePosition");
73631
+ const pageBreakPositionCache = /* @__PURE__ */ new WeakMap();
73353
73632
  const ImagePositionPlugin = ({ editor }) => {
73354
73633
  const { view } = editor;
73355
73634
  let shouldUpdate = false;
@@ -73362,6 +73641,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73362
73641
  },
73363
73642
  apply(tr, oldDecorationSet, oldState, newState) {
73364
73643
  if (!tr.docChanged && !shouldUpdate) return oldDecorationSet;
73644
+ let affectsImages = false;
73645
+ tr.steps.forEach((step) => {
73646
+ if (stepHasSlice(step)) {
73647
+ step.slice.content.descendants((node2) => {
73648
+ if (node2.type.name === "image" || node2.attrs?.anchorData) {
73649
+ affectsImages = true;
73650
+ return false;
73651
+ }
73652
+ });
73653
+ }
73654
+ });
73655
+ if (!affectsImages && !shouldUpdate) {
73656
+ return oldDecorationSet.map(tr.mapping, tr.doc);
73657
+ }
73365
73658
  const decorations = getImagePositionDecorations(newState, view);
73366
73659
  shouldUpdate = false;
73367
73660
  return DecorationSet.create(newState.doc, decorations);
@@ -73391,6 +73684,16 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73391
73684
  };
73392
73685
  const getImagePositionDecorations = (state2, view) => {
73393
73686
  let decorations = [];
73687
+ let hasAnchoredImages = false;
73688
+ state2.doc.descendants((node2) => {
73689
+ if (node2.attrs?.anchorData) {
73690
+ hasAnchoredImages = true;
73691
+ return false;
73692
+ }
73693
+ });
73694
+ if (!hasAnchoredImages) {
73695
+ return decorations;
73696
+ }
73394
73697
  state2.doc.descendants((node2, pos) => {
73395
73698
  if (node2.attrs.anchorData) {
73396
73699
  let style2 = "";
@@ -73399,7 +73702,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73399
73702
  const { size: size2, padding } = node2.attrs;
73400
73703
  const pageBreak = findPreviousDomNodeWithClass(view, pos, "pagination-break-wrapper");
73401
73704
  if (pageBreak && vRelativeFrom === "margin" && alignH) {
73402
- const topPos = pageBreak?.offsetTop + pageBreak?.offsetHeight;
73705
+ let pageBreakPos = pageBreakPositionCache.get(pageBreak);
73706
+ if (!pageBreakPos) {
73707
+ pageBreakPos = {
73708
+ top: pageBreak.offsetTop,
73709
+ height: pageBreak.offsetHeight
73710
+ };
73711
+ pageBreakPositionCache.set(pageBreak, pageBreakPos);
73712
+ }
73713
+ const topPos = pageBreakPos.top + pageBreakPos.height;
73403
73714
  let horizontalAlignment = `${alignH}: 0;`;
73404
73715
  if (alignH === "center") horizontalAlignment = "left: 50%; transform: translateX(-50%);";
73405
73716
  style2 += vRelativeFrom === "margin" ? `position: absolute; top: ${topPos}px; ${horizontalAlignment}` : "";
@@ -74891,11 +75202,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
74891
75202
  },
74892
75203
  addPmPlugins() {
74893
75204
  let hasInitialized = false;
75205
+ const assignBlockId = (tr, node2, pos) => {
75206
+ tr.setNodeMarkup(
75207
+ pos,
75208
+ void 0,
75209
+ {
75210
+ ...node2.attrs,
75211
+ sdBlockId: v4$1()
75212
+ },
75213
+ node2.marks
75214
+ );
75215
+ };
74894
75216
  return [
74895
75217
  new Plugin({
74896
75218
  key: BlockNodePluginKey,
74897
75219
  appendTransaction: (transactions, oldState, newState) => {
74898
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
75220
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
74899
75221
  if (hasInitialized && !docChanges) {
74900
75222
  return;
74901
75223
  }
@@ -74904,21 +75226,87 @@ Please report this to https://github.com/markedjs/marked.`, e) {
74904
75226
  }
74905
75227
  const { tr } = newState;
74906
75228
  let changed = false;
74907
- newState.doc.descendants((node2, pos) => {
74908
- if (!nodeAllowsSdBlockIdAttr(node2) || !nodeNeedsSdBlockId(node2)) {
74909
- return;
75229
+ if (!hasInitialized) {
75230
+ newState.doc.descendants((node2, pos) => {
75231
+ if (nodeAllowsSdBlockIdAttr(node2) && nodeNeedsSdBlockId(node2)) {
75232
+ assignBlockId(tr, node2, pos);
75233
+ changed = true;
75234
+ }
75235
+ });
75236
+ } else {
75237
+ const rangesToCheck = [];
75238
+ let shouldFallbackToFullTraversal = false;
75239
+ transactions.forEach((transaction, txIndex) => {
75240
+ transaction.steps.forEach((step, stepIndex) => {
75241
+ if (!(step instanceof ReplaceStep)) return;
75242
+ const hasNewBlockNodes = step.slice?.content?.content?.some((node2) => nodeAllowsSdBlockIdAttr(node2));
75243
+ if (!hasNewBlockNodes) return;
75244
+ const stepMap = step.getMap();
75245
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
75246
+ if (newEnd <= newStart) {
75247
+ if (process$1$1.env.NODE_ENV === "development") {
75248
+ console.debug("Block node: invalid range in step map, falling back to full traversal");
75249
+ }
75250
+ shouldFallbackToFullTraversal = true;
75251
+ return;
75252
+ }
75253
+ let rangeStart = newStart;
75254
+ let rangeEnd = newEnd;
75255
+ for (let i2 = stepIndex + 1; i2 < transaction.steps.length; i2++) {
75256
+ const laterStepMap = transaction.steps[i2].getMap();
75257
+ rangeStart = laterStepMap.map(rangeStart, -1);
75258
+ rangeEnd = laterStepMap.map(rangeEnd, 1);
75259
+ }
75260
+ for (let i2 = txIndex + 1; i2 < transactions.length; i2++) {
75261
+ const laterTx = transactions[i2];
75262
+ rangeStart = laterTx.mapping.map(rangeStart, -1);
75263
+ rangeEnd = laterTx.mapping.map(rangeEnd, 1);
75264
+ }
75265
+ if (rangeEnd <= rangeStart) {
75266
+ if (process$1$1.env.NODE_ENV === "development") {
75267
+ console.debug("Block node: invalid range after mapping, falling back to full traversal");
75268
+ }
75269
+ shouldFallbackToFullTraversal = true;
75270
+ return;
75271
+ }
75272
+ rangesToCheck.push([rangeStart, rangeEnd]);
75273
+ });
75274
+ });
75275
+ });
75276
+ const mergedRanges = mergeRanges(rangesToCheck);
75277
+ for (const [start2, end2] of mergedRanges) {
75278
+ const docSize = newState.doc.content.size;
75279
+ const clampedRange = clampRange(start2, end2, docSize);
75280
+ if (!clampedRange) {
75281
+ if (process$1$1.env.NODE_ENV === "development") {
75282
+ console.debug("Block node: invalid range after clamping, falling back to full traversal");
75283
+ }
75284
+ shouldFallbackToFullTraversal = true;
75285
+ break;
75286
+ }
75287
+ const [safeStart, safeEnd] = clampedRange;
75288
+ try {
75289
+ newState.doc.nodesBetween(safeStart, safeEnd, (node2, pos) => {
75290
+ if (nodeAllowsSdBlockIdAttr(node2) && nodeNeedsSdBlockId(node2)) {
75291
+ assignBlockId(tr, node2, pos);
75292
+ changed = true;
75293
+ }
75294
+ });
75295
+ } catch (error) {
75296
+ console.warn("Block node plugin: nodesBetween failed, falling back to full traversal", error);
75297
+ shouldFallbackToFullTraversal = true;
75298
+ break;
75299
+ }
74910
75300
  }
74911
- tr.setNodeMarkup(
74912
- pos,
74913
- void 0,
74914
- {
74915
- ...node2.attrs,
74916
- sdBlockId: v4$1()
74917
- },
74918
- node2.marks
74919
- );
74920
- changed = true;
74921
- });
75301
+ if (shouldFallbackToFullTraversal) {
75302
+ newState.doc.descendants((node2, pos) => {
75303
+ if (nodeAllowsSdBlockIdAttr(node2) && nodeNeedsSdBlockId(node2)) {
75304
+ assignBlockId(tr, node2, pos);
75305
+ changed = true;
75306
+ }
75307
+ });
75308
+ }
75309
+ }
74922
75310
  if (changed && !hasInitialized) {
74923
75311
  hasInitialized = true;
74924
75312
  tr.setMeta("blockNodeInitialUpdate", true);
@@ -81394,8 +81782,8 @@ ${l}
81394
81782
  return {};
81395
81783
  },
81396
81784
  apply: (tr, value) => {
81397
- let newValue = { ...value };
81398
- if (tr.docChanged) {
81785
+ const newValue = { ...value };
81786
+ if (tr.docChanged || tr.selectionSet) {
81399
81787
  newValue.shouldUpdate = true;
81400
81788
  } else {
81401
81789
  newValue.shouldUpdate = false;
@@ -82650,6 +83038,8 @@ ${l}
82650
83038
  let shouldUpdate = false;
82651
83039
  let hasInitialized = false;
82652
83040
  let shouldInitialize = false;
83041
+ let paginationTimeout = null;
83042
+ const PAGINATION_DEBOUNCE_MS = 150;
82653
83043
  const paginationPlugin = new Plugin({
82654
83044
  key: PaginationPluginKey,
82655
83045
  state: {
@@ -82677,6 +83067,9 @@ ${l}
82677
83067
  shouldUpdate = true;
82678
83068
  shouldInitialize = meta2.isReadyToInit;
82679
83069
  }
83070
+ if (meta2 && meta2.skipPagination) {
83071
+ return { ...oldState };
83072
+ }
82680
83073
  const syncMeta = tr.getMeta("y-sync$");
82681
83074
  const listSyncMeta = tr.getMeta("orderedListSync");
82682
83075
  if (syncMeta && syncMeta.isChangeOrigin || listSyncMeta) {
@@ -82708,11 +83101,23 @@ ${l}
82708
83101
  shouldUpdate = false;
82709
83102
  return { ...oldState };
82710
83103
  }
83104
+ if (!isForceUpdate && hasInitialized && tr.docChanged) {
83105
+ let isMarkOnlyChange = true;
83106
+ tr.steps.forEach((step) => {
83107
+ if (step.jsonID !== "addMark" && step.jsonID !== "removeMark") {
83108
+ isMarkOnlyChange = false;
83109
+ }
83110
+ });
83111
+ if (isMarkOnlyChange) {
83112
+ shouldUpdate = false;
83113
+ return { ...oldState };
83114
+ }
83115
+ }
82711
83116
  shouldUpdate = true;
82712
83117
  if (isForceUpdate) shouldUpdate = true;
82713
83118
  return {
82714
83119
  ...oldState,
82715
- decorations: meta2?.decorations?.map(tr.mapping, tr.doc) || DecorationSet.empty,
83120
+ decorations: meta2?.decorations?.map(tr.mapping, tr.doc) || oldState.decorations.map(tr.mapping, tr.doc),
82716
83121
  isReadyToInit: shouldInitialize
82717
83122
  };
82718
83123
  }
@@ -82724,11 +83129,22 @@ ${l}
82724
83129
  update: (view) => {
82725
83130
  if (!PaginationPluginKey.getState(view.state)?.isEnabled) return;
82726
83131
  if (!shouldUpdate || isUpdating) return;
82727
- isUpdating = true;
82728
- hasInitialized = true;
82729
- performUpdate(editor, view, previousDecorations);
82730
- isUpdating = false;
82731
- shouldUpdate = false;
83132
+ const performPaginationUpdate = () => {
83133
+ if (!shouldUpdate) return;
83134
+ isUpdating = true;
83135
+ hasInitialized = true;
83136
+ performUpdate(editor, view, previousDecorations);
83137
+ isUpdating = false;
83138
+ shouldUpdate = false;
83139
+ };
83140
+ if (!hasInitialized) {
83141
+ performPaginationUpdate();
83142
+ return;
83143
+ }
83144
+ if (paginationTimeout) {
83145
+ clearTimeout(paginationTimeout);
83146
+ }
83147
+ paginationTimeout = setTimeout(performPaginationUpdate, PAGINATION_DEBOUNCE_MS);
82732
83148
  }
82733
83149
  };
82734
83150
  },