superdoc 1.0.0-beta.4 → 1.0.0-beta.6

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-DUns3s8O.es.js → PdfViewer-CdGAVn-4.es.js} +1 -1
  2. package/dist/chunks/{PdfViewer-ZtwLhE_8.cjs → PdfViewer-DmPiOFJ8.cjs} +1 -1
  3. package/dist/chunks/{index-BW38mdZF.cjs → index-QulG3CF7.cjs} +3 -3
  4. package/dist/chunks/{index-BNGaD3Up-D2cRHMMk.cjs → index-hjUbJ86s-BLl65XJn.cjs} +1 -1
  5. package/dist/chunks/{index-BNGaD3Up-CQuoo1EF.es.js → index-hjUbJ86s-BMiwCR8J.es.js} +1 -1
  6. package/dist/chunks/{index-DIccWgYh.es.js → index-nXifzD54.es.js} +3 -3
  7. package/dist/chunks/{super-editor.es-C06-V-Iy.cjs → super-editor.es-0GatZWs9.cjs} +452 -183
  8. package/dist/chunks/{super-editor.es-CtCHBIPE.es.js → super-editor.es-BYVEYLjl.es.js} +452 -183
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-ZJiSHoiq.js → converter-CZF9SnYh.js} +1 -1
  11. package/dist/super-editor/chunks/{docx-zipper-B7FStorN.js → docx-zipper-DWypbE0V.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-DvepAjbe.js → editor-BdXHlHt-.js} +440 -176
  13. package/dist/super-editor/chunks/{index-BNGaD3Up.js → index-hjUbJ86s.js} +1 -1
  14. package/dist/super-editor/chunks/{toolbar-CKXXbIQO.js → toolbar-CmelvLTd.js} +2 -2
  15. package/dist/super-editor/converter.es.js +1 -1
  16. package/dist/super-editor/docx-zipper.es.js +2 -2
  17. package/dist/super-editor/editor.es.js +3 -3
  18. package/dist/super-editor/file-zipper.es.js +1 -1
  19. package/dist/super-editor/super-editor.es.js +19 -14
  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 +454 -185
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -12,8 +12,8 @@ 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, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_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, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, updateDecorationProviders_fn, createDecorationProvider_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, computeHeaderFooterCaretRect_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _visibleHost2, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, updateHTMLAttributes_fn, updateDOMStyles_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_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 htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as ListHelpers, O as updateNumberingProperties, Q as changeListLevel, U as findParentNode, V as isList, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as calculateResolvedParagraphProperties, ar as encodeCSSFromPPr, as as twipsToPixels$2, at as resolveRunProperties, au as encodeCSSFromRPr, av as generateOrderedListIndex, aw as docxNumberingHelpers, ax as InputRule, ay as convertSizeToCSS, az as SelectionRange, aA as Transform, aB as findParentNodeClosestToPos, aC as isInTable$1, aD as generateDocxRandomId, aE as insertNewRelationship, aF as inchesToPixels, aG as kebabCase, aH as getUnderlineCssString } from "./converter-ZJiSHoiq.js";
16
- import { D as DocxZipper } from "./docx-zipper-B7FStorN.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 htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as ListHelpers, O as updateNumberingProperties, Q as changeListLevel, U as findParentNode, V as isList, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as calculateResolvedParagraphProperties, ar as encodeCSSFromPPr, as as twipsToPixels$2, at as resolveRunProperties, au as encodeCSSFromRPr, av as generateOrderedListIndex, aw as docxNumberingHelpers, ax as InputRule, ay as convertSizeToCSS, az as SelectionRange, aA as Transform, aB as findParentNodeClosestToPos, aC as isInTable$1, aD as generateDocxRandomId, aE as insertNewRelationship, aF as inchesToPixels, aG as kebabCase, aH as getUnderlineCssString } from "./converter-CZF9SnYh.js";
16
+ import { D as DocxZipper } from "./docx-zipper-DWypbE0V.js";
17
17
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
18
18
  var GOOD_LEAF_SIZE = 200;
19
19
  var RopeSequence = function RopeSequence2() {
@@ -13553,7 +13553,7 @@ const isHeadless = (editor) => {
13553
13553
  const shouldSkipNodeView = (editor) => {
13554
13554
  return isHeadless(editor);
13555
13555
  };
13556
- const summaryVersion = "1.0.0-beta.4";
13556
+ const summaryVersion = "1.0.0-beta.6";
13557
13557
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
13558
13558
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
13559
13559
  function mapAttributes(attrs) {
@@ -14335,7 +14335,7 @@ const _Editor = class _Editor extends EventEmitter {
14335
14335
  { default: remarkStringify },
14336
14336
  { default: remarkGfm }
14337
14337
  ] = await Promise.all([
14338
- import("./index-BNGaD3Up.js"),
14338
+ import("./index-hjUbJ86s.js"),
14339
14339
  import("./index-DRCvimau.js"),
14340
14340
  import("./index-C_x_N6Uh.js"),
14341
14341
  import("./index-D_sWOSiG.js"),
@@ -14540,7 +14540,7 @@ const _Editor = class _Editor extends EventEmitter {
14540
14540
  * Process collaboration migrations
14541
14541
  */
14542
14542
  processCollaborationMigrations() {
14543
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.4");
14543
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.6");
14544
14544
  if (!this.options.ydoc) return;
14545
14545
  const metaMap = this.options.ydoc.getMap("meta");
14546
14546
  let docVersion = metaMap.get("version");
@@ -16760,9 +16760,10 @@ function extractTableBorders(bordersInput) {
16760
16760
  }
16761
16761
  function extractCellBorders(cellAttrs) {
16762
16762
  if (!cellAttrs?.borders) return void 0;
16763
+ const bordersData = cellAttrs.borders;
16763
16764
  const borders = {};
16764
16765
  for (const side of ["top", "right", "bottom", "left"]) {
16765
- const spec = convertBorderSpec(cellAttrs.borders[side]);
16766
+ const spec = convertBorderSpec(bordersData[side]);
16766
16767
  if (spec) {
16767
16768
  borders[side] = spec;
16768
16769
  }
@@ -16866,7 +16867,7 @@ const normalizeString = (value) => {
16866
16867
  return trimmed ? trimmed : void 0;
16867
16868
  };
16868
16869
  const MAX_AUTO_LINE_MULTIPLIER = 10;
16869
- const TWIPS_THRESHOLD = 50;
16870
+ const TWIPS_THRESHOLD$1 = 50;
16870
16871
  const spacingPxToPt = (spacing) => {
16871
16872
  const result = {};
16872
16873
  if (spacing.before != null) result.before = pxToPt(spacing.before);
@@ -17006,7 +17007,7 @@ const normalizeParagraphIndent = (value) => {
17006
17007
  const convert = (value2) => {
17007
17008
  const num = pickNumber(value2);
17008
17009
  if (num == null) return void 0;
17009
- if (Math.abs(num) <= TWIPS_THRESHOLD) {
17010
+ if (Math.abs(num) <= TWIPS_THRESHOLD$1) {
17010
17011
  return num;
17011
17012
  }
17012
17013
  return twipsToPx$1(Number(num));
@@ -17021,24 +17022,18 @@ const normalizeParagraphIndent = (value) => {
17021
17022
  if (hanging != null) indent.hanging = hanging;
17022
17023
  return Object.keys(indent).length > 0 ? indent : void 0;
17023
17024
  };
17025
+ const PX_TO_TWIPS = 15;
17026
+ const TWIPS_THRESHOLD = 1e3;
17024
17027
  const normalizeOoxmlTabs = (tabs) => {
17025
17028
  if (!Array.isArray(tabs)) return void 0;
17026
17029
  const normalized = [];
17027
17030
  for (const entry of tabs) {
17028
17031
  if (!entry || typeof entry !== "object") continue;
17029
- const source = entry;
17030
- let posTwips;
17031
- const originalPos = pickNumber(source.originalPos);
17032
- if (originalPos != null) {
17033
- posTwips = originalPos;
17034
- } else {
17035
- const posPx = pickNumber(source.pos ?? source.position ?? source.offset);
17036
- if (posPx != null) {
17037
- posTwips = Math.round(posPx * 15);
17038
- }
17039
- }
17032
+ const rawEntry = entry;
17033
+ const source = rawEntry.tab && typeof rawEntry.tab === "object" ? rawEntry.tab : rawEntry;
17034
+ const posTwips = resolveTabPosition(source);
17040
17035
  if (posTwips == null) continue;
17041
- const val = normalizeTabVal(source.val ?? source.align ?? source.alignment ?? source.type);
17036
+ const val = normalizeTabVal(source.val ?? source.align ?? source.alignment ?? source.type ?? source.tabType);
17042
17037
  if (!val) continue;
17043
17038
  const tab = {
17044
17039
  val,
@@ -17050,6 +17045,21 @@ const normalizeOoxmlTabs = (tabs) => {
17050
17045
  }
17051
17046
  return normalized.length > 0 ? normalized : void 0;
17052
17047
  };
17048
+ const resolveTabPosition = (source) => {
17049
+ const originalPos = pickNumber(source.originalPos);
17050
+ if (originalPos != null) {
17051
+ return originalPos;
17052
+ }
17053
+ const posValue = pickNumber(source.pos ?? source.position ?? source.offset);
17054
+ if (posValue == null) {
17055
+ return void 0;
17056
+ }
17057
+ if (posValue > TWIPS_THRESHOLD) {
17058
+ return posValue;
17059
+ } else {
17060
+ return Math.round(posValue * PX_TO_TWIPS);
17061
+ }
17062
+ };
17053
17063
  const normalizeTabVal = (value) => {
17054
17064
  switch (value) {
17055
17065
  case "start":
@@ -17061,12 +17071,13 @@ const normalizeTabVal = (value) => {
17061
17071
  return value;
17062
17072
  case "left":
17063
17073
  return "start";
17064
- // Legacy mapping
17074
+ // Legacy mapping for RTL support
17065
17075
  case "right":
17066
17076
  return "end";
17067
- // Legacy mapping
17077
+ // Legacy mapping for RTL support
17068
17078
  case "dec":
17069
17079
  return "decimal";
17080
+ // Abbreviation mapping
17070
17081
  default:
17071
17082
  return void 0;
17072
17083
  }
@@ -17082,7 +17093,7 @@ const normalizeTabLeader = (value) => {
17082
17093
  return value;
17083
17094
  case "thick":
17084
17095
  return "heavy";
17085
- // Map legacy 'thick' to OOXML 'heavy'
17096
+ // Legacy mapping
17086
17097
  default:
17087
17098
  return void 0;
17088
17099
  }
@@ -18010,29 +18021,6 @@ const normalizeSuffix = (suffix) => {
18010
18021
  }
18011
18022
  return void 0;
18012
18023
  };
18013
- function resolveSpacingIndent$1(style, numbering) {
18014
- const spacing = {
18015
- before: style.spacing?.before ?? 0,
18016
- after: style.spacing?.after ?? 0,
18017
- line: style.spacing?.line ?? 12,
18018
- // Default line spacing
18019
- lineRule: style.spacing?.lineRule ?? "auto"
18020
- };
18021
- let indent = {
18022
- left: style.indent?.left ?? 0,
18023
- right: style.indent?.right ?? 0,
18024
- firstLine: style.indent?.firstLine ?? 0,
18025
- hanging: style.indent?.hanging ?? 0
18026
- };
18027
- if (numbering?.indent) {
18028
- indent = {
18029
- ...indent,
18030
- left: numbering.indent.left ?? indent.left,
18031
- hanging: numbering.indent.hanging ?? indent.hanging
18032
- };
18033
- }
18034
- return { spacing, indent };
18035
- }
18036
18024
  function computeTabStops$1(context) {
18037
18025
  const { explicitStops, defaultTabInterval, paragraphIndent } = context;
18038
18026
  const leftIndent = paragraphIndent.left ?? 0;
@@ -18144,6 +18132,90 @@ function computeEndAlignedX(entry, stop) {
18144
18132
  const targetX = stop.pos - width;
18145
18133
  return targetX < 0 ? 0 : targetX;
18146
18134
  }
18135
+ function calculateTabWidth(params2) {
18136
+ const {
18137
+ currentX,
18138
+ tabStops,
18139
+ paragraphWidth,
18140
+ defaultTabDistance: defaultTabDistance2,
18141
+ defaultLineLength: defaultLineLength2,
18142
+ followingText = "",
18143
+ measureText: measureText2,
18144
+ decimalSeparator = "."
18145
+ } = params2;
18146
+ const nextStop = tabStops.find((stop) => stop.val !== "clear" && stop.pos > currentX);
18147
+ const fallbackWidth = () => {
18148
+ let tabWidth = defaultTabDistance2 - currentX % defaultLineLength2 % defaultTabDistance2;
18149
+ if (tabWidth <= 0) tabWidth = defaultTabDistance2;
18150
+ return {
18151
+ width: tabWidth,
18152
+ alignment: "default",
18153
+ tabStopPosUsed: "default"
18154
+ };
18155
+ };
18156
+ if (!nextStop) {
18157
+ return fallbackWidth();
18158
+ }
18159
+ let width = Math.min(nextStop.pos, paragraphWidth) - currentX;
18160
+ const alignment = nextStop.val;
18161
+ if (alignment === "bar") {
18162
+ return {
18163
+ width: 0,
18164
+ leader: nextStop.leader,
18165
+ alignment,
18166
+ tabStopPosUsed: nextStop.pos
18167
+ };
18168
+ }
18169
+ if (alignment === "center" || alignment === "end") {
18170
+ const textWidth = measureText2 ? measureText2(followingText) : 0;
18171
+ if (alignment === "center") {
18172
+ width -= textWidth / 2;
18173
+ } else {
18174
+ width -= textWidth;
18175
+ }
18176
+ } else if (alignment === "decimal") {
18177
+ const decimalIndex = followingText.indexOf(decimalSeparator);
18178
+ if (decimalIndex >= 0) {
18179
+ const before = followingText.slice(0, decimalIndex);
18180
+ const beforeWidth = measureText2 ? measureText2(before) : 0;
18181
+ width -= beforeWidth;
18182
+ }
18183
+ } else if (alignment === "bar") {
18184
+ width = 0;
18185
+ }
18186
+ if (width < 1) {
18187
+ return fallbackWidth();
18188
+ }
18189
+ return {
18190
+ width,
18191
+ leader: nextStop.leader,
18192
+ alignment,
18193
+ tabStopPosUsed: nextStop.pos
18194
+ };
18195
+ }
18196
+ function resolveSpacingIndent$1(style, numbering) {
18197
+ const spacing = {
18198
+ before: style.spacing?.before ?? 0,
18199
+ after: style.spacing?.after ?? 0,
18200
+ line: style.spacing?.line ?? 12,
18201
+ // Default line spacing
18202
+ lineRule: style.spacing?.lineRule ?? "auto"
18203
+ };
18204
+ let indent = {
18205
+ left: style.indent?.left ?? 0,
18206
+ right: style.indent?.right ?? 0,
18207
+ firstLine: style.indent?.firstLine ?? 0,
18208
+ hanging: style.indent?.hanging ?? 0
18209
+ };
18210
+ if (numbering?.indent) {
18211
+ indent = {
18212
+ ...indent,
18213
+ left: numbering.indent.left ?? indent.left,
18214
+ hanging: numbering.indent.hanging ?? indent.hanging
18215
+ };
18216
+ }
18217
+ return { spacing, indent };
18218
+ }
18147
18219
  function formatListLabel(level, indices) {
18148
18220
  const { format, text: template, start: start2 } = level;
18149
18221
  if (format === "bullet" || format === "custom") {
@@ -18309,6 +18381,7 @@ function measureRowHeights(cells, _columnWidths) {
18309
18381
  }
18310
18382
  const Engines = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
18311
18383
  __proto__: null,
18384
+ calculateTabWidth,
18312
18385
  computeListIndent,
18313
18386
  computeTabStops: computeTabStops$1,
18314
18387
  computeWrapExclusion,
@@ -18357,17 +18430,18 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
18357
18430
  return null;
18358
18431
  }
18359
18432
  const resolvedExtended = resolved;
18433
+ const resolvedAsRecord = resolved;
18360
18434
  const hydrated = {
18361
18435
  resolved,
18362
- spacing: cloneIfObject(resolved.spacing),
18363
- indent: cloneIfObject(resolved.indent),
18436
+ spacing: cloneIfObject(resolvedAsRecord.spacing),
18437
+ indent: cloneIfObject(resolvedAsRecord.indent),
18364
18438
  borders: cloneIfObject(resolvedExtended.borders),
18365
18439
  shading: cloneIfObject(resolvedExtended.shading),
18366
18440
  alignment: resolvedExtended.justification,
18367
18441
  tabStops: cloneIfObject(resolvedExtended.tabStops),
18368
18442
  keepLines: resolvedExtended.keepLines,
18369
18443
  keepNext: resolvedExtended.keepNext,
18370
- numberingProperties: cloneIfObject(resolved.numberingProperties)
18444
+ numberingProperties: cloneIfObject(resolvedAsRecord.numberingProperties)
18371
18445
  };
18372
18446
  return hydrated;
18373
18447
  };
@@ -18580,6 +18654,9 @@ const normalizeResolvedTabAlignment = (value) => {
18580
18654
  }
18581
18655
  };
18582
18656
  const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext) => {
18657
+ if (numberingProps === null) {
18658
+ return null;
18659
+ }
18583
18660
  try {
18584
18661
  let effectiveIndent = paragraphAttrs.indent;
18585
18662
  if (numberingProps?.resolvedLevelIndent) {
@@ -18614,7 +18691,7 @@ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleCont
18614
18691
  return computeWordParagraphLayout({
18615
18692
  paragraph: resolvedParagraph,
18616
18693
  numbering: numberingProps,
18617
- markerRun: numberingProps.resolvedMarkerRpr,
18694
+ markerRun: numberingProps?.resolvedMarkerRpr,
18618
18695
  // Use cached if available
18619
18696
  docDefaults
18620
18697
  });
@@ -19060,7 +19137,7 @@ function processImageChild(child, sectionMetadata, context, output, converters)
19060
19137
  function processNestedStructuredContent(child, sectionMetadata, context, output, converters) {
19061
19138
  const { getListCounter, incrementListCounter, resetListCounter } = context.listCounterContext;
19062
19139
  const nestedMetadata = resolveNodeSdtMetadata(child, "structuredContentBlock");
19063
- child.content.forEach((grandchild) => {
19140
+ child.content?.forEach((grandchild) => {
19064
19141
  if (grandchild.type === "paragraph") {
19065
19142
  const paragraphBlocks = converters.paragraphToFlowBlocks(
19066
19143
  grandchild,
@@ -19112,7 +19189,7 @@ function processDocumentPartObject(child, sectionMetadata, context, output, conv
19112
19189
  if (docPartGallery === "Table of Contents") {
19113
19190
  const blocksBeforeToc = output.blocks.length;
19114
19191
  processTocChildren(
19115
- Array.from(child.content),
19192
+ Array.from(child.content ?? []),
19116
19193
  { docPartGallery, docPartObjectId, tocInstruction, sdtMetadata: docPartSdtMetadata },
19117
19194
  {
19118
19195
  nextBlockId: context.nextBlockId,
@@ -19790,7 +19867,8 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
19790
19867
  trackedChanges,
19791
19868
  bookmarks,
19792
19869
  hyperlinkConfig,
19793
- converterContext
19870
+ themeColors,
19871
+ ...converterContext !== void 0 ? [converterContext] : []
19794
19872
  );
19795
19873
  if (tableBlock) {
19796
19874
  blocks.push(tableBlock);
@@ -19916,6 +19994,8 @@ function handleParagraphNode(node, context) {
19916
19994
  trackedChangesConfig,
19917
19995
  bookmarks,
19918
19996
  hyperlinkConfig,
19997
+ void 0,
19998
+ // themeColors - not available in NodeHandlerContext
19919
19999
  context.converterContext
19920
20000
  );
19921
20001
  paragraphBlocks.forEach((block) => {
@@ -20425,9 +20505,9 @@ const parseTableCell = (args) => {
20425
20505
  const paragraph = paragraphBlocks.find((b) => b.kind === "paragraph");
20426
20506
  if (!paragraph) return null;
20427
20507
  const cellAttrs = {};
20428
- const borders = extractCellBorders(cellNode.attrs);
20508
+ const borders = extractCellBorders(cellNode.attrs ?? {});
20429
20509
  if (borders) cellAttrs.borders = borders;
20430
- const padding = extractCellPadding(cellNode.attrs) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
20510
+ const padding = extractCellPadding(cellNode.attrs ?? {}) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
20431
20511
  if (padding) cellAttrs.padding = padding;
20432
20512
  const verticalAlign = cellNode.attrs?.verticalAlign;
20433
20513
  if (verticalAlign === "top" || verticalAlign === "middle" || verticalAlign === "bottom") {
@@ -20764,7 +20844,7 @@ function toFlowBlocks(pmDoc, options) {
20764
20844
  themeColors,
20765
20845
  converterContext
20766
20846
  );
20767
- const tableConverter = (node, nextBlockId2, positions2, defaultFont2, defaultSize2, context, trackedChanges, bookmarks2, hyperlinkConfig2) => tableNodeToBlock(
20847
+ const tableConverter = (node, nextBlockId2, positions2, defaultFont2, defaultSize2, context, trackedChanges, bookmarks2, hyperlinkConfig2, themeColorsParam, converterCtx) => tableNodeToBlock(
20768
20848
  node,
20769
20849
  nextBlockId2,
20770
20850
  positions2,
@@ -20774,8 +20854,8 @@ function toFlowBlocks(pmDoc, options) {
20774
20854
  trackedChanges,
20775
20855
  bookmarks2,
20776
20856
  hyperlinkConfig2,
20777
- themeColors,
20778
- converterContext
20857
+ themeColorsParam ?? themeColors,
20858
+ converterCtx ?? converterContext
20779
20859
  );
20780
20860
  const handlerContext = {
20781
20861
  blocks,
@@ -27457,7 +27537,7 @@ const _DomPainter = class _DomPainter {
27457
27537
  markerEl.style.display = "inline-block";
27458
27538
  markerEl.style.width = `${Math.max(0, fragment.markerWidth - LIST_MARKER_GAP$1)}px`;
27459
27539
  markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
27460
- markerEl.style.textAlign = marker.justification ?? "";
27540
+ markerEl.style.textAlign = marker.justification ?? "left";
27461
27541
  markerEl.style.fontFamily = marker.run.fontFamily;
27462
27542
  markerEl.style.fontSize = `${marker.run.fontSize}px`;
27463
27543
  if (marker.run.bold) markerEl.style.fontWeight = "bold";
@@ -27845,7 +27925,7 @@ const _DomPainter = class _DomPainter {
27845
27925
  buildLinkRenderData(link) {
27846
27926
  const dataset = buildLinkDataset(link);
27847
27927
  const sanitized = typeof link.href === "string" ? sanitizeHref(link.href) : null;
27848
- const anchorHref = normalizeAnchor(link.anchor ?? link.name ?? null);
27928
+ const anchorHref = normalizeAnchor(link.anchor ?? link.name ?? "");
27849
27929
  let href = sanitized?.href ?? anchorHref;
27850
27930
  if (link.version === 2) {
27851
27931
  href = appendDocLocation(href, link.docLocation ?? null);
@@ -28023,6 +28103,10 @@ const _DomPainter = class _DomPainter {
28023
28103
  const el = this.doc.createElement("div");
28024
28104
  el.classList.add(CLASS_NAMES.line);
28025
28105
  applyStyles$2(el, lineStyles(line.lineHeight));
28106
+ const styleId = block.attrs?.styleId;
28107
+ if (styleId) {
28108
+ el.setAttribute("styleid", styleId);
28109
+ }
28026
28110
  const lineRange = computeLinePmRange(block, line);
28027
28111
  if (lineRange.pmStart != null) {
28028
28112
  el.dataset.pmStart = String(lineRange.pmStart);
@@ -28050,7 +28134,7 @@ const _DomPainter = class _DomPainter {
28050
28134
  leaderEl.style.height = ld.style === "heavy" ? "2px" : "1px";
28051
28135
  leaderEl.style.pointerEvents = "none";
28052
28136
  leaderEl.style.zIndex = "0";
28053
- if (ld.style === "dot") {
28137
+ if (ld.style === "dot" || ld.style === "middleDot") {
28054
28138
  leaderEl.style.borderBottom = "1px dotted currentColor";
28055
28139
  } else if (ld.style === "hyphen") {
28056
28140
  leaderEl.style.borderBottom = "1px dashed currentColor";
@@ -28087,6 +28171,9 @@ const _DomPainter = class _DomPainter {
28087
28171
  const segmentRun = { ...baseRun, text: segmentText };
28088
28172
  const elem = this.renderRun(segmentRun, context, trackedConfig);
28089
28173
  if (elem) {
28174
+ if (styleId) {
28175
+ elem.setAttribute("styleid", styleId);
28176
+ }
28090
28177
  let xPos;
28091
28178
  if (segment.x !== void 0) {
28092
28179
  xPos = segment.x;
@@ -28112,6 +28199,9 @@ const _DomPainter = class _DomPainter {
28112
28199
  runs.forEach((run) => {
28113
28200
  const elem = this.renderRun(run, context, trackedConfig);
28114
28201
  if (elem) {
28202
+ if (styleId) {
28203
+ elem.setAttribute("styleid", styleId);
28204
+ }
28115
28205
  el.appendChild(elem);
28116
28206
  }
28117
28207
  });
@@ -28531,6 +28621,9 @@ const applyRunDataAttributes = (element, dataAttrs) => {
28531
28621
  };
28532
28622
  const applyParagraphBlockStyles = (element, attrs) => {
28533
28623
  if (!attrs) return;
28624
+ if (attrs.styleId) {
28625
+ element.setAttribute("styleid", attrs.styleId);
28626
+ }
28534
28627
  if (attrs.alignment) {
28535
28628
  element.style.textAlign = attrs.alignment;
28536
28629
  }
@@ -28752,6 +28845,7 @@ const pxToTwips = (px) => Math.round(px * TWIPS_PER_PX);
28752
28845
  const DEFAULT_TAB_INTERVAL_PX = twipsToPx(DEFAULT_TAB_INTERVAL_TWIPS);
28753
28846
  const TAB_EPSILON = 0.1;
28754
28847
  const DEFAULT_DECIMAL_SEPARATOR = ".";
28848
+ const ALLOWED_TAB_VALS = /* @__PURE__ */ new Set(["start", "center", "end", "decimal", "bar", "clear"]);
28755
28849
  const roundValue = (value) => value;
28756
28850
  function getCanvasContext() {
28757
28851
  if (!canvasContext) {
@@ -28874,6 +28968,14 @@ async function measureParagraphBlock(block, maxWidth) {
28874
28968
  let tabStopCursor = 0;
28875
28969
  let pendingTabAlignment = null;
28876
28970
  let lastAppliedTabAlign = null;
28971
+ const warnedTabVals = /* @__PURE__ */ new Set();
28972
+ const validateTabStopVal = (stop) => {
28973
+ if (!ALLOWED_TAB_VALS.has(stop.val) && !warnedTabVals.has(stop.val)) {
28974
+ warnedTabVals.add(stop.val);
28975
+ return false;
28976
+ }
28977
+ return true;
28978
+ };
28877
28979
  const alignSegmentAtTab = (segmentText, font, runContext) => {
28878
28980
  if (!pendingTabAlignment || !currentLine) return;
28879
28981
  const { target, val } = pendingTabAlignment;
@@ -28922,8 +29024,13 @@ async function measureParagraphBlock(block, maxWidth) {
28922
29024
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, 12);
28923
29025
  currentLine.toRun = runIndex;
28924
29026
  currentLine.toChar = 1;
28925
- pendingTabAlignment = stop ? { target, val: stop.val } : null;
28926
- if (stop && stop.leader && stop.leader !== "none" && stop.leader !== "middleDot") {
29027
+ if (stop) {
29028
+ validateTabStopVal(stop);
29029
+ pendingTabAlignment = { target, val: stop.val };
29030
+ } else {
29031
+ pendingTabAlignment = null;
29032
+ }
29033
+ if (stop && stop.leader && stop.leader !== "none") {
28927
29034
  const leaderStyle = stop.leader;
28928
29035
  const from2 = Math.min(originX, target);
28929
29036
  const to = Math.max(originX, target);
@@ -29069,7 +29176,12 @@ async function measureParagraphBlock(block, maxWidth) {
29069
29176
  currentLine.toRun = runIndex;
29070
29177
  currentLine.toChar = charPosInRun;
29071
29178
  charPosInRun += 1;
29072
- pendingTabAlignment = stop ? { target, val: stop.val } : null;
29179
+ if (stop) {
29180
+ validateTabStopVal(stop);
29181
+ pendingTabAlignment = { target, val: stop.val };
29182
+ } else {
29183
+ pendingTabAlignment = null;
29184
+ }
29073
29185
  if (stop && stop.leader && stop.leader !== "none" && stop.leader !== "middleDot") {
29074
29186
  const leaderStyle = stop.leader;
29075
29187
  const from2 = Math.min(originX, target);
@@ -29121,10 +29233,6 @@ async function measureParagraphBlock(block, maxWidth) {
29121
29233
  markerTextWidth: glyphWidth,
29122
29234
  indentLeft: wordLayout.indentLeftPx ?? 0
29123
29235
  };
29124
- console.log(
29125
- "[measure] Marker:",
29126
- JSON.stringify({ text: markerText, width: markerInfo.markerWidth, indent: markerInfo.indentLeft })
29127
- );
29128
29236
  }
29129
29237
  return {
29130
29238
  kind: "paragraph",
@@ -36206,29 +36314,6 @@ const restartNumbering = ({ editor, tr, state, dispatch }) => {
36206
36314
  };
36207
36315
  const defaultTabDistance = 48;
36208
36316
  const defaultLineLength = 816;
36209
- const getTabDecorations = (doc2, view, helpers2, from2 = 0, to = null) => {
36210
- const decorations = [];
36211
- const paragraphCache = /* @__PURE__ */ new Map();
36212
- const coordCache = /* @__PURE__ */ new Map();
36213
- const domPosCache = /* @__PURE__ */ new Map();
36214
- const end2 = to ?? doc2.content.size;
36215
- doc2.nodesBetween(from2, end2, (node, pos) => {
36216
- if (node.type.name !== "tab") return;
36217
- const $pos = doc2.resolve(pos);
36218
- const paragraphContext = findParagraphContext($pos, paragraphCache, helpers2);
36219
- if (!paragraphContext) return;
36220
- const blockParent2 = $pos.node(paragraphContext.paragraphDepth);
36221
- const style = calculateTabStyle(node.nodeSize, view, pos, blockParent2, paragraphContext, coordCache, domPosCache);
36222
- if (style) {
36223
- decorations.push(
36224
- Decoration.node(pos, pos + node.nodeSize, {
36225
- style
36226
- })
36227
- );
36228
- }
36229
- });
36230
- return decorations;
36231
- };
36232
36317
  function calculateTabStyle(nodeSize2, view, pos, blockParent2, paragraphContext, coordCache = null, domPosCache = null) {
36233
36318
  let extraStyles = "";
36234
36319
  try {
@@ -36280,14 +36365,14 @@ function calculateTabStyle(nodeSize2, view, pos, blockParent2, paragraphContext,
36280
36365
  tabWidth -= integralWidth;
36281
36366
  }
36282
36367
  if (tabStop.leader) {
36283
- const leaderStyles = {
36368
+ const leaderStyles2 = {
36284
36369
  dot: "border-bottom: 1px dotted black;",
36285
36370
  heavy: "border-bottom: 2px solid black;",
36286
36371
  hyphen: "border-bottom: 1px solid black;",
36287
36372
  middleDot: "border-bottom: 1px dotted black; margin-bottom: 2px;",
36288
36373
  underscore: "border-bottom: 1px solid black;"
36289
36374
  };
36290
- extraStyles += leaderStyles[tabStop.leader] || "";
36375
+ extraStyles += leaderStyles2[tabStop.leader] || "";
36291
36376
  }
36292
36377
  }
36293
36378
  }
@@ -36299,7 +36384,7 @@ function calculateTabStyle(nodeSize2, view, pos, blockParent2, paragraphContext,
36299
36384
  paragraphContext.accumulatedTabWidth = accumulatedTabWidth + tabWidth;
36300
36385
  return `width: ${tabWidth}px; height: ${tabHeight}; ${extraStyles}`;
36301
36386
  } catch (error) {
36302
- console.error("tab decoration error", error);
36387
+ return null;
36303
36388
  }
36304
36389
  }
36305
36390
  function findParagraphContext($pos, cache, helpers2) {
@@ -36318,13 +36403,16 @@ function findParagraphContext($pos, cache, helpers2) {
36318
36403
  }
36319
36404
  function extractParagraphContext(node, startPos, helpers2, depth = 0) {
36320
36405
  const paragraphProperties = getResolvedParagraphProperties(node);
36406
+ const alignmentAliases = { left: "start", right: "end" };
36321
36407
  let tabStops = [];
36322
36408
  if (Array.isArray(paragraphProperties.tabStops)) {
36323
36409
  tabStops = paragraphProperties.tabStops.map((stop) => {
36324
36410
  const ref2 = stop?.tab;
36325
36411
  if (!ref2) return stop || null;
36412
+ const rawType = ref2.tabType || "start";
36413
+ const mappedVal = alignmentAliases[rawType] || rawType;
36326
36414
  return {
36327
- val: ref2.tabType || "start",
36415
+ val: mappedVal,
36328
36416
  pos: twipsToPixels(Number(ref2.pos) || 0),
36329
36417
  leader: ref2.leader
36330
36418
  };
@@ -37437,6 +37525,184 @@ const CommentsMark = Mark.create({
37437
37525
  return [CommentMarkName, Attribute.mergeAttributes(this.options.htmlAttributes, htmlAttributes)];
37438
37526
  }
37439
37527
  });
37528
+ const leaderStyles = {
37529
+ dot: "border-bottom: 1px dotted black;",
37530
+ heavy: "border-bottom: 2px solid black;",
37531
+ hyphen: "border-bottom: 1px solid black;",
37532
+ middleDot: "border-bottom: 1px dotted black; margin-bottom: 2px;",
37533
+ underscore: "border-bottom: 1px solid black;"
37534
+ };
37535
+ const paragraphIdFromPos = (startPos) => `para-${startPos}`;
37536
+ const tabIdForIndex = (paragraphId, index2) => `${paragraphId}-tab-${index2}`;
37537
+ function createLayoutRequest(doc2, paragraphPos, view, helpers2, revision, paragraphWidthOverride) {
37538
+ const $pos = doc2.resolve(paragraphPos);
37539
+ const paragraphCache = /* @__PURE__ */ new Map();
37540
+ const paragraphContext = findParagraphContext($pos, paragraphCache, helpers2);
37541
+ if (!paragraphContext) return null;
37542
+ const paragraphId = paragraphIdFromPos(paragraphContext.startPos);
37543
+ const paragraphNode = paragraphContext.paragraph;
37544
+ const { entries } = flattenParagraph(paragraphNode, paragraphContext.startPos);
37545
+ const spans = [];
37546
+ let tabIndex = 0;
37547
+ entries.forEach((entry, idx) => {
37548
+ const node = entry.node;
37549
+ const spanId = `${paragraphId}-span-${idx}`;
37550
+ const from2 = entry.pos;
37551
+ const to = entry.pos + node.nodeSize;
37552
+ if (node.type.name === "tab") {
37553
+ spans.push({
37554
+ type: "tab",
37555
+ spanId,
37556
+ tabId: tabIdForIndex(paragraphId, tabIndex++),
37557
+ pos: entry.pos,
37558
+ nodeSize: node.nodeSize
37559
+ });
37560
+ } else if (node.type.name === "text") {
37561
+ spans.push({
37562
+ type: "text",
37563
+ spanId,
37564
+ text: node.text || "",
37565
+ style: node.marks?.find((mark) => mark.type.name === "textStyle")?.attrs || {},
37566
+ from: from2,
37567
+ to
37568
+ });
37569
+ }
37570
+ });
37571
+ const tabStops = Array.isArray(paragraphContext.tabStops) ? [...paragraphContext.tabStops] : [];
37572
+ const hangingPx = twipsToPixels(Number(paragraphContext.indent?.hanging) || 0);
37573
+ if (hangingPx > 0 && paragraphContext.indentWidth != null) {
37574
+ tabStops.unshift({ val: "start", pos: paragraphContext.indentWidth + hangingPx, leader: "none" });
37575
+ }
37576
+ const paragraphWidth = getBlockNodeWidth(view, paragraphContext.startPos) ?? defaultLineLength;
37577
+ const indentWidth = paragraphContext.indentWidth ?? getIndentWidth(view, paragraphContext.startPos, paragraphContext.indent);
37578
+ return {
37579
+ paragraphId,
37580
+ revision,
37581
+ paragraphWidth,
37582
+ defaultTabDistance,
37583
+ defaultLineLength,
37584
+ indents: {
37585
+ left: twipsToPixels(Number(paragraphContext.indent?.left) || 0),
37586
+ right: twipsToPixels(Number(paragraphContext.indent?.right) || 0),
37587
+ firstLine: twipsToPixels(Number(paragraphContext.indent?.firstLine) || 0),
37588
+ hanging: hangingPx
37589
+ },
37590
+ tabStops,
37591
+ spans,
37592
+ indentWidth,
37593
+ paragraphNode
37594
+ };
37595
+ }
37596
+ function calculateTabLayout(request, measurement, view) {
37597
+ const {
37598
+ spans,
37599
+ tabStops,
37600
+ paragraphWidth,
37601
+ defaultTabDistance: defaultTabDistance2,
37602
+ defaultLineLength: defaultLineLength2,
37603
+ paragraphId,
37604
+ revision,
37605
+ indentWidth = 0,
37606
+ paragraphNode
37607
+ } = request;
37608
+ const tabs = {};
37609
+ let currentX = indentWidth;
37610
+ const measureText2 = (span) => {
37611
+ if (view && typeof span.from === "number" && typeof span.to === "number") {
37612
+ return measureRangeWidth(view, span.from, span.to);
37613
+ }
37614
+ return 0;
37615
+ };
37616
+ const tabHeight = paragraphNode ? calcTabHeight(paragraphNode) : void 0;
37617
+ for (let i = 0; i < spans.length; i++) {
37618
+ const span = spans[i];
37619
+ if (span.type === "text") {
37620
+ currentX += measureText2(span);
37621
+ } else if (span.type === "tab") {
37622
+ const followingText = collectFollowingText(spans, i + 1);
37623
+ let measureTextCallback;
37624
+ if (view) {
37625
+ const followingRange = getFollowingTextRange(spans, i + 1);
37626
+ if (followingRange) {
37627
+ const fullWidth = measureRangeWidth(view, followingRange.from, followingRange.to);
37628
+ const fullText = followingText;
37629
+ measureTextCallback = (text) => {
37630
+ if (text === fullText) return fullWidth;
37631
+ if (fullText.length > 0) {
37632
+ return text.length / fullText.length * fullWidth;
37633
+ }
37634
+ return 0;
37635
+ };
37636
+ }
37637
+ }
37638
+ const result = calculateTabWidth({
37639
+ currentX,
37640
+ tabStops,
37641
+ paragraphWidth,
37642
+ defaultTabDistance: defaultTabDistance2,
37643
+ defaultLineLength: defaultLineLength2,
37644
+ followingText,
37645
+ measureText: measureTextCallback
37646
+ });
37647
+ tabs[span.tabId] = {
37648
+ width: result.width,
37649
+ height: tabHeight,
37650
+ leader: result.leader,
37651
+ alignment: result.alignment,
37652
+ tabStopPosUsed: result.tabStopPosUsed
37653
+ };
37654
+ currentX += result.width;
37655
+ }
37656
+ }
37657
+ return {
37658
+ paragraphId,
37659
+ revision,
37660
+ tabs
37661
+ };
37662
+ }
37663
+ function applyLayoutResult(result, paragraph, paragraphPos) {
37664
+ const decorations = [];
37665
+ let tabIndex = 0;
37666
+ paragraph.forEach((node, offset2) => {
37667
+ if (node.type.name !== "tab") return;
37668
+ const pos = paragraphPos + offset2 + 1;
37669
+ const tabId = tabIdForIndex(result.paragraphId, tabIndex++);
37670
+ const layout = result.tabs[tabId];
37671
+ if (!layout) return;
37672
+ let style = `width: ${layout.width}px;`;
37673
+ if (layout.height) style += ` height: ${layout.height};`;
37674
+ if (layout.leader && leaderStyles[layout.leader]) {
37675
+ style += ` ${leaderStyles[layout.leader]}`;
37676
+ }
37677
+ decorations.push(Decoration.node(pos, pos + node.nodeSize, { style }));
37678
+ });
37679
+ return decorations;
37680
+ }
37681
+ function collectFollowingText(spans, startIndex) {
37682
+ let text = "";
37683
+ for (let i = startIndex; i < spans.length; i++) {
37684
+ const span = spans[i];
37685
+ if (span.type === "tab") break;
37686
+ if (span.type === "text") text += span.text || "";
37687
+ }
37688
+ return text;
37689
+ }
37690
+ function getFollowingTextRange(spans, startIndex) {
37691
+ let from2 = null;
37692
+ let to = null;
37693
+ for (let i = startIndex; i < spans.length; i++) {
37694
+ const span = spans[i];
37695
+ if (span.type === "tab") break;
37696
+ if (span.type === "text" && typeof span.from === "number" && typeof span.to === "number") {
37697
+ if (from2 === null) from2 = span.from;
37698
+ to = span.to;
37699
+ }
37700
+ }
37701
+ if (from2 !== null && to !== null) {
37702
+ return { from: from2, to };
37703
+ }
37704
+ return null;
37705
+ }
37440
37706
  const TabNode = Node$1.create({
37441
37707
  name: "tab",
37442
37708
  group: "inline",
@@ -37478,87 +37744,24 @@ const TabNode = Node$1.create({
37478
37744
  return [];
37479
37745
  }
37480
37746
  const { view, helpers: helpers2 } = this.editor;
37481
- const mergeRanges2 = (ranges) => {
37482
- if (ranges.length === 0) return [];
37483
- const sorted = ranges.slice().sort((a, b) => a[0] - b[0]);
37484
- const merged = [sorted[0]];
37485
- for (let i = 1; i < sorted.length; i++) {
37486
- const [start2, end2] = sorted[i];
37487
- const last = merged[merged.length - 1];
37488
- if (start2 <= last[1]) {
37489
- last[1] = Math.max(last[1], end2);
37490
- } else {
37491
- merged.push([start2, end2]);
37492
- }
37493
- }
37494
- return merged;
37495
- };
37496
37747
  const tabPlugin = new Plugin({
37497
37748
  name: "tabPlugin",
37498
37749
  key: new PluginKey("tabPlugin"),
37499
37750
  state: {
37500
37751
  init() {
37501
- return { decorations: false };
37752
+ return { decorations: false, revision: 0 };
37502
37753
  },
37503
- apply(tr, { decorations }, _oldState, newState) {
37754
+ apply(tr, { decorations, revision }, _oldState, newState) {
37504
37755
  if (!decorations) {
37505
- decorations = DecorationSet.create(newState.doc, getTabDecorations(newState.doc, view, helpers2));
37506
- return { decorations };
37756
+ const newDecorations2 = buildDecorations(newState.doc, view, helpers2, 0);
37757
+ return { decorations: newDecorations2, revision: 0 };
37507
37758
  }
37508
37759
  if (!tr.docChanged || tr.getMeta("blockNodeInitialUpdate")) {
37509
- return { decorations };
37510
- }
37511
- decorations = decorations.map(tr.mapping, tr.doc);
37512
- const rangesToRecalculate = [];
37513
- const containsTab = (node) => node.type.name === "tab";
37514
- tr.steps.forEach((step, index2) => {
37515
- if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep$1)) {
37516
- return;
37517
- }
37518
- let hasTabInRange = false;
37519
- if (step.slice?.content) {
37520
- step.slice.content.descendants((node) => {
37521
- if (containsTab(node)) {
37522
- hasTabInRange = true;
37523
- return false;
37524
- }
37525
- });
37526
- }
37527
- if (!hasTabInRange) {
37528
- tr.docs[index2].nodesBetween(step.from, step.to, (node) => {
37529
- if (containsTab(node)) {
37530
- hasTabInRange = true;
37531
- return false;
37532
- }
37533
- });
37534
- }
37535
- if (!hasTabInRange) {
37536
- return;
37537
- }
37538
- let fromPos = step.from;
37539
- let toPos = step.to;
37540
- for (let i = index2; i < tr.steps.length; i++) {
37541
- const stepMap = tr.steps[i].getMap();
37542
- fromPos = stepMap.map(fromPos, -1);
37543
- toPos = stepMap.map(toPos, 1);
37544
- }
37545
- const $from = newState.doc.resolve(fromPos);
37546
- const $to = newState.doc.resolve(toPos);
37547
- const start2 = $from.start(Math.min($from.depth, 1));
37548
- const end2 = $to.end(Math.min($to.depth, 1));
37549
- rangesToRecalculate.push([start2, end2]);
37550
- });
37551
- if (rangesToRecalculate.length === 0) {
37552
- return { decorations };
37760
+ return { decorations, revision };
37553
37761
  }
37554
- const mergedRanges = mergeRanges2(rangesToRecalculate);
37555
- mergedRanges.forEach(([start2, end2]) => {
37556
- const oldDecorations = decorations.find(start2, end2);
37557
- decorations = decorations.remove(oldDecorations);
37558
- const newDecorations = getTabDecorations(newState.doc, view, helpers2, start2, end2);
37559
- decorations = decorations.add(newState.doc, newDecorations);
37560
- });
37561
- return { decorations };
37762
+ const nextRevision = revision + 1;
37763
+ const newDecorations = buildDecorations(newState.doc, view, helpers2, nextRevision);
37764
+ return { decorations: newDecorations, revision: nextRevision };
37562
37765
  }
37563
37766
  },
37564
37767
  props: {
@@ -37570,6 +37773,27 @@ const TabNode = Node$1.create({
37570
37773
  return [tabPlugin];
37571
37774
  }
37572
37775
  });
37776
+ function buildDecorations(doc2, view, helpers2, revision) {
37777
+ const decorations = [];
37778
+ doc2.descendants((node, pos) => {
37779
+ if (node.type.name !== "paragraph") return;
37780
+ let hasTab = false;
37781
+ node.descendants((child) => {
37782
+ if (child.type.name === "tab") {
37783
+ hasTab = true;
37784
+ return false;
37785
+ }
37786
+ return true;
37787
+ });
37788
+ if (!hasTab) return;
37789
+ const request = createLayoutRequest(doc2, pos + 1, view, helpers2, revision);
37790
+ if (!request) return;
37791
+ const result = calculateTabLayout(request, void 0, view);
37792
+ const paragraphDecorations = applyLayoutResult(result, node, pos);
37793
+ decorations.push(...paragraphDecorations);
37794
+ });
37795
+ return DecorationSet.create(doc2, decorations);
37796
+ }
37573
37797
  const LineBreak = Node$1.create({
37574
37798
  name: "lineBreak",
37575
37799
  group: "inline",
@@ -51046,13 +51270,22 @@ function checkWordBoundary(state, pos) {
51046
51270
  return !/\p{L}$/u.test(before.text) || !/^\p{L}/u.test(after.text);
51047
51271
  }
51048
51272
  class SearchState {
51049
- constructor(query, range, deco) {
51273
+ /**
51274
+ * Create a new SearchState instance.
51275
+ *
51276
+ * @param {SearchQuery} query - The search query to execute
51277
+ * @param {{from: number, to: number}|null} range - Optional range to restrict search to, or null for entire document
51278
+ * @param {boolean} highlight - Whether to apply CSS classes for visual highlighting of matches
51279
+ * @param {DecorationSet} deco - The decoration set containing match highlights
51280
+ */
51281
+ constructor(query, range, highlight, deco) {
51050
51282
  this.query = query;
51051
51283
  this.range = range;
51284
+ this.highlight = highlight;
51052
51285
  this.deco = deco;
51053
51286
  }
51054
51287
  }
51055
- function buildMatchDeco(state, query, range) {
51288
+ function buildMatchDeco(state, query, range, highlight = true) {
51056
51289
  if (!query.valid) return DecorationSet.empty;
51057
51290
  let deco = [];
51058
51291
  let sel = state.selection;
@@ -51060,7 +51293,8 @@ function buildMatchDeco(state, query, range) {
51060
51293
  let next = query.findNext(state, pos, end2);
51061
51294
  if (!next) break;
51062
51295
  let cls = next.from == sel.from && next.to == sel.to ? "ProseMirror-active-search-match" : "ProseMirror-search-match";
51063
- deco.push(Decoration.inline(next.from, next.to, { class: cls }));
51296
+ const attrs = highlight ? { class: cls } : {};
51297
+ deco.push(Decoration.inline(next.from, next.to, attrs));
51064
51298
  pos = next.to;
51065
51299
  }
51066
51300
  return DecorationSet.create(state.doc, deco);
@@ -51073,11 +51307,20 @@ function search(options = {}) {
51073
51307
  init(_config, state) {
51074
51308
  let query = options.initialQuery || new SearchQuery({ search: "" });
51075
51309
  let range = options.initialRange || null;
51076
- return new SearchState(query, range, buildMatchDeco(state, query, range));
51310
+ const highlight = options.initialHighlight ?? true;
51311
+ return new SearchState(query, range, highlight, buildMatchDeco(state, query, range, highlight));
51077
51312
  },
51078
51313
  apply(tr, search2, _oldState, state) {
51079
51314
  let set = tr.getMeta(searchKey);
51080
- if (set) return new SearchState(set.query, set.range, buildMatchDeco(state, set.query, set.range));
51315
+ if (set) {
51316
+ const highlight = typeof set.highlight === "boolean" ? set.highlight : true;
51317
+ return new SearchState(
51318
+ set.query,
51319
+ set.range,
51320
+ highlight,
51321
+ buildMatchDeco(state, set.query, set.range, highlight)
51322
+ );
51323
+ }
51081
51324
  if (tr.docChanged || tr.selectionSet) {
51082
51325
  let range = search2.range;
51083
51326
  if (range) {
@@ -51085,7 +51328,13 @@ function search(options = {}) {
51085
51328
  let to = tr.mapping.map(range.to, -1);
51086
51329
  range = from2 < to ? { from: from2, to } : null;
51087
51330
  }
51088
- search2 = new SearchState(search2.query, range, buildMatchDeco(state, search2.query, range));
51331
+ const highlight = typeof search2.highlight === "boolean" ? search2.highlight : true;
51332
+ search2 = new SearchState(
51333
+ search2.query,
51334
+ range,
51335
+ highlight,
51336
+ buildMatchDeco(state, search2.query, range, highlight)
51337
+ );
51089
51338
  }
51090
51339
  return search2;
51091
51340
  }
@@ -51099,8 +51348,12 @@ function getMatchHighlights(state) {
51099
51348
  let search2 = searchKey.getState(state);
51100
51349
  return search2 ? search2.deco : DecorationSet.empty;
51101
51350
  }
51102
- function setSearchState(tr, query, range = null) {
51103
- return tr.setMeta(searchKey, { query, range });
51351
+ function setSearchState(tr, query, range = null, options = {}) {
51352
+ if (options != null && (typeof options !== "object" || Array.isArray(options))) {
51353
+ throw new TypeError("setSearchState options must be an object");
51354
+ }
51355
+ const highlight = typeof options?.highlight === "boolean" ? options.highlight : true;
51356
+ return tr.setMeta(searchKey, { query, range, highlight });
51104
51357
  }
51105
51358
  const isRegExp = (value) => Object.prototype.toString.call(value) === "[object RegExp]";
51106
51359
  const Search = Extension.create({
@@ -51161,14 +51414,25 @@ const Search = Extension.create({
51161
51414
  * Search for string matches in editor content
51162
51415
  * @category Command
51163
51416
  * @param {String|RegExp} patternInput - Search string or pattern
51417
+ * @param {SearchCommandOptions} [options={}] - Options to control search behavior
51164
51418
  * @example
51419
+ * // Basic search with highlighting (default)
51165
51420
  * const matches = editor.commands.search('test string')
51421
+ *
51422
+ * // Regex search
51166
51423
  * const regexMatches = editor.commands.search(/test/i)
51424
+ *
51425
+ * // Search without visual highlighting
51426
+ * const silentMatches = editor.commands.search('test', { highlight: false })
51167
51427
  * @note Returns array of SearchMatch objects with positions and IDs
51168
51428
  */
51169
- search: (patternInput) => (
51429
+ search: (patternInput, options = {}) => (
51170
51430
  /** @returns {SearchMatch[]} */
51171
51431
  ({ state, dispatch }) => {
51432
+ if (options != null && (typeof options !== "object" || Array.isArray(options))) {
51433
+ throw new TypeError("Search options must be an object");
51434
+ }
51435
+ const highlight = typeof options?.highlight === "boolean" ? options.highlight : true;
51172
51436
  let pattern;
51173
51437
  let caseSensitive = false;
51174
51438
  let regexp = false;
@@ -51195,7 +51459,7 @@ const Search = Extension.create({
51195
51459
  regexp,
51196
51460
  wholeWord
51197
51461
  });
51198
- const tr = setSearchState(state.tr, query);
51462
+ const tr = setSearchState(state.tr, query, null, { highlight });
51199
51463
  dispatch(tr);
51200
51464
  const newState = state.apply(tr);
51201
51465
  const decoSet = getMatchHighlights(newState);