@harbour-enterprises/superdoc 0.28.1 → 0.28.2

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 (60) hide show
  1. package/dist/chunks/{PdfViewer-DJkdA-8o.es.js → PdfViewer-DpWYWlWj.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-Can0yoW4.cjs → PdfViewer-lAbA0-lT.cjs} +1 -1
  3. package/dist/chunks/{index-BY-vlgKe.cjs → index-ByVhw_G0.cjs} +3 -3
  4. package/dist/chunks/{index-DidXsI6u.es.js → index-Dw2T2UIP.es.js} +3 -3
  5. package/dist/chunks/{index-njnq8umX-DU2xcaHZ.es.js → index-Dz5_CDAf-B9kc0ArX.es.js} +1 -1
  6. package/dist/chunks/{index-njnq8umX-_TfP84XP.cjs → index-Dz5_CDAf-C5D7BTD6.cjs} +1 -1
  7. package/dist/chunks/{super-editor.es-ksiTgGLm.cjs → super-editor.es-7iRvcDFc.cjs} +1607 -1123
  8. package/dist/chunks/{super-editor.es-Br566URP.es.js → super-editor.es-DnZ5Ru-q.es.js} +1607 -1123
  9. package/dist/core/types/index.d.ts.map +1 -1
  10. package/dist/super-editor/ai-writer.es.js +2 -2
  11. package/dist/super-editor/chunks/{converter-D6Z6OmA3.js → converter-C5g1OhUM.js} +654 -644
  12. package/dist/super-editor/chunks/{docx-zipper-Dni97kMT.js → docx-zipper-D9LLIDXC.js} +1 -1
  13. package/dist/super-editor/chunks/{editor-D3TKfdXs.js → editor-CD7hiFDo.js} +606 -132
  14. package/dist/super-editor/chunks/{index-njnq8umX.js → index-Dz5_CDAf.js} +1 -1
  15. package/dist/super-editor/chunks/{toolbar-fNE3luLB.js → toolbar-BC_z_xMq.js} +2 -2
  16. package/dist/super-editor/converter.es.js +1 -1
  17. package/dist/super-editor/docx-zipper.es.js +2 -2
  18. package/dist/super-editor/editor.es.js +3 -3
  19. package/dist/super-editor/file-zipper.es.js +1 -1
  20. package/dist/super-editor/super-editor/src/core/helpers/rangeUtils.d.ts +2 -0
  21. package/dist/super-editor/super-editor/src/extensions/field-annotation/FieldAnnotationPlugin.d.ts +5 -1
  22. package/dist/super-editor/super-editor/src/extensions/image/imageHelpers/imagePositionPlugin.d.ts +2 -0
  23. package/dist/super-editor/super-editor/src/extensions/list-item/helpers/listItemTypography.d.ts +5 -0
  24. package/dist/super-editor/super-editor/src/extensions/list-item/helpers/styledListMarkerPlugin.d.ts +11 -2
  25. package/dist/super-editor/super-editor/src/extensions/tab/helpers/tabDecorations.d.ts +4 -1
  26. package/dist/super-editor/super-editor.es.js +6 -6
  27. package/dist/super-editor/toolbar.es.js +2 -2
  28. package/dist/super-editor.cjs +1 -1
  29. package/dist/super-editor.es.js +1 -1
  30. package/dist/superdoc.cjs +2 -2
  31. package/dist/superdoc.es.js +2 -2
  32. package/dist/superdoc.umd.js +1371 -887
  33. package/dist/superdoc.umd.js.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/images/altText_add.svg +0 -3
  36. package/dist/images/altText_disclaimer.svg +0 -3
  37. package/dist/images/altText_done.svg +0 -3
  38. package/dist/images/altText_spinner.svg +0 -30
  39. package/dist/images/altText_warning.svg +0 -3
  40. package/dist/images/annotation-check.svg +0 -11
  41. package/dist/images/annotation-comment.svg +0 -16
  42. package/dist/images/annotation-help.svg +0 -26
  43. package/dist/images/annotation-insert.svg +0 -10
  44. package/dist/images/annotation-key.svg +0 -11
  45. package/dist/images/annotation-newparagraph.svg +0 -11
  46. package/dist/images/annotation-noicon.svg +0 -7
  47. package/dist/images/annotation-note.svg +0 -42
  48. package/dist/images/annotation-paperclip.svg +0 -6
  49. package/dist/images/annotation-paragraph.svg +0 -16
  50. package/dist/images/annotation-pushpin.svg +0 -7
  51. package/dist/images/cursor-editorFreeHighlight.svg +0 -6
  52. package/dist/images/cursor-editorFreeText.svg +0 -3
  53. package/dist/images/cursor-editorInk.svg +0 -4
  54. package/dist/images/cursor-editorTextHighlight.svg +0 -8
  55. package/dist/images/editor-toolbar-delete.svg +0 -5
  56. package/dist/images/loading-icon.gif +0 -0
  57. package/dist/images/messageBar_closingButton.svg +0 -3
  58. package/dist/images/messageBar_warning.svg +0 -3
  59. package/dist/images/toolbarButton-editorHighlight.svg +0 -6
  60. package/dist/images/toolbarButton-menuArrow.svg +0 -3
@@ -12,9 +12,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
12
12
  var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, initPagination_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ListItemNodeView_instances, init_fn3, applyIndentStyling_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn;
13
13
  import * as Y from "yjs";
14
14
  import { UndoManager, Item as Item$1, ContentType, Text as Text$1, XmlElement, encodeStateAsUpdate } from "yjs";
15
- import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as ReplaceStep, E as NodeRange, G as findWrapping, L as ListHelpers, H as findParentNode, I as isMacOS, J as isIOS, K as getSchemaTypeByName, O as inputRulesPlugin, Q as TrackDeleteMarkName, U as TrackInsertMarkName, V as v4, W as TrackFormatMarkName, X as comments_module_events, Y as findMark, Z as objectIncludes, _ as AddMarkStep, $ as RemoveMarkStep, a0 as twipsToLines, a1 as pixelsToTwips, a2 as helpers, a3 as posToDOMRect, a4 as CommandService, a5 as SuperConverter, a6 as createDocument, a7 as createDocFromMarkdown, a8 as createDocFromHTML, a9 as EditorState, aa as hasSomeParentWithClass, ab as isActive, ac as unflattenListsInHtml, ad as parseSizeUnit, ae as minMax, af as getLineHeightValueString, ag as updateDOMAttributes, ah as findChildren$5, ai as htmlHandler, aj as generateRandomSigned32BitIntStrId, ak as InputRule, al as kebabCase, am as findParentNodeClosestToPos, an as getListItemStyleDefinitions, ao as docxNumberingHelpers, ap as parseIndentElement, aq as combineIndents, ar as twipsToPixels, as as PIXELS_PER_INCH, at as SelectionRange, au as Transform, av as isInTable$1, aw as generateDocxRandomId, ax as insertNewRelationship, ay as inchesToPixels } from "./converter-D6Z6OmA3.js";
15
+ import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as ReplaceStep, E as NodeRange, G as findWrapping, L as ListHelpers, H as findParentNode, I as isMacOS, J as isIOS, K as getSchemaTypeByName, O as inputRulesPlugin, Q as TrackDeleteMarkName, U as TrackInsertMarkName, V as v4, W as TrackFormatMarkName, X as comments_module_events, Y as findMark, Z as objectIncludes, _ as AddMarkStep, $ as RemoveMarkStep, a0 as twipsToLines, a1 as pixelsToTwips, a2 as helpers, a3 as posToDOMRect, a4 as CommandService, a5 as SuperConverter, a6 as createDocument, a7 as createDocFromMarkdown, a8 as createDocFromHTML, a9 as EditorState, aa as hasSomeParentWithClass, ab as isActive, ac as unflattenListsInHtml, ad as parseSizeUnit, ae as minMax, af as getLineHeightValueString, ag as updateDOMAttributes, ah as findChildren$5, ai as htmlHandler, aj as generateRandomSigned32BitIntStrId, ak as InputRule, al as kebabCase, am as findParentNodeClosestToPos, an as getListItemStyleDefinitions, ao as docxNumberingHelpers, ap as parseIndentElement, aq as combineIndents, ar as twipsToPixels, as as PIXELS_PER_INCH, at as SelectionRange, au as Transform, av as isInTable$1, aw as generateDocxRandomId, ax as insertNewRelationship, ay as inchesToPixels } from "./converter-C5g1OhUM.js";
16
16
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
17
- import { D as DocxZipper } from "./docx-zipper-Dni97kMT.js";
17
+ import { D as DocxZipper } from "./docx-zipper-D9LLIDXC.js";
18
18
  var GOOD_LEAF_SIZE = 200;
19
19
  var RopeSequence = function RopeSequence2() {
20
20
  };
@@ -11302,17 +11302,7 @@ const TrackChangesBasePlugin = () => {
11302
11302
  },
11303
11303
  apply(tr, oldState, prevEditorState, newEditorState) {
11304
11304
  const meta = tr.getMeta(TrackChangesBasePluginKey);
11305
- if (!meta) {
11306
- return {
11307
- ...oldState,
11308
- decorations: getTrackChangesDecorations(
11309
- newEditorState,
11310
- oldState.onlyOriginalShown,
11311
- oldState.onlyModifiedShown
11312
- )
11313
- };
11314
- }
11315
- if (meta.type === "TRACK_CHANGES_ENABLE") {
11305
+ if (meta && meta.type === "TRACK_CHANGES_ENABLE") {
11316
11306
  return {
11317
11307
  ...oldState,
11318
11308
  isTrackChangesActive: meta.value === true,
@@ -11323,7 +11313,7 @@ const TrackChangesBasePlugin = () => {
11323
11313
  )
11324
11314
  };
11325
11315
  }
11326
- if (meta.type === "SHOW_ONLY_ORIGINAL") {
11316
+ if (meta && meta.type === "SHOW_ONLY_ORIGINAL") {
11327
11317
  return {
11328
11318
  ...oldState,
11329
11319
  onlyOriginalShown: meta.value === true,
@@ -11331,7 +11321,7 @@ const TrackChangesBasePlugin = () => {
11331
11321
  decorations: getTrackChangesDecorations(newEditorState, meta.value === true, false)
11332
11322
  };
11333
11323
  }
11334
- if (meta.type === "SHOW_ONLY_MODIFIED") {
11324
+ if (meta && meta.type === "SHOW_ONLY_MODIFIED") {
11335
11325
  return {
11336
11326
  ...oldState,
11337
11327
  onlyOriginalShown: false,
@@ -11339,6 +11329,31 @@ const TrackChangesBasePlugin = () => {
11339
11329
  decorations: getTrackChangesDecorations(newEditorState, false, meta.value === true)
11340
11330
  };
11341
11331
  }
11332
+ if (!tr.docChanged) {
11333
+ return oldState;
11334
+ }
11335
+ if (!meta) {
11336
+ let mightAffectTrackChanges = false;
11337
+ tr.steps.forEach((step) => {
11338
+ if (step.slice || step.from !== step.to) {
11339
+ mightAffectTrackChanges = true;
11340
+ }
11341
+ });
11342
+ if (mightAffectTrackChanges) {
11343
+ return {
11344
+ ...oldState,
11345
+ decorations: getTrackChangesDecorations(
11346
+ newEditorState,
11347
+ oldState.onlyOriginalShown,
11348
+ oldState.onlyModifiedShown
11349
+ )
11350
+ };
11351
+ }
11352
+ return {
11353
+ ...oldState,
11354
+ decorations: oldState.decorations.map(tr.mapping, tr.doc)
11355
+ };
11356
+ }
11342
11357
  return {
11343
11358
  ...oldState,
11344
11359
  decorations: getTrackChangesDecorations(
@@ -12093,6 +12108,7 @@ const CommentsPlugin = Extension.create({
12093
12108
  view() {
12094
12109
  let prevDoc;
12095
12110
  let prevActiveThreadId;
12111
+ let prevAllCommentPositions = {};
12096
12112
  return {
12097
12113
  update(view) {
12098
12114
  const { state } = view;
@@ -12103,16 +12119,19 @@ const CommentsPlugin = Extension.create({
12103
12119
  if (meta?.type === "setActiveComment" || meta?.forceUpdate) {
12104
12120
  shouldUpdate = true;
12105
12121
  }
12106
- if (prevDoc && !prevDoc.eq(doc2)) shouldUpdate = true;
12107
- if (prevActiveThreadId !== currentActiveThreadId) {
12122
+ const docChanged = prevDoc && !prevDoc.eq(doc2);
12123
+ if (docChanged) shouldUpdate = true;
12124
+ const activeThreadChanged = prevActiveThreadId !== currentActiveThreadId;
12125
+ if (activeThreadChanged) {
12108
12126
  shouldUpdate = true;
12109
12127
  prevActiveThreadId = currentActiveThreadId;
12110
12128
  }
12129
+ const onlyActiveThreadChanged = !docChanged && activeThreadChanged;
12111
12130
  if (!shouldUpdate) return;
12112
12131
  prevDoc = doc2;
12113
12132
  shouldUpdate = false;
12114
12133
  const decorations = [];
12115
- const allCommentPositions = {};
12134
+ const allCommentPositions = onlyActiveThreadChanged ? prevAllCommentPositions : {};
12116
12135
  doc2.descendants((node, pos) => {
12117
12136
  const { marks = [] } = node;
12118
12137
  const commentMarks = marks.filter((mark) => mark.type.name === CommentMarkName);
@@ -12120,14 +12139,16 @@ const CommentsPlugin = Extension.create({
12120
12139
  commentMarks.forEach((commentMark) => {
12121
12140
  const { attrs } = commentMark;
12122
12141
  const threadId = attrs.commentId || attrs.importedId;
12123
- const currentBounds = view.coordsAtPos(pos);
12124
- updatePosition({
12125
- allCommentPositions,
12126
- threadId,
12127
- pos,
12128
- currentBounds,
12129
- node
12130
- });
12142
+ if (!onlyActiveThreadChanged) {
12143
+ const currentBounds = view.coordsAtPos(pos);
12144
+ updatePosition({
12145
+ allCommentPositions,
12146
+ threadId,
12147
+ pos,
12148
+ currentBounds,
12149
+ node
12150
+ });
12151
+ }
12131
12152
  const isInternal = attrs.internal;
12132
12153
  if (!hasActive) hasActive = currentActiveThreadId === threadId;
12133
12154
  let color = getHighlightColor({
@@ -12150,20 +12171,22 @@ const CommentsPlugin = Extension.create({
12150
12171
  to: pos + node.nodeSize
12151
12172
  });
12152
12173
  if (trackedChangeMark) {
12153
- const currentBounds = view.coordsAtPos(pos);
12154
- const { id } = trackedChangeMark.mark.attrs;
12155
- updatePosition({
12156
- allCommentPositions,
12157
- threadId: id,
12158
- pos,
12159
- currentBounds,
12160
- node
12161
- });
12162
- const isActiveTrackedChange = currentActiveThreadId === id;
12174
+ if (!onlyActiveThreadChanged) {
12175
+ const currentBounds = view.coordsAtPos(pos);
12176
+ const { id } = trackedChangeMark.mark.attrs;
12177
+ updatePosition({
12178
+ allCommentPositions,
12179
+ threadId: id,
12180
+ pos,
12181
+ currentBounds,
12182
+ node
12183
+ });
12184
+ }
12185
+ const isActiveTrackedChange = currentActiveThreadId === trackedChangeMark.mark.attrs.id;
12163
12186
  if (isActiveTrackedChange) {
12164
12187
  const trackedChangeDeco = Decoration.inline(pos, pos + node.nodeSize, {
12165
12188
  style: `border-width: 2px;`,
12166
- "data-thread-id": id,
12189
+ "data-thread-id": trackedChangeMark.mark.attrs.id,
12167
12190
  class: "sd-editor-tracked-change-highlight"
12168
12191
  });
12169
12192
  decorations.push(trackedChangeDeco);
@@ -12181,7 +12204,13 @@ const CommentsPlugin = Extension.create({
12181
12204
  });
12182
12205
  view.dispatch(tr2);
12183
12206
  }
12184
- editor.emit("comment-positions", { allCommentPositions });
12207
+ if (!onlyActiveThreadChanged) {
12208
+ const positionsChanged = hasPositionsChanged(prevAllCommentPositions, allCommentPositions);
12209
+ if (positionsChanged) {
12210
+ prevAllCommentPositions = allCommentPositions;
12211
+ editor.emit("comment-positions", { allCommentPositions });
12212
+ }
12213
+ }
12185
12214
  }
12186
12215
  };
12187
12216
  }
@@ -12189,6 +12218,19 @@ const CommentsPlugin = Extension.create({
12189
12218
  return [commentsPlugin];
12190
12219
  }
12191
12220
  });
12221
+ const hasPositionsChanged = (prevPositions, currPositions) => {
12222
+ const prevKeys = Object.keys(prevPositions);
12223
+ const currKeys = Object.keys(currPositions);
12224
+ if (prevKeys.length !== currKeys.length) return true;
12225
+ for (const key2 of currKeys) {
12226
+ const prev = prevPositions[key2];
12227
+ const curr = currPositions[key2];
12228
+ if (!prev || prev.top !== curr.top || prev.left !== curr.left) {
12229
+ return true;
12230
+ }
12231
+ }
12232
+ return false;
12233
+ };
12192
12234
  const getActiveCommentId = (doc2, selection) => {
12193
12235
  if (!selection) return;
12194
12236
  const { $from, $to } = selection;
@@ -15002,7 +15044,7 @@ const _Editor = class _Editor extends EventEmitter {
15002
15044
  { default: remarkStringify },
15003
15045
  { default: remarkGfm }
15004
15046
  ] = await Promise.all([
15005
- import("./index-njnq8umX.js"),
15047
+ import("./index-Dz5_CDAf.js"),
15006
15048
  import("./index-DRCvimau.js"),
15007
15049
  import("./index-C_x_N6Uh.js"),
15008
15050
  import("./index-D_sWOSiG.js"),
@@ -15220,7 +15262,7 @@ const _Editor = class _Editor extends EventEmitter {
15220
15262
  * @returns {Object | void} Migration results
15221
15263
  */
15222
15264
  processCollaborationMigrations() {
15223
- console.debug("[checkVersionMigrations] Current editor version", "0.28.0");
15265
+ console.debug("[checkVersionMigrations] Current editor version", "0.28.1");
15224
15266
  if (!this.options.ydoc) return;
15225
15267
  const metaMap = this.options.ydoc.getMap("meta");
15226
15268
  let docVersion = metaMap.get("version");
@@ -19561,8 +19603,36 @@ const createLinkedStylesPlugin = (editor) => {
19561
19603
  if (!editor.converter || editor.options.mode !== "docx") return { ...prev };
19562
19604
  let decorations = prev.decorations || DecorationSet.empty;
19563
19605
  if (tr.docChanged) {
19564
- const styles = LinkedStylesPluginKey.getState(editor.state).styles;
19565
- decorations = generateDecorations(newEditorState, styles);
19606
+ let mightAffectStyles = false;
19607
+ const styleRelatedMarks = /* @__PURE__ */ new Set(["textStyle", "bold", "italic", "underline", "strike"]);
19608
+ tr.steps.forEach((step) => {
19609
+ if (step.slice) {
19610
+ step.slice.content.descendants((node) => {
19611
+ if (node.attrs?.styleId) {
19612
+ mightAffectStyles = true;
19613
+ return false;
19614
+ }
19615
+ if (node.marks.length > 0) {
19616
+ const hasStyleMarks = node.marks.some((mark) => styleRelatedMarks.has(mark.type.name));
19617
+ if (hasStyleMarks) {
19618
+ mightAffectStyles = true;
19619
+ return false;
19620
+ }
19621
+ }
19622
+ });
19623
+ }
19624
+ if (step.jsonID === "addMark" || step.jsonID === "removeMark") {
19625
+ if (step.mark && styleRelatedMarks.has(step.mark.type.name)) {
19626
+ mightAffectStyles = true;
19627
+ }
19628
+ }
19629
+ });
19630
+ if (mightAffectStyles) {
19631
+ const styles = LinkedStylesPluginKey.getState(editor.state).styles;
19632
+ decorations = generateDecorations(newEditorState, styles);
19633
+ } else {
19634
+ decorations = decorations.map(tr.mapping, tr.doc);
19635
+ }
19566
19636
  }
19567
19637
  return { ...prev, decorations };
19568
19638
  }
@@ -19875,6 +19945,12 @@ function parseFontFamilyFromRunProperties(listRunProperties) {
19875
19945
  const eastAsia = listRunProperties?.["w:eastAsia"];
19876
19946
  return ascii || hAnsi || eastAsia || null;
19877
19947
  }
19948
+ const computedStylesCache = /* @__PURE__ */ new WeakMap();
19949
+ function clearComputedStyleCache(domNode) {
19950
+ if (domNode) {
19951
+ computedStylesCache.delete(domNode);
19952
+ }
19953
+ }
19878
19954
  function readNodeViewStyles(view) {
19879
19955
  const fallback = { fontSize: null, fontFamily: null, lineHeight: null };
19880
19956
  if (!view?.dom) return fallback;
@@ -19884,13 +19960,27 @@ function readNodeViewStyles(view) {
19884
19960
  lineHeight: view.dom.style?.lineHeight || null
19885
19961
  };
19886
19962
  if (inline.fontSize && inline.fontFamily && inline.lineHeight) return inline;
19963
+ if (computedStylesCache.has(view.dom)) {
19964
+ const cached = computedStylesCache.get(view.dom);
19965
+ return {
19966
+ fontSize: inline.fontSize || cached.fontSize,
19967
+ fontFamily: inline.fontFamily || cached.fontFamily,
19968
+ lineHeight: inline.lineHeight || cached.lineHeight
19969
+ };
19970
+ }
19887
19971
  const globalWindow = typeof window !== "undefined" ? window : void 0;
19888
19972
  if (globalWindow?.getComputedStyle) {
19889
19973
  const computed2 = globalWindow.getComputedStyle(view.dom);
19974
+ const computedStyles = {
19975
+ fontSize: computed2.fontSize,
19976
+ fontFamily: computed2.fontFamily,
19977
+ lineHeight: computed2.lineHeight
19978
+ };
19979
+ computedStylesCache.set(view.dom, computedStyles);
19890
19980
  return {
19891
- fontSize: inline.fontSize || computed2.fontSize,
19892
- fontFamily: inline.fontFamily || computed2.fontFamily,
19893
- lineHeight: inline.lineHeight || computed2.lineHeight
19981
+ fontSize: inline.fontSize || computedStyles.fontSize,
19982
+ fontFamily: inline.fontFamily || computedStyles.fontFamily,
19983
+ lineHeight: inline.lineHeight || computedStyles.lineHeight
19894
19984
  };
19895
19985
  }
19896
19986
  return inline;
@@ -20104,9 +20194,14 @@ class ListItemNodeView {
20104
20194
  });
20105
20195
  }
20106
20196
  update(node, decorations) {
20197
+ const prevNode = this.node;
20107
20198
  this.node = node;
20108
20199
  this.decorations = decorations;
20109
20200
  this.invalidateResolvedPos();
20201
+ const stylingAttrsChanged = !prevNode || prevNode.attrs.styleId !== node.attrs.styleId || prevNode.attrs.numId !== node.attrs.numId || prevNode.attrs.level !== node.attrs.level;
20202
+ if (stylingAttrsChanged) {
20203
+ clearComputedStyleCache(this.dom);
20204
+ }
20110
20205
  const { fontSize, fontFamily, lineHeight } = resolveListItemTypography({
20111
20206
  node,
20112
20207
  pos: this.getResolvedPos(),
@@ -20117,11 +20212,15 @@ class ListItemNodeView {
20117
20212
  this.dom.style.fontSize = fontSize;
20118
20213
  this.dom.style.fontFamily = fontFamily || "inherit";
20119
20214
  this.dom.style.lineHeight = lineHeight || "";
20120
- this.refreshIndentStyling();
20215
+ const attrsChanged = stylingAttrsChanged || prevNode?.attrs.indent !== node.attrs.indent;
20216
+ if (attrsChanged) {
20217
+ this.refreshIndentStyling();
20218
+ }
20121
20219
  }
20122
20220
  destroy() {
20123
20221
  activeListItemNodeViews.delete(this);
20124
20222
  this.numberingDOM.removeEventListener("click", this.handleNumberingClick);
20223
+ clearComputedStyleCache(this.dom);
20125
20224
  const caf = typeof globalThis !== "undefined" ? globalThis.cancelAnimationFrame : void 0;
20126
20225
  if (this._pendingIndentRefresh != null && typeof caf === "function") {
20127
20226
  caf(this._pendingIndentRefresh);
@@ -20240,8 +20339,11 @@ function calculateMarkerWidth(dom, numberingDOM, editor, { withPadding = true }
20240
20339
  if (!markerText.trim()) return 0;
20241
20340
  try {
20242
20341
  if (editor?.options?.isHeadless) return 0;
20342
+ if (typeof globalThis.CanvasRenderingContext2D === "undefined") return 0;
20243
20343
  const canvas = document.createElement("canvas");
20344
+ if (typeof canvas.getContext !== "function") return 0;
20244
20345
  const context = canvas.getContext("2d");
20346
+ if (!context) return 0;
20245
20347
  const fontSizePx = fontSize.includes("pt") ? Number.parseFloat(fontSize) * POINT_TO_PIXEL_CONVERSION_FACTOR : Number.parseFloat(fontSize);
20246
20348
  context.font = `${fontSizePx}px ${fontFamily}`;
20247
20349
  const textWidth = context.measureText(markerText).width;
@@ -20260,7 +20362,9 @@ function orderedListSync(editor) {
20260
20362
  appendTransaction(transactions, oldState, newState) {
20261
20363
  if (transactions.every((tr2) => tr2.getMeta("y-sync$"))) return null;
20262
20364
  const updateNodeViews = transactions.some((tr2) => tr2.getMeta("updatedListItemNodeViews"));
20263
- if (updateNodeViews || !hasInitialized) refreshAllListItemNodeViews();
20365
+ if (updateNodeViews || !hasInitialized) {
20366
+ refreshAllListItemNodeViews();
20367
+ }
20264
20368
  const isFromPlugin = transactions.some((tr2) => tr2.getMeta("orderedListSync"));
20265
20369
  const docChanged = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
20266
20370
  if (isFromPlugin || !docChanged) {
@@ -20272,10 +20376,24 @@ function orderedListSync(editor) {
20272
20376
  const listMap = /* @__PURE__ */ new Map();
20273
20377
  const listInitialized = /* @__PURE__ */ new Map();
20274
20378
  const shouldProcess = transactions.some((tr2) => {
20379
+ if (tr2.getMeta("updateListSync")) return true;
20275
20380
  return tr2.steps.some((step) => {
20276
20381
  const stepJSON = step.toJSON();
20277
- const hasUpdateMeta = tr2.getMeta("updateListSync");
20278
- return hasUpdateMeta || stepJSON && stepJSON.slice && JSON.stringify(stepJSON).includes('"listItem"');
20382
+ if (step.slice?.content) {
20383
+ let hasListItem = false;
20384
+ step.slice.content.descendants((node) => {
20385
+ if (node.type.name === "listItem") {
20386
+ hasListItem = true;
20387
+ return false;
20388
+ }
20389
+ });
20390
+ if (hasListItem) return true;
20391
+ }
20392
+ if (stepJSON && stepJSON.slice) {
20393
+ const jsonStr = JSON.stringify(stepJSON);
20394
+ if (jsonStr.includes('"listItem"')) return true;
20395
+ }
20396
+ return false;
20279
20397
  });
20280
20398
  });
20281
20399
  if (!shouldProcess) return null;
@@ -20745,17 +20863,68 @@ const Paragraph = OxmlNode.create({
20745
20863
  },
20746
20864
  addPmPlugins() {
20747
20865
  const { view } = this.editor;
20866
+ const dropcapWidthCache = /* @__PURE__ */ new Map();
20867
+ const hasDropcapParagraph = (node) => node.type.name === "paragraph" && node.attrs.dropcap?.type === "margin";
20868
+ const invalidateCacheForRange = (from2, to) => {
20869
+ for (const [pos] of dropcapWidthCache) {
20870
+ if (pos >= from2 && pos <= to) {
20871
+ dropcapWidthCache.delete(pos);
20872
+ }
20873
+ }
20874
+ };
20748
20875
  const dropcapPlugin = new Plugin({
20749
20876
  name: "dropcapPlugin",
20750
20877
  key: new PluginKey("dropcapPlugin"),
20751
20878
  state: {
20752
20879
  init(_, state) {
20753
- let decorations = getDropcapDecorations(state, view);
20880
+ const decorations = getDropcapDecorations(state, view, dropcapWidthCache);
20754
20881
  return DecorationSet.create(state.doc, decorations);
20755
20882
  },
20756
20883
  apply(tr, oldDecorationSet, oldState, newState) {
20757
20884
  if (!tr.docChanged) return oldDecorationSet;
20758
- const decorations = getDropcapDecorations(newState, view);
20885
+ let hasDropcaps = false;
20886
+ newState.doc.descendants((node) => {
20887
+ if (hasDropcapParagraph(node)) {
20888
+ hasDropcaps = true;
20889
+ return false;
20890
+ }
20891
+ });
20892
+ if (!hasDropcaps) {
20893
+ dropcapWidthCache.clear();
20894
+ return DecorationSet.empty;
20895
+ }
20896
+ let affectsDropcaps = false;
20897
+ tr.steps.forEach((step) => {
20898
+ if (step.slice?.content) {
20899
+ step.slice.content.descendants((node) => {
20900
+ if (hasDropcapParagraph(node)) {
20901
+ affectsDropcaps = true;
20902
+ return false;
20903
+ }
20904
+ });
20905
+ }
20906
+ if (step.jsonID === "replace" && step.from !== void 0 && step.to !== void 0) {
20907
+ try {
20908
+ oldState.doc.nodesBetween(step.from, step.to, (node) => {
20909
+ if (hasDropcapParagraph(node)) {
20910
+ affectsDropcaps = true;
20911
+ return false;
20912
+ }
20913
+ });
20914
+ } catch {
20915
+ affectsDropcaps = true;
20916
+ }
20917
+ }
20918
+ });
20919
+ if (!affectsDropcaps) {
20920
+ return oldDecorationSet.map(tr.mapping, tr.doc);
20921
+ }
20922
+ tr.steps.forEach((step) => {
20923
+ if (step.from !== void 0 && step.to !== void 0) {
20924
+ invalidateCacheForRange(step.from, step.to);
20925
+ }
20926
+ });
20927
+ const decorations = getDropcapDecorations(newState, view, dropcapWidthCache);
20759
20928
  return DecorationSet.create(newState.doc, decorations);
20760
20929
  }
20761
20930
  },
@@ -20768,12 +20937,12 @@ const Paragraph = OxmlNode.create({
20768
20937
  return [dropcapPlugin];
20769
20938
  }
20770
20939
  });
20771
- const getDropcapDecorations = (state, view) => {
20772
- let decorations = [];
20940
+ const getDropcapDecorations = (state, view, widthCache) => {
20941
+ const decorations = [];
20773
20942
  state.doc.descendants((node, pos) => {
20774
20943
  if (node.type.name === "paragraph") {
20775
20944
  if (node.attrs.dropcap?.type === "margin") {
20776
- const width = getDropcapWidth(view, pos);
20945
+ const width = getDropcapWidth(view, pos, widthCache);
20777
20946
  decorations.push(Decoration.inline(pos, pos + node.nodeSize, { style: `margin-left: -${width}px;` }));
20778
20947
  }
20779
20948
  return false;
@@ -20781,12 +20950,17 @@ const getDropcapDecorations = (state, view) => {
20781
20950
  });
20782
20951
  return decorations;
20783
20952
  };
20784
- function getDropcapWidth(view, pos) {
20953
+ function getDropcapWidth(view, pos, widthCache) {
20954
+ if (widthCache.has(pos)) {
20955
+ return widthCache.get(pos);
20956
+ }
20785
20957
  const domNode = view.nodeDOM(pos);
20786
20958
  if (domNode) {
20787
20959
  const range = document.createRange();
20788
20960
  range.selectNodeContents(domNode);
20789
- return range.getBoundingClientRect().width;
20961
+ const width = range.getBoundingClientRect().width;
20962
+ widthCache.set(pos, width);
20963
+ return width;
20790
20964
  }
20791
20965
  return 0;
20792
20966
  }
@@ -20972,10 +21146,16 @@ const getTabDecorations = (doc2, view, helpers2, from2 = 0, to = null) => {
20972
21146
  const paragraphContext = getParagraphContext($pos, paragraphCache, helpers2);
20973
21147
  if (!paragraphContext) return;
20974
21148
  try {
20975
- const { tabStops, flattened, startPos } = paragraphContext;
20976
- const entryIndex = flattened.findIndex((entry) => entry.pos === pos);
20977
- if (entryIndex === -1) return;
20978
- const indentWidth = getIndentWidth(view, startPos, paragraphContext.indent, coordCache, domPosCache);
21149
+ const { tabStops, flattened, positionMap, startPos } = paragraphContext;
21150
+ const entryIndex = positionMap.get(pos);
21151
+ if (entryIndex === void 0) return;
21152
+ if (paragraphContext.indentWidth === void 0) {
21153
+ paragraphContext.indentWidth = getIndentWidth(view, startPos, paragraphContext.indent, coordCache, domPosCache);
21154
+ }
21155
+ if (paragraphContext.tabHeight === void 0) {
21156
+ paragraphContext.tabHeight = calcTabHeight($pos);
21157
+ }
21158
+ const indentWidth = paragraphContext.indentWidth;
20979
21159
  const accumulatedTabWidth = paragraphContext.accumulatedTabWidth || 0;
20980
21160
  const currentWidth = indentWidth + measureRangeWidth(view, startPos + 1, pos, coordCache, domPosCache) + accumulatedTabWidth;
20981
21161
  let tabWidth;
@@ -21017,7 +21197,7 @@ const getTabDecorations = (doc2, view, helpers2, from2 = 0, to = null) => {
21017
21197
  tabWidth = defaultTabDistance - currentWidth % defaultLineLength % defaultTabDistance;
21018
21198
  if (tabWidth === 0) tabWidth = defaultTabDistance;
21019
21199
  }
21020
- const tabHeight = calcTabHeight($pos);
21200
+ const tabHeight = paragraphContext.tabHeight;
21021
21201
  decorations.push(
21022
21202
  Decoration.node(pos, pos + node.nodeSize, {
21023
21203
  style: `width: ${tabWidth}px; height: ${tabHeight};${extraStyles}`
@@ -21045,13 +21225,16 @@ function getParagraphContext($pos, cache, helpers2) {
21045
21225
  tabStops = style.definition.styles.tabStops;
21046
21226
  }
21047
21227
  }
21228
+ const { entries, positionMap } = flattenParagraph(node, startPos);
21048
21229
  cache.set(startPos, {
21049
21230
  paragraph: node,
21050
21231
  paragraphDepth: depth,
21051
21232
  startPos,
21052
21233
  indent: node.attrs?.indent || {},
21053
21234
  tabStops,
21054
- flattened: flattenParagraph(node, startPos),
21235
+ flattened: entries,
21236
+ positionMap,
21237
+ // Store position map for O(1) lookups
21055
21238
  accumulatedTabWidth: 0
21056
21239
  });
21057
21240
  }
@@ -21062,6 +21245,7 @@ function getParagraphContext($pos, cache, helpers2) {
21062
21245
  }
21063
21246
  function flattenParagraph(paragraph, paragraphStartPos) {
21064
21247
  const entries = [];
21248
+ const positionMap = /* @__PURE__ */ new Map();
21065
21249
  const walk = (node, basePos) => {
21066
21250
  if (!node) return;
21067
21251
  if (node.type?.name === "run") {
@@ -21071,13 +21255,16 @@ function flattenParagraph(paragraph, paragraphStartPos) {
21071
21255
  });
21072
21256
  return;
21073
21257
  }
21074
- entries.push({ node, pos: basePos - 1 });
21258
+ const pos = basePos - 1;
21259
+ const index2 = entries.length;
21260
+ entries.push({ node, pos });
21261
+ positionMap.set(pos, index2);
21075
21262
  };
21076
21263
  paragraph.forEach((child, offset2) => {
21077
21264
  const childPos = paragraphStartPos + offset2 + 1;
21078
21265
  walk(child, childPos);
21079
21266
  });
21080
- return entries;
21267
+ return { entries, positionMap };
21081
21268
  }
21082
21269
  function findNextTabIndex(flattened, fromIndex) {
21083
21270
  for (let i = fromIndex; i < flattened.length; i++) {
@@ -21235,6 +21422,21 @@ const TabNode = Node$1.create({
21235
21422
  },
21236
21423
  addPmPlugins() {
21237
21424
  const { view, helpers: helpers2 } = this.editor;
21425
+ const mergeRanges2 = (ranges) => {
21426
+ if (ranges.length === 0) return [];
21427
+ const sorted = ranges.slice().sort((a, b) => a[0] - b[0]);
21428
+ const merged = [sorted[0]];
21429
+ for (let i = 1; i < sorted.length; i++) {
21430
+ const [start2, end2] = sorted[i];
21431
+ const last = merged[merged.length - 1];
21432
+ if (start2 <= last[1]) {
21433
+ last[1] = Math.max(last[1], end2);
21434
+ } else {
21435
+ merged.push([start2, end2]);
21436
+ }
21437
+ }
21438
+ return merged;
21439
+ };
21238
21440
  const tabPlugin = new Plugin({
21239
21441
  name: "tabPlugin",
21240
21442
  key: new PluginKey("tabPlugin"),
@@ -21245,43 +21447,56 @@ const TabNode = Node$1.create({
21245
21447
  apply(tr, { decorations }, _oldState, newState) {
21246
21448
  if (!decorations) {
21247
21449
  decorations = DecorationSet.create(newState.doc, getTabDecorations(newState.doc, view, helpers2));
21450
+ return { decorations };
21248
21451
  }
21249
- if (!tr.docChanged || tr.getMeta("blockNodeInitialUpdate") === true) {
21452
+ if (!tr.docChanged || tr.getMeta("blockNodeInitialUpdate")) {
21250
21453
  return { decorations };
21251
21454
  }
21252
21455
  decorations = decorations.map(tr.mapping, tr.doc);
21253
- let rangesToRecalculate = [];
21456
+ const rangesToRecalculate = [];
21457
+ const containsTab = (node) => node.type.name === "tab";
21254
21458
  tr.steps.forEach((step, index2) => {
21255
- const stepMap = step.getMap();
21256
- if (step instanceof ReplaceStep || step instanceof ReplaceAroundStep$1) {
21257
- const $from = tr.docs[index2].resolve(step.from);
21258
- const $to = tr.docs[index2].resolve(step.to);
21259
- const start2 = $from.start(Math.min($from.depth, 1));
21260
- const end2 = $to.end(Math.min($to.depth, 1));
21261
- let addRange = false;
21262
- tr.docs[index2].nodesBetween(start2, end2, (node) => {
21263
- if (node.type.name === "tab") {
21264
- addRange = true;
21459
+ if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep$1)) {
21460
+ return;
21461
+ }
21462
+ let hasTabInRange = false;
21463
+ if (step.slice?.content) {
21464
+ step.slice.content.descendants((node) => {
21465
+ if (containsTab(node)) {
21466
+ hasTabInRange = true;
21467
+ return false;
21265
21468
  }
21266
21469
  });
21267
- if (!addRange && step.slice?.content) {
21268
- step.slice.content.descendants((node) => {
21269
- if (node.type.name === "tab") {
21270
- addRange = true;
21271
- }
21272
- });
21273
- }
21274
- if (addRange) {
21275
- rangesToRecalculate.push([start2, end2]);
21276
- }
21277
21470
  }
21278
- rangesToRecalculate = rangesToRecalculate.map(([from2, to]) => {
21279
- const mappedFrom = stepMap.map(from2, -1);
21280
- const mappedTo = stepMap.map(to, 1);
21281
- return [mappedFrom, mappedTo];
21282
- });
21471
+ if (!hasTabInRange) {
21472
+ tr.docs[index2].nodesBetween(step.from, step.to, (node) => {
21473
+ if (containsTab(node)) {
21474
+ hasTabInRange = true;
21475
+ return false;
21476
+ }
21477
+ });
21478
+ }
21479
+ if (!hasTabInRange) {
21480
+ return;
21481
+ }
21482
+ let fromPos = step.from;
21483
+ let toPos = step.to;
21484
+ for (let i = index2; i < tr.steps.length; i++) {
21485
+ const stepMap = tr.steps[i].getMap();
21486
+ fromPos = stepMap.map(fromPos, -1);
21487
+ toPos = stepMap.map(toPos, 1);
21488
+ }
21489
+ const $from = newState.doc.resolve(fromPos);
21490
+ const $to = newState.doc.resolve(toPos);
21491
+ const start2 = $from.start(Math.min($from.depth, 1));
21492
+ const end2 = $to.end(Math.min($to.depth, 1));
21493
+ rangesToRecalculate.push([start2, end2]);
21283
21494
  });
21284
- rangesToRecalculate.forEach(([start2, end2]) => {
21495
+ if (rangesToRecalculate.length === 0) {
21496
+ return { decorations };
21497
+ }
21498
+ const mergedRanges = mergeRanges2(rangesToRecalculate);
21499
+ mergedRanges.forEach(([start2, end2]) => {
21285
21500
  const oldDecorations = decorations.find(start2, end2);
21286
21501
  decorations = decorations.remove(oldDecorations);
21287
21502
  const newDecorations = getTabDecorations(newState.doc, view, helpers2, start2, end2);
@@ -25183,6 +25398,29 @@ createAnnotation_fn = function({ displayLabel } = {}) {
25183
25398
  content
25184
25399
  };
25185
25400
  };
25401
+ const mergeRanges = (ranges) => {
25402
+ if (ranges.length === 0) return [];
25403
+ const sorted = [...ranges].sort((a, b) => a[0] - b[0]).map((range) => [...range]);
25404
+ const merged = [sorted[0]];
25405
+ for (let i = 1; i < sorted.length; i++) {
25406
+ const current = sorted[i];
25407
+ const lastMerged = merged[merged.length - 1];
25408
+ if (current[0] <= lastMerged[1]) {
25409
+ lastMerged[1] = Math.max(lastMerged[1], current[1]);
25410
+ } else {
25411
+ merged.push(current);
25412
+ }
25413
+ }
25414
+ return merged;
25415
+ };
25416
+ const clampRange = (start2, end2, docSize) => {
25417
+ const safeStart = Math.max(0, Math.min(start2, docSize));
25418
+ const safeEnd = Math.max(0, Math.min(end2, docSize));
25419
+ if (safeStart >= safeEnd) {
25420
+ return null;
25421
+ }
25422
+ return [safeStart, safeEnd];
25423
+ };
25186
25424
  const FieldAnnotationPlugin = (options = {}) => {
25187
25425
  let { editor, annotationClass: annotationClass2 } = options;
25188
25426
  return new Plugin({
@@ -25257,24 +25495,104 @@ const FieldAnnotationPlugin = (options = {}) => {
25257
25495
  },
25258
25496
  /// For y-prosemirror support.
25259
25497
  appendTransaction: (transactions, oldState, newState) => {
25260
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
25498
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
25261
25499
  if (!docChanges) {
25262
25500
  return;
25263
25501
  }
25264
- let { tr } = newState;
25265
- let changed = false;
25266
- let annotations = getAllFieldAnnotations(newState);
25267
- if (!annotations.length) {
25268
- return;
25502
+ const affectedRanges = [];
25503
+ let hasFieldAnnotationsInSlice = false;
25504
+ let hasSteps = false;
25505
+ transactions.forEach((transaction) => {
25506
+ if (!transaction.steps) return;
25507
+ hasSteps = true;
25508
+ transaction.steps.forEach((step) => {
25509
+ if (step.slice?.content) {
25510
+ step.slice.content.descendants((node) => {
25511
+ if (node.type.name === "fieldAnnotation") {
25512
+ hasFieldAnnotationsInSlice = true;
25513
+ return false;
25514
+ }
25515
+ });
25516
+ }
25517
+ if (typeof step.from === "number" && typeof step.to === "number") {
25518
+ const from2 = step.from;
25519
+ const to = step.from === step.to && step.slice?.size ? step.from + step.slice.size : step.to;
25520
+ affectedRanges.push([from2, to]);
25521
+ }
25522
+ });
25523
+ });
25524
+ if (hasSteps && !hasFieldAnnotationsInSlice && affectedRanges.length > 0) {
25525
+ const mergedRanges = mergeRanges(affectedRanges);
25526
+ let hasExistingAnnotations = false;
25527
+ for (const [start2, end2] of mergedRanges) {
25528
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
25529
+ if (!clampedRange) continue;
25530
+ const [validStart, validEnd] = clampedRange;
25531
+ try {
25532
+ newState.doc.nodesBetween(validStart, validEnd, (node) => {
25533
+ if (node.type.name === "fieldAnnotation") {
25534
+ hasExistingAnnotations = true;
25535
+ return false;
25536
+ }
25537
+ });
25538
+ } catch (error) {
25539
+ console.warn("FieldAnnotationPlugin: range check failed, assuming annotations exist", error);
25540
+ hasExistingAnnotations = true;
25541
+ break;
25542
+ }
25543
+ if (hasExistingAnnotations) break;
25544
+ }
25545
+ if (!hasExistingAnnotations) {
25546
+ return;
25547
+ }
25269
25548
  }
25270
- annotations.forEach(({ node, pos }) => {
25271
- let { marks } = node;
25272
- let currentNode = tr.doc.nodeAt(pos);
25549
+ const { tr } = newState;
25550
+ let changed = false;
25551
+ const removeMarksFromAnnotation = (node, pos) => {
25552
+ const { marks } = node;
25553
+ const currentNode = tr.doc.nodeAt(pos);
25273
25554
  if (marks.length > 0 && node.eq(currentNode)) {
25274
25555
  tr.removeMark(pos, pos + node.nodeSize, null);
25275
25556
  changed = true;
25276
25557
  }
25277
- });
25558
+ };
25559
+ if (affectedRanges.length > 0) {
25560
+ const mergedRanges = mergeRanges(affectedRanges);
25561
+ let shouldFallbackToFullScan = false;
25562
+ for (const [start2, end2] of mergedRanges) {
25563
+ const clampedRange = clampRange(start2, end2, newState.doc.content.size);
25564
+ if (!clampedRange) continue;
25565
+ const [validStart, validEnd] = clampedRange;
25566
+ try {
25567
+ newState.doc.nodesBetween(validStart, validEnd, (node, pos) => {
25568
+ if (node.type.name === "fieldAnnotation") {
25569
+ removeMarksFromAnnotation(node, pos);
25570
+ }
25571
+ });
25572
+ } catch (error) {
25573
+ console.warn("FieldAnnotationPlugin: nodesBetween failed, falling back to full scan", error);
25574
+ shouldFallbackToFullScan = true;
25575
+ break;
25576
+ }
25577
+ }
25578
+ if (shouldFallbackToFullScan) {
25579
+ const annotations = getAllFieldAnnotations(newState);
25580
+ if (!annotations.length) {
25581
+ return changed ? tr : null;
25582
+ }
25583
+ annotations.forEach(({ node, pos }) => {
25584
+ removeMarksFromAnnotation(node, pos);
25585
+ });
25586
+ }
25587
+ } else {
25588
+ const annotations = getAllFieldAnnotations(newState);
25589
+ if (!annotations.length) {
25590
+ return;
25591
+ }
25592
+ annotations.forEach(({ node, pos }) => {
25593
+ removeMarksFromAnnotation(node, pos);
25594
+ });
25595
+ }
25278
25596
  return changed ? tr : null;
25279
25597
  }
25280
25598
  ///
@@ -27084,7 +27402,9 @@ const registerImages = async (foundImages, editor, view) => {
27084
27402
  }
27085
27403
  });
27086
27404
  };
27405
+ const stepHasSlice = (step) => "slice" in step && Boolean(step.slice);
27087
27406
  const ImagePositionPluginKey = new PluginKey("ImagePosition");
27407
+ const pageBreakPositionCache = /* @__PURE__ */ new WeakMap();
27088
27408
  const ImagePositionPlugin = ({ editor }) => {
27089
27409
  const { view } = editor;
27090
27410
  let shouldUpdate = false;
@@ -27097,6 +27417,20 @@ const ImagePositionPlugin = ({ editor }) => {
27097
27417
  },
27098
27418
  apply(tr, oldDecorationSet, oldState, newState) {
27099
27419
  if (!tr.docChanged && !shouldUpdate) return oldDecorationSet;
27420
+ let affectsImages = false;
27421
+ tr.steps.forEach((step) => {
27422
+ if (stepHasSlice(step)) {
27423
+ step.slice.content.descendants((node) => {
27424
+ if (node.type.name === "image" || node.attrs?.anchorData) {
27425
+ affectsImages = true;
27426
+ return false;
27427
+ }
27428
+ });
27429
+ }
27430
+ });
27431
+ if (!affectsImages && !shouldUpdate) {
27432
+ return oldDecorationSet.map(tr.mapping, tr.doc);
27433
+ }
27100
27434
  const decorations = getImagePositionDecorations(newState, view);
27101
27435
  shouldUpdate = false;
27102
27436
  return DecorationSet.create(newState.doc, decorations);
@@ -27126,6 +27460,16 @@ const ImagePositionPlugin = ({ editor }) => {
27126
27460
  };
27127
27461
  const getImagePositionDecorations = (state, view) => {
27128
27462
  let decorations = [];
27463
+ let hasAnchoredImages = false;
27464
+ state.doc.descendants((node) => {
27465
+ if (node.attrs?.anchorData) {
27466
+ hasAnchoredImages = true;
27467
+ return false;
27468
+ }
27469
+ });
27470
+ if (!hasAnchoredImages) {
27471
+ return decorations;
27472
+ }
27129
27473
  state.doc.descendants((node, pos) => {
27130
27474
  if (node.attrs.anchorData) {
27131
27475
  let style = "";
@@ -27134,7 +27478,15 @@ const getImagePositionDecorations = (state, view) => {
27134
27478
  const { size, padding } = node.attrs;
27135
27479
  const pageBreak = findPreviousDomNodeWithClass(view, pos, "pagination-break-wrapper");
27136
27480
  if (pageBreak && vRelativeFrom === "margin" && alignH) {
27137
- const topPos = pageBreak?.offsetTop + pageBreak?.offsetHeight;
27481
+ let pageBreakPos = pageBreakPositionCache.get(pageBreak);
27482
+ if (!pageBreakPos) {
27483
+ pageBreakPos = {
27484
+ top: pageBreak.offsetTop,
27485
+ height: pageBreak.offsetHeight
27486
+ };
27487
+ pageBreakPositionCache.set(pageBreak, pageBreakPos);
27488
+ }
27489
+ const topPos = pageBreakPos.top + pageBreakPos.height;
27138
27490
  let horizontalAlignment = `${alignH}: 0;`;
27139
27491
  if (alignH === "center") horizontalAlignment = "left: 50%; transform: translateX(-50%);";
27140
27492
  style += vRelativeFrom === "margin" ? `position: absolute; top: ${topPos}px; ${horizontalAlignment}` : "";
@@ -27445,15 +27797,15 @@ const Image = Node$1.create({
27445
27797
  style += "float: right;";
27446
27798
  floatRight = true;
27447
27799
  } else if (["largest", "bothSides"].includes(attrs.wrapText)) {
27448
- const pageStylesData2 = getDataFromPageStyles({
27800
+ const pageStylesData = getDataFromPageStyles({
27449
27801
  editor: this.editor,
27450
27802
  marginOffset,
27451
27803
  size,
27452
27804
  attrs
27453
27805
  });
27454
- style += pageStylesData2.style;
27455
- floatRight = pageStylesData2.floatRight;
27456
- baseHorizontal = pageStylesData2.baseHorizontal;
27806
+ style += pageStylesData.style;
27807
+ floatRight = pageStylesData.floatRight;
27808
+ baseHorizontal = pageStylesData.baseHorizontal;
27457
27809
  }
27458
27810
  if (attrs.distTop) margin.top += attrs.distTop;
27459
27811
  if (attrs.distBottom) margin.bottom += attrs.distBottom;
@@ -27461,7 +27813,7 @@ const Image = Node$1.create({
27461
27813
  if (attrs.distRight) margin.right += attrs.distRight;
27462
27814
  break;
27463
27815
  case "Through":
27464
- case "Tight":
27816
+ case "Tight": {
27465
27817
  style += "clear: both;";
27466
27818
  const pageStylesData = getDataFromPageStyles({
27467
27819
  editor: this.editor,
@@ -27498,11 +27850,14 @@ const Image = Node$1.create({
27498
27850
  style += `shape-outside: polygon(${points});`;
27499
27851
  }
27500
27852
  break;
27853
+ }
27501
27854
  case "TopAndBottom":
27502
27855
  style += "display: block; clear: both;";
27856
+ if (!anchorData) {
27857
+ centered = true;
27858
+ }
27503
27859
  if (attrs.distTop) margin.top += attrs.distTop;
27504
27860
  if (attrs.distBottom) margin.bottom += attrs.distBottom;
27505
- centered = true;
27506
27861
  break;
27507
27862
  }
27508
27863
  }
@@ -27522,6 +27877,20 @@ const Image = Node$1.create({
27522
27877
  style += `position: absolute; ${anchorData.alignH}: 0;`;
27523
27878
  }
27524
27879
  break;
27880
+ case "column":
27881
+ if (anchorData.alignH === "center") {
27882
+ centered = true;
27883
+ } else if (anchorData.alignH === "right") {
27884
+ floatRight = true;
27885
+ if (!style.includes("float: right;")) {
27886
+ style += "float: right;";
27887
+ }
27888
+ } else if (anchorData.alignH === "left") {
27889
+ if (!style.includes("float: left;")) {
27890
+ style += "float: left;";
27891
+ }
27892
+ }
27893
+ break;
27525
27894
  }
27526
27895
  }
27527
27896
  if (hasAnchorData || hasMarginOffsets) {
@@ -28609,11 +28978,22 @@ const BlockNode = Extension.create({
28609
28978
  },
28610
28979
  addPmPlugins() {
28611
28980
  let hasInitialized = false;
28981
+ const assignBlockId = (tr, node, pos) => {
28982
+ tr.setNodeMarkup(
28983
+ pos,
28984
+ void 0,
28985
+ {
28986
+ ...node.attrs,
28987
+ sdBlockId: v4()
28988
+ },
28989
+ node.marks
28990
+ );
28991
+ };
28612
28992
  return [
28613
28993
  new Plugin({
28614
28994
  key: BlockNodePluginKey,
28615
28995
  appendTransaction: (transactions, oldState, newState) => {
28616
- let docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
28996
+ const docChanges = transactions.some((tr2) => tr2.docChanged) && !oldState.doc.eq(newState.doc);
28617
28997
  if (hasInitialized && !docChanges) {
28618
28998
  return;
28619
28999
  }
@@ -28622,21 +29002,87 @@ const BlockNode = Extension.create({
28622
29002
  }
28623
29003
  const { tr } = newState;
28624
29004
  let changed = false;
28625
- newState.doc.descendants((node, pos) => {
28626
- if (!nodeAllowsSdBlockIdAttr(node) || !nodeNeedsSdBlockId(node)) {
28627
- return;
29005
+ if (!hasInitialized) {
29006
+ newState.doc.descendants((node, pos) => {
29007
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
29008
+ assignBlockId(tr, node, pos);
29009
+ changed = true;
29010
+ }
29011
+ });
29012
+ } else {
29013
+ const rangesToCheck = [];
29014
+ let shouldFallbackToFullTraversal = false;
29015
+ transactions.forEach((transaction, txIndex) => {
29016
+ transaction.steps.forEach((step, stepIndex) => {
29017
+ if (!(step instanceof ReplaceStep)) return;
29018
+ const hasNewBlockNodes = step.slice?.content?.content?.some((node) => nodeAllowsSdBlockIdAttr(node));
29019
+ if (!hasNewBlockNodes) return;
29020
+ const stepMap = step.getMap();
29021
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
29022
+ if (newEnd <= newStart) {
29023
+ if (process$1.env.NODE_ENV === "development") {
29024
+ console.debug("Block node: invalid range in step map, falling back to full traversal");
29025
+ }
29026
+ shouldFallbackToFullTraversal = true;
29027
+ return;
29028
+ }
29029
+ let rangeStart = newStart;
29030
+ let rangeEnd = newEnd;
29031
+ for (let i = stepIndex + 1; i < transaction.steps.length; i++) {
29032
+ const laterStepMap = transaction.steps[i].getMap();
29033
+ rangeStart = laterStepMap.map(rangeStart, -1);
29034
+ rangeEnd = laterStepMap.map(rangeEnd, 1);
29035
+ }
29036
+ for (let i = txIndex + 1; i < transactions.length; i++) {
29037
+ const laterTx = transactions[i];
29038
+ rangeStart = laterTx.mapping.map(rangeStart, -1);
29039
+ rangeEnd = laterTx.mapping.map(rangeEnd, 1);
29040
+ }
29041
+ if (rangeEnd <= rangeStart) {
29042
+ if (process$1.env.NODE_ENV === "development") {
29043
+ console.debug("Block node: invalid range after mapping, falling back to full traversal");
29044
+ }
29045
+ shouldFallbackToFullTraversal = true;
29046
+ return;
29047
+ }
29048
+ rangesToCheck.push([rangeStart, rangeEnd]);
29049
+ });
29050
+ });
29051
+ });
29052
+ const mergedRanges = mergeRanges(rangesToCheck);
29053
+ for (const [start2, end2] of mergedRanges) {
29054
+ const docSize = newState.doc.content.size;
29055
+ const clampedRange = clampRange(start2, end2, docSize);
29056
+ if (!clampedRange) {
29057
+ if (process$1.env.NODE_ENV === "development") {
29058
+ console.debug("Block node: invalid range after clamping, falling back to full traversal");
29059
+ }
29060
+ shouldFallbackToFullTraversal = true;
29061
+ break;
29062
+ }
29063
+ const [safeStart, safeEnd] = clampedRange;
29064
+ try {
29065
+ newState.doc.nodesBetween(safeStart, safeEnd, (node, pos) => {
29066
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
29067
+ assignBlockId(tr, node, pos);
29068
+ changed = true;
29069
+ }
29070
+ });
29071
+ } catch (error) {
29072
+ console.warn("Block node plugin: nodesBetween failed, falling back to full traversal", error);
29073
+ shouldFallbackToFullTraversal = true;
29074
+ break;
29075
+ }
28628
29076
  }
28629
- tr.setNodeMarkup(
28630
- pos,
28631
- void 0,
28632
- {
28633
- ...node.attrs,
28634
- sdBlockId: v4()
28635
- },
28636
- node.marks
28637
- );
28638
- changed = true;
28639
- });
29077
+ if (shouldFallbackToFullTraversal) {
29078
+ newState.doc.descendants((node, pos) => {
29079
+ if (nodeAllowsSdBlockIdAttr(node) && nodeNeedsSdBlockId(node)) {
29080
+ assignBlockId(tr, node, pos);
29081
+ changed = true;
29082
+ }
29083
+ });
29084
+ }
29085
+ }
28640
29086
  if (changed && !hasInitialized) {
28641
29087
  hasInitialized = true;
28642
29088
  tr.setMeta("blockNodeInitialUpdate", true);
@@ -35112,8 +35558,8 @@ const PopoverPlugin = Extension.create({
35112
35558
  return {};
35113
35559
  },
35114
35560
  apply: (tr, value) => {
35115
- let newValue = { ...value };
35116
- if (tr.docChanged) {
35561
+ const newValue = { ...value };
35562
+ if (tr.docChanged || tr.selectionSet) {
35117
35563
  newValue.shouldUpdate = true;
35118
35564
  } else {
35119
35565
  newValue.shouldUpdate = false;
@@ -36368,6 +36814,8 @@ const Pagination = Extension.create({
36368
36814
  let shouldUpdate = false;
36369
36815
  let hasInitialized = false;
36370
36816
  let shouldInitialize = false;
36817
+ let paginationTimeout = null;
36818
+ const PAGINATION_DEBOUNCE_MS = 150;
36371
36819
  const paginationPlugin = new Plugin({
36372
36820
  key: PaginationPluginKey,
36373
36821
  state: {
@@ -36395,6 +36843,9 @@ const Pagination = Extension.create({
36395
36843
  shouldUpdate = true;
36396
36844
  shouldInitialize = meta.isReadyToInit;
36397
36845
  }
36846
+ if (meta && meta.skipPagination) {
36847
+ return { ...oldState };
36848
+ }
36398
36849
  const syncMeta = tr.getMeta("y-sync$");
36399
36850
  const listSyncMeta = tr.getMeta("orderedListSync");
36400
36851
  if (syncMeta && syncMeta.isChangeOrigin || listSyncMeta) {
@@ -36426,11 +36877,23 @@ const Pagination = Extension.create({
36426
36877
  shouldUpdate = false;
36427
36878
  return { ...oldState };
36428
36879
  }
36880
+ if (!isForceUpdate && hasInitialized && tr.docChanged) {
36881
+ let isMarkOnlyChange = true;
36882
+ tr.steps.forEach((step) => {
36883
+ if (step.jsonID !== "addMark" && step.jsonID !== "removeMark") {
36884
+ isMarkOnlyChange = false;
36885
+ }
36886
+ });
36887
+ if (isMarkOnlyChange) {
36888
+ shouldUpdate = false;
36889
+ return { ...oldState };
36890
+ }
36891
+ }
36429
36892
  shouldUpdate = true;
36430
36893
  if (isForceUpdate) shouldUpdate = true;
36431
36894
  return {
36432
36895
  ...oldState,
36433
- decorations: meta?.decorations?.map(tr.mapping, tr.doc) || DecorationSet.empty,
36896
+ decorations: meta?.decorations?.map(tr.mapping, tr.doc) || oldState.decorations.map(tr.mapping, tr.doc),
36434
36897
  isReadyToInit: shouldInitialize
36435
36898
  };
36436
36899
  }
@@ -36442,11 +36905,22 @@ const Pagination = Extension.create({
36442
36905
  update: (view) => {
36443
36906
  if (!PaginationPluginKey.getState(view.state)?.isEnabled) return;
36444
36907
  if (!shouldUpdate || isUpdating) return;
36445
- isUpdating = true;
36446
- hasInitialized = true;
36447
- performUpdate(editor, view, previousDecorations);
36448
- isUpdating = false;
36449
- shouldUpdate = false;
36908
+ const performPaginationUpdate = () => {
36909
+ if (!shouldUpdate) return;
36910
+ isUpdating = true;
36911
+ hasInitialized = true;
36912
+ performUpdate(editor, view, previousDecorations);
36913
+ isUpdating = false;
36914
+ shouldUpdate = false;
36915
+ };
36916
+ if (!hasInitialized) {
36917
+ performPaginationUpdate();
36918
+ return;
36919
+ }
36920
+ if (paginationTimeout) {
36921
+ clearTimeout(paginationTimeout);
36922
+ }
36923
+ paginationTimeout = setTimeout(performPaginationUpdate, PAGINATION_DEBOUNCE_MS);
36450
36924
  }
36451
36925
  };
36452
36926
  },