superdoc 1.0.0-beta.14 → 1.0.0-beta.16
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.
- package/dist/chunks/{PdfViewer-Cdc_EOZ9.cjs → PdfViewer-93eWvs8z.cjs} +1 -1
- package/dist/chunks/{PdfViewer-DrsLL5TV.es.js → PdfViewer-ODeuH1gb.es.js} +1 -1
- package/dist/chunks/{index-DB1DyDmZ.es.js → index-DW5_UKLM.es.js} +3 -3
- package/dist/chunks/{index-I4Ew0HDV-Bht7-IGi.es.js → index-DexFffM7-Cbdy0Zy6.es.js} +1 -1
- package/dist/chunks/{index-I4Ew0HDV-EPhjcu7T.cjs → index-DexFffM7-XZD_g6eY.cjs} +1 -1
- package/dist/chunks/{index-9ZvcPlCg.cjs → index-RquHXtgI.cjs} +3 -3
- package/dist/chunks/{super-editor.es-DuS77THX.cjs → super-editor.es-BLKWkx5G.cjs} +3220 -569
- package/dist/chunks/{super-editor.es-DxAG4BVh.es.js → super-editor.es-Dg5uoFkw.es.js} +3220 -569
- package/dist/packages/superdoc/src/core/SuperDoc.d.ts.map +1 -1
- package/dist/style.css +6 -6
- package/dist/super-editor/ai-writer.es.js +2 -2
- package/dist/super-editor/chunks/{converter-CfmIU--8.js → converter-C_R_BK8X.js} +412 -252
- package/dist/super-editor/chunks/{docx-zipper-B-CXiNSb.js → docx-zipper-BvQAYmi1.js} +1 -1
- package/dist/super-editor/chunks/{editor-wC_gs8Bl.js → editor-DFFvalb1.js} +2822 -312
- package/dist/super-editor/chunks/{index-I4Ew0HDV.js → index-DexFffM7.js} +1 -1
- package/dist/super-editor/chunks/{toolbar-BR1GYvwW.js → toolbar-DLPfegtw.js} +2 -2
- package/dist/super-editor/converter.es.js +1 -1
- package/dist/super-editor/docx-zipper.es.js +2 -2
- package/dist/super-editor/editor.es.js +3 -3
- package/dist/super-editor/file-zipper.es.js +1 -1
- package/dist/super-editor/style.css +6 -6
- package/dist/super-editor/super-editor.es.js +8 -100
- package/dist/super-editor/toolbar.es.js +2 -2
- package/dist/super-editor.cjs +1 -1
- package/dist/super-editor.es.js +1 -1
- package/dist/superdoc.cjs +2 -2
- package/dist/superdoc.es.js +2 -2
- package/dist/superdoc.umd.js +3222 -571
- package/dist/superdoc.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,11 +9,11 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
9
9
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
10
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
11
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
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, _lastSelectedImageBlockId, _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, findHeaderFooterPageForPageNumber_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, _layoutSurfaces, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_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, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
|
|
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, _lastSelectedImageBlockId, _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, findHeaderFooterPageForPageNumber_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, computeCaretLayoutRectFromDOM_fn, computeTableCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_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, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
|
|
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-
|
|
16
|
-
import { D as DocxZipper } from "./docx-zipper-
|
|
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-C_R_BK8X.js";
|
|
16
|
+
import { D as DocxZipper } from "./docx-zipper-BvQAYmi1.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() {
|
|
@@ -887,17 +887,20 @@ function findOffsetInNode(node, coords) {
|
|
|
887
887
|
}
|
|
888
888
|
function findOffsetInText(node, coords) {
|
|
889
889
|
let len = node.nodeValue.length;
|
|
890
|
-
let range = document.createRange();
|
|
890
|
+
let range = document.createRange(), result;
|
|
891
891
|
for (let i = 0; i < len; i++) {
|
|
892
892
|
range.setEnd(node, i + 1);
|
|
893
893
|
range.setStart(node, i);
|
|
894
894
|
let rect = singleRect(range, 1);
|
|
895
895
|
if (rect.top == rect.bottom)
|
|
896
896
|
continue;
|
|
897
|
-
if (inRect(coords, rect))
|
|
898
|
-
|
|
897
|
+
if (inRect(coords, rect)) {
|
|
898
|
+
result = { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
899
901
|
}
|
|
900
|
-
|
|
902
|
+
range.detach();
|
|
903
|
+
return result || { node, offset: 0 };
|
|
901
904
|
}
|
|
902
905
|
function inRect(coords, rect) {
|
|
903
906
|
return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1;
|
|
@@ -3644,7 +3647,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
|
|
|
3644
3647
|
if (!view.composing) {
|
|
3645
3648
|
view.domObserver.flush();
|
|
3646
3649
|
let { state } = view, $pos = state.selection.$to;
|
|
3647
|
-
if (state.selection instanceof TextSelection && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false))) {
|
|
3650
|
+
if (state.selection instanceof TextSelection && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false) || chrome && windows$1 && selectionBeforeUneditable(view))) {
|
|
3648
3651
|
view.markCursor = view.state.storedMarks || $pos.marks();
|
|
3649
3652
|
endComposition(view, true);
|
|
3650
3653
|
view.markCursor = null;
|
|
@@ -3672,6 +3675,13 @@ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
|
|
|
3672
3675
|
}
|
|
3673
3676
|
scheduleComposeEnd(view, timeoutComposition);
|
|
3674
3677
|
};
|
|
3678
|
+
function selectionBeforeUneditable(view) {
|
|
3679
|
+
let { focusNode, focusOffset } = view.domSelectionRange();
|
|
3680
|
+
if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
|
|
3681
|
+
return false;
|
|
3682
|
+
let next = focusNode.childNodes[focusOffset];
|
|
3683
|
+
return next.nodeType == 1 && next.contentEditable == "false";
|
|
3684
|
+
}
|
|
3675
3685
|
editHandlers.compositionend = (view, event) => {
|
|
3676
3686
|
if (view.composing) {
|
|
3677
3687
|
view.input.composing = false;
|
|
@@ -3875,10 +3885,14 @@ handlers.dragend = (view) => {
|
|
|
3875
3885
|
}, 50);
|
|
3876
3886
|
};
|
|
3877
3887
|
editHandlers.dragover = editHandlers.dragenter = (_, e) => e.preventDefault();
|
|
3878
|
-
editHandlers.drop = (view,
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3888
|
+
editHandlers.drop = (view, event) => {
|
|
3889
|
+
try {
|
|
3890
|
+
handleDrop(view, event, view.dragging);
|
|
3891
|
+
} finally {
|
|
3892
|
+
view.dragging = null;
|
|
3893
|
+
}
|
|
3894
|
+
};
|
|
3895
|
+
function handleDrop(view, event, dragging) {
|
|
3882
3896
|
if (!event.dataTransfer)
|
|
3883
3897
|
return;
|
|
3884
3898
|
let eventPos = view.posAtCoords(eventCoords(event));
|
|
@@ -3931,7 +3945,7 @@ editHandlers.drop = (view, _event) => {
|
|
|
3931
3945
|
}
|
|
3932
3946
|
view.focus();
|
|
3933
3947
|
view.dispatch(tr.setMeta("uiEvent", "drop"));
|
|
3934
|
-
}
|
|
3948
|
+
}
|
|
3935
3949
|
handlers.focus = (view) => {
|
|
3936
3950
|
view.input.lastFocus = Date.now();
|
|
3937
3951
|
if (!view.focused) {
|
|
@@ -4781,6 +4795,13 @@ class DOMObserver {
|
|
|
4781
4795
|
br.remove();
|
|
4782
4796
|
}
|
|
4783
4797
|
}
|
|
4798
|
+
} else if ((chrome || safari) && added.some((n) => n.nodeName == "BR") && (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46)) {
|
|
4799
|
+
for (let node of added)
|
|
4800
|
+
if (node.nodeName == "BR" && node.parentNode) {
|
|
4801
|
+
let after = node.nextSibling;
|
|
4802
|
+
if (after && after.nodeType == 1 && after.contentEditable == "false")
|
|
4803
|
+
node.parentNode.removeChild(node);
|
|
4804
|
+
}
|
|
4784
4805
|
}
|
|
4785
4806
|
let readSel = null;
|
|
4786
4807
|
if (from2 < 0 && newSel && view.input.lastFocus > Date.now() - 200 && Math.max(view.input.lastTouch, view.input.lastClick.time) < Date.now() - 300 && selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) && readSel.eq(Selection.near(view.state.doc.resolve(0), 1))) {
|
|
@@ -9964,7 +9985,7 @@ const Keymap = Extension.create({
|
|
|
9964
9985
|
const baseKeymap = {
|
|
9965
9986
|
Enter: () => handleEnter(this.editor),
|
|
9966
9987
|
"Shift-Enter": () => this.editor.commands.insertLineBreak(),
|
|
9967
|
-
"Mod-Enter": () => this.editor.commands.
|
|
9988
|
+
"Mod-Enter": () => this.editor.commands.insertPageBreak(),
|
|
9968
9989
|
Backspace: () => handleBackspace(this.editor),
|
|
9969
9990
|
"Mod-Backspace": () => handleBackspace(this.editor),
|
|
9970
9991
|
"Shift-Backspace": () => handleBackspace(this.editor),
|
|
@@ -13553,7 +13574,7 @@ const isHeadless = (editor) => {
|
|
|
13553
13574
|
const shouldSkipNodeView = (editor) => {
|
|
13554
13575
|
return isHeadless(editor);
|
|
13555
13576
|
};
|
|
13556
|
-
const summaryVersion = "1.0.0-beta.
|
|
13577
|
+
const summaryVersion = "1.0.0-beta.16";
|
|
13557
13578
|
const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
|
|
13558
13579
|
const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
|
|
13559
13580
|
function mapAttributes(attrs) {
|
|
@@ -14335,7 +14356,7 @@ const _Editor = class _Editor extends EventEmitter {
|
|
|
14335
14356
|
{ default: remarkStringify },
|
|
14336
14357
|
{ default: remarkGfm }
|
|
14337
14358
|
] = await Promise.all([
|
|
14338
|
-
import("./index-
|
|
14359
|
+
import("./index-DexFffM7.js"),
|
|
14339
14360
|
import("./index-DRCvimau.js"),
|
|
14340
14361
|
import("./index-C_x_N6Uh.js"),
|
|
14341
14362
|
import("./index-D_sWOSiG.js"),
|
|
@@ -14540,7 +14561,7 @@ const _Editor = class _Editor extends EventEmitter {
|
|
|
14540
14561
|
* Process collaboration migrations
|
|
14541
14562
|
*/
|
|
14542
14563
|
processCollaborationMigrations() {
|
|
14543
|
-
console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.
|
|
14564
|
+
console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.16");
|
|
14544
14565
|
if (!this.options.ydoc) return;
|
|
14545
14566
|
const metaMap = this.options.ydoc.getMap("meta");
|
|
14546
14567
|
let docVersion = metaMap.get("version");
|
|
@@ -15703,7 +15724,7 @@ const pickLang = (value) => {
|
|
|
15703
15724
|
const normalized = value.trim().toLowerCase();
|
|
15704
15725
|
return normalized || void 0;
|
|
15705
15726
|
};
|
|
15706
|
-
const normalizeColor = (value) => {
|
|
15727
|
+
const normalizeColor$1 = (value) => {
|
|
15707
15728
|
if (typeof value !== "string") return void 0;
|
|
15708
15729
|
const trimmed = value.trim();
|
|
15709
15730
|
if (!trimmed || trimmed === "auto" || trimmed === "none") return void 0;
|
|
@@ -16343,20 +16364,37 @@ const resolveThemeColor = (attrs, themeColors) => {
|
|
|
16343
16364
|
const resolveColorFromAttributes = (attrs, themeColors) => {
|
|
16344
16365
|
if (!attrs) return void 0;
|
|
16345
16366
|
if (typeof attrs.color === "string") {
|
|
16346
|
-
const normalized = normalizeColor(attrs.color);
|
|
16367
|
+
const normalized = normalizeColor$1(attrs.color);
|
|
16347
16368
|
if (normalized) {
|
|
16348
16369
|
return normalized;
|
|
16349
16370
|
}
|
|
16350
16371
|
}
|
|
16351
16372
|
const theme = resolveThemeColor(attrs, themeColors);
|
|
16352
16373
|
if (theme) {
|
|
16353
|
-
return normalizeColor(theme);
|
|
16374
|
+
return normalizeColor$1(theme);
|
|
16354
16375
|
}
|
|
16355
16376
|
return void 0;
|
|
16356
16377
|
};
|
|
16357
16378
|
const MAX_DATA_ATTR_COUNT = 50;
|
|
16358
16379
|
const MAX_DATA_ATTR_VALUE_LENGTH = 1e3;
|
|
16359
16380
|
const MAX_DATA_ATTR_NAME_LENGTH = 100;
|
|
16381
|
+
const pushCommentAnnotation = (run, attrs) => {
|
|
16382
|
+
const commentId = typeof attrs?.commentId === "string" ? attrs.commentId : void 0;
|
|
16383
|
+
const importedId = typeof attrs?.importedId === "string" ? attrs.importedId : void 0;
|
|
16384
|
+
const internal = attrs?.internal === true;
|
|
16385
|
+
if (!commentId && !importedId) return;
|
|
16386
|
+
const annotations = run.comments ? [...run.comments] : [];
|
|
16387
|
+
const key2 = `${commentId ?? ""}::${importedId ?? ""}`;
|
|
16388
|
+
const exists = annotations.some((c) => `${c.commentId ?? ""}::${c.importedId ?? ""}` === key2);
|
|
16389
|
+
if (!exists) {
|
|
16390
|
+
annotations.push({
|
|
16391
|
+
commentId: commentId ?? importedId,
|
|
16392
|
+
importedId,
|
|
16393
|
+
internal
|
|
16394
|
+
});
|
|
16395
|
+
}
|
|
16396
|
+
run.comments = annotations;
|
|
16397
|
+
};
|
|
16360
16398
|
const extractDataAttributes = (attrs) => {
|
|
16361
16399
|
if (!attrs) return void 0;
|
|
16362
16400
|
const result = {};
|
|
@@ -16639,6 +16677,11 @@ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG,
|
|
|
16639
16677
|
case "textStyle":
|
|
16640
16678
|
applyTextStyleMark(run, mark.attrs ?? {}, themeColors);
|
|
16641
16679
|
break;
|
|
16680
|
+
case "commentMark":
|
|
16681
|
+
case "comment": {
|
|
16682
|
+
pushCommentAnnotation(run, mark.attrs ?? {});
|
|
16683
|
+
break;
|
|
16684
|
+
}
|
|
16642
16685
|
case "underline": {
|
|
16643
16686
|
const style = normalizeUnderlineStyle(mark.attrs?.underlineType);
|
|
16644
16687
|
if (style) {
|
|
@@ -16763,13 +16806,8 @@ const MAX_BORDER_SIZE_PX = 100;
|
|
|
16763
16806
|
const borderSizeToPx = (size) => {
|
|
16764
16807
|
if (!isFiniteNumber(size)) return void 0;
|
|
16765
16808
|
if (size <= 0) return 0;
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
pixelValue = size;
|
|
16769
|
-
} else {
|
|
16770
|
-
const points = size / EIGHTHS_PER_POINT;
|
|
16771
|
-
pixelValue = points * PX_PER_PT;
|
|
16772
|
-
}
|
|
16809
|
+
const points = size / EIGHTHS_PER_POINT;
|
|
16810
|
+
const pixelValue = points * PX_PER_PT;
|
|
16773
16811
|
return Math.min(MAX_BORDER_SIZE_PX, Math.max(MIN_BORDER_SIZE_PX, pixelValue));
|
|
16774
16812
|
};
|
|
16775
16813
|
const normalizeColorWithDefault = (color) => {
|
|
@@ -16908,7 +16946,7 @@ const normalizeBorderSide = (value) => {
|
|
|
16908
16946
|
if (style === "none") return void 0;
|
|
16909
16947
|
const width = pickNumber(raw.size);
|
|
16910
16948
|
const widthPx = borderSizeToPx(width);
|
|
16911
|
-
const color = normalizeColor(raw.color);
|
|
16949
|
+
const color = normalizeColor$1(raw.color);
|
|
16912
16950
|
const space = pickNumber(raw.space);
|
|
16913
16951
|
if (!style && widthPx == null && space == null && !color) {
|
|
16914
16952
|
return void 0;
|
|
@@ -16964,7 +17002,7 @@ const normalizeParagraphShading = (value) => {
|
|
|
16964
17002
|
return Object.keys(shading).length > 0 ? shading : void 0;
|
|
16965
17003
|
};
|
|
16966
17004
|
const normalizeShadingColor = (value) => {
|
|
16967
|
-
const normalized = normalizeColor(value);
|
|
17005
|
+
const normalized = normalizeColor$1(value);
|
|
16968
17006
|
if (!normalized) return void 0;
|
|
16969
17007
|
if (normalized.toLowerCase() === "#auto") {
|
|
16970
17008
|
return void 0;
|
|
@@ -18127,11 +18165,11 @@ const buildMarkerLayout = ({
|
|
|
18127
18165
|
baselineOffsetPx: markerRun.baselineShift ?? 0,
|
|
18128
18166
|
gutterWidthPx: markerBoxWidthPx,
|
|
18129
18167
|
justification: numbering.lvlJc ?? "left",
|
|
18130
|
-
suffix: normalizeSuffix(numbering.suffix) ?? "tab",
|
|
18168
|
+
suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
|
|
18131
18169
|
run: markerRun,
|
|
18132
18170
|
path: numbering.path
|
|
18133
18171
|
});
|
|
18134
|
-
const normalizeSuffix = (suffix) => {
|
|
18172
|
+
const normalizeSuffix$1 = (suffix) => {
|
|
18135
18173
|
if (suffix === "tab" || suffix === "space" || suffix === "nothing") {
|
|
18136
18174
|
return suffix;
|
|
18137
18175
|
}
|
|
@@ -18555,10 +18593,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
|
|
|
18555
18593
|
}
|
|
18556
18594
|
const resolvedExtended = resolved;
|
|
18557
18595
|
const resolvedAsRecord = resolved;
|
|
18596
|
+
let resolvedIndent = cloneIfObject(resolvedAsRecord.indent);
|
|
18597
|
+
const styleIdLower = typeof styleId === "string" ? styleId.toLowerCase() : "";
|
|
18598
|
+
const isHeadingStyle = typeof resolvedExtended.outlineLvl === "number" || styleIdLower.startsWith("heading ") || styleIdLower.startsWith("heading");
|
|
18599
|
+
const onlyFirstLineIndent = resolvedIndent && resolvedIndent.firstLine != null && resolvedIndent.hanging == null && resolvedIndent.left == null && resolvedIndent.right == null;
|
|
18600
|
+
if (isHeadingStyle && (!resolvedIndent || Object.keys(resolvedIndent).length === 0 || onlyFirstLineIndent)) {
|
|
18601
|
+
resolvedIndent = { firstLine: 0, hanging: 0, left: resolvedIndent?.left, right: resolvedIndent?.right };
|
|
18602
|
+
}
|
|
18558
18603
|
const hydrated = {
|
|
18559
18604
|
resolved,
|
|
18560
18605
|
spacing: cloneIfObject(resolvedAsRecord.spacing),
|
|
18561
|
-
indent:
|
|
18606
|
+
indent: resolvedIndent,
|
|
18562
18607
|
borders: cloneIfObject(resolvedExtended.borders),
|
|
18563
18608
|
shading: cloneIfObject(resolvedExtended.shading),
|
|
18564
18609
|
alignment: resolvedExtended.justification,
|
|
@@ -18578,6 +18623,154 @@ const cloneIfObject = (value) => {
|
|
|
18578
18623
|
};
|
|
18579
18624
|
const { resolveSpacingIndent } = Engines;
|
|
18580
18625
|
const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
|
|
18626
|
+
const asOoxmlElement = (value) => {
|
|
18627
|
+
if (!value || typeof value !== "object") return void 0;
|
|
18628
|
+
const element = value;
|
|
18629
|
+
if (element.name == null && element.attributes == null && element.elements == null) return void 0;
|
|
18630
|
+
return element;
|
|
18631
|
+
};
|
|
18632
|
+
const findChild = (parent, name) => {
|
|
18633
|
+
return parent?.elements?.find((child) => child?.name === name);
|
|
18634
|
+
};
|
|
18635
|
+
const getAttribute = (element, key2) => {
|
|
18636
|
+
if (!element?.attributes) return void 0;
|
|
18637
|
+
const attrs = element.attributes;
|
|
18638
|
+
return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
|
|
18639
|
+
};
|
|
18640
|
+
const parseNumberAttr = (value) => {
|
|
18641
|
+
if (value == null) return void 0;
|
|
18642
|
+
const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
|
|
18643
|
+
return Number.isFinite(num) ? num : void 0;
|
|
18644
|
+
};
|
|
18645
|
+
const normalizeNumFmt = (value) => {
|
|
18646
|
+
if (typeof value !== "string") return void 0;
|
|
18647
|
+
switch (value) {
|
|
18648
|
+
case "decimal":
|
|
18649
|
+
return "decimal";
|
|
18650
|
+
case "lowerLetter":
|
|
18651
|
+
return "lowerLetter";
|
|
18652
|
+
case "upperLetter":
|
|
18653
|
+
return "upperLetter";
|
|
18654
|
+
case "lowerRoman":
|
|
18655
|
+
return "lowerRoman";
|
|
18656
|
+
case "upperRoman":
|
|
18657
|
+
return "upperRoman";
|
|
18658
|
+
case "bullet":
|
|
18659
|
+
return "bullet";
|
|
18660
|
+
default:
|
|
18661
|
+
return void 0;
|
|
18662
|
+
}
|
|
18663
|
+
};
|
|
18664
|
+
const normalizeSuffix = (value) => {
|
|
18665
|
+
if (typeof value !== "string") return void 0;
|
|
18666
|
+
if (value === "tab" || value === "space" || value === "nothing") {
|
|
18667
|
+
return value;
|
|
18668
|
+
}
|
|
18669
|
+
return void 0;
|
|
18670
|
+
};
|
|
18671
|
+
const normalizeJustification = (value) => {
|
|
18672
|
+
if (typeof value !== "string") return void 0;
|
|
18673
|
+
if (value === "start") return "left";
|
|
18674
|
+
if (value === "end") return "right";
|
|
18675
|
+
if (value === "left" || value === "center" || value === "right") return value;
|
|
18676
|
+
return void 0;
|
|
18677
|
+
};
|
|
18678
|
+
const extractIndentFromLevel = (lvl) => {
|
|
18679
|
+
const pPr = findChild(lvl, "w:pPr");
|
|
18680
|
+
const ind = findChild(pPr, "w:ind");
|
|
18681
|
+
if (!ind) return void 0;
|
|
18682
|
+
const left2 = parseNumberAttr(getAttribute(ind, "w:left"));
|
|
18683
|
+
const right2 = parseNumberAttr(getAttribute(ind, "w:right"));
|
|
18684
|
+
const firstLine = parseNumberAttr(getAttribute(ind, "w:firstLine"));
|
|
18685
|
+
const hanging = parseNumberAttr(getAttribute(ind, "w:hanging"));
|
|
18686
|
+
const indent = {};
|
|
18687
|
+
if (left2 != null) indent.left = left2;
|
|
18688
|
+
if (right2 != null) indent.right = right2;
|
|
18689
|
+
if (firstLine != null) indent.firstLine = firstLine;
|
|
18690
|
+
if (hanging != null) indent.hanging = hanging;
|
|
18691
|
+
return Object.keys(indent).length ? indent : void 0;
|
|
18692
|
+
};
|
|
18693
|
+
const normalizeColor = (value) => {
|
|
18694
|
+
if (typeof value !== "string") return void 0;
|
|
18695
|
+
const trimmed = value.trim();
|
|
18696
|
+
if (!trimmed || trimmed.toLowerCase() === "auto") return void 0;
|
|
18697
|
+
const upper = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
|
|
18698
|
+
return `#${upper.toUpperCase()}`;
|
|
18699
|
+
};
|
|
18700
|
+
const extractMarkerRun = (lvl) => {
|
|
18701
|
+
const rPr = findChild(lvl, "w:rPr");
|
|
18702
|
+
if (!rPr) return void 0;
|
|
18703
|
+
const run = {};
|
|
18704
|
+
const rFonts = findChild(rPr, "w:rFonts");
|
|
18705
|
+
const font = getAttribute(rFonts, "w:ascii") ?? getAttribute(rFonts, "w:hAnsi") ?? getAttribute(rFonts, "w:eastAsia");
|
|
18706
|
+
if (typeof font === "string" && font.trim()) {
|
|
18707
|
+
run.fontFamily = font;
|
|
18708
|
+
}
|
|
18709
|
+
const sz = parseNumberAttr(getAttribute(findChild(rPr, "w:sz"), "w:val")) ?? parseNumberAttr(getAttribute(findChild(rPr, "w:szCs"), "w:val"));
|
|
18710
|
+
if (sz != null) {
|
|
18711
|
+
run.fontSize = sz / 2;
|
|
18712
|
+
}
|
|
18713
|
+
const color = normalizeColor(getAttribute(findChild(rPr, "w:color"), "w:val"));
|
|
18714
|
+
if (color) run.color = color;
|
|
18715
|
+
if (findChild(rPr, "w:b")) run.bold = true;
|
|
18716
|
+
if (findChild(rPr, "w:i")) run.italic = true;
|
|
18717
|
+
const spacingTwips = parseNumberAttr(getAttribute(findChild(rPr, "w:spacing"), "w:val"));
|
|
18718
|
+
if (spacingTwips != null && Number.isFinite(spacingTwips)) {
|
|
18719
|
+
run.letterSpacing = twipsToPx$1(spacingTwips);
|
|
18720
|
+
}
|
|
18721
|
+
return Object.keys(run).length ? run : void 0;
|
|
18722
|
+
};
|
|
18723
|
+
const findNumFmtElement = (lvl) => {
|
|
18724
|
+
if (!lvl) return void 0;
|
|
18725
|
+
const direct = findChild(lvl, "w:numFmt");
|
|
18726
|
+
if (direct) return direct;
|
|
18727
|
+
const alternate = findChild(lvl, "mc:AlternateContent");
|
|
18728
|
+
const choice = findChild(alternate, "mc:Choice");
|
|
18729
|
+
if (choice) {
|
|
18730
|
+
return findChild(choice, "w:numFmt");
|
|
18731
|
+
}
|
|
18732
|
+
return void 0;
|
|
18733
|
+
};
|
|
18734
|
+
const resolveNumberingFromContext = (numId, ilvl, numbering) => {
|
|
18735
|
+
const definitions = numbering?.definitions;
|
|
18736
|
+
const abstracts = numbering?.abstracts;
|
|
18737
|
+
if (!definitions || !abstracts) return void 0;
|
|
18738
|
+
const numDef = asOoxmlElement(definitions[String(numId)]);
|
|
18739
|
+
if (!numDef) return void 0;
|
|
18740
|
+
const abstractId = getAttribute(findChild(numDef, "w:abstractNumId"), "w:val");
|
|
18741
|
+
if (abstractId == null) return void 0;
|
|
18742
|
+
const abstract = asOoxmlElement(abstracts[String(abstractId)]);
|
|
18743
|
+
if (!abstract) return void 0;
|
|
18744
|
+
let levelDef = abstract.elements?.find(
|
|
18745
|
+
(el) => el?.name === "w:lvl" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
|
|
18746
|
+
);
|
|
18747
|
+
const override = numDef.elements?.find(
|
|
18748
|
+
(el) => el?.name === "w:lvlOverride" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
|
|
18749
|
+
);
|
|
18750
|
+
const overrideLvl = findChild(override, "w:lvl");
|
|
18751
|
+
if (overrideLvl) {
|
|
18752
|
+
levelDef = overrideLvl;
|
|
18753
|
+
}
|
|
18754
|
+
const startOverride = parseNumberAttr(getAttribute(findChild(override, "w:startOverride"), "w:val"));
|
|
18755
|
+
if (!levelDef) return void 0;
|
|
18756
|
+
const numFmtEl = findNumFmtElement(levelDef);
|
|
18757
|
+
const lvlText = getAttribute(findChild(levelDef, "w:lvlText"), "w:val");
|
|
18758
|
+
const start2 = startOverride ?? parseNumberAttr(getAttribute(findChild(levelDef, "w:start"), "w:val"));
|
|
18759
|
+
const suffix = normalizeSuffix(getAttribute(findChild(levelDef, "w:suff"), "w:val"));
|
|
18760
|
+
const lvlJc = normalizeJustification(getAttribute(findChild(levelDef, "w:lvlJc"), "w:val"));
|
|
18761
|
+
const indent = extractIndentFromLevel(levelDef);
|
|
18762
|
+
const markerRun = extractMarkerRun(levelDef);
|
|
18763
|
+
const numFmt = normalizeNumFmt(getAttribute(numFmtEl, "w:val"));
|
|
18764
|
+
return {
|
|
18765
|
+
format: numFmt,
|
|
18766
|
+
lvlText,
|
|
18767
|
+
start: start2,
|
|
18768
|
+
suffix,
|
|
18769
|
+
lvlJc,
|
|
18770
|
+
resolvedLevelIndent: indent,
|
|
18771
|
+
resolvedMarkerRpr: markerRun
|
|
18772
|
+
};
|
|
18773
|
+
};
|
|
18581
18774
|
const isTruthy = (value) => {
|
|
18582
18775
|
if (value === true || value === 1) return true;
|
|
18583
18776
|
if (typeof value === "string") {
|
|
@@ -18666,6 +18859,12 @@ const cloneParagraphAttrs = (attrs) => {
|
|
|
18666
18859
|
}
|
|
18667
18860
|
if (attrs.shading) clone.shading = { ...attrs.shading };
|
|
18668
18861
|
if (attrs.tabs) clone.tabs = attrs.tabs.map((tab) => ({ ...tab }));
|
|
18862
|
+
if (attrs.dropCapDescriptor) {
|
|
18863
|
+
clone.dropCapDescriptor = {
|
|
18864
|
+
...attrs.dropCapDescriptor,
|
|
18865
|
+
run: { ...attrs.dropCapDescriptor.run }
|
|
18866
|
+
};
|
|
18867
|
+
}
|
|
18669
18868
|
return clone;
|
|
18670
18869
|
};
|
|
18671
18870
|
const buildStyleNodeFromAttrs = (attrs, spacing, indent) => {
|
|
@@ -18777,6 +18976,119 @@ const normalizeResolvedTabAlignment = (value) => {
|
|
|
18777
18976
|
return void 0;
|
|
18778
18977
|
}
|
|
18779
18978
|
};
|
|
18979
|
+
const DEFAULT_DROP_CAP_FONT_SIZE_PX = 64;
|
|
18980
|
+
const DEFAULT_DROP_CAP_FONT_FAMILY = "Times New Roman";
|
|
18981
|
+
const extractDropCapRunFromParagraph = (para) => {
|
|
18982
|
+
const content = para.content;
|
|
18983
|
+
if (!Array.isArray(content) || content.length === 0) {
|
|
18984
|
+
return null;
|
|
18985
|
+
}
|
|
18986
|
+
let text = "";
|
|
18987
|
+
let runProperties = {};
|
|
18988
|
+
let textStyleMarks = {};
|
|
18989
|
+
const MAX_RECURSION_DEPTH = 50;
|
|
18990
|
+
const extractTextAndStyle = (nodes, depth = 0) => {
|
|
18991
|
+
if (depth > MAX_RECURSION_DEPTH) {
|
|
18992
|
+
console.warn(`extractTextAndStyle exceeded max recursion depth (${MAX_RECURSION_DEPTH})`);
|
|
18993
|
+
return false;
|
|
18994
|
+
}
|
|
18995
|
+
for (const node of nodes) {
|
|
18996
|
+
if (!node) continue;
|
|
18997
|
+
if (node.type === "text" && typeof node.text === "string" && node.text.length > 0) {
|
|
18998
|
+
text = node.text;
|
|
18999
|
+
if (Array.isArray(node.marks)) {
|
|
19000
|
+
for (const mark of node.marks) {
|
|
19001
|
+
if (mark?.type === "textStyle" && mark.attrs) {
|
|
19002
|
+
textStyleMarks = { ...textStyleMarks, ...mark.attrs };
|
|
19003
|
+
}
|
|
19004
|
+
}
|
|
19005
|
+
}
|
|
19006
|
+
return true;
|
|
19007
|
+
}
|
|
19008
|
+
if (node.type === "run") {
|
|
19009
|
+
if (node.attrs?.runProperties && typeof node.attrs.runProperties === "object") {
|
|
19010
|
+
runProperties = { ...runProperties, ...node.attrs.runProperties };
|
|
19011
|
+
}
|
|
19012
|
+
if (Array.isArray(node.marks)) {
|
|
19013
|
+
for (const mark of node.marks) {
|
|
19014
|
+
if (mark?.type === "textStyle" && mark.attrs) {
|
|
19015
|
+
textStyleMarks = { ...textStyleMarks, ...mark.attrs };
|
|
19016
|
+
}
|
|
19017
|
+
}
|
|
19018
|
+
}
|
|
19019
|
+
if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
|
|
19020
|
+
return true;
|
|
19021
|
+
}
|
|
19022
|
+
}
|
|
19023
|
+
if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
|
|
19024
|
+
return true;
|
|
19025
|
+
}
|
|
19026
|
+
}
|
|
19027
|
+
return false;
|
|
19028
|
+
};
|
|
19029
|
+
extractTextAndStyle(content);
|
|
19030
|
+
if (!text) {
|
|
19031
|
+
return null;
|
|
19032
|
+
}
|
|
19033
|
+
const mergedStyle = { ...runProperties, ...textStyleMarks };
|
|
19034
|
+
let fontSizePx = DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
19035
|
+
const rawFontSize = mergedStyle.fontSize ?? mergedStyle["w:sz"] ?? mergedStyle.sz;
|
|
19036
|
+
if (rawFontSize != null) {
|
|
19037
|
+
if (typeof rawFontSize === "number") {
|
|
19038
|
+
const converted = rawFontSize > 100 ? ptToPx(rawFontSize / 2) : rawFontSize;
|
|
19039
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
19040
|
+
} else if (typeof rawFontSize === "string") {
|
|
19041
|
+
const numericPart = parseFloat(rawFontSize);
|
|
19042
|
+
if (Number.isFinite(numericPart)) {
|
|
19043
|
+
if (rawFontSize.endsWith("pt")) {
|
|
19044
|
+
const converted = ptToPx(numericPart);
|
|
19045
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
19046
|
+
} else if (rawFontSize.endsWith("px")) {
|
|
19047
|
+
fontSizePx = numericPart;
|
|
19048
|
+
} else {
|
|
19049
|
+
const converted = numericPart > 100 ? ptToPx(numericPart / 2) : numericPart;
|
|
19050
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
19051
|
+
}
|
|
19052
|
+
}
|
|
19053
|
+
}
|
|
19054
|
+
}
|
|
19055
|
+
let fontFamily = DEFAULT_DROP_CAP_FONT_FAMILY;
|
|
19056
|
+
const rawFontFamily = mergedStyle.fontFamily ?? mergedStyle["w:rFonts"] ?? mergedStyle.rFonts;
|
|
19057
|
+
if (typeof rawFontFamily === "string") {
|
|
19058
|
+
fontFamily = rawFontFamily;
|
|
19059
|
+
} else if (rawFontFamily && typeof rawFontFamily === "object") {
|
|
19060
|
+
const rFonts = rawFontFamily;
|
|
19061
|
+
const ascii = rFonts["w:ascii"] ?? rFonts.ascii;
|
|
19062
|
+
if (typeof ascii === "string") {
|
|
19063
|
+
fontFamily = ascii;
|
|
19064
|
+
}
|
|
19065
|
+
}
|
|
19066
|
+
const dropCapRun = {
|
|
19067
|
+
text,
|
|
19068
|
+
fontFamily,
|
|
19069
|
+
fontSize: fontSizePx
|
|
19070
|
+
};
|
|
19071
|
+
const bold = mergedStyle.bold ?? mergedStyle["w:b"] ?? mergedStyle.b;
|
|
19072
|
+
if (isTruthy(bold)) {
|
|
19073
|
+
dropCapRun.bold = true;
|
|
19074
|
+
}
|
|
19075
|
+
const italic = mergedStyle.italic ?? mergedStyle["w:i"] ?? mergedStyle.i;
|
|
19076
|
+
if (isTruthy(italic)) {
|
|
19077
|
+
dropCapRun.italic = true;
|
|
19078
|
+
}
|
|
19079
|
+
const color = mergedStyle.color ?? mergedStyle["w:color"] ?? mergedStyle.val;
|
|
19080
|
+
if (typeof color === "string" && color.length > 0 && color.toLowerCase() !== "auto") {
|
|
19081
|
+
dropCapRun.color = color.startsWith("#") ? color : `#${color}`;
|
|
19082
|
+
}
|
|
19083
|
+
const position = mergedStyle.position ?? mergedStyle["w:position"];
|
|
19084
|
+
if (position != null) {
|
|
19085
|
+
const posNum = pickNumber(position);
|
|
19086
|
+
if (posNum != null) {
|
|
19087
|
+
dropCapRun.position = ptToPx(posNum / 2);
|
|
19088
|
+
}
|
|
19089
|
+
}
|
|
19090
|
+
return dropCapRun;
|
|
19091
|
+
};
|
|
18780
19092
|
const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
|
|
18781
19093
|
if (numberingProps === null) {
|
|
18782
19094
|
return null;
|
|
@@ -19042,6 +19354,24 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
|
|
|
19042
19354
|
const dropCap = framePr["w:dropCap"] ?? framePr.dropCap;
|
|
19043
19355
|
if (dropCap != null && (typeof dropCap === "string" || typeof dropCap === "number" || typeof dropCap === "boolean")) {
|
|
19044
19356
|
paragraphAttrs.dropCap = dropCap;
|
|
19357
|
+
const dropCapMode = typeof dropCap === "string" ? dropCap.toLowerCase() : "drop";
|
|
19358
|
+
const linesValue = pickNumber(framePr["w:lines"] ?? framePr.lines);
|
|
19359
|
+
const wrapValue = asString(framePr["w:wrap"] ?? framePr.wrap);
|
|
19360
|
+
const dropCapRunInfo = extractDropCapRunFromParagraph(para);
|
|
19361
|
+
if (dropCapRunInfo) {
|
|
19362
|
+
const descriptor = {
|
|
19363
|
+
mode: dropCapMode === "margin" ? "margin" : "drop",
|
|
19364
|
+
lines: linesValue != null && linesValue > 0 ? linesValue : 3,
|
|
19365
|
+
run: dropCapRunInfo
|
|
19366
|
+
};
|
|
19367
|
+
if (wrapValue) {
|
|
19368
|
+
const normalizedWrap = wrapValue.toLowerCase();
|
|
19369
|
+
if (normalizedWrap === "around" || normalizedWrap === "notbeside" || normalizedWrap === "none" || normalizedWrap === "tight") {
|
|
19370
|
+
descriptor.wrap = normalizedWrap === "notbeside" ? "notBeside" : normalizedWrap;
|
|
19371
|
+
}
|
|
19372
|
+
}
|
|
19373
|
+
paragraphAttrs.dropCapDescriptor = descriptor;
|
|
19374
|
+
}
|
|
19045
19375
|
}
|
|
19046
19376
|
const frame = {};
|
|
19047
19377
|
const wrap = asString(framePr["w:wrap"] ?? framePr.wrap);
|
|
@@ -19073,6 +19403,30 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
|
|
|
19073
19403
|
const ilvl = Number.isFinite(numberingProps.ilvl) ? Math.max(0, Math.floor(Number(numberingProps.ilvl))) : 0;
|
|
19074
19404
|
const listRendering = normalizeListRenderingAttrs(attrs.listRendering);
|
|
19075
19405
|
const numericNumId = typeof numId === "number" ? numId : void 0;
|
|
19406
|
+
const resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
|
|
19407
|
+
if (resolvedLevel) {
|
|
19408
|
+
if (resolvedLevel.format && numberingProps.format == null) {
|
|
19409
|
+
numberingProps.format = resolvedLevel.format;
|
|
19410
|
+
}
|
|
19411
|
+
if (resolvedLevel.lvlText && numberingProps.lvlText == null) {
|
|
19412
|
+
numberingProps.lvlText = resolvedLevel.lvlText;
|
|
19413
|
+
}
|
|
19414
|
+
if (resolvedLevel.start != null && numberingProps.start == null) {
|
|
19415
|
+
numberingProps.start = resolvedLevel.start;
|
|
19416
|
+
}
|
|
19417
|
+
if (resolvedLevel.suffix && numberingProps.suffix == null) {
|
|
19418
|
+
numberingProps.suffix = resolvedLevel.suffix;
|
|
19419
|
+
}
|
|
19420
|
+
if (resolvedLevel.lvlJc && numberingProps.lvlJc == null) {
|
|
19421
|
+
numberingProps.lvlJc = resolvedLevel.lvlJc;
|
|
19422
|
+
}
|
|
19423
|
+
if (resolvedLevel.resolvedLevelIndent && !numberingProps.resolvedLevelIndent) {
|
|
19424
|
+
numberingProps.resolvedLevelIndent = resolvedLevel.resolvedLevelIndent;
|
|
19425
|
+
}
|
|
19426
|
+
if (resolvedLevel.resolvedMarkerRpr && !numberingProps.resolvedMarkerRpr) {
|
|
19427
|
+
numberingProps.resolvedMarkerRpr = resolvedLevel.resolvedMarkerRpr;
|
|
19428
|
+
}
|
|
19429
|
+
}
|
|
19076
19430
|
let counterValue = 1;
|
|
19077
19431
|
if (listCounterContext && typeof numericNumId === "number") {
|
|
19078
19432
|
counterValue = listCounterContext.incrementListCounter(numericNumId, ilvl);
|
|
@@ -19815,13 +20169,26 @@ const dataAttrsCompatible = (a, b) => {
|
|
|
19815
20169
|
}
|
|
19816
20170
|
return true;
|
|
19817
20171
|
};
|
|
20172
|
+
const commentsCompatible = (a, b) => {
|
|
20173
|
+
const aComments = a.comments ?? [];
|
|
20174
|
+
const bComments = b.comments ?? [];
|
|
20175
|
+
if (aComments.length === 0 && bComments.length === 0) return true;
|
|
20176
|
+
if (aComments.length !== bComments.length) return false;
|
|
20177
|
+
const normalize2 = (c) => `${c.commentId ?? ""}::${c.importedId ?? ""}::${c.internal ? "1" : "0"}`;
|
|
20178
|
+
const aKeys = aComments.map(normalize2).sort();
|
|
20179
|
+
const bKeys = bComments.map(normalize2).sort();
|
|
20180
|
+
for (let i = 0; i < aKeys.length; i++) {
|
|
20181
|
+
if (aKeys[i] !== bKeys[i]) return false;
|
|
20182
|
+
}
|
|
20183
|
+
return true;
|
|
20184
|
+
};
|
|
19818
20185
|
function mergeAdjacentRuns(runs) {
|
|
19819
20186
|
if (runs.length <= 1) return runs;
|
|
19820
20187
|
const merged = [];
|
|
19821
20188
|
let current = runs[0];
|
|
19822
20189
|
for (let i = 1; i < runs.length; i++) {
|
|
19823
20190
|
const next = runs[i];
|
|
19824
|
-
const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next);
|
|
20191
|
+
const canMerge = isTextRun$1(current) && isTextRun$1(next) && !current.token && !next.token && current.pmStart != null && current.pmEnd != null && next.pmStart != null && next.pmEnd != null && current.pmEnd === next.pmStart && current.fontFamily === next.fontFamily && current.fontSize === next.fontSize && current.bold === next.bold && current.italic === next.italic && current.underline === next.underline && current.strike === next.strike && current.color === next.color && current.highlight === next.highlight && (current.letterSpacing ?? 0) === (next.letterSpacing ?? 0) && trackedChangesCompatible(current, next) && dataAttrsCompatible(current, next) && commentsCompatible(current, next);
|
|
19825
20192
|
if (canMerge) {
|
|
19826
20193
|
const currText = current.text ?? "";
|
|
19827
20194
|
const nextText = next.text ?? "";
|
|
@@ -20285,25 +20652,45 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
|
|
|
20285
20652
|
}
|
|
20286
20653
|
return;
|
|
20287
20654
|
}
|
|
20288
|
-
if (node.type === "hardBreak") {
|
|
20289
|
-
flushParagraph();
|
|
20290
|
-
blocks.push({
|
|
20291
|
-
kind: "pageBreak",
|
|
20292
|
-
id: nextId(),
|
|
20293
|
-
attrs: node.attrs || {}
|
|
20294
|
-
});
|
|
20295
|
-
return;
|
|
20296
|
-
}
|
|
20297
|
-
if (node.type === "lineBreak") {
|
|
20655
|
+
if (node.type === "hardBreak" || node.type === "lineBreak") {
|
|
20298
20656
|
const attrs = node.attrs ?? {};
|
|
20299
|
-
|
|
20657
|
+
const breakType = attrs.pageBreakType ?? attrs.lineBreakType ?? "line";
|
|
20658
|
+
if (breakType === "page") {
|
|
20659
|
+
flushParagraph();
|
|
20660
|
+
blocks.push({
|
|
20661
|
+
kind: "pageBreak",
|
|
20662
|
+
id: nextId(),
|
|
20663
|
+
attrs: node.attrs || {}
|
|
20664
|
+
});
|
|
20665
|
+
return;
|
|
20666
|
+
}
|
|
20667
|
+
if (breakType === "column") {
|
|
20300
20668
|
flushParagraph();
|
|
20301
20669
|
blocks.push({
|
|
20302
20670
|
kind: "columnBreak",
|
|
20303
20671
|
id: nextId(),
|
|
20304
20672
|
attrs: node.attrs || {}
|
|
20305
20673
|
});
|
|
20674
|
+
return;
|
|
20675
|
+
}
|
|
20676
|
+
const lineBreakRun = { kind: "lineBreak", attrs: {} };
|
|
20677
|
+
const lbAttrs = {};
|
|
20678
|
+
if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
|
|
20679
|
+
if (attrs.clear) lbAttrs.clear = String(attrs.clear);
|
|
20680
|
+
if (Object.keys(lbAttrs).length > 0) {
|
|
20681
|
+
lineBreakRun.attrs = lbAttrs;
|
|
20682
|
+
} else {
|
|
20683
|
+
delete lineBreakRun.attrs;
|
|
20306
20684
|
}
|
|
20685
|
+
const pos = positions.get(node);
|
|
20686
|
+
if (pos) {
|
|
20687
|
+
lineBreakRun.pmStart = pos.start;
|
|
20688
|
+
lineBreakRun.pmEnd = pos.end;
|
|
20689
|
+
}
|
|
20690
|
+
if (activeSdt) {
|
|
20691
|
+
lineBreakRun.sdt = activeSdt;
|
|
20692
|
+
}
|
|
20693
|
+
currentRuns.push(lineBreakRun);
|
|
20307
20694
|
return;
|
|
20308
20695
|
}
|
|
20309
20696
|
};
|
|
@@ -20896,6 +21283,22 @@ const normalizeTableWidth = (value) => {
|
|
|
20896
21283
|
};
|
|
20897
21284
|
const isTableRowNode = (node) => node.type === "tableRow" || node.type === "table_row";
|
|
20898
21285
|
const isTableCellNode = (node) => node.type === "tableCell" || node.type === "table_cell" || node.type === "tableHeader" || node.type === "table_header";
|
|
21286
|
+
const normalizeRowHeight = (rowProps) => {
|
|
21287
|
+
if (!rowProps || typeof rowProps !== "object") return void 0;
|
|
21288
|
+
const rawRowHeight = rowProps.rowHeight;
|
|
21289
|
+
if (!rawRowHeight || typeof rawRowHeight !== "object") return void 0;
|
|
21290
|
+
const heightObj = rawRowHeight;
|
|
21291
|
+
const rawValue = pickNumber(heightObj.value ?? heightObj.val);
|
|
21292
|
+
if (rawValue == null) return void 0;
|
|
21293
|
+
const rawRule = heightObj.rule ?? heightObj.hRule;
|
|
21294
|
+
const rule = rawRule === "exact" || rawRule === "atLeast" || rawRule === "auto" ? rawRule : "atLeast";
|
|
21295
|
+
const isLikelyTwips = rawValue >= 300 || Math.abs(rawValue % 15) < 1e-6;
|
|
21296
|
+
const valuePx = isLikelyTwips ? twipsToPx$1(rawValue) : rawValue;
|
|
21297
|
+
return {
|
|
21298
|
+
value: valuePx,
|
|
21299
|
+
rule
|
|
21300
|
+
};
|
|
21301
|
+
};
|
|
20899
21302
|
const parseTableCell = (args) => {
|
|
20900
21303
|
const { cellNode, rowIndex, cellIndex, context, defaultCellPadding } = args;
|
|
20901
21304
|
if (!isTableCellNode(cellNode) || !Array.isArray(cellNode.content)) {
|
|
@@ -20933,8 +21336,9 @@ const parseTableCell = (args) => {
|
|
|
20933
21336
|
const padding = extractCellPadding(cellNode.attrs ?? {}) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
|
|
20934
21337
|
if (padding) cellAttrs.padding = padding;
|
|
20935
21338
|
const verticalAlign = cellNode.attrs?.verticalAlign;
|
|
20936
|
-
|
|
20937
|
-
|
|
21339
|
+
const normalizedVerticalAlign = verticalAlign === "middle" ? "center" : verticalAlign === "center" ? "center" : verticalAlign;
|
|
21340
|
+
if (normalizedVerticalAlign === "top" || normalizedVerticalAlign === "center" || normalizedVerticalAlign === "bottom") {
|
|
21341
|
+
cellAttrs.verticalAlign = normalizedVerticalAlign;
|
|
20938
21342
|
}
|
|
20939
21343
|
const background = cellNode.attrs?.background;
|
|
20940
21344
|
if (background && typeof background.color === "string") {
|
|
@@ -20977,15 +21381,89 @@ const parseTableRow = (args) => {
|
|
|
20977
21381
|
});
|
|
20978
21382
|
if (cells.length === 0) return null;
|
|
20979
21383
|
const rowProps = rowNode.attrs?.tableRowProperties;
|
|
21384
|
+
const rowHeight = normalizeRowHeight(rowProps);
|
|
20980
21385
|
const attrs = rowProps && typeof rowProps === "object" ? {
|
|
20981
|
-
tableRowProperties: rowProps
|
|
20982
|
-
|
|
21386
|
+
tableRowProperties: rowProps,
|
|
21387
|
+
...rowHeight ? { rowHeight } : {}
|
|
21388
|
+
} : rowHeight ? { rowHeight } : void 0;
|
|
20983
21389
|
return {
|
|
20984
21390
|
id: context.nextBlockId(`row-${rowIndex}`),
|
|
20985
21391
|
cells,
|
|
20986
21392
|
attrs
|
|
20987
21393
|
};
|
|
20988
21394
|
};
|
|
21395
|
+
function extractFloatingTableAnchorWrap(node) {
|
|
21396
|
+
const tableProperties = node.attrs?.tableProperties;
|
|
21397
|
+
const floatingProps = tableProperties?.floatingTableProperties;
|
|
21398
|
+
if (!floatingProps) {
|
|
21399
|
+
return {};
|
|
21400
|
+
}
|
|
21401
|
+
const hasPositioning = floatingProps.tblpX !== void 0 || floatingProps.tblpY !== void 0 || floatingProps.tblpXSpec !== void 0 || floatingProps.tblpYSpec !== void 0 || floatingProps.horzAnchor !== void 0 || floatingProps.vertAnchor !== void 0;
|
|
21402
|
+
if (!hasPositioning) {
|
|
21403
|
+
return {};
|
|
21404
|
+
}
|
|
21405
|
+
const mapHorzAnchor = (val) => {
|
|
21406
|
+
switch (val) {
|
|
21407
|
+
case "page":
|
|
21408
|
+
return "page";
|
|
21409
|
+
case "margin":
|
|
21410
|
+
return "margin";
|
|
21411
|
+
case "text":
|
|
21412
|
+
default:
|
|
21413
|
+
return "column";
|
|
21414
|
+
}
|
|
21415
|
+
};
|
|
21416
|
+
const mapVertAnchor = (val) => {
|
|
21417
|
+
switch (val) {
|
|
21418
|
+
case "page":
|
|
21419
|
+
return "page";
|
|
21420
|
+
case "margin":
|
|
21421
|
+
return "margin";
|
|
21422
|
+
case "text":
|
|
21423
|
+
default:
|
|
21424
|
+
return "paragraph";
|
|
21425
|
+
}
|
|
21426
|
+
};
|
|
21427
|
+
const anchor = {
|
|
21428
|
+
isAnchored: true,
|
|
21429
|
+
hRelativeFrom: mapHorzAnchor(floatingProps.horzAnchor),
|
|
21430
|
+
vRelativeFrom: mapVertAnchor(floatingProps.vertAnchor)
|
|
21431
|
+
};
|
|
21432
|
+
if (floatingProps.tblpXSpec) {
|
|
21433
|
+
anchor.alignH = floatingProps.tblpXSpec;
|
|
21434
|
+
}
|
|
21435
|
+
if (floatingProps.tblpYSpec) {
|
|
21436
|
+
anchor.alignV = floatingProps.tblpYSpec;
|
|
21437
|
+
}
|
|
21438
|
+
if (floatingProps.tblpX !== void 0) {
|
|
21439
|
+
anchor.offsetH = twipsToPx$1(floatingProps.tblpX);
|
|
21440
|
+
}
|
|
21441
|
+
if (floatingProps.tblpY !== void 0) {
|
|
21442
|
+
anchor.offsetV = twipsToPx$1(floatingProps.tblpY);
|
|
21443
|
+
}
|
|
21444
|
+
const hasDistances = floatingProps.leftFromText !== void 0 || floatingProps.rightFromText !== void 0 || floatingProps.topFromText !== void 0 || floatingProps.bottomFromText !== void 0;
|
|
21445
|
+
const wrap = {
|
|
21446
|
+
type: "Square",
|
|
21447
|
+
// Floating tables with text distances use square wrapping
|
|
21448
|
+
wrapText: "bothSides"
|
|
21449
|
+
// Default to text on both sides
|
|
21450
|
+
};
|
|
21451
|
+
if (hasDistances) {
|
|
21452
|
+
if (floatingProps.topFromText !== void 0) {
|
|
21453
|
+
wrap.distTop = twipsToPx$1(floatingProps.topFromText);
|
|
21454
|
+
}
|
|
21455
|
+
if (floatingProps.bottomFromText !== void 0) {
|
|
21456
|
+
wrap.distBottom = twipsToPx$1(floatingProps.bottomFromText);
|
|
21457
|
+
}
|
|
21458
|
+
if (floatingProps.leftFromText !== void 0) {
|
|
21459
|
+
wrap.distLeft = twipsToPx$1(floatingProps.leftFromText);
|
|
21460
|
+
}
|
|
21461
|
+
if (floatingProps.rightFromText !== void 0) {
|
|
21462
|
+
wrap.distRight = twipsToPx$1(floatingProps.rightFromText);
|
|
21463
|
+
}
|
|
21464
|
+
}
|
|
21465
|
+
return { anchor, wrap };
|
|
21466
|
+
}
|
|
20989
21467
|
function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSize, _styleContext, trackedChanges, bookmarks, hyperlinkConfig, themeColors, paragraphToFlowBlocks2, converterContext) {
|
|
20990
21468
|
if (!Array.isArray(node.content) || node.content.length === 0) return null;
|
|
20991
21469
|
if (!paragraphToFlowBlocks2) return null;
|
|
@@ -21050,6 +21528,10 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
|
|
|
21050
21528
|
if (tableLayout) {
|
|
21051
21529
|
tableAttrs.tableLayout = tableLayout;
|
|
21052
21530
|
}
|
|
21531
|
+
const tableProperties = node.attrs?.tableProperties;
|
|
21532
|
+
if (tableProperties && typeof tableProperties === "object") {
|
|
21533
|
+
tableAttrs.tableProperties = tableProperties;
|
|
21534
|
+
}
|
|
21053
21535
|
let columnWidths = void 0;
|
|
21054
21536
|
const twipsToPixels2 = (twips) => {
|
|
21055
21537
|
const PIXELS_PER_INCH2 = 96;
|
|
@@ -21093,12 +21575,15 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
|
|
|
21093
21575
|
columnWidths = void 0;
|
|
21094
21576
|
}
|
|
21095
21577
|
}
|
|
21578
|
+
const { anchor, wrap } = extractFloatingTableAnchorWrap(node);
|
|
21096
21579
|
const tableBlock = {
|
|
21097
21580
|
kind: "table",
|
|
21098
21581
|
id: nextBlockId("table"),
|
|
21099
21582
|
rows,
|
|
21100
21583
|
attrs: Object.keys(tableAttrs).length > 0 ? tableAttrs : void 0,
|
|
21101
|
-
columnWidths
|
|
21584
|
+
columnWidths,
|
|
21585
|
+
...anchor ? { anchor } : {},
|
|
21586
|
+
...wrap ? { wrap } : {}
|
|
21102
21587
|
};
|
|
21103
21588
|
return tableBlock;
|
|
21104
21589
|
}
|
|
@@ -21327,7 +21812,39 @@ function toFlowBlocks(pmDoc, options) {
|
|
|
21327
21812
|
}
|
|
21328
21813
|
instrumentation?.log?.({ totalBlocks: blocks.length, blockCounts, bookmarks: bookmarks.size });
|
|
21329
21814
|
const hydratedBlocks = hydrateImageBlocks(blocks, options?.mediaFiles);
|
|
21330
|
-
|
|
21815
|
+
const mergedBlocks = mergeDropCapParagraphs(hydratedBlocks);
|
|
21816
|
+
return { blocks: mergedBlocks, bookmarks };
|
|
21817
|
+
}
|
|
21818
|
+
function mergeDropCapParagraphs(blocks) {
|
|
21819
|
+
const result = [];
|
|
21820
|
+
let i = 0;
|
|
21821
|
+
while (i < blocks.length) {
|
|
21822
|
+
const block = blocks[i];
|
|
21823
|
+
if (block.kind === "paragraph" && block.attrs?.dropCapDescriptor && i + 1 < blocks.length) {
|
|
21824
|
+
const dropCapBlock = block;
|
|
21825
|
+
const nextBlock = blocks[i + 1];
|
|
21826
|
+
if (nextBlock.kind === "paragraph") {
|
|
21827
|
+
const textBlock = nextBlock;
|
|
21828
|
+
const mergedBlock = {
|
|
21829
|
+
kind: "paragraph",
|
|
21830
|
+
id: textBlock.id,
|
|
21831
|
+
runs: textBlock.runs,
|
|
21832
|
+
attrs: {
|
|
21833
|
+
...textBlock.attrs,
|
|
21834
|
+
dropCapDescriptor: dropCapBlock.attrs?.dropCapDescriptor,
|
|
21835
|
+
// Clear the legacy dropCap flag on the merged block
|
|
21836
|
+
dropCap: void 0
|
|
21837
|
+
}
|
|
21838
|
+
};
|
|
21839
|
+
result.push(mergedBlock);
|
|
21840
|
+
i += 2;
|
|
21841
|
+
continue;
|
|
21842
|
+
}
|
|
21843
|
+
}
|
|
21844
|
+
result.push(block);
|
|
21845
|
+
i += 1;
|
|
21846
|
+
}
|
|
21847
|
+
return result;
|
|
21331
21848
|
}
|
|
21332
21849
|
function paragraphToFlowBlocks(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converterContext) {
|
|
21333
21850
|
return paragraphToFlowBlocks$1(
|
|
@@ -21402,7 +21919,7 @@ function getMeasurementContext() {
|
|
|
21402
21919
|
return measurementCtx;
|
|
21403
21920
|
}
|
|
21404
21921
|
function getRunFontString(run) {
|
|
21405
|
-
if (run.kind === "tab" || run.kind === "
|
|
21922
|
+
if (run.kind === "tab" || run.kind === "lineBreak" || run.kind === "break" || "src" in run) {
|
|
21406
21923
|
return "normal normal 16px Arial";
|
|
21407
21924
|
}
|
|
21408
21925
|
const style = run.italic ? "italic" : "normal";
|
|
@@ -21421,7 +21938,15 @@ function sliceRunsForLine$1(block, line) {
|
|
|
21421
21938
|
result.push(run);
|
|
21422
21939
|
continue;
|
|
21423
21940
|
}
|
|
21424
|
-
if (
|
|
21941
|
+
if ("src" in run) {
|
|
21942
|
+
result.push(run);
|
|
21943
|
+
continue;
|
|
21944
|
+
}
|
|
21945
|
+
if (run.kind === "lineBreak") {
|
|
21946
|
+
result.push(run);
|
|
21947
|
+
continue;
|
|
21948
|
+
}
|
|
21949
|
+
if (run.kind === "break") {
|
|
21425
21950
|
result.push(run);
|
|
21426
21951
|
continue;
|
|
21427
21952
|
}
|
|
@@ -21448,13 +21973,17 @@ function sliceRunsForLine$1(block, line) {
|
|
|
21448
21973
|
}
|
|
21449
21974
|
function measureCharacterX(block, line, charOffset) {
|
|
21450
21975
|
const ctx2 = getMeasurementContext();
|
|
21976
|
+
const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
|
|
21977
|
+
if (hasExplicitPositioning && line.segments && ctx2) {
|
|
21978
|
+
return measureCharacterXSegmentBased(block, line, charOffset, ctx2);
|
|
21979
|
+
}
|
|
21451
21980
|
if (!ctx2) {
|
|
21452
21981
|
const runs2 = sliceRunsForLine$1(block, line);
|
|
21453
21982
|
const charsInLine = Math.max(
|
|
21454
21983
|
1,
|
|
21455
21984
|
runs2.reduce((sum, run) => {
|
|
21456
21985
|
if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
|
|
21457
|
-
if (run.kind === "
|
|
21986
|
+
if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
|
|
21458
21987
|
return sum + (run.text ?? "").length;
|
|
21459
21988
|
}, 0)
|
|
21460
21989
|
);
|
|
@@ -21475,7 +22004,7 @@ function measureCharacterX(block, line, charOffset) {
|
|
|
21475
22004
|
currentCharOffset += runLength2;
|
|
21476
22005
|
continue;
|
|
21477
22006
|
}
|
|
21478
|
-
const text = run.kind === "
|
|
22007
|
+
const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
|
|
21479
22008
|
const runLength = text.length;
|
|
21480
22009
|
if (currentCharOffset + runLength >= charOffset) {
|
|
21481
22010
|
const offsetInRun = charOffset - currentCharOffset;
|
|
@@ -21492,6 +22021,47 @@ function measureCharacterX(block, line, charOffset) {
|
|
|
21492
22021
|
}
|
|
21493
22022
|
return currentX;
|
|
21494
22023
|
}
|
|
22024
|
+
function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
|
|
22025
|
+
if (block.kind !== "paragraph" || !line.segments) return 0;
|
|
22026
|
+
let lineCharCount = 0;
|
|
22027
|
+
for (const segment of line.segments) {
|
|
22028
|
+
const run = block.runs[segment.runIndex];
|
|
22029
|
+
if (!run) continue;
|
|
22030
|
+
const segmentChars = segment.toChar - segment.fromChar;
|
|
22031
|
+
if (lineCharCount + segmentChars >= charOffset) {
|
|
22032
|
+
const offsetInSegment = charOffset - lineCharCount;
|
|
22033
|
+
let segmentBaseX = segment.x;
|
|
22034
|
+
if (segmentBaseX === void 0) {
|
|
22035
|
+
segmentBaseX = 0;
|
|
22036
|
+
for (const prevSeg of line.segments) {
|
|
22037
|
+
if (prevSeg === segment) break;
|
|
22038
|
+
const prevRun = block.runs[prevSeg.runIndex];
|
|
22039
|
+
if (!prevRun) continue;
|
|
22040
|
+
if (prevSeg.x !== void 0) {
|
|
22041
|
+
segmentBaseX = prevSeg.x + (prevSeg.width ?? 0);
|
|
22042
|
+
} else {
|
|
22043
|
+
segmentBaseX += prevSeg.width ?? 0;
|
|
22044
|
+
}
|
|
22045
|
+
}
|
|
22046
|
+
}
|
|
22047
|
+
if (isTabRun$1(run)) {
|
|
22048
|
+
return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
|
|
22049
|
+
}
|
|
22050
|
+
if ("src" in run || run.kind === "lineBreak" || run.kind === "break") {
|
|
22051
|
+
return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
|
|
22052
|
+
}
|
|
22053
|
+
const text = run.text ?? "";
|
|
22054
|
+
const segmentText = text.slice(segment.fromChar, segment.toChar);
|
|
22055
|
+
const textUpToTarget = segmentText.slice(0, offsetInSegment);
|
|
22056
|
+
ctx2.font = getRunFontString(run);
|
|
22057
|
+
const measured = ctx2.measureText(textUpToTarget);
|
|
22058
|
+
const spacingWidth = computeLetterSpacingWidth(run, offsetInSegment, segmentChars);
|
|
22059
|
+
return segmentBaseX + measured.width + spacingWidth;
|
|
22060
|
+
}
|
|
22061
|
+
lineCharCount += segmentChars;
|
|
22062
|
+
}
|
|
22063
|
+
return line.width;
|
|
22064
|
+
}
|
|
21495
22065
|
function findCharacterAtX(block, line, x, pmStart) {
|
|
21496
22066
|
const ctx2 = getMeasurementContext();
|
|
21497
22067
|
if (!ctx2) {
|
|
@@ -21500,7 +22070,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21500
22070
|
1,
|
|
21501
22071
|
runs2.reduce((sum, run) => {
|
|
21502
22072
|
if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
|
|
21503
|
-
if (run.kind === "
|
|
22073
|
+
if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
|
|
21504
22074
|
return sum + (run.text ?? "").length;
|
|
21505
22075
|
}, 0)
|
|
21506
22076
|
);
|
|
@@ -21535,7 +22105,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21535
22105
|
currentCharOffset += TAB_CHAR_LENGTH;
|
|
21536
22106
|
continue;
|
|
21537
22107
|
}
|
|
21538
|
-
const text = run.kind === "
|
|
22108
|
+
const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
|
|
21539
22109
|
const runLength = text.length;
|
|
21540
22110
|
if (runLength === 0) continue;
|
|
21541
22111
|
ctx2.font = getRunFontString(run);
|
|
@@ -21572,7 +22142,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21572
22142
|
};
|
|
21573
22143
|
}
|
|
21574
22144
|
const computeLetterSpacingWidth = (run, precedingChars, runLength) => {
|
|
21575
|
-
if (isTabRun$1(run) || run
|
|
22145
|
+
if (isTabRun$1(run) || "src" in run || !("letterSpacing" in run) || !run.letterSpacing) {
|
|
21576
22146
|
return 0;
|
|
21577
22147
|
}
|
|
21578
22148
|
const maxGaps = Math.max(runLength - 1, 0);
|
|
@@ -21582,6 +22152,8 @@ const computeLetterSpacingWidth = (run, precedingChars, runLength) => {
|
|
|
21582
22152
|
const clamped = Math.min(Math.max(precedingChars, 0), maxGaps);
|
|
21583
22153
|
return clamped * run.letterSpacing;
|
|
21584
22154
|
};
|
|
22155
|
+
const log = (...args) => {
|
|
22156
|
+
};
|
|
21585
22157
|
const CLASS_NAMES$1 = {
|
|
21586
22158
|
page: "superdoc-page",
|
|
21587
22159
|
fragment: "superdoc-fragment",
|
|
@@ -21597,6 +22169,11 @@ function clickToPositionDom(domContainer, clientX, clientY) {
|
|
|
21597
22169
|
const pageLocalY = clientY - pageRect.top;
|
|
21598
22170
|
const viewX = pageRect.left + pageLocalX;
|
|
21599
22171
|
const viewY = pageRect.top + pageLocalY;
|
|
22172
|
+
log("Page found:", {
|
|
22173
|
+
pageIndex: pageEl.dataset.pageIndex,
|
|
22174
|
+
pageRect: { left: pageRect.left, top: pageRect.top, width: pageRect.width, height: pageRect.height },
|
|
22175
|
+
viewCoords: { viewX, viewY }
|
|
22176
|
+
});
|
|
21600
22177
|
let hitChain = [];
|
|
21601
22178
|
const doc2 = document;
|
|
21602
22179
|
if (typeof doc2.elementsFromPoint === "function") {
|
|
@@ -21608,15 +22185,62 @@ function clickToPositionDom(domContainer, clientX, clientY) {
|
|
|
21608
22185
|
if (!Array.isArray(hitChain)) {
|
|
21609
22186
|
return null;
|
|
21610
22187
|
}
|
|
22188
|
+
const hitChainData = hitChain.map((el) => {
|
|
22189
|
+
const rect = el.getBoundingClientRect();
|
|
22190
|
+
return {
|
|
22191
|
+
tag: el.tagName,
|
|
22192
|
+
classes: el.className,
|
|
22193
|
+
blockId: el.dataset?.blockId,
|
|
22194
|
+
pmStart: el.dataset?.pmStart,
|
|
22195
|
+
pmEnd: el.dataset?.pmEnd,
|
|
22196
|
+
rect: {
|
|
22197
|
+
top: Math.round(rect.top),
|
|
22198
|
+
bottom: Math.round(rect.bottom),
|
|
22199
|
+
left: Math.round(rect.left),
|
|
22200
|
+
right: Math.round(rect.right),
|
|
22201
|
+
height: Math.round(rect.height)
|
|
22202
|
+
}
|
|
22203
|
+
};
|
|
22204
|
+
});
|
|
22205
|
+
log("Hit chain elements:", JSON.stringify(hitChainData, null, 2));
|
|
22206
|
+
const allFragments = Array.from(pageEl.querySelectorAll(`.${CLASS_NAMES$1.fragment}`));
|
|
22207
|
+
const fragmentData = allFragments.map((el) => {
|
|
22208
|
+
const rect = el.getBoundingClientRect();
|
|
22209
|
+
return {
|
|
22210
|
+
blockId: el.dataset.blockId,
|
|
22211
|
+
pmStart: el.dataset.pmStart,
|
|
22212
|
+
pmEnd: el.dataset.pmEnd,
|
|
22213
|
+
rect: {
|
|
22214
|
+
top: Math.round(rect.top),
|
|
22215
|
+
bottom: Math.round(rect.bottom),
|
|
22216
|
+
left: Math.round(rect.left),
|
|
22217
|
+
right: Math.round(rect.right),
|
|
22218
|
+
height: Math.round(rect.height)
|
|
22219
|
+
}
|
|
22220
|
+
};
|
|
22221
|
+
});
|
|
22222
|
+
log("All fragments on page:", JSON.stringify(fragmentData, null, 2));
|
|
21611
22223
|
const fragmentEl = hitChain.find((el) => el.classList?.contains?.(CLASS_NAMES$1.fragment));
|
|
21612
22224
|
if (!fragmentEl) {
|
|
21613
22225
|
const fallbackFragment = pageEl.querySelector(`.${CLASS_NAMES$1.fragment}`);
|
|
21614
22226
|
if (!fallbackFragment) {
|
|
21615
22227
|
return null;
|
|
21616
22228
|
}
|
|
21617
|
-
|
|
22229
|
+
log("Using fallback fragment:", {
|
|
22230
|
+
blockId: fallbackFragment.dataset.blockId,
|
|
22231
|
+
pmStart: fallbackFragment.dataset.pmStart,
|
|
22232
|
+
pmEnd: fallbackFragment.dataset.pmEnd
|
|
22233
|
+
});
|
|
22234
|
+
const result2 = processFragment(fallbackFragment, viewX, viewY);
|
|
22235
|
+
return result2;
|
|
21618
22236
|
}
|
|
21619
|
-
|
|
22237
|
+
log("Fragment found:", {
|
|
22238
|
+
blockId: fragmentEl.dataset.blockId,
|
|
22239
|
+
pmStart: fragmentEl.dataset.pmStart,
|
|
22240
|
+
pmEnd: fragmentEl.dataset.pmEnd
|
|
22241
|
+
});
|
|
22242
|
+
const result = processFragment(fragmentEl, viewX, viewY);
|
|
22243
|
+
return result;
|
|
21620
22244
|
}
|
|
21621
22245
|
function findPageElement(domContainer, clientX, clientY) {
|
|
21622
22246
|
if (domContainer.classList?.contains?.(CLASS_NAMES$1.page)) {
|
|
@@ -21648,7 +22272,20 @@ function findPageElement(domContainer, clientX, clientY) {
|
|
|
21648
22272
|
return null;
|
|
21649
22273
|
}
|
|
21650
22274
|
function processFragment(fragmentEl, viewX, viewY) {
|
|
22275
|
+
log("processFragment:", { viewX, viewY, blockId: fragmentEl.dataset.blockId });
|
|
21651
22276
|
const lineEls = Array.from(fragmentEl.querySelectorAll(`.${CLASS_NAMES$1.line}`));
|
|
22277
|
+
log(
|
|
22278
|
+
"Lines in fragment:",
|
|
22279
|
+
lineEls.map((el, i) => {
|
|
22280
|
+
const rect = el.getBoundingClientRect();
|
|
22281
|
+
return {
|
|
22282
|
+
index: i,
|
|
22283
|
+
pmStart: el.dataset.pmStart,
|
|
22284
|
+
pmEnd: el.dataset.pmEnd,
|
|
22285
|
+
rect: { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right }
|
|
22286
|
+
};
|
|
22287
|
+
})
|
|
22288
|
+
);
|
|
21652
22289
|
if (lineEls.length === 0) {
|
|
21653
22290
|
return null;
|
|
21654
22291
|
}
|
|
@@ -21658,10 +22295,30 @@ function processFragment(fragmentEl, viewX, viewY) {
|
|
|
21658
22295
|
}
|
|
21659
22296
|
const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
|
|
21660
22297
|
const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
|
|
22298
|
+
const lineRect = lineEl.getBoundingClientRect();
|
|
22299
|
+
log("Selected line:", {
|
|
22300
|
+
pmStart: lineStart,
|
|
22301
|
+
pmEnd: lineEnd,
|
|
22302
|
+
rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
|
|
22303
|
+
});
|
|
21661
22304
|
if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
|
|
21662
22305
|
return null;
|
|
21663
22306
|
}
|
|
21664
22307
|
const spanEls = Array.from(lineEl.querySelectorAll("span"));
|
|
22308
|
+
log(
|
|
22309
|
+
"Spans in line:",
|
|
22310
|
+
spanEls.map((el, i) => {
|
|
22311
|
+
const rect = el.getBoundingClientRect();
|
|
22312
|
+
return {
|
|
22313
|
+
index: i,
|
|
22314
|
+
pmStart: el.dataset.pmStart,
|
|
22315
|
+
pmEnd: el.dataset.pmEnd,
|
|
22316
|
+
text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
|
|
22317
|
+
visibility: el.style.visibility,
|
|
22318
|
+
rect: { left: rect.left, right: rect.right, width: rect.width }
|
|
22319
|
+
};
|
|
22320
|
+
})
|
|
22321
|
+
);
|
|
21665
22322
|
if (spanEls.length === 0) {
|
|
21666
22323
|
return lineStart;
|
|
21667
22324
|
}
|
|
@@ -21679,6 +22336,14 @@ function processFragment(fragmentEl, viewX, viewY) {
|
|
|
21679
22336
|
}
|
|
21680
22337
|
const spanStart = Number(targetSpan.dataset.pmStart ?? "NaN");
|
|
21681
22338
|
const spanEnd = Number(targetSpan.dataset.pmEnd ?? "NaN");
|
|
22339
|
+
const targetRect = targetSpan.getBoundingClientRect();
|
|
22340
|
+
log("Target span:", {
|
|
22341
|
+
pmStart: spanStart,
|
|
22342
|
+
pmEnd: spanEnd,
|
|
22343
|
+
text: targetSpan.textContent?.substring(0, 30),
|
|
22344
|
+
visibility: targetSpan.style.visibility,
|
|
22345
|
+
rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width }
|
|
22346
|
+
});
|
|
21682
22347
|
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
|
|
21683
22348
|
return null;
|
|
21684
22349
|
}
|
|
@@ -21698,28 +22363,53 @@ function findLineAtY(lineEls, viewY) {
|
|
|
21698
22363
|
if (lineEls.length === 0) {
|
|
21699
22364
|
return null;
|
|
21700
22365
|
}
|
|
21701
|
-
for (
|
|
22366
|
+
for (let i = 0; i < lineEls.length; i++) {
|
|
22367
|
+
const lineEl = lineEls[i];
|
|
21702
22368
|
const rect = lineEl.getBoundingClientRect();
|
|
21703
22369
|
if (viewY >= rect.top && viewY <= rect.bottom) {
|
|
22370
|
+
log("findLineAtY: Found line at index", i, {
|
|
22371
|
+
pmStart: lineEl.dataset.pmStart,
|
|
22372
|
+
pmEnd: lineEl.dataset.pmEnd,
|
|
22373
|
+
rect: { top: rect.top, bottom: rect.bottom },
|
|
22374
|
+
viewY
|
|
22375
|
+
});
|
|
21704
22376
|
return lineEl;
|
|
21705
22377
|
}
|
|
21706
22378
|
}
|
|
21707
|
-
|
|
22379
|
+
const lastLine = lineEls[lineEls.length - 1];
|
|
22380
|
+
log("findLineAtY: Y beyond all lines, using last line:", {
|
|
22381
|
+
pmStart: lastLine.dataset.pmStart,
|
|
22382
|
+
pmEnd: lastLine.dataset.pmEnd,
|
|
22383
|
+
viewY
|
|
22384
|
+
});
|
|
22385
|
+
return lastLine;
|
|
21708
22386
|
}
|
|
21709
22387
|
function findSpanAtX(spanEls, viewX) {
|
|
21710
22388
|
if (spanEls.length === 0) {
|
|
21711
22389
|
return null;
|
|
21712
22390
|
}
|
|
21713
22391
|
let targetSpan = spanEls[0];
|
|
21714
|
-
for (
|
|
22392
|
+
for (let i = 0; i < spanEls.length; i++) {
|
|
22393
|
+
const span = spanEls[i];
|
|
21715
22394
|
const rect = span.getBoundingClientRect();
|
|
21716
22395
|
if (viewX >= rect.left && viewX <= rect.right) {
|
|
22396
|
+
log("findSpanAtX: Found containing span at index", i, {
|
|
22397
|
+
pmStart: span.dataset.pmStart,
|
|
22398
|
+
pmEnd: span.dataset.pmEnd,
|
|
22399
|
+
rect: { left: rect.left, right: rect.right },
|
|
22400
|
+
viewX
|
|
22401
|
+
});
|
|
21717
22402
|
return span;
|
|
21718
22403
|
}
|
|
21719
22404
|
if (viewX > rect.right) {
|
|
21720
22405
|
targetSpan = span;
|
|
21721
22406
|
}
|
|
21722
22407
|
}
|
|
22408
|
+
log("findSpanAtX: No containing span, using nearest:", {
|
|
22409
|
+
pmStart: targetSpan.dataset.pmStart,
|
|
22410
|
+
pmEnd: targetSpan.dataset.pmEnd,
|
|
22411
|
+
viewX
|
|
22412
|
+
});
|
|
21723
22413
|
return targetSpan;
|
|
21724
22414
|
}
|
|
21725
22415
|
function findCharIndexAtX(textNode, span, targetX) {
|
|
@@ -21848,8 +22538,42 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21848
22538
|
};
|
|
21849
22539
|
zones.push(zone);
|
|
21850
22540
|
},
|
|
22541
|
+
registerTable(tableBlock, measure, anchorY, columnIndex, pageNumber) {
|
|
22542
|
+
if (!tableBlock.anchor?.isAnchored) {
|
|
22543
|
+
return;
|
|
22544
|
+
}
|
|
22545
|
+
const { wrap, anchor } = tableBlock;
|
|
22546
|
+
const wrapType = wrap?.type ?? "None";
|
|
22547
|
+
if (wrapType === "None") {
|
|
22548
|
+
return;
|
|
22549
|
+
}
|
|
22550
|
+
const tableWidth = measure.totalWidth ?? 0;
|
|
22551
|
+
const tableHeight = measure.totalHeight ?? 0;
|
|
22552
|
+
const x = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
|
|
22553
|
+
const y = anchorY + (anchor.offsetV ?? 0);
|
|
22554
|
+
const zone = {
|
|
22555
|
+
imageBlockId: tableBlock.id,
|
|
22556
|
+
// Reusing imageBlockId field for table id
|
|
22557
|
+
pageNumber,
|
|
22558
|
+
columnIndex,
|
|
22559
|
+
bounds: {
|
|
22560
|
+
x,
|
|
22561
|
+
y,
|
|
22562
|
+
width: tableWidth,
|
|
22563
|
+
height: tableHeight
|
|
22564
|
+
},
|
|
22565
|
+
distances: {
|
|
22566
|
+
top: wrap?.distTop ?? 0,
|
|
22567
|
+
bottom: wrap?.distBottom ?? 0,
|
|
22568
|
+
left: wrap?.distLeft ?? 0,
|
|
22569
|
+
right: wrap?.distRight ?? 0
|
|
22570
|
+
},
|
|
22571
|
+
wrapMode: computeTableWrapMode(wrap)
|
|
22572
|
+
};
|
|
22573
|
+
zones.push(zone);
|
|
22574
|
+
},
|
|
21851
22575
|
getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber) {
|
|
21852
|
-
|
|
22576
|
+
const result = zones.filter((zone) => {
|
|
21853
22577
|
if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
|
|
21854
22578
|
return false;
|
|
21855
22579
|
}
|
|
@@ -21857,8 +22581,10 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21857
22581
|
const lineBottom = lineY + lineHeight;
|
|
21858
22582
|
const zoneTop = zone.bounds.y - zone.distances.top;
|
|
21859
22583
|
const zoneBottom = zone.bounds.y + zone.bounds.height + zone.distances.bottom;
|
|
21860
|
-
|
|
22584
|
+
const overlaps = lineBottom > zoneTop && lineTop < zoneBottom;
|
|
22585
|
+
return overlaps;
|
|
21861
22586
|
});
|
|
22587
|
+
return result;
|
|
21862
22588
|
},
|
|
21863
22589
|
computeAvailableWidth(lineY, lineHeight, baseWidth, columnIndex, pageNumber) {
|
|
21864
22590
|
const exclusions = this.getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber);
|
|
@@ -21871,6 +22597,8 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21871
22597
|
}
|
|
21872
22598
|
const leftFloats = [];
|
|
21873
22599
|
const rightFloats = [];
|
|
22600
|
+
const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
|
|
22601
|
+
const columnCenter = columnOrigin + baseWidth / 2;
|
|
21874
22602
|
for (const zone of wrappingZones) {
|
|
21875
22603
|
if (zone.wrapMode === "left") {
|
|
21876
22604
|
leftFloats.push(zone);
|
|
@@ -21878,7 +22606,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21878
22606
|
rightFloats.push(zone);
|
|
21879
22607
|
} else if (zone.wrapMode === "both" || zone.wrapMode === "largest") {
|
|
21880
22608
|
const zoneCenter = zone.bounds.x + zone.bounds.width / 2;
|
|
21881
|
-
if (zoneCenter <
|
|
22609
|
+
if (zoneCenter < columnCenter) {
|
|
21882
22610
|
leftFloats.push(zone);
|
|
21883
22611
|
} else {
|
|
21884
22612
|
rightFloats.push(zone);
|
|
@@ -21890,7 +22618,6 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21890
22618
|
const boundary = zone.bounds.x + zone.bounds.width + zone.distances.left + zone.distances.right;
|
|
21891
22619
|
leftBoundary = Math.max(leftBoundary, boundary);
|
|
21892
22620
|
}
|
|
21893
|
-
const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
|
|
21894
22621
|
const columnRightEdge = columnOrigin + baseWidth;
|
|
21895
22622
|
let rightBoundary = columnRightEdge;
|
|
21896
22623
|
for (const zone of rightFloats) {
|
|
@@ -21952,6 +22679,49 @@ function computeWrapMode(wrap, _anchor) {
|
|
|
21952
22679
|
if (wrapText === "largest") return "largest";
|
|
21953
22680
|
return "both";
|
|
21954
22681
|
}
|
|
22682
|
+
function computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth) {
|
|
22683
|
+
const alignH = anchor.alignH ?? "left";
|
|
22684
|
+
const offsetH = anchor.offsetH ?? 0;
|
|
22685
|
+
const marginLeft = Math.max(0, margins?.left ?? 0);
|
|
22686
|
+
const marginRight = Math.max(0, margins?.right ?? 0);
|
|
22687
|
+
const contentWidth = pageWidth != null ? Math.max(1, pageWidth - (marginLeft + marginRight)) : columns.width;
|
|
22688
|
+
const contentLeft = marginLeft;
|
|
22689
|
+
const columnLeft = contentLeft + columnIndex * (columns.width + columns.gap);
|
|
22690
|
+
const relativeFrom = anchor.hRelativeFrom ?? "column";
|
|
22691
|
+
let baseX;
|
|
22692
|
+
let availableWidth;
|
|
22693
|
+
if (relativeFrom === "page") {
|
|
22694
|
+
if (columns.count === 1) {
|
|
22695
|
+
baseX = contentLeft;
|
|
22696
|
+
availableWidth = contentWidth;
|
|
22697
|
+
} else {
|
|
22698
|
+
baseX = 0;
|
|
22699
|
+
availableWidth = pageWidth != null ? pageWidth : contentWidth;
|
|
22700
|
+
}
|
|
22701
|
+
} else if (relativeFrom === "margin") {
|
|
22702
|
+
baseX = contentLeft;
|
|
22703
|
+
availableWidth = contentWidth;
|
|
22704
|
+
} else {
|
|
22705
|
+
baseX = columnLeft;
|
|
22706
|
+
availableWidth = columns.width;
|
|
22707
|
+
}
|
|
22708
|
+
let effectiveAlignH = alignH;
|
|
22709
|
+
if (alignH === "inside") effectiveAlignH = "left";
|
|
22710
|
+
if (alignH === "outside") effectiveAlignH = "right";
|
|
22711
|
+
const result = effectiveAlignH === "left" ? baseX + offsetH : effectiveAlignH === "right" ? baseX + availableWidth - tableWidth - offsetH : effectiveAlignH === "center" ? baseX + (availableWidth - tableWidth) / 2 + offsetH : baseX;
|
|
22712
|
+
return result;
|
|
22713
|
+
}
|
|
22714
|
+
function computeTableWrapMode(wrap) {
|
|
22715
|
+
if (!wrap) return "none";
|
|
22716
|
+
if (wrap.type === "None") {
|
|
22717
|
+
return "none";
|
|
22718
|
+
}
|
|
22719
|
+
const wrapText = wrap.wrapText ?? "bothSides";
|
|
22720
|
+
if (wrapText === "left") return "right";
|
|
22721
|
+
if (wrapText === "right") return "left";
|
|
22722
|
+
if (wrapText === "largest") return "largest";
|
|
22723
|
+
return "both";
|
|
22724
|
+
}
|
|
21955
22725
|
function computeNextSectionPropsAtBreak(blocks) {
|
|
21956
22726
|
const nextSectionPropsAtBreak = /* @__PURE__ */ new Map();
|
|
21957
22727
|
const docxBreakIndexes = [];
|
|
@@ -22213,9 +22983,6 @@ const extractBlockPmRange = (block) => {
|
|
|
22213
22983
|
pmEnd: end2 ?? (start2 != null ? start2 + 1 : void 0)
|
|
22214
22984
|
};
|
|
22215
22985
|
};
|
|
22216
|
-
const anchorDebugLog = (...args) => {
|
|
22217
|
-
return;
|
|
22218
|
-
};
|
|
22219
22986
|
function layoutParagraphBlock(ctx2, anchors) {
|
|
22220
22987
|
const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
|
|
22221
22988
|
const remeasureParagraph2 = ctx2.remeasureParagraph;
|
|
@@ -22224,23 +22991,45 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22224
22991
|
for (const entry of anchors.anchoredDrawings) {
|
|
22225
22992
|
if (anchors.placedAnchoredIds.has(entry.block.id)) continue;
|
|
22226
22993
|
const state = ensurePage();
|
|
22227
|
-
const baseAnchorY = state.cursorY;
|
|
22228
|
-
const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
|
|
22229
22994
|
const vRelativeFrom = entry.block.anchor?.vRelativeFrom;
|
|
22230
|
-
const
|
|
22231
|
-
const
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22995
|
+
const alignV = entry.block.anchor?.alignV;
|
|
22996
|
+
const offsetV = entry.block.anchor?.offsetV ?? 0;
|
|
22997
|
+
const imageHeight = entry.measure.height;
|
|
22998
|
+
const contentTop = state.topMargin;
|
|
22999
|
+
const contentBottom = state.contentBottom;
|
|
23000
|
+
const contentHeight = Math.max(0, contentBottom - contentTop);
|
|
23001
|
+
let anchorY;
|
|
23002
|
+
if (vRelativeFrom === "margin") {
|
|
23003
|
+
if (alignV === "top") {
|
|
23004
|
+
anchorY = contentTop + offsetV;
|
|
23005
|
+
} else if (alignV === "bottom") {
|
|
23006
|
+
anchorY = contentBottom - imageHeight + offsetV;
|
|
23007
|
+
} else if (alignV === "center") {
|
|
23008
|
+
anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
|
|
23009
|
+
} else {
|
|
23010
|
+
anchorY = contentTop + offsetV;
|
|
23011
|
+
}
|
|
23012
|
+
} else if (vRelativeFrom === "page") {
|
|
23013
|
+
if (alignV === "top") {
|
|
23014
|
+
anchorY = offsetV;
|
|
23015
|
+
} else if (alignV === "bottom") {
|
|
23016
|
+
const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
|
|
23017
|
+
anchorY = pageHeight - imageHeight + offsetV;
|
|
23018
|
+
} else if (alignV === "center") {
|
|
23019
|
+
const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
|
|
23020
|
+
anchorY = (pageHeight - imageHeight) / 2 + offsetV;
|
|
23021
|
+
} else {
|
|
23022
|
+
anchorY = offsetV;
|
|
23023
|
+
}
|
|
23024
|
+
} else if (vRelativeFrom === "paragraph") {
|
|
23025
|
+
const baseAnchorY = state.cursorY;
|
|
23026
|
+
const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
|
|
23027
|
+
const paragraphAdjustment = firstLineHeight / 2;
|
|
23028
|
+
anchorY = baseAnchorY + paragraphAdjustment + offsetV;
|
|
23029
|
+
} else {
|
|
23030
|
+
const baseAnchorY = state.cursorY;
|
|
23031
|
+
anchorY = baseAnchorY + offsetV;
|
|
23032
|
+
}
|
|
22244
23033
|
floatManager.registerDrawing(entry.block, entry.measure, anchorY, state.columnIndex, state.page.number);
|
|
22245
23034
|
const anchorX = entry.block.anchor ? computeAnchorX(
|
|
22246
23035
|
entry.block.anchor,
|
|
@@ -22280,7 +23069,7 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22280
23069
|
kind: "image",
|
|
22281
23070
|
blockId: entry.block.id,
|
|
22282
23071
|
x: anchorX,
|
|
22283
|
-
y: anchorY
|
|
23072
|
+
y: anchorY,
|
|
22284
23073
|
width: entry.measure.width,
|
|
22285
23074
|
height: entry.measure.height,
|
|
22286
23075
|
isAnchored: true,
|
|
@@ -22296,7 +23085,7 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22296
23085
|
blockId: entry.block.id,
|
|
22297
23086
|
drawingKind: entry.block.drawingKind,
|
|
22298
23087
|
x: anchorX,
|
|
22299
|
-
y: anchorY
|
|
23088
|
+
y: anchorY,
|
|
22300
23089
|
width: entry.measure.width,
|
|
22301
23090
|
height: entry.measure.height,
|
|
22302
23091
|
geometry: entry.measure.geometry,
|
|
@@ -22357,7 +23146,39 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22357
23146
|
state.lastParagraphStyleId = styleId;
|
|
22358
23147
|
return;
|
|
22359
23148
|
}
|
|
23149
|
+
let narrowestWidth = columnWidth;
|
|
23150
|
+
let narrowestOffsetX = 0;
|
|
22360
23151
|
let didRemeasureForFloats = false;
|
|
23152
|
+
if (typeof remeasureParagraph2 === "function") {
|
|
23153
|
+
const tempState = ensurePage();
|
|
23154
|
+
let tempY = tempState.cursorY;
|
|
23155
|
+
if (!appliedSpacingBefore && spacingBefore > 0) {
|
|
23156
|
+
const prevTrailing = tempState.trailingSpacing ?? 0;
|
|
23157
|
+
const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
|
|
23158
|
+
tempY += neededSpacingBefore;
|
|
23159
|
+
}
|
|
23160
|
+
for (let i = 0; i < lines.length; i++) {
|
|
23161
|
+
const lineY = tempY;
|
|
23162
|
+
const lineHeight = lines[i]?.lineHeight || 0;
|
|
23163
|
+
const { width: availableWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
|
|
23164
|
+
lineY,
|
|
23165
|
+
lineHeight,
|
|
23166
|
+
columnWidth,
|
|
23167
|
+
tempState.columnIndex,
|
|
23168
|
+
tempState.page.number
|
|
23169
|
+
);
|
|
23170
|
+
if (availableWidth < narrowestWidth) {
|
|
23171
|
+
narrowestWidth = availableWidth;
|
|
23172
|
+
narrowestOffsetX = computedOffset;
|
|
23173
|
+
}
|
|
23174
|
+
tempY += lineHeight;
|
|
23175
|
+
}
|
|
23176
|
+
if (narrowestWidth < columnWidth) {
|
|
23177
|
+
const newMeasure = remeasureParagraph2(block, narrowestWidth);
|
|
23178
|
+
lines = normalizeLines(newMeasure);
|
|
23179
|
+
didRemeasureForFloats = true;
|
|
23180
|
+
}
|
|
23181
|
+
}
|
|
22361
23182
|
while (fromLine < lines.length) {
|
|
22362
23183
|
let state = ensurePage();
|
|
22363
23184
|
if (state.trailingSpacing == null) state.trailingSpacing = 0;
|
|
@@ -22402,23 +23223,9 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22402
23223
|
}
|
|
22403
23224
|
let effectiveColumnWidth = columnWidth;
|
|
22404
23225
|
let offsetX = 0;
|
|
22405
|
-
if (
|
|
22406
|
-
|
|
22407
|
-
|
|
22408
|
-
const { width: adjustedWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
|
|
22409
|
-
firstLineY,
|
|
22410
|
-
firstLineHeight,
|
|
22411
|
-
columnWidth,
|
|
22412
|
-
state.columnIndex,
|
|
22413
|
-
state.page.number
|
|
22414
|
-
);
|
|
22415
|
-
if (adjustedWidth < columnWidth) {
|
|
22416
|
-
const newMeasure = remeasureParagraph2(block, adjustedWidth);
|
|
22417
|
-
lines = normalizeLines(newMeasure);
|
|
22418
|
-
didRemeasureForFloats = true;
|
|
22419
|
-
effectiveColumnWidth = adjustedWidth;
|
|
22420
|
-
offsetX = computedOffset;
|
|
22421
|
-
}
|
|
23226
|
+
if (didRemeasureForFloats) {
|
|
23227
|
+
effectiveColumnWidth = narrowestWidth;
|
|
23228
|
+
offsetX = narrowestOffsetX;
|
|
22422
23229
|
}
|
|
22423
23230
|
const slice2 = sliceLines(lines, fromLine, state.contentBottom - state.cursorY);
|
|
22424
23231
|
const fragmentHeight = slice2.height;
|
|
@@ -22432,15 +23239,6 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22432
23239
|
width: effectiveColumnWidth,
|
|
22433
23240
|
...computeFragmentPmRange(block, lines, fromLine, slice2.toLine)
|
|
22434
23241
|
};
|
|
22435
|
-
anchorDebugLog("Positioning paragraph fragment:", {
|
|
22436
|
-
blockId: block.id,
|
|
22437
|
-
fragmentY: state.cursorY,
|
|
22438
|
-
fragmentHeight,
|
|
22439
|
-
firstLineHeight: lines[fromLine]?.lineHeight,
|
|
22440
|
-
firstLineAscent: lines[fromLine]?.ascent,
|
|
22441
|
-
firstLineDescent: lines[fromLine]?.descent,
|
|
22442
|
-
pageNumber: state.page.number
|
|
22443
|
-
});
|
|
22444
23242
|
if (measure.marker && fromLine === 0) {
|
|
22445
23243
|
fragment.markerWidth = measure.marker.markerWidth;
|
|
22446
23244
|
}
|
|
@@ -22620,6 +23418,206 @@ function generateColumnBoundaries(measure) {
|
|
|
22620
23418
|
}
|
|
22621
23419
|
return boundaries;
|
|
22622
23420
|
}
|
|
23421
|
+
function countHeaderRows(block) {
|
|
23422
|
+
let count = 0;
|
|
23423
|
+
for (let i = 0; i < block.rows.length; i++) {
|
|
23424
|
+
const row = block.rows[i];
|
|
23425
|
+
const repeatHeader = row.attrs?.tableRowProperties?.repeatHeader;
|
|
23426
|
+
if (repeatHeader === true) {
|
|
23427
|
+
count++;
|
|
23428
|
+
} else {
|
|
23429
|
+
break;
|
|
23430
|
+
}
|
|
23431
|
+
}
|
|
23432
|
+
return count;
|
|
23433
|
+
}
|
|
23434
|
+
function sumRowHeights(rows, fromRow, toRow) {
|
|
23435
|
+
let total = 0;
|
|
23436
|
+
for (let i = fromRow; i < toRow && i < rows.length; i++) {
|
|
23437
|
+
total += rows[i].height;
|
|
23438
|
+
}
|
|
23439
|
+
return total;
|
|
23440
|
+
}
|
|
23441
|
+
function calculateFragmentHeight(fragment, measure, _headerCount) {
|
|
23442
|
+
let height = 0;
|
|
23443
|
+
if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
|
|
23444
|
+
height += sumRowHeights(measure.rows, 0, fragment.repeatHeaderCount);
|
|
23445
|
+
}
|
|
23446
|
+
height += sumRowHeights(measure.rows, fragment.fromRow, fragment.toRow);
|
|
23447
|
+
return height;
|
|
23448
|
+
}
|
|
23449
|
+
const MIN_PARTIAL_ROW_HEIGHT = 20;
|
|
23450
|
+
function getCellLines(cell) {
|
|
23451
|
+
if (cell.blocks && cell.blocks.length > 0) {
|
|
23452
|
+
const allLines = [];
|
|
23453
|
+
for (const block of cell.blocks) {
|
|
23454
|
+
if (block.kind === "paragraph") {
|
|
23455
|
+
if (block.kind === "paragraph" && "lines" in block) {
|
|
23456
|
+
const paraBlock = block;
|
|
23457
|
+
if (paraBlock.lines) {
|
|
23458
|
+
allLines.push(...paraBlock.lines);
|
|
23459
|
+
}
|
|
23460
|
+
}
|
|
23461
|
+
}
|
|
23462
|
+
}
|
|
23463
|
+
return allLines;
|
|
23464
|
+
}
|
|
23465
|
+
if (cell.paragraph?.lines) {
|
|
23466
|
+
return cell.paragraph.lines;
|
|
23467
|
+
}
|
|
23468
|
+
return [];
|
|
23469
|
+
}
|
|
23470
|
+
function getCellPadding(cellIdx, blockRow) {
|
|
23471
|
+
const padding = blockRow?.cells?.[cellIdx]?.attrs?.padding ?? {};
|
|
23472
|
+
return {
|
|
23473
|
+
top: padding.top ?? 2,
|
|
23474
|
+
bottom: padding.bottom ?? 2,
|
|
23475
|
+
left: padding.left ?? 4,
|
|
23476
|
+
right: padding.right ?? 4
|
|
23477
|
+
};
|
|
23478
|
+
}
|
|
23479
|
+
function getCellTotalLines(cell) {
|
|
23480
|
+
return getCellLines(cell).length;
|
|
23481
|
+
}
|
|
23482
|
+
function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
|
|
23483
|
+
const row = measure.rows[rowIndex];
|
|
23484
|
+
if (!row) {
|
|
23485
|
+
throw new Error(`Invalid rowIndex ${rowIndex}: measure.rows has ${measure.rows.length} rows`);
|
|
23486
|
+
}
|
|
23487
|
+
const cellCount = row.cells.length;
|
|
23488
|
+
const startLines = fromLineByCell || new Array(cellCount).fill(0);
|
|
23489
|
+
const toLineByCell = [];
|
|
23490
|
+
const heightByCell = [];
|
|
23491
|
+
const cellPaddings = row.cells.map((_, idx) => getCellPadding(idx, blockRow));
|
|
23492
|
+
for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
|
|
23493
|
+
const cell = row.cells[cellIdx];
|
|
23494
|
+
const startLine = startLines[cellIdx] || 0;
|
|
23495
|
+
const cellPadding = cellPaddings[cellIdx];
|
|
23496
|
+
const availableForLines = Math.max(0, availableHeight - (cellPadding.top + cellPadding.bottom));
|
|
23497
|
+
const lines = getCellLines(cell);
|
|
23498
|
+
let cumulativeHeight = 0;
|
|
23499
|
+
let cutLine = startLine;
|
|
23500
|
+
for (let i = startLine; i < lines.length; i++) {
|
|
23501
|
+
const lineHeight = lines[i].lineHeight || 0;
|
|
23502
|
+
if (cumulativeHeight + lineHeight > availableForLines) {
|
|
23503
|
+
break;
|
|
23504
|
+
}
|
|
23505
|
+
cumulativeHeight += lineHeight;
|
|
23506
|
+
cutLine = i + 1;
|
|
23507
|
+
}
|
|
23508
|
+
toLineByCell.push(cutLine);
|
|
23509
|
+
heightByCell.push(cumulativeHeight);
|
|
23510
|
+
}
|
|
23511
|
+
const positiveHeights = heightByCell.filter((h) => h > 0);
|
|
23512
|
+
const minHeight = positiveHeights.length > 0 ? Math.min(...positiveHeights) : 0;
|
|
23513
|
+
let actualPartialHeight = 0;
|
|
23514
|
+
let maxPaddingTotal = 0;
|
|
23515
|
+
for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
|
|
23516
|
+
const cell = row.cells[cellIdx];
|
|
23517
|
+
const startLine = startLines[cellIdx] || 0;
|
|
23518
|
+
const lines = getCellLines(cell);
|
|
23519
|
+
const cellPadding = cellPaddings[cellIdx];
|
|
23520
|
+
const paddingTotal = cellPadding.top + cellPadding.bottom;
|
|
23521
|
+
maxPaddingTotal = Math.max(maxPaddingTotal, paddingTotal);
|
|
23522
|
+
let cumulativeHeight = 0;
|
|
23523
|
+
let cutLine = startLine;
|
|
23524
|
+
for (let i = startLine; i < lines.length; i++) {
|
|
23525
|
+
const lineHeight = lines[i].lineHeight || 0;
|
|
23526
|
+
if (cumulativeHeight + lineHeight > minHeight) {
|
|
23527
|
+
break;
|
|
23528
|
+
}
|
|
23529
|
+
cumulativeHeight += lineHeight;
|
|
23530
|
+
cutLine = i + 1;
|
|
23531
|
+
}
|
|
23532
|
+
toLineByCell[cellIdx] = cutLine;
|
|
23533
|
+
actualPartialHeight = Math.max(actualPartialHeight, cumulativeHeight + paddingTotal);
|
|
23534
|
+
}
|
|
23535
|
+
const madeProgress = toLineByCell.some((cutLine, idx) => cutLine > (startLines[idx] || 0));
|
|
23536
|
+
const isFirstPart = startLines.every((l) => l === 0);
|
|
23537
|
+
const allCellsExhausted = toLineByCell.every((cutLine, idx) => {
|
|
23538
|
+
const totalLines = getCellTotalLines(row.cells[idx]);
|
|
23539
|
+
return cutLine >= totalLines;
|
|
23540
|
+
});
|
|
23541
|
+
const isLastPart = allCellsExhausted || !madeProgress;
|
|
23542
|
+
if (actualPartialHeight === 0 && isFirstPart) {
|
|
23543
|
+
actualPartialHeight = maxPaddingTotal;
|
|
23544
|
+
}
|
|
23545
|
+
return {
|
|
23546
|
+
rowIndex,
|
|
23547
|
+
fromLineByCell: startLines,
|
|
23548
|
+
toLineByCell,
|
|
23549
|
+
isFirstPart,
|
|
23550
|
+
isLastPart,
|
|
23551
|
+
partialHeight: actualPartialHeight
|
|
23552
|
+
};
|
|
23553
|
+
}
|
|
23554
|
+
function findSplitPoint(block, measure, startRow, availableHeight, fullPageHeight, _pendingPartialRow) {
|
|
23555
|
+
let accumulatedHeight = 0;
|
|
23556
|
+
let lastFitRow = startRow;
|
|
23557
|
+
for (let i = startRow; i < block.rows.length; i++) {
|
|
23558
|
+
const row = block.rows[i];
|
|
23559
|
+
const rowHeight = measure.rows[i]?.height || 0;
|
|
23560
|
+
const cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
|
|
23561
|
+
if (accumulatedHeight + rowHeight <= availableHeight) {
|
|
23562
|
+
accumulatedHeight += rowHeight;
|
|
23563
|
+
lastFitRow = i + 1;
|
|
23564
|
+
} else {
|
|
23565
|
+
const remainingHeight = availableHeight - accumulatedHeight;
|
|
23566
|
+
if (fullPageHeight && rowHeight > fullPageHeight) {
|
|
23567
|
+
const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
|
|
23568
|
+
return { endRow: i + 1, partialRow };
|
|
23569
|
+
}
|
|
23570
|
+
if (cantSplit) {
|
|
23571
|
+
if (lastFitRow === startRow) {
|
|
23572
|
+
return { endRow: startRow, partialRow: null };
|
|
23573
|
+
}
|
|
23574
|
+
return { endRow: lastFitRow, partialRow: null };
|
|
23575
|
+
}
|
|
23576
|
+
if (remainingHeight >= MIN_PARTIAL_ROW_HEIGHT) {
|
|
23577
|
+
const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
|
|
23578
|
+
const hasContent = partialRow.toLineByCell.some(
|
|
23579
|
+
(cutLine, idx) => cutLine > (partialRow.fromLineByCell[idx] || 0)
|
|
23580
|
+
);
|
|
23581
|
+
if (hasContent) {
|
|
23582
|
+
return { endRow: i + 1, partialRow };
|
|
23583
|
+
}
|
|
23584
|
+
}
|
|
23585
|
+
return { endRow: lastFitRow, partialRow: null };
|
|
23586
|
+
}
|
|
23587
|
+
}
|
|
23588
|
+
return { endRow: block.rows.length, partialRow: null };
|
|
23589
|
+
}
|
|
23590
|
+
function generateFragmentMetadata(measure, _fromRow, _toRow, _repeatHeaderCount) {
|
|
23591
|
+
return {
|
|
23592
|
+
columnBoundaries: generateColumnBoundaries(measure),
|
|
23593
|
+
coordinateSystem: "fragment"
|
|
23594
|
+
};
|
|
23595
|
+
}
|
|
23596
|
+
function layoutMonolithicTable(context) {
|
|
23597
|
+
let state = context.ensurePage();
|
|
23598
|
+
if (state.cursorY + context.measure.totalHeight > state.contentBottom && state.page.fragments.length > 0) {
|
|
23599
|
+
state = context.advanceColumn(state);
|
|
23600
|
+
}
|
|
23601
|
+
state = context.ensurePage();
|
|
23602
|
+
const height = Math.min(context.measure.totalHeight, state.contentBottom - state.cursorY);
|
|
23603
|
+
const metadata = {
|
|
23604
|
+
columnBoundaries: generateColumnBoundaries(context.measure),
|
|
23605
|
+
coordinateSystem: "fragment"
|
|
23606
|
+
};
|
|
23607
|
+
const fragment = {
|
|
23608
|
+
kind: "table",
|
|
23609
|
+
blockId: context.block.id,
|
|
23610
|
+
fromRow: 0,
|
|
23611
|
+
toRow: context.block.rows.length,
|
|
23612
|
+
x: context.columnX(state.columnIndex),
|
|
23613
|
+
y: state.cursorY,
|
|
23614
|
+
width: Math.min(context.columnWidth, context.measure.totalWidth || context.columnWidth),
|
|
23615
|
+
height,
|
|
23616
|
+
metadata
|
|
23617
|
+
};
|
|
23618
|
+
state.page.fragments.push(fragment);
|
|
23619
|
+
state.cursorY += height;
|
|
23620
|
+
}
|
|
22623
23621
|
function layoutTableBlock({
|
|
22624
23622
|
block,
|
|
22625
23623
|
measure,
|
|
@@ -22628,36 +23626,202 @@ function layoutTableBlock({
|
|
|
22628
23626
|
advanceColumn,
|
|
22629
23627
|
columnX
|
|
22630
23628
|
}) {
|
|
23629
|
+
if (block.anchor?.isAnchored) {
|
|
23630
|
+
return;
|
|
23631
|
+
}
|
|
23632
|
+
const tableProps = block.attrs?.tableProperties;
|
|
23633
|
+
const floatingProps = tableProps?.floatingTableProperties;
|
|
23634
|
+
if (floatingProps && Object.keys(floatingProps).length > 0) {
|
|
23635
|
+
layoutMonolithicTable({ block, measure, columnWidth, ensurePage, advanceColumn, columnX });
|
|
23636
|
+
return;
|
|
23637
|
+
}
|
|
23638
|
+
const headerCount = countHeaderRows(block);
|
|
23639
|
+
const headerHeight = headerCount > 0 ? sumRowHeights(measure.rows, 0, headerCount) : 0;
|
|
22631
23640
|
let state = ensurePage();
|
|
22632
|
-
|
|
22633
|
-
|
|
23641
|
+
let currentRow = 0;
|
|
23642
|
+
let isTableContinuation = false;
|
|
23643
|
+
let pendingPartialRow = null;
|
|
23644
|
+
while (currentRow < block.rows.length || pendingPartialRow !== null) {
|
|
23645
|
+
state = ensurePage();
|
|
23646
|
+
const availableHeight = state.contentBottom - state.cursorY;
|
|
23647
|
+
let repeatHeaderCount = 0;
|
|
23648
|
+
if (currentRow === 0 && !pendingPartialRow) {
|
|
23649
|
+
repeatHeaderCount = 0;
|
|
23650
|
+
} else {
|
|
23651
|
+
if (headerCount > 0 && headerHeight <= availableHeight) {
|
|
23652
|
+
repeatHeaderCount = headerCount;
|
|
23653
|
+
} else if (headerCount > 0 && headerHeight > availableHeight) {
|
|
23654
|
+
repeatHeaderCount = 0;
|
|
23655
|
+
}
|
|
23656
|
+
}
|
|
23657
|
+
const availableForBody = repeatHeaderCount > 0 ? availableHeight - headerHeight : availableHeight;
|
|
23658
|
+
const fullPageHeight = state.contentBottom;
|
|
23659
|
+
if (pendingPartialRow !== null) {
|
|
23660
|
+
const rowIndex = pendingPartialRow.rowIndex;
|
|
23661
|
+
const fromLineByCell = pendingPartialRow.toLineByCell;
|
|
23662
|
+
const continuationPartialRow = computePartialRow(
|
|
23663
|
+
rowIndex,
|
|
23664
|
+
block.rows[rowIndex],
|
|
23665
|
+
measure,
|
|
23666
|
+
availableForBody,
|
|
23667
|
+
fromLineByCell
|
|
23668
|
+
);
|
|
23669
|
+
const madeProgress = continuationPartialRow.toLineByCell.some(
|
|
23670
|
+
(toLine, idx) => toLine > (fromLineByCell[idx] || 0)
|
|
23671
|
+
);
|
|
23672
|
+
const hasRemainingLinesAfterContinuation = continuationPartialRow.toLineByCell.some(
|
|
23673
|
+
(toLine, idx) => {
|
|
23674
|
+
const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
|
|
23675
|
+
return toLine < totalLines;
|
|
23676
|
+
}
|
|
23677
|
+
);
|
|
23678
|
+
const hadRemainingLinesBefore = fromLineByCell.some((fromLine, idx) => {
|
|
23679
|
+
const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
|
|
23680
|
+
return fromLine < totalLines;
|
|
23681
|
+
});
|
|
23682
|
+
const fragmentHeight2 = continuationPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
|
|
23683
|
+
if (fragmentHeight2 > 0) {
|
|
23684
|
+
const fragment2 = {
|
|
23685
|
+
kind: "table",
|
|
23686
|
+
blockId: block.id,
|
|
23687
|
+
fromRow: rowIndex,
|
|
23688
|
+
toRow: rowIndex + 1,
|
|
23689
|
+
x: columnX(state.columnIndex),
|
|
23690
|
+
y: state.cursorY,
|
|
23691
|
+
width: Math.min(columnWidth, measure.totalWidth || columnWidth),
|
|
23692
|
+
height: fragmentHeight2,
|
|
23693
|
+
continuesFromPrev: true,
|
|
23694
|
+
continuesOnNext: hasRemainingLinesAfterContinuation || rowIndex + 1 < block.rows.length,
|
|
23695
|
+
repeatHeaderCount,
|
|
23696
|
+
partialRow: continuationPartialRow,
|
|
23697
|
+
metadata: generateFragmentMetadata(measure)
|
|
23698
|
+
};
|
|
23699
|
+
state.page.fragments.push(fragment2);
|
|
23700
|
+
state.cursorY += fragmentHeight2;
|
|
23701
|
+
}
|
|
23702
|
+
const rowComplete = !hasRemainingLinesAfterContinuation;
|
|
23703
|
+
if (rowComplete) {
|
|
23704
|
+
currentRow = rowIndex + 1;
|
|
23705
|
+
pendingPartialRow = null;
|
|
23706
|
+
} else if (!madeProgress && hadRemainingLinesBefore) {
|
|
23707
|
+
state = advanceColumn(state);
|
|
23708
|
+
} else {
|
|
23709
|
+
state = advanceColumn(state);
|
|
23710
|
+
pendingPartialRow = continuationPartialRow;
|
|
23711
|
+
}
|
|
23712
|
+
isTableContinuation = true;
|
|
23713
|
+
continue;
|
|
23714
|
+
}
|
|
23715
|
+
const bodyStartRow = currentRow;
|
|
23716
|
+
const { endRow, partialRow } = findSplitPoint(block, measure, bodyStartRow, availableForBody, fullPageHeight);
|
|
23717
|
+
if (endRow === bodyStartRow && partialRow === null && state.page.fragments.length > 0) {
|
|
23718
|
+
state = advanceColumn(state);
|
|
23719
|
+
continue;
|
|
23720
|
+
}
|
|
23721
|
+
if (endRow === bodyStartRow && partialRow === null) {
|
|
23722
|
+
const forcedPartialRow = computePartialRow(bodyStartRow, block.rows[bodyStartRow], measure, availableForBody);
|
|
23723
|
+
const forcedEndRow = bodyStartRow + 1;
|
|
23724
|
+
const fragmentHeight2 = forcedPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
|
|
23725
|
+
const fragment2 = {
|
|
23726
|
+
kind: "table",
|
|
23727
|
+
blockId: block.id,
|
|
23728
|
+
fromRow: bodyStartRow,
|
|
23729
|
+
toRow: forcedEndRow,
|
|
23730
|
+
x: columnX(state.columnIndex),
|
|
23731
|
+
y: state.cursorY,
|
|
23732
|
+
width: Math.min(columnWidth, measure.totalWidth || columnWidth),
|
|
23733
|
+
height: fragmentHeight2,
|
|
23734
|
+
continuesFromPrev: isTableContinuation,
|
|
23735
|
+
continuesOnNext: !forcedPartialRow.isLastPart || forcedEndRow < block.rows.length,
|
|
23736
|
+
repeatHeaderCount,
|
|
23737
|
+
partialRow: forcedPartialRow,
|
|
23738
|
+
metadata: generateFragmentMetadata(measure)
|
|
23739
|
+
};
|
|
23740
|
+
state.page.fragments.push(fragment2);
|
|
23741
|
+
state.cursorY += fragmentHeight2;
|
|
23742
|
+
pendingPartialRow = forcedPartialRow;
|
|
23743
|
+
isTableContinuation = true;
|
|
23744
|
+
continue;
|
|
23745
|
+
}
|
|
23746
|
+
let fragmentHeight;
|
|
23747
|
+
if (partialRow) {
|
|
23748
|
+
const fullRowsHeight = sumRowHeights(measure.rows, bodyStartRow, endRow - 1);
|
|
23749
|
+
fragmentHeight = fullRowsHeight + partialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
|
|
23750
|
+
} else {
|
|
23751
|
+
fragmentHeight = calculateFragmentHeight(
|
|
23752
|
+
{ fromRow: bodyStartRow, toRow: endRow, repeatHeaderCount },
|
|
23753
|
+
measure
|
|
23754
|
+
);
|
|
23755
|
+
}
|
|
23756
|
+
const fragment = {
|
|
23757
|
+
kind: "table",
|
|
23758
|
+
blockId: block.id,
|
|
23759
|
+
fromRow: bodyStartRow,
|
|
23760
|
+
toRow: endRow,
|
|
23761
|
+
x: columnX(state.columnIndex),
|
|
23762
|
+
y: state.cursorY,
|
|
23763
|
+
width: Math.min(columnWidth, measure.totalWidth || columnWidth),
|
|
23764
|
+
height: fragmentHeight,
|
|
23765
|
+
continuesFromPrev: isTableContinuation,
|
|
23766
|
+
continuesOnNext: endRow < block.rows.length || (partialRow ? !partialRow.isLastPart : false),
|
|
23767
|
+
repeatHeaderCount,
|
|
23768
|
+
partialRow: partialRow || void 0,
|
|
23769
|
+
metadata: generateFragmentMetadata(measure)
|
|
23770
|
+
};
|
|
23771
|
+
state.page.fragments.push(fragment);
|
|
23772
|
+
state.cursorY += fragmentHeight;
|
|
23773
|
+
if (partialRow && !partialRow.isLastPart) {
|
|
23774
|
+
pendingPartialRow = partialRow;
|
|
23775
|
+
currentRow = partialRow.rowIndex;
|
|
23776
|
+
} else {
|
|
23777
|
+
currentRow = endRow;
|
|
23778
|
+
pendingPartialRow = null;
|
|
23779
|
+
}
|
|
23780
|
+
isTableContinuation = true;
|
|
22634
23781
|
}
|
|
22635
|
-
|
|
22636
|
-
|
|
23782
|
+
}
|
|
23783
|
+
function createAnchoredTableFragment(block, measure, x, y) {
|
|
22637
23784
|
const metadata = {
|
|
22638
23785
|
columnBoundaries: generateColumnBoundaries(measure),
|
|
22639
23786
|
coordinateSystem: "fragment"
|
|
22640
|
-
// rowBoundaries omitted - not needed for column resize, reduces DOM overhead
|
|
22641
23787
|
};
|
|
22642
|
-
|
|
23788
|
+
return {
|
|
22643
23789
|
kind: "table",
|
|
22644
23790
|
blockId: block.id,
|
|
22645
23791
|
fromRow: 0,
|
|
22646
23792
|
toRow: block.rows.length,
|
|
22647
|
-
x
|
|
22648
|
-
y
|
|
22649
|
-
width:
|
|
22650
|
-
height,
|
|
23793
|
+
x,
|
|
23794
|
+
y,
|
|
23795
|
+
width: measure.totalWidth ?? 0,
|
|
23796
|
+
height: measure.totalHeight ?? 0,
|
|
22651
23797
|
metadata
|
|
22652
23798
|
};
|
|
22653
|
-
|
|
22654
|
-
|
|
23799
|
+
}
|
|
23800
|
+
function isPageRelativeAnchor(block) {
|
|
23801
|
+
const vRelativeFrom = block.anchor?.vRelativeFrom;
|
|
23802
|
+
return vRelativeFrom === "margin" || vRelativeFrom === "page";
|
|
23803
|
+
}
|
|
23804
|
+
function collectPreRegisteredAnchors(blocks, measures) {
|
|
23805
|
+
const result = [];
|
|
23806
|
+
const len = Math.min(blocks.length, measures.length);
|
|
23807
|
+
for (let i = 0; i < len; i += 1) {
|
|
23808
|
+
const block = blocks[i];
|
|
23809
|
+
const measure = measures[i];
|
|
23810
|
+
const isImage = block.kind === "image" && measure?.kind === "image";
|
|
23811
|
+
const isDrawing = block.kind === "drawing" && measure?.kind === "drawing";
|
|
23812
|
+
if (!isImage && !isDrawing) continue;
|
|
23813
|
+
const drawingBlock = block;
|
|
23814
|
+
const drawingMeasure = measure;
|
|
23815
|
+
if (!drawingBlock.anchor?.isAnchored) continue;
|
|
23816
|
+
if (isPageRelativeAnchor(drawingBlock)) {
|
|
23817
|
+
result.push({ block: drawingBlock, measure: drawingMeasure });
|
|
23818
|
+
}
|
|
23819
|
+
}
|
|
23820
|
+
return result;
|
|
22655
23821
|
}
|
|
22656
23822
|
function collectAnchoredDrawings(blocks, measures) {
|
|
22657
23823
|
const map2 = /* @__PURE__ */ new Map();
|
|
22658
|
-
|
|
22659
|
-
if (blocks[i].kind === "paragraph") ;
|
|
22660
|
-
}
|
|
23824
|
+
const len = Math.min(blocks.length, measures.length);
|
|
22661
23825
|
const nearestPrevParagraph = (fromIndex) => {
|
|
22662
23826
|
for (let i = fromIndex - 1; i >= 0; i -= 1) {
|
|
22663
23827
|
if (blocks[i].kind === "paragraph") return i;
|
|
@@ -22665,12 +23829,12 @@ function collectAnchoredDrawings(blocks, measures) {
|
|
|
22665
23829
|
return null;
|
|
22666
23830
|
};
|
|
22667
23831
|
const nearestNextParagraph = (fromIndex) => {
|
|
22668
|
-
for (let i = fromIndex + 1; i <
|
|
23832
|
+
for (let i = fromIndex + 1; i < len; i += 1) {
|
|
22669
23833
|
if (blocks[i].kind === "paragraph") return i;
|
|
22670
23834
|
}
|
|
22671
23835
|
return null;
|
|
22672
23836
|
};
|
|
22673
|
-
for (let i = 0; i <
|
|
23837
|
+
for (let i = 0; i < len; i += 1) {
|
|
22674
23838
|
const block = blocks[i];
|
|
22675
23839
|
const measure = measures[i];
|
|
22676
23840
|
const isImage = block.kind === "image" && measure?.kind === "image";
|
|
@@ -22678,7 +23842,12 @@ function collectAnchoredDrawings(blocks, measures) {
|
|
|
22678
23842
|
if (!isImage && !isDrawing) continue;
|
|
22679
23843
|
const drawingBlock = block;
|
|
22680
23844
|
const drawingMeasure = measure;
|
|
22681
|
-
if (!drawingBlock.anchor?.isAnchored)
|
|
23845
|
+
if (!drawingBlock.anchor?.isAnchored) {
|
|
23846
|
+
continue;
|
|
23847
|
+
}
|
|
23848
|
+
if (isPageRelativeAnchor(drawingBlock)) {
|
|
23849
|
+
continue;
|
|
23850
|
+
}
|
|
22682
23851
|
let anchorParaIndex = nearestPrevParagraph(i);
|
|
22683
23852
|
if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
|
|
22684
23853
|
if (anchorParaIndex == null) continue;
|
|
@@ -22688,6 +23857,36 @@ function collectAnchoredDrawings(blocks, measures) {
|
|
|
22688
23857
|
}
|
|
22689
23858
|
return map2;
|
|
22690
23859
|
}
|
|
23860
|
+
function collectAnchoredTables(blocks, measures) {
|
|
23861
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
23862
|
+
const nearestPrevParagraph = (fromIndex) => {
|
|
23863
|
+
for (let i = fromIndex - 1; i >= 0; i -= 1) {
|
|
23864
|
+
if (blocks[i].kind === "paragraph") return i;
|
|
23865
|
+
}
|
|
23866
|
+
return null;
|
|
23867
|
+
};
|
|
23868
|
+
const nearestNextParagraph = (fromIndex) => {
|
|
23869
|
+
for (let i = fromIndex + 1; i < blocks.length; i += 1) {
|
|
23870
|
+
if (blocks[i].kind === "paragraph") return i;
|
|
23871
|
+
}
|
|
23872
|
+
return null;
|
|
23873
|
+
};
|
|
23874
|
+
for (let i = 0; i < blocks.length; i += 1) {
|
|
23875
|
+
const block = blocks[i];
|
|
23876
|
+
const measure = measures[i];
|
|
23877
|
+
if (block.kind !== "table" || measure?.kind !== "table") continue;
|
|
23878
|
+
const tableBlock = block;
|
|
23879
|
+
const tableMeasure = measure;
|
|
23880
|
+
if (!tableBlock.anchor?.isAnchored) continue;
|
|
23881
|
+
let anchorParaIndex = nearestPrevParagraph(i);
|
|
23882
|
+
if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
|
|
23883
|
+
if (anchorParaIndex == null) continue;
|
|
23884
|
+
const list = map2.get(anchorParaIndex) ?? [];
|
|
23885
|
+
list.push({ block: tableBlock, measure: tableMeasure });
|
|
23886
|
+
map2.set(anchorParaIndex, list);
|
|
23887
|
+
}
|
|
23888
|
+
return map2;
|
|
23889
|
+
}
|
|
22691
23890
|
function createPaginator(opts) {
|
|
22692
23891
|
const states = [];
|
|
22693
23892
|
const pages = [];
|
|
@@ -23273,7 +24472,57 @@ function layoutDocument(blocks, measures, options = {}) {
|
|
|
23273
24472
|
cachedColumnsState.state = null;
|
|
23274
24473
|
};
|
|
23275
24474
|
const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
|
|
24475
|
+
const anchoredTablesByParagraph = collectAnchoredTables(blocks, measures);
|
|
23276
24476
|
const placedAnchoredIds = /* @__PURE__ */ new Set();
|
|
24477
|
+
const placedAnchoredTableIds = /* @__PURE__ */ new Set();
|
|
24478
|
+
const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
|
|
24479
|
+
const preRegisteredPositions = /* @__PURE__ */ new Map();
|
|
24480
|
+
for (const entry of preRegisteredAnchors) {
|
|
24481
|
+
const state = paginator.ensurePage();
|
|
24482
|
+
const vRelativeFrom = entry.block.anchor?.vRelativeFrom ?? "paragraph";
|
|
24483
|
+
const alignV = entry.block.anchor?.alignV ?? "top";
|
|
24484
|
+
const offsetV = entry.block.anchor?.offsetV ?? 0;
|
|
24485
|
+
const imageHeight = entry.measure.height ?? 0;
|
|
24486
|
+
const contentTop = state.topMargin;
|
|
24487
|
+
const contentBottom = state.contentBottom;
|
|
24488
|
+
const contentHeight = Math.max(0, contentBottom - contentTop);
|
|
24489
|
+
let anchorY;
|
|
24490
|
+
if (vRelativeFrom === "margin") {
|
|
24491
|
+
if (alignV === "top") {
|
|
24492
|
+
anchorY = contentTop + offsetV;
|
|
24493
|
+
} else if (alignV === "bottom") {
|
|
24494
|
+
anchorY = contentBottom - imageHeight + offsetV;
|
|
24495
|
+
} else if (alignV === "center") {
|
|
24496
|
+
anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
|
|
24497
|
+
} else {
|
|
24498
|
+
anchorY = contentTop + offsetV;
|
|
24499
|
+
}
|
|
24500
|
+
} else if (vRelativeFrom === "page") {
|
|
24501
|
+
if (alignV === "top") {
|
|
24502
|
+
anchorY = offsetV;
|
|
24503
|
+
} else if (alignV === "bottom") {
|
|
24504
|
+
const pageHeight = contentBottom + margins.bottom;
|
|
24505
|
+
anchorY = pageHeight - imageHeight + offsetV;
|
|
24506
|
+
} else if (alignV === "center") {
|
|
24507
|
+
const pageHeight = contentBottom + margins.bottom;
|
|
24508
|
+
anchorY = (pageHeight - imageHeight) / 2 + offsetV;
|
|
24509
|
+
} else {
|
|
24510
|
+
anchorY = offsetV;
|
|
24511
|
+
}
|
|
24512
|
+
} else {
|
|
24513
|
+
anchorY = contentTop + offsetV;
|
|
24514
|
+
}
|
|
24515
|
+
const anchorX = entry.block.anchor ? computeAnchorX(
|
|
24516
|
+
entry.block.anchor,
|
|
24517
|
+
state.columnIndex,
|
|
24518
|
+
normalizeColumns(activeColumns, contentWidth),
|
|
24519
|
+
entry.measure.width,
|
|
24520
|
+
{ left: margins.left, right: margins.right },
|
|
24521
|
+
activePageSize.w
|
|
24522
|
+
) : margins.left;
|
|
24523
|
+
floatManager.registerDrawing(entry.block, entry.measure, anchorY, state.columnIndex, state.page.number);
|
|
24524
|
+
preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state.page.number });
|
|
24525
|
+
}
|
|
23277
24526
|
for (let index2 = 0; index2 < blocks.length; index2 += 1) {
|
|
23278
24527
|
const block = blocks[index2];
|
|
23279
24528
|
const measure = measures[index2];
|
|
@@ -23403,6 +24652,19 @@ function layoutDocument(blocks, measures, options = {}) {
|
|
|
23403
24652
|
}
|
|
23404
24653
|
}
|
|
23405
24654
|
const anchorsForPara = anchoredByParagraph.get(index2);
|
|
24655
|
+
const tablesForPara = anchoredTablesByParagraph.get(index2);
|
|
24656
|
+
if (tablesForPara) {
|
|
24657
|
+
const state = paginator.ensurePage();
|
|
24658
|
+
for (const { block: tableBlock, measure: tableMeasure } of tablesForPara) {
|
|
24659
|
+
if (placedAnchoredTableIds.has(tableBlock.id)) continue;
|
|
24660
|
+
floatManager.registerTable(tableBlock, tableMeasure, state.cursorY, state.columnIndex, state.page.number);
|
|
24661
|
+
const anchorX = tableBlock.anchor?.offsetH ?? columnX(state.columnIndex);
|
|
24662
|
+
const anchorY = state.cursorY + (tableBlock.anchor?.offsetV ?? 0);
|
|
24663
|
+
const tableFragment = createAnchoredTableFragment(tableBlock, tableMeasure, anchorX, anchorY);
|
|
24664
|
+
state.page.fragments.push(tableFragment);
|
|
24665
|
+
placedAnchoredTableIds.add(tableBlock.id);
|
|
24666
|
+
}
|
|
24667
|
+
}
|
|
23406
24668
|
layoutParagraphBlock(
|
|
23407
24669
|
{
|
|
23408
24670
|
block,
|
|
@@ -23433,6 +24695,52 @@ function layoutDocument(blocks, measures, options = {}) {
|
|
|
23433
24695
|
if (measure.kind !== "image") {
|
|
23434
24696
|
throw new Error(`layoutDocument: expected image measure for block ${block.id}`);
|
|
23435
24697
|
}
|
|
24698
|
+
const preRegPos = preRegisteredPositions.get(block.id);
|
|
24699
|
+
if (preRegPos && Number.isFinite(preRegPos.anchorX) && Number.isFinite(preRegPos.anchorY) && Number.isFinite(preRegPos.pageNumber)) {
|
|
24700
|
+
const state = paginator.ensurePage();
|
|
24701
|
+
const imgBlock = block;
|
|
24702
|
+
const imgMeasure = measure;
|
|
24703
|
+
const pageContentHeight = Math.max(0, state.contentBottom - state.topMargin);
|
|
24704
|
+
const relativeFrom = imgBlock.anchor?.hRelativeFrom ?? "column";
|
|
24705
|
+
const cols = getCurrentColumns();
|
|
24706
|
+
let maxWidth;
|
|
24707
|
+
if (relativeFrom === "page") {
|
|
24708
|
+
maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
|
|
24709
|
+
} else if (relativeFrom === "margin") {
|
|
24710
|
+
maxWidth = activePageSize.w - margins.left - margins.right;
|
|
24711
|
+
} else {
|
|
24712
|
+
maxWidth = cols.width;
|
|
24713
|
+
}
|
|
24714
|
+
const aspectRatio = imgMeasure.width > 0 && imgMeasure.height > 0 ? imgMeasure.width / imgMeasure.height : 1;
|
|
24715
|
+
const minWidth = 20;
|
|
24716
|
+
const minHeight = minWidth / aspectRatio;
|
|
24717
|
+
const metadata = {
|
|
24718
|
+
originalWidth: imgMeasure.width,
|
|
24719
|
+
originalHeight: imgMeasure.height,
|
|
24720
|
+
maxWidth,
|
|
24721
|
+
maxHeight: pageContentHeight,
|
|
24722
|
+
aspectRatio,
|
|
24723
|
+
minWidth,
|
|
24724
|
+
minHeight
|
|
24725
|
+
};
|
|
24726
|
+
const fragment = {
|
|
24727
|
+
kind: "image",
|
|
24728
|
+
blockId: imgBlock.id,
|
|
24729
|
+
x: preRegPos.anchorX,
|
|
24730
|
+
y: preRegPos.anchorY,
|
|
24731
|
+
width: imgMeasure.width,
|
|
24732
|
+
height: imgMeasure.height,
|
|
24733
|
+
isAnchored: true,
|
|
24734
|
+
zIndex: imgBlock.anchor?.behindDoc ? 0 : 1,
|
|
24735
|
+
metadata
|
|
24736
|
+
};
|
|
24737
|
+
const attrs = imgBlock.attrs;
|
|
24738
|
+
if (attrs?.pmStart != null) fragment.pmStart = attrs.pmStart;
|
|
24739
|
+
if (attrs?.pmEnd != null) fragment.pmEnd = attrs.pmEnd;
|
|
24740
|
+
state.page.fragments.push(fragment);
|
|
24741
|
+
placedAnchoredIds.add(imgBlock.id);
|
|
24742
|
+
continue;
|
|
24743
|
+
}
|
|
23436
24744
|
layoutImageBlock({
|
|
23437
24745
|
block,
|
|
23438
24746
|
measure,
|
|
@@ -23628,7 +24936,9 @@ const hashRuns = (block) => {
|
|
|
23628
24936
|
const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
|
|
23629
24937
|
const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
|
|
23630
24938
|
const runsHash = block.runs.map((run) => {
|
|
23631
|
-
const text = normalizeText(
|
|
24939
|
+
const text = normalizeText(
|
|
24940
|
+
"src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? ""
|
|
24941
|
+
);
|
|
23632
24942
|
const bold = "bold" in run ? run.bold : false;
|
|
23633
24943
|
const italic = "italic" in run ? run.italic : false;
|
|
23634
24944
|
const color = "color" in run ? run.color : void 0;
|
|
@@ -23897,7 +25207,13 @@ const FeatureFlags = {
|
|
|
23897
25207
|
* Logs cache hits, misses, invalidations, and bucket selection.
|
|
23898
25208
|
* Should be disabled in production (only enabled for debugging).
|
|
23899
25209
|
*/
|
|
23900
|
-
DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false)
|
|
25210
|
+
DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false),
|
|
25211
|
+
/**
|
|
25212
|
+
* Enable debug logging for layout version tracking.
|
|
25213
|
+
* Logs stale layout reads, geometry fallbacks, PM transactions, and layout completions.
|
|
25214
|
+
* Should be disabled in production (only enabled for debugging).
|
|
25215
|
+
*/
|
|
25216
|
+
DEBUG_LAYOUT_VERSION: isEnabled("SD_DEBUG_LAYOUT_VERSION", false)
|
|
23901
25217
|
};
|
|
23902
25218
|
const PageTokenLogger = {
|
|
23903
25219
|
/**
|
|
@@ -24282,7 +25598,7 @@ function fontString(run) {
|
|
|
24282
25598
|
return `${italic}${bold}${size}px ${family}`.trim();
|
|
24283
25599
|
}
|
|
24284
25600
|
function runText(run) {
|
|
24285
|
-
return run.kind === "
|
|
25601
|
+
return "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
|
|
24286
25602
|
}
|
|
24287
25603
|
function measureRunSliceWidth(run, fromChar, toChar) {
|
|
24288
25604
|
const context = getCtx();
|
|
@@ -24444,7 +25760,7 @@ const paragraphBlocksEqual = (a, b) => {
|
|
|
24444
25760
|
for (let i = 0; i < a.runs.length; i += 1) {
|
|
24445
25761
|
const runA = a.runs[i];
|
|
24446
25762
|
const runB = b.runs[i];
|
|
24447
|
-
if ((runA.kind === "
|
|
25763
|
+
if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
|
|
24448
25764
|
return false;
|
|
24449
25765
|
}
|
|
24450
25766
|
}
|
|
@@ -24564,7 +25880,7 @@ function computeHeaderFooterContentHash(blocks) {
|
|
|
24564
25880
|
parts.push(block.id);
|
|
24565
25881
|
if (block.kind === "paragraph") {
|
|
24566
25882
|
for (const run of block.runs) {
|
|
24567
|
-
if (run.kind !== "
|
|
25883
|
+
if (!("src" in run) && run.kind !== "lineBreak" && run.kind !== "break") {
|
|
24568
25884
|
parts.push(run.text ?? "");
|
|
24569
25885
|
}
|
|
24570
25886
|
if ("bold" in run && run.bold) parts.push("b");
|
|
@@ -24993,6 +26309,23 @@ async function remeasureAffectedBlocks(blocks, measures, affectedBlockIds, const
|
|
|
24993
26309
|
}
|
|
24994
26310
|
return updatedMeasures;
|
|
24995
26311
|
}
|
|
26312
|
+
var Priority = /* @__PURE__ */ ((Priority2) => {
|
|
26313
|
+
Priority2[Priority2["P0"] = 0] = "P0";
|
|
26314
|
+
Priority2[Priority2["P1"] = 1] = "P1";
|
|
26315
|
+
Priority2[Priority2["P2"] = 2] = "P2";
|
|
26316
|
+
Priority2[Priority2["P3"] = 3] = "P3";
|
|
26317
|
+
return Priority2;
|
|
26318
|
+
})(Priority || {});
|
|
26319
|
+
({
|
|
26320
|
+
/** P0: No debounce for synchronous cursor positioning */
|
|
26321
|
+
[Priority.P0]: 0,
|
|
26322
|
+
/** P1: One animation frame (~60fps) for viewport layout */
|
|
26323
|
+
[Priority.P1]: 16,
|
|
26324
|
+
/** P2: Typing burst threshold for adjacent pages layout */
|
|
26325
|
+
[Priority.P2]: 50,
|
|
26326
|
+
/** P3: Heavy debounce for full document layout */
|
|
26327
|
+
[Priority.P3]: 150
|
|
26328
|
+
});
|
|
24996
26329
|
const isAtomicFragment = (fragment) => {
|
|
24997
26330
|
return fragment.kind === "drawing" || fragment.kind === "image";
|
|
24998
26331
|
};
|
|
@@ -25080,6 +26413,111 @@ const hitTestAtomicFragment = (pageHit, blocks, measures, point) => {
|
|
|
25080
26413
|
}
|
|
25081
26414
|
return null;
|
|
25082
26415
|
};
|
|
26416
|
+
const hitTestTableFragment = (pageHit, blocks, measures, point) => {
|
|
26417
|
+
for (const fragment of pageHit.page.fragments) {
|
|
26418
|
+
if (fragment.kind !== "table") continue;
|
|
26419
|
+
const tableFragment = fragment;
|
|
26420
|
+
const withinX = point.x >= tableFragment.x && point.x <= tableFragment.x + tableFragment.width;
|
|
26421
|
+
const withinY = point.y >= tableFragment.y && point.y <= tableFragment.y + tableFragment.height;
|
|
26422
|
+
if (!withinX || !withinY) continue;
|
|
26423
|
+
const blockIndex = blocks.findIndex((block2) => block2.id === tableFragment.blockId);
|
|
26424
|
+
if (blockIndex === -1) continue;
|
|
26425
|
+
const block = blocks[blockIndex];
|
|
26426
|
+
const measure = measures[blockIndex];
|
|
26427
|
+
if (!block || block.kind !== "table" || !measure || measure.kind !== "table") continue;
|
|
26428
|
+
const tableBlock = block;
|
|
26429
|
+
const tableMeasure = measure;
|
|
26430
|
+
const localX = point.x - tableFragment.x;
|
|
26431
|
+
const localY = point.y - tableFragment.y;
|
|
26432
|
+
let rowY = 0;
|
|
26433
|
+
let rowIndex = -1;
|
|
26434
|
+
if (tableMeasure.rows.length === 0 || tableBlock.rows.length === 0) continue;
|
|
26435
|
+
for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableMeasure.rows.length; r2++) {
|
|
26436
|
+
const rowMeasure2 = tableMeasure.rows[r2];
|
|
26437
|
+
if (localY >= rowY && localY < rowY + rowMeasure2.height) {
|
|
26438
|
+
rowIndex = r2;
|
|
26439
|
+
break;
|
|
26440
|
+
}
|
|
26441
|
+
rowY += rowMeasure2.height;
|
|
26442
|
+
}
|
|
26443
|
+
if (rowIndex === -1) {
|
|
26444
|
+
rowIndex = Math.min(tableFragment.toRow - 1, tableMeasure.rows.length - 1);
|
|
26445
|
+
if (rowIndex < tableFragment.fromRow) continue;
|
|
26446
|
+
}
|
|
26447
|
+
const rowMeasure = tableMeasure.rows[rowIndex];
|
|
26448
|
+
const row = tableBlock.rows[rowIndex];
|
|
26449
|
+
if (!rowMeasure || !row) continue;
|
|
26450
|
+
let colX = 0;
|
|
26451
|
+
let colIndex = -1;
|
|
26452
|
+
if (rowMeasure.cells.length === 0 || row.cells.length === 0) continue;
|
|
26453
|
+
for (let c = 0; c < rowMeasure.cells.length; c++) {
|
|
26454
|
+
const cellMeasure2 = rowMeasure.cells[c];
|
|
26455
|
+
if (localX >= colX && localX < colX + cellMeasure2.width) {
|
|
26456
|
+
colIndex = c;
|
|
26457
|
+
break;
|
|
26458
|
+
}
|
|
26459
|
+
colX += cellMeasure2.width;
|
|
26460
|
+
}
|
|
26461
|
+
if (colIndex === -1) {
|
|
26462
|
+
colIndex = rowMeasure.cells.length - 1;
|
|
26463
|
+
if (colIndex < 0) continue;
|
|
26464
|
+
}
|
|
26465
|
+
const cellMeasure = rowMeasure.cells[colIndex];
|
|
26466
|
+
const cell = row.cells[colIndex];
|
|
26467
|
+
if (!cellMeasure || !cell) continue;
|
|
26468
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
26469
|
+
const rawMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
|
|
26470
|
+
const cellBlockMeasures = (Array.isArray(rawMeasures) ? rawMeasures : []).filter(
|
|
26471
|
+
(m) => m != null && typeof m === "object" && "kind" in m
|
|
26472
|
+
);
|
|
26473
|
+
let blockStartY = 0;
|
|
26474
|
+
const getBlockHeight = (m) => {
|
|
26475
|
+
if (!m) return 0;
|
|
26476
|
+
if ("totalHeight" in m && typeof m.totalHeight === "number") {
|
|
26477
|
+
return m.totalHeight;
|
|
26478
|
+
}
|
|
26479
|
+
if ("height" in m && typeof m.height === "number") {
|
|
26480
|
+
return m.height;
|
|
26481
|
+
}
|
|
26482
|
+
return 0;
|
|
26483
|
+
};
|
|
26484
|
+
for (let i = 0; i < cellBlocks.length && i < cellBlockMeasures.length; i++) {
|
|
26485
|
+
const cellBlock = cellBlocks[i];
|
|
26486
|
+
const cellBlockMeasure = cellBlockMeasures[i];
|
|
26487
|
+
if (cellBlock?.kind !== "paragraph" || cellBlockMeasure?.kind !== "paragraph") {
|
|
26488
|
+
blockStartY += getBlockHeight(cellBlockMeasure);
|
|
26489
|
+
continue;
|
|
26490
|
+
}
|
|
26491
|
+
const blockHeight = getBlockHeight(cellBlockMeasure);
|
|
26492
|
+
const blockEndY = blockStartY + blockHeight;
|
|
26493
|
+
const padding = cell.attrs?.padding ?? { top: 2, left: 4 };
|
|
26494
|
+
const cellLocalX = localX - colX - (padding.left ?? 4);
|
|
26495
|
+
const cellLocalY = localY - rowY - (padding.top ?? 2);
|
|
26496
|
+
const paragraphBlock = cellBlock;
|
|
26497
|
+
const paragraphMeasure = cellBlockMeasure;
|
|
26498
|
+
const isWithinBlock = cellLocalY >= blockStartY && cellLocalY < blockEndY;
|
|
26499
|
+
const isLastParagraph = i === Math.min(cellBlocks.length, cellBlockMeasures.length) - 1;
|
|
26500
|
+
if (isWithinBlock || isLastParagraph) {
|
|
26501
|
+
const unclampedLocalY = cellLocalY - blockStartY;
|
|
26502
|
+
const localYWithinBlock = Math.max(0, Math.min(unclampedLocalY, Math.max(blockHeight, 0)));
|
|
26503
|
+
return {
|
|
26504
|
+
fragment: tableFragment,
|
|
26505
|
+
block: tableBlock,
|
|
26506
|
+
measure: tableMeasure,
|
|
26507
|
+
pageIndex: pageHit.pageIndex,
|
|
26508
|
+
cellRowIndex: rowIndex,
|
|
26509
|
+
cellColIndex: colIndex,
|
|
26510
|
+
cellBlock: paragraphBlock,
|
|
26511
|
+
cellMeasure: paragraphMeasure,
|
|
26512
|
+
localX: Math.max(0, cellLocalX),
|
|
26513
|
+
localY: Math.max(0, localYWithinBlock)
|
|
26514
|
+
};
|
|
26515
|
+
}
|
|
26516
|
+
blockStartY = blockEndY;
|
|
26517
|
+
}
|
|
26518
|
+
}
|
|
26519
|
+
return null;
|
|
26520
|
+
};
|
|
25083
26521
|
function clickToPosition(layout, blocks, measures, containerPoint, domContainer, clientX, clientY) {
|
|
25084
26522
|
logClickStage("log", "entry", {
|
|
25085
26523
|
pages: layout.pages.length
|
|
@@ -25174,6 +26612,49 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
|
|
|
25174
26612
|
// lineIndex is now already absolute (within measure.lines), no need to add fragment.fromLine
|
|
25175
26613
|
};
|
|
25176
26614
|
}
|
|
26615
|
+
const tableHit = hitTestTableFragment(pageHit, blocks, measures, pageRelativePoint);
|
|
26616
|
+
if (tableHit) {
|
|
26617
|
+
const { cellBlock, cellMeasure, localX, localY, pageIndex } = tableHit;
|
|
26618
|
+
const lineIndex = findLineIndexAtY(cellMeasure, localY, 0, cellMeasure.lines.length);
|
|
26619
|
+
if (lineIndex != null) {
|
|
26620
|
+
const line = cellMeasure.lines[lineIndex];
|
|
26621
|
+
const isRTL = isRtlBlock(cellBlock);
|
|
26622
|
+
const pos = mapPointToPm(cellBlock, line, localX, isRTL);
|
|
26623
|
+
if (pos != null) {
|
|
26624
|
+
logClickStage("log", "success", {
|
|
26625
|
+
blockId: tableHit.fragment.blockId,
|
|
26626
|
+
column: determineColumn(layout, tableHit.fragment.x)
|
|
26627
|
+
});
|
|
26628
|
+
return {
|
|
26629
|
+
pos,
|
|
26630
|
+
blockId: tableHit.fragment.blockId,
|
|
26631
|
+
pageIndex,
|
|
26632
|
+
column: determineColumn(layout, tableHit.fragment.x),
|
|
26633
|
+
lineIndex
|
|
26634
|
+
};
|
|
26635
|
+
}
|
|
26636
|
+
}
|
|
26637
|
+
const firstRun = cellBlock.runs?.[0];
|
|
26638
|
+
if (firstRun && firstRun.pmStart != null) {
|
|
26639
|
+
logClickStage("log", "success", {
|
|
26640
|
+
blockId: tableHit.fragment.blockId,
|
|
26641
|
+
pos: firstRun.pmStart,
|
|
26642
|
+
column: determineColumn(layout, tableHit.fragment.x)
|
|
26643
|
+
});
|
|
26644
|
+
return {
|
|
26645
|
+
pos: firstRun.pmStart,
|
|
26646
|
+
blockId: tableHit.fragment.blockId,
|
|
26647
|
+
pageIndex,
|
|
26648
|
+
column: determineColumn(layout, tableHit.fragment.x),
|
|
26649
|
+
lineIndex: 0
|
|
26650
|
+
};
|
|
26651
|
+
}
|
|
26652
|
+
logClickStage("warn", "table-cell-no-position", {
|
|
26653
|
+
blockId: tableHit.fragment.blockId,
|
|
26654
|
+
cellRow: tableHit.cellRowIndex,
|
|
26655
|
+
cellCol: tableHit.cellColIndex
|
|
26656
|
+
});
|
|
26657
|
+
}
|
|
25177
26658
|
const atomicHit = hitTestAtomicFragment(pageHit, blocks, measures, pageRelativePoint);
|
|
25178
26659
|
if (atomicHit && isAtomicFragment(atomicHit.fragment)) {
|
|
25179
26660
|
const { fragment, block, pageIndex } = atomicHit;
|
|
@@ -25285,6 +26766,44 @@ function getFragmentAtPosition(layout, blocks, measures, pos) {
|
|
|
25285
26766
|
}
|
|
25286
26767
|
continue;
|
|
25287
26768
|
}
|
|
26769
|
+
if (fragment.kind === "table") {
|
|
26770
|
+
if (block.kind !== "table" || measure.kind !== "table") continue;
|
|
26771
|
+
const tableBlock = block;
|
|
26772
|
+
const tableFragment = fragment;
|
|
26773
|
+
let tableMinPos = null;
|
|
26774
|
+
let tableMaxPos = null;
|
|
26775
|
+
for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableBlock.rows.length; r2++) {
|
|
26776
|
+
const row = tableBlock.rows[r2];
|
|
26777
|
+
for (const cell of row.cells) {
|
|
26778
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
26779
|
+
for (const cellBlock of cellBlocks) {
|
|
26780
|
+
if (cellBlock?.kind === "paragraph") {
|
|
26781
|
+
const paraBlock = cellBlock;
|
|
26782
|
+
for (const run of paraBlock.runs ?? []) {
|
|
26783
|
+
if (run.pmStart != null) {
|
|
26784
|
+
if (tableMinPos === null || run.pmStart < tableMinPos) tableMinPos = run.pmStart;
|
|
26785
|
+
if (tableMaxPos === null || run.pmStart > tableMaxPos) tableMaxPos = run.pmStart;
|
|
26786
|
+
}
|
|
26787
|
+
if (run.pmEnd != null) {
|
|
26788
|
+
if (tableMinPos === null || run.pmEnd < tableMinPos) tableMinPos = run.pmEnd;
|
|
26789
|
+
if (tableMaxPos === null || run.pmEnd > tableMaxPos) tableMaxPos = run.pmEnd;
|
|
26790
|
+
}
|
|
26791
|
+
}
|
|
26792
|
+
}
|
|
26793
|
+
}
|
|
26794
|
+
}
|
|
26795
|
+
}
|
|
26796
|
+
if (tableMinPos != null && tableMaxPos != null && pos >= tableMinPos && pos <= tableMaxPos) {
|
|
26797
|
+
return {
|
|
26798
|
+
fragment,
|
|
26799
|
+
block,
|
|
26800
|
+
measure,
|
|
26801
|
+
pageIndex,
|
|
26802
|
+
pageY: 0
|
|
26803
|
+
};
|
|
26804
|
+
}
|
|
26805
|
+
continue;
|
|
26806
|
+
}
|
|
25288
26807
|
if (isAtomicFragment(fragment)) {
|
|
25289
26808
|
const { pmStart, pmEnd } = getAtomicPmRange(fragment, block);
|
|
25290
26809
|
const start2 = pmStart ?? pmEnd;
|
|
@@ -25332,7 +26851,7 @@ function computeLinePmRange$1(block, line) {
|
|
|
25332
26851
|
for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
|
|
25333
26852
|
const run = block.runs[runIndex];
|
|
25334
26853
|
if (!run) continue;
|
|
25335
|
-
const text = run.kind === "
|
|
26854
|
+
const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
|
|
25336
26855
|
const runLength = text.length;
|
|
25337
26856
|
const runPmStart = run.pmStart ?? null;
|
|
25338
26857
|
const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
|
|
@@ -27728,16 +29247,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27728
29247
|
opacity: 0.8;
|
|
27729
29248
|
}
|
|
27730
29249
|
|
|
27731
|
-
/* External link indicator (WCAG 2.4.4 Link Purpose) */
|
|
27732
|
-
.superdoc-link[target="_blank"]::after {
|
|
27733
|
-
content: "↗";
|
|
27734
|
-
display: inline-block;
|
|
27735
|
-
margin-left: 0.25em;
|
|
27736
|
-
font-size: 0.85em;
|
|
27737
|
-
text-decoration: none;
|
|
27738
|
-
speak: literal-punctuation; /* Screen readers read the arrow */
|
|
27739
|
-
}
|
|
27740
|
-
|
|
27741
29250
|
/* Print mode: show URLs after links */
|
|
27742
29251
|
@media print {
|
|
27743
29252
|
.superdoc-link::after {
|
|
@@ -27750,11 +29259,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27750
29259
|
.superdoc-link[href^="#"]::after {
|
|
27751
29260
|
content: "";
|
|
27752
29261
|
}
|
|
27753
|
-
|
|
27754
|
-
/* Don't show URL for external link indicator */
|
|
27755
|
-
.superdoc-link[target="_blank"]::after {
|
|
27756
|
-
content: " (" attr(href) ")";
|
|
27757
|
-
}
|
|
27758
29262
|
}
|
|
27759
29263
|
|
|
27760
29264
|
/* High contrast mode support */
|
|
@@ -27772,13 +29276,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27772
29276
|
}
|
|
27773
29277
|
}
|
|
27774
29278
|
|
|
27775
|
-
/* RTL layout support */
|
|
27776
|
-
.superdoc-layout[dir="rtl"] .superdoc-link[target="_blank"]::after {
|
|
27777
|
-
margin-left: 0;
|
|
27778
|
-
margin-right: 0.25em;
|
|
27779
|
-
content: "↖"; /* Mirror the arrow for RTL */
|
|
27780
|
-
}
|
|
27781
|
-
|
|
27782
29279
|
/* Screen reader only content (WCAG SC 1.3.1) */
|
|
27783
29280
|
.sr-only {
|
|
27784
29281
|
position: absolute;
|
|
@@ -27962,7 +29459,20 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
|
|
|
27962
29459
|
};
|
|
27963
29460
|
};
|
|
27964
29461
|
const renderTableCell = (deps) => {
|
|
27965
|
-
const {
|
|
29462
|
+
const {
|
|
29463
|
+
doc: doc2,
|
|
29464
|
+
x,
|
|
29465
|
+
y,
|
|
29466
|
+
rowHeight,
|
|
29467
|
+
cellMeasure,
|
|
29468
|
+
cell,
|
|
29469
|
+
borders,
|
|
29470
|
+
renderLine,
|
|
29471
|
+
context,
|
|
29472
|
+
applySdtDataset,
|
|
29473
|
+
fromLine,
|
|
29474
|
+
toLine
|
|
29475
|
+
} = deps;
|
|
27966
29476
|
const cellEl = doc2.createElement("div");
|
|
27967
29477
|
cellEl.style.position = "absolute";
|
|
27968
29478
|
cellEl.style.left = `${x}px`;
|
|
@@ -27970,6 +29480,7 @@ const renderTableCell = (deps) => {
|
|
|
27970
29480
|
cellEl.style.width = `${cellMeasure.width}px`;
|
|
27971
29481
|
cellEl.style.height = `${rowHeight}px`;
|
|
27972
29482
|
cellEl.style.boxSizing = "border-box";
|
|
29483
|
+
cellEl.style.overflow = "hidden";
|
|
27973
29484
|
if (borders) {
|
|
27974
29485
|
applyCellBorders(cellEl, borders);
|
|
27975
29486
|
}
|
|
@@ -27983,36 +29494,87 @@ const renderTableCell = (deps) => {
|
|
|
27983
29494
|
}
|
|
27984
29495
|
let contentElement;
|
|
27985
29496
|
const attrs = cell?.attrs;
|
|
27986
|
-
const padding = attrs?.padding || { top: 2, left: 4, right: 4 };
|
|
29497
|
+
const padding = attrs?.padding || { top: 2, left: 4, right: 4, bottom: 2 };
|
|
27987
29498
|
const paddingLeft = padding.left ?? 4;
|
|
27988
29499
|
const paddingTop = padding.top ?? 2;
|
|
27989
29500
|
const paddingRight = padding.right ?? 4;
|
|
29501
|
+
const paddingBottom = padding.bottom ?? 2;
|
|
27990
29502
|
const cellBlocks = cell?.blocks ?? (cell?.paragraph ? [cell.paragraph] : []);
|
|
27991
|
-
const blockMeasures = cellMeasure
|
|
29503
|
+
const blockMeasures = cellMeasure?.blocks ?? (cellMeasure?.paragraph ? [cellMeasure.paragraph] : []);
|
|
27992
29504
|
if (cellBlocks.length > 0 && blockMeasures.length > 0) {
|
|
27993
29505
|
const content = doc2.createElement("div");
|
|
27994
29506
|
content.style.position = "absolute";
|
|
27995
29507
|
content.style.left = `${x + paddingLeft}px`;
|
|
27996
29508
|
content.style.top = `${y + paddingTop}px`;
|
|
27997
|
-
|
|
27998
|
-
|
|
29509
|
+
const contentWidth = Math.max(0, cellMeasure.width - paddingLeft - paddingRight);
|
|
29510
|
+
const contentHeight = Math.max(0, rowHeight - paddingTop - paddingBottom);
|
|
29511
|
+
content.style.width = `${contentWidth + 1}px`;
|
|
29512
|
+
content.style.height = `${contentHeight}px`;
|
|
29513
|
+
content.style.display = "flex";
|
|
29514
|
+
content.style.flexDirection = "column";
|
|
29515
|
+
content.style.overflowX = "visible";
|
|
29516
|
+
content.style.overflowY = "hidden";
|
|
29517
|
+
if (cell?.attrs?.verticalAlign === "center") {
|
|
29518
|
+
content.style.justifyContent = "center";
|
|
29519
|
+
} else if (cell?.attrs?.verticalAlign === "bottom") {
|
|
29520
|
+
content.style.justifyContent = "flex-end";
|
|
29521
|
+
} else {
|
|
29522
|
+
content.style.justifyContent = "flex-start";
|
|
29523
|
+
}
|
|
29524
|
+
const blockLineCounts = [];
|
|
29525
|
+
for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
|
|
29526
|
+
const bm = blockMeasures[i];
|
|
29527
|
+
if (bm.kind === "paragraph") {
|
|
29528
|
+
blockLineCounts.push(bm.lines?.length || 0);
|
|
29529
|
+
} else {
|
|
29530
|
+
blockLineCounts.push(0);
|
|
29531
|
+
}
|
|
29532
|
+
}
|
|
29533
|
+
const totalLines = blockLineCounts.reduce((a, b) => a + b, 0);
|
|
29534
|
+
const globalFromLine = fromLine ?? 0;
|
|
29535
|
+
const globalToLine = toLine === -1 || toLine === void 0 ? totalLines : toLine;
|
|
29536
|
+
let cumulativeLineCount = 0;
|
|
27999
29537
|
for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
|
|
28000
29538
|
const blockMeasure = blockMeasures[i];
|
|
28001
29539
|
const block = cellBlocks[i];
|
|
28002
29540
|
if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
|
|
29541
|
+
const lines = blockMeasure.lines;
|
|
29542
|
+
const blockLineCount = lines?.length || 0;
|
|
29543
|
+
const blockStartGlobal = cumulativeLineCount;
|
|
29544
|
+
const blockEndGlobal = cumulativeLineCount + blockLineCount;
|
|
29545
|
+
if (blockEndGlobal <= globalFromLine) {
|
|
29546
|
+
cumulativeLineCount += blockLineCount;
|
|
29547
|
+
continue;
|
|
29548
|
+
}
|
|
29549
|
+
if (blockStartGlobal >= globalToLine) {
|
|
29550
|
+
cumulativeLineCount += blockLineCount;
|
|
29551
|
+
continue;
|
|
29552
|
+
}
|
|
29553
|
+
const localStartLine = Math.max(0, globalFromLine - blockStartGlobal);
|
|
29554
|
+
const localEndLine = Math.min(blockLineCount, globalToLine - blockStartGlobal);
|
|
28003
29555
|
const paraWrapper = doc2.createElement("div");
|
|
28004
|
-
paraWrapper.style.position = "
|
|
28005
|
-
paraWrapper.style.top = `${blockY}px`;
|
|
29556
|
+
paraWrapper.style.position = "relative";
|
|
28006
29557
|
paraWrapper.style.left = "0";
|
|
28007
29558
|
paraWrapper.style.width = "100%";
|
|
28008
29559
|
applySdtDataset(paraWrapper, block.attrs?.sdt);
|
|
28009
|
-
|
|
28010
|
-
lines.
|
|
29560
|
+
let renderedHeight = 0;
|
|
29561
|
+
for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
|
|
29562
|
+
const line = lines[lineIdx];
|
|
28011
29563
|
const lineEl = renderLine(block, line, { ...context, section: "body" });
|
|
28012
29564
|
paraWrapper.appendChild(lineEl);
|
|
28013
|
-
|
|
29565
|
+
renderedHeight += line.lineHeight;
|
|
29566
|
+
}
|
|
29567
|
+
const renderedEntireBlock = localStartLine === 0 && localEndLine >= blockLineCount;
|
|
29568
|
+
if (renderedEntireBlock && blockMeasure.totalHeight && blockMeasure.totalHeight > renderedHeight) {
|
|
29569
|
+
renderedHeight = blockMeasure.totalHeight;
|
|
29570
|
+
}
|
|
28014
29571
|
content.appendChild(paraWrapper);
|
|
28015
|
-
|
|
29572
|
+
if (renderedHeight > 0) {
|
|
29573
|
+
paraWrapper.style.height = `${renderedHeight}px`;
|
|
29574
|
+
}
|
|
29575
|
+
cumulativeLineCount += blockLineCount;
|
|
29576
|
+
} else {
|
|
29577
|
+
cumulativeLineCount += 0;
|
|
28016
29578
|
}
|
|
28017
29579
|
}
|
|
28018
29580
|
contentElement = content;
|
|
@@ -28033,7 +29595,10 @@ const renderTableRow = (deps) => {
|
|
|
28033
29595
|
allRowHeights,
|
|
28034
29596
|
context,
|
|
28035
29597
|
renderLine,
|
|
28036
|
-
applySdtDataset
|
|
29598
|
+
applySdtDataset,
|
|
29599
|
+
continuesFromPrev,
|
|
29600
|
+
continuesOnNext,
|
|
29601
|
+
partialRow
|
|
28037
29602
|
} = deps;
|
|
28038
29603
|
const calculateXPosition = (gridColumnStart) => {
|
|
28039
29604
|
let x = 0;
|
|
@@ -28066,25 +29631,57 @@ const renderTableRow = (deps) => {
|
|
|
28066
29631
|
const isLastRow = rowIndex === totalRows - 1;
|
|
28067
29632
|
const isFirstCol = gridColIndex === 0;
|
|
28068
29633
|
const isLastCol = gridColIndex === totalCols - 1;
|
|
29634
|
+
const treatAsFirstRow = isFirstRow || continuesFromPrev;
|
|
29635
|
+
const treatAsLastRow = isLastRow || continuesOnNext;
|
|
28069
29636
|
resolvedBorders = {
|
|
28070
|
-
// For top: use cell's if defined, otherwise use table's top for first row
|
|
28071
|
-
top: cellBordersAttr.top ?? borderValueToSpec(
|
|
28072
|
-
// For bottom: use cell's if defined, otherwise use table's bottom for last row
|
|
28073
|
-
bottom: cellBordersAttr.bottom ?? borderValueToSpec(
|
|
29637
|
+
// For top: use cell's if defined, otherwise use table's top border for first row OR continuation
|
|
29638
|
+
top: cellBordersAttr.top ?? borderValueToSpec(treatAsFirstRow ? tableBorders.top : tableBorders.insideH),
|
|
29639
|
+
// For bottom: use cell's if defined, otherwise use table's bottom border for last row OR before continuation
|
|
29640
|
+
bottom: cellBordersAttr.bottom ?? borderValueToSpec(treatAsLastRow ? tableBorders.bottom : void 0),
|
|
28074
29641
|
// For left: use cell's if defined, otherwise use table's left for first col
|
|
28075
29642
|
left: cellBordersAttr.left ?? borderValueToSpec(isFirstCol ? tableBorders.left : tableBorders.insideV),
|
|
28076
29643
|
// For right: use cell's if defined, otherwise use table's right for last col only
|
|
28077
29644
|
right: cellBordersAttr.right ?? borderValueToSpec(isLastCol ? tableBorders.right : void 0)
|
|
28078
29645
|
};
|
|
28079
29646
|
} else if (hasExplicitBorders) {
|
|
28080
|
-
resolvedBorders =
|
|
29647
|
+
resolvedBorders = {
|
|
29648
|
+
top: cellBordersAttr.top,
|
|
29649
|
+
bottom: cellBordersAttr.bottom,
|
|
29650
|
+
left: cellBordersAttr.left,
|
|
29651
|
+
right: cellBordersAttr.right
|
|
29652
|
+
};
|
|
28081
29653
|
} else if (tableBorders) {
|
|
28082
|
-
|
|
29654
|
+
const isFirstRow = rowIndex === 0;
|
|
29655
|
+
const isLastRow = rowIndex === totalRows - 1;
|
|
29656
|
+
const treatAsFirstRow = isFirstRow || continuesFromPrev;
|
|
29657
|
+
const treatAsLastRow = isLastRow || continuesOnNext;
|
|
29658
|
+
const baseBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
|
|
29659
|
+
if (baseBorders) {
|
|
29660
|
+
resolvedBorders = {
|
|
29661
|
+
// If this is a continuation (continuesFromPrev), use table's top border
|
|
29662
|
+
top: treatAsFirstRow ? borderValueToSpec(tableBorders.top) : baseBorders.top,
|
|
29663
|
+
// If this continues on next (continuesOnNext), use table's bottom border
|
|
29664
|
+
bottom: treatAsLastRow ? borderValueToSpec(tableBorders.bottom) : baseBorders.bottom,
|
|
29665
|
+
left: baseBorders.left,
|
|
29666
|
+
right: baseBorders.right
|
|
29667
|
+
};
|
|
29668
|
+
} else {
|
|
29669
|
+
resolvedBorders = void 0;
|
|
29670
|
+
}
|
|
28083
29671
|
} else {
|
|
28084
29672
|
resolvedBorders = void 0;
|
|
28085
29673
|
}
|
|
28086
29674
|
const rowSpan = cellMeasure.rowSpan ?? 1;
|
|
28087
|
-
|
|
29675
|
+
let cellHeight;
|
|
29676
|
+
if (partialRow) {
|
|
29677
|
+
cellHeight = partialRow.partialHeight;
|
|
29678
|
+
} else if (rowSpan > 1) {
|
|
29679
|
+
cellHeight = calculateRowspanHeight(rowIndex, rowSpan);
|
|
29680
|
+
} else {
|
|
29681
|
+
cellHeight = rowMeasure.height;
|
|
29682
|
+
}
|
|
29683
|
+
const fromLine = partialRow?.fromLineByCell?.[cellIndex];
|
|
29684
|
+
const toLine = partialRow?.toLineByCell?.[cellIndex];
|
|
28088
29685
|
const { cellElement, contentElement } = renderTableCell({
|
|
28089
29686
|
doc: doc2,
|
|
28090
29687
|
x,
|
|
@@ -28095,7 +29692,9 @@ const renderTableRow = (deps) => {
|
|
|
28095
29692
|
borders: resolvedBorders,
|
|
28096
29693
|
renderLine,
|
|
28097
29694
|
context,
|
|
28098
|
-
applySdtDataset
|
|
29695
|
+
applySdtDataset,
|
|
29696
|
+
fromLine,
|
|
29697
|
+
toLine
|
|
28099
29698
|
});
|
|
28100
29699
|
container.appendChild(cellElement);
|
|
28101
29700
|
if (contentElement) {
|
|
@@ -28209,11 +29808,46 @@ const renderTableFragment = (deps) => {
|
|
|
28209
29808
|
if (borderCollapse === "separate" && block.attrs?.cellSpacing) {
|
|
28210
29809
|
container.style.borderSpacing = `${block.attrs.cellSpacing}px`;
|
|
28211
29810
|
}
|
|
28212
|
-
const allRowHeights = measure.rows.map((r2) =>
|
|
29811
|
+
const allRowHeights = measure.rows.map((r2, idx) => {
|
|
29812
|
+
if (fragment.partialRow && fragment.partialRow.rowIndex === idx) {
|
|
29813
|
+
return fragment.partialRow.partialHeight;
|
|
29814
|
+
}
|
|
29815
|
+
return r2?.height ?? 0;
|
|
29816
|
+
});
|
|
28213
29817
|
let y = 0;
|
|
29818
|
+
if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
|
|
29819
|
+
for (let r2 = 0; r2 < fragment.repeatHeaderCount; r2 += 1) {
|
|
29820
|
+
const rowMeasure = measure.rows[r2];
|
|
29821
|
+
if (!rowMeasure) break;
|
|
29822
|
+
renderTableRow({
|
|
29823
|
+
doc: doc2,
|
|
29824
|
+
container,
|
|
29825
|
+
rowIndex: r2,
|
|
29826
|
+
y,
|
|
29827
|
+
rowMeasure,
|
|
29828
|
+
row: block.rows[r2],
|
|
29829
|
+
totalRows: block.rows.length,
|
|
29830
|
+
tableBorders,
|
|
29831
|
+
columnWidths: measure.columnWidths,
|
|
29832
|
+
allRowHeights,
|
|
29833
|
+
context,
|
|
29834
|
+
renderLine,
|
|
29835
|
+
applySdtDataset,
|
|
29836
|
+
// Headers are always rendered as-is (no border suppression)
|
|
29837
|
+
continuesFromPrev: false,
|
|
29838
|
+
continuesOnNext: false
|
|
29839
|
+
});
|
|
29840
|
+
y += rowMeasure.height;
|
|
29841
|
+
}
|
|
29842
|
+
}
|
|
28214
29843
|
for (let r2 = fragment.fromRow; r2 < fragment.toRow; r2 += 1) {
|
|
28215
29844
|
const rowMeasure = measure.rows[r2];
|
|
28216
29845
|
if (!rowMeasure) break;
|
|
29846
|
+
const isFirstRenderedBodyRow = r2 === fragment.fromRow;
|
|
29847
|
+
const isLastRenderedBodyRow = r2 === fragment.toRow - 1;
|
|
29848
|
+
const isPartialRow = fragment.partialRow && fragment.partialRow.rowIndex === r2;
|
|
29849
|
+
const partialRowData = isPartialRow ? fragment.partialRow : void 0;
|
|
29850
|
+
const actualRowHeight = partialRowData ? partialRowData.partialHeight : rowMeasure.height;
|
|
28217
29851
|
renderTableRow({
|
|
28218
29852
|
doc: doc2,
|
|
28219
29853
|
container,
|
|
@@ -28227,13 +29861,112 @@ const renderTableFragment = (deps) => {
|
|
|
28227
29861
|
allRowHeights,
|
|
28228
29862
|
context,
|
|
28229
29863
|
renderLine,
|
|
28230
|
-
applySdtDataset
|
|
29864
|
+
applySdtDataset,
|
|
29865
|
+
// Draw top border if table continues from previous fragment (MS Word behavior)
|
|
29866
|
+
continuesFromPrev: isFirstRenderedBodyRow && fragment.continuesFromPrev === true,
|
|
29867
|
+
// Draw bottom border if table continues on next fragment (MS Word behavior)
|
|
29868
|
+
continuesOnNext: isLastRenderedBodyRow && fragment.continuesOnNext === true,
|
|
29869
|
+
// Pass partial row data for mid-row splits
|
|
29870
|
+
partialRow: partialRowData
|
|
28231
29871
|
});
|
|
28232
|
-
y +=
|
|
29872
|
+
y += actualRowHeight;
|
|
28233
29873
|
}
|
|
28234
29874
|
return container;
|
|
28235
29875
|
};
|
|
29876
|
+
const isDevelopment = () => {
|
|
29877
|
+
if (typeof process$1 !== "undefined" && typeof process$1.env !== "undefined") {
|
|
29878
|
+
return process$1.env.NODE_ENV === "development";
|
|
29879
|
+
}
|
|
29880
|
+
return false;
|
|
29881
|
+
};
|
|
29882
|
+
class ValidationStatsCollector {
|
|
29883
|
+
constructor() {
|
|
29884
|
+
this.stats = {
|
|
29885
|
+
totalSpans: 0,
|
|
29886
|
+
validSpans: 0,
|
|
29887
|
+
missingPmStart: 0,
|
|
29888
|
+
missingPmEnd: 0,
|
|
29889
|
+
missingBoth: 0
|
|
29890
|
+
};
|
|
29891
|
+
}
|
|
29892
|
+
record(hasPmStart, hasPmEnd) {
|
|
29893
|
+
this.stats.totalSpans++;
|
|
29894
|
+
if (hasPmStart && hasPmEnd) {
|
|
29895
|
+
this.stats.validSpans++;
|
|
29896
|
+
} else if (!hasPmStart && !hasPmEnd) {
|
|
29897
|
+
this.stats.missingBoth++;
|
|
29898
|
+
} else if (!hasPmStart) {
|
|
29899
|
+
this.stats.missingPmStart++;
|
|
29900
|
+
} else {
|
|
29901
|
+
this.stats.missingPmEnd++;
|
|
29902
|
+
}
|
|
29903
|
+
}
|
|
29904
|
+
getStats() {
|
|
29905
|
+
return { ...this.stats };
|
|
29906
|
+
}
|
|
29907
|
+
reset() {
|
|
29908
|
+
this.stats = {
|
|
29909
|
+
totalSpans: 0,
|
|
29910
|
+
validSpans: 0,
|
|
29911
|
+
missingPmStart: 0,
|
|
29912
|
+
missingPmEnd: 0,
|
|
29913
|
+
missingBoth: 0
|
|
29914
|
+
};
|
|
29915
|
+
}
|
|
29916
|
+
getCoveragePercent() {
|
|
29917
|
+
if (this.stats.totalSpans === 0) return 100;
|
|
29918
|
+
return this.stats.validSpans / this.stats.totalSpans * 100;
|
|
29919
|
+
}
|
|
29920
|
+
logSummary() {
|
|
29921
|
+
if (!isDevelopment()) return;
|
|
29922
|
+
const coverage = this.getCoveragePercent();
|
|
29923
|
+
const s2 = this.stats;
|
|
29924
|
+
if (coverage < 100) {
|
|
29925
|
+
console.warn("[PmPositionValidation] PM position coverage:", {
|
|
29926
|
+
coverage: `${coverage.toFixed(1)}%`,
|
|
29927
|
+
totalSpans: s2.totalSpans,
|
|
29928
|
+
validSpans: s2.validSpans,
|
|
29929
|
+
missingPmStart: s2.missingPmStart,
|
|
29930
|
+
missingPmEnd: s2.missingPmEnd,
|
|
29931
|
+
missingBoth: s2.missingBoth
|
|
29932
|
+
});
|
|
29933
|
+
}
|
|
29934
|
+
}
|
|
29935
|
+
}
|
|
29936
|
+
const globalValidationStats = new ValidationStatsCollector();
|
|
29937
|
+
function assertPmPositions(run, context) {
|
|
29938
|
+
const hasPmStart = run.pmStart != null;
|
|
29939
|
+
const hasPmEnd = run.pmEnd != null;
|
|
29940
|
+
globalValidationStats.record(hasPmStart, hasPmEnd);
|
|
29941
|
+
if (!isDevelopment()) return;
|
|
29942
|
+
if (!hasPmStart || !hasPmEnd) {
|
|
29943
|
+
const textPreview = run.text ? run.text.substring(0, 20) + (run.text.length > 20 ? "..." : "") : "(no text)";
|
|
29944
|
+
console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
|
|
29945
|
+
hasPmStart,
|
|
29946
|
+
hasPmEnd,
|
|
29947
|
+
textPreview,
|
|
29948
|
+
fallback: "Will use PM DOM coordinates for cursor positioning"
|
|
29949
|
+
});
|
|
29950
|
+
}
|
|
29951
|
+
}
|
|
29952
|
+
function assertFragmentPmPositions(fragment, context) {
|
|
29953
|
+
const hasPmStart = fragment.pmStart != null;
|
|
29954
|
+
const hasPmEnd = fragment.pmEnd != null;
|
|
29955
|
+
globalValidationStats.record(hasPmStart, hasPmEnd);
|
|
29956
|
+
if (!isDevelopment()) return;
|
|
29957
|
+
if (!hasPmStart || !hasPmEnd) {
|
|
29958
|
+
console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
|
|
29959
|
+
fragmentKind: fragment.kind ?? "unknown",
|
|
29960
|
+
hasPmStart,
|
|
29961
|
+
hasPmEnd,
|
|
29962
|
+
fallback: "Will use PM DOM coordinates for cursor positioning"
|
|
29963
|
+
});
|
|
29964
|
+
}
|
|
29965
|
+
}
|
|
28236
29966
|
const LIST_MARKER_GAP$1 = 8;
|
|
29967
|
+
const COMMENT_EXTERNAL_COLOR = "#B1124B";
|
|
29968
|
+
const COMMENT_INTERNAL_COLOR = "#078383";
|
|
29969
|
+
const COMMENT_INACTIVE_ALPHA = "22";
|
|
28237
29970
|
const LINK_DATASET_KEYS = {
|
|
28238
29971
|
blocked: "linkBlocked",
|
|
28239
29972
|
docLocation: "linkDocLocation",
|
|
@@ -28890,7 +30623,7 @@ const _DomPainter = class _DomPainter {
|
|
|
28890
30623
|
current.element = replacement;
|
|
28891
30624
|
current.signature = fragmentSignature(fragment, this.blockLookup);
|
|
28892
30625
|
}
|
|
28893
|
-
this.updateFragmentElement(current.element, fragment);
|
|
30626
|
+
this.updateFragmentElement(current.element, fragment, contextBase.section);
|
|
28894
30627
|
current.fragment = fragment;
|
|
28895
30628
|
current.key = key2;
|
|
28896
30629
|
current.context = contextBase;
|
|
@@ -28958,10 +30691,10 @@ const _DomPainter = class _DomPainter {
|
|
|
28958
30691
|
return this.renderListItemFragment(fragment, context);
|
|
28959
30692
|
}
|
|
28960
30693
|
if (fragment.kind === "image") {
|
|
28961
|
-
return this.renderImageFragment(fragment);
|
|
30694
|
+
return this.renderImageFragment(fragment, context);
|
|
28962
30695
|
}
|
|
28963
30696
|
if (fragment.kind === "drawing") {
|
|
28964
|
-
return this.renderDrawingFragment(fragment);
|
|
30697
|
+
return this.renderDrawingFragment(fragment, context);
|
|
28965
30698
|
}
|
|
28966
30699
|
if (fragment.kind === "table") {
|
|
28967
30700
|
return this.renderTableFragment(fragment, context);
|
|
@@ -28994,7 +30727,7 @@ const _DomPainter = class _DomPainter {
|
|
|
28994
30727
|
const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
|
|
28995
30728
|
const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
|
|
28996
30729
|
applyStyles$2(fragmentEl, styles);
|
|
28997
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
30730
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
28998
30731
|
if (isTocEntry) {
|
|
28999
30732
|
fragmentEl.classList.add("superdoc-toc-entry");
|
|
29000
30733
|
}
|
|
@@ -29012,8 +30745,32 @@ const _DomPainter = class _DomPainter {
|
|
|
29012
30745
|
}
|
|
29013
30746
|
this.applySdtDataset(fragmentEl, block.attrs?.sdt);
|
|
29014
30747
|
this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
|
|
30748
|
+
const dropCapDescriptor = block.attrs?.dropCapDescriptor;
|
|
30749
|
+
const dropCapMeasure = measure.dropCap;
|
|
30750
|
+
if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
|
|
30751
|
+
const dropCapEl = this.renderDropCap(dropCapDescriptor, dropCapMeasure);
|
|
30752
|
+
fragmentEl.appendChild(dropCapEl);
|
|
30753
|
+
}
|
|
30754
|
+
if (fragmentEl.style.paddingLeft) fragmentEl.style.removeProperty("padding-left");
|
|
30755
|
+
if (fragmentEl.style.paddingRight) fragmentEl.style.removeProperty("padding-right");
|
|
30756
|
+
if (fragmentEl.style.textIndent) fragmentEl.style.removeProperty("text-indent");
|
|
30757
|
+
const paraIndent = block.attrs?.indent;
|
|
30758
|
+
const paraIndentLeft = paraIndent?.left ?? 0;
|
|
30759
|
+
const paraIndentRight = paraIndent?.right ?? 0;
|
|
30760
|
+
const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
|
|
29015
30761
|
lines.forEach((line, index2) => {
|
|
29016
30762
|
const lineEl = this.renderLine(block, line, context);
|
|
30763
|
+
if (paraIndentLeft) {
|
|
30764
|
+
lineEl.style.paddingLeft = `${paraIndentLeft}px`;
|
|
30765
|
+
}
|
|
30766
|
+
if (paraIndentRight) {
|
|
30767
|
+
lineEl.style.paddingRight = `${paraIndentRight}px`;
|
|
30768
|
+
}
|
|
30769
|
+
if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
|
|
30770
|
+
lineEl.style.textIndent = `${firstLineOffset}px`;
|
|
30771
|
+
} else if (firstLineOffset) {
|
|
30772
|
+
lineEl.style.textIndent = "0px";
|
|
30773
|
+
}
|
|
29017
30774
|
if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
|
|
29018
30775
|
const markerContainer = this.doc.createElement("span");
|
|
29019
30776
|
markerContainer.style.display = "inline-block";
|
|
@@ -29024,6 +30781,12 @@ const _DomPainter = class _DomPainter {
|
|
|
29024
30781
|
markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
|
|
29025
30782
|
markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
|
|
29026
30783
|
markerEl.style.pointerEvents = "none";
|
|
30784
|
+
const indentLeft = paraIndentLeft;
|
|
30785
|
+
const hanging = paraIndent?.hanging ?? 0;
|
|
30786
|
+
const textStartX = indentLeft - hanging;
|
|
30787
|
+
const markerLeftX = textStartX - fragment.markerWidth;
|
|
30788
|
+
markerEl.style.position = "relative";
|
|
30789
|
+
markerEl.style.left = `${markerLeftX}px`;
|
|
29027
30790
|
markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
|
|
29028
30791
|
markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
|
|
29029
30792
|
markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
|
|
@@ -29082,6 +30845,53 @@ const _DomPainter = class _DomPainter {
|
|
|
29082
30845
|
}
|
|
29083
30846
|
return el;
|
|
29084
30847
|
}
|
|
30848
|
+
/**
|
|
30849
|
+
* Renders a drop cap element as a floated span at the start of a paragraph.
|
|
30850
|
+
*
|
|
30851
|
+
* Drop caps are large initial letters that span multiple lines of text.
|
|
30852
|
+
* This method creates a floated element with the drop cap letter styled
|
|
30853
|
+
* according to the descriptor's run properties.
|
|
30854
|
+
*
|
|
30855
|
+
* @param descriptor - The drop cap descriptor with text and styling info
|
|
30856
|
+
* @param measure - The measured dimensions of the drop cap
|
|
30857
|
+
* @returns HTMLElement containing the rendered drop cap
|
|
30858
|
+
*/
|
|
30859
|
+
renderDropCap(descriptor, measure) {
|
|
30860
|
+
const doc2 = this.doc;
|
|
30861
|
+
const { run, mode } = descriptor;
|
|
30862
|
+
const dropCapEl = doc2.createElement("span");
|
|
30863
|
+
dropCapEl.classList.add("superdoc-drop-cap");
|
|
30864
|
+
dropCapEl.textContent = run.text;
|
|
30865
|
+
dropCapEl.style.fontFamily = run.fontFamily;
|
|
30866
|
+
dropCapEl.style.fontSize = `${run.fontSize}px`;
|
|
30867
|
+
if (run.bold) {
|
|
30868
|
+
dropCapEl.style.fontWeight = "bold";
|
|
30869
|
+
}
|
|
30870
|
+
if (run.italic) {
|
|
30871
|
+
dropCapEl.style.fontStyle = "italic";
|
|
30872
|
+
}
|
|
30873
|
+
if (run.color) {
|
|
30874
|
+
dropCapEl.style.color = run.color;
|
|
30875
|
+
}
|
|
30876
|
+
if (mode === "drop") {
|
|
30877
|
+
dropCapEl.style.float = "left";
|
|
30878
|
+
dropCapEl.style.marginRight = "4px";
|
|
30879
|
+
dropCapEl.style.lineHeight = "1";
|
|
30880
|
+
} else if (mode === "margin") {
|
|
30881
|
+
dropCapEl.style.position = "absolute";
|
|
30882
|
+
dropCapEl.style.left = "0";
|
|
30883
|
+
dropCapEl.style.lineHeight = "1";
|
|
30884
|
+
}
|
|
30885
|
+
if (run.position && run.position !== 0) {
|
|
30886
|
+
dropCapEl.style.position = dropCapEl.style.position || "relative";
|
|
30887
|
+
dropCapEl.style.top = `${run.position}px`;
|
|
30888
|
+
}
|
|
30889
|
+
if (measure) {
|
|
30890
|
+
dropCapEl.style.width = `${measure.width}px`;
|
|
30891
|
+
dropCapEl.style.height = `${measure.height}px`;
|
|
30892
|
+
}
|
|
30893
|
+
return dropCapEl;
|
|
30894
|
+
}
|
|
29085
30895
|
renderListItemFragment(fragment, context) {
|
|
29086
30896
|
try {
|
|
29087
30897
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
@@ -29159,7 +30969,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29159
30969
|
return this.createErrorPlaceholder(fragment.blockId, error);
|
|
29160
30970
|
}
|
|
29161
30971
|
}
|
|
29162
|
-
renderImageFragment(fragment) {
|
|
30972
|
+
renderImageFragment(fragment, context) {
|
|
29163
30973
|
try {
|
|
29164
30974
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
29165
30975
|
if (!lookup || lookup.block.kind !== "image" || lookup.measure.kind !== "image") {
|
|
@@ -29172,7 +30982,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29172
30982
|
const fragmentEl = this.doc.createElement("div");
|
|
29173
30983
|
fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-image-fragment");
|
|
29174
30984
|
applyStyles$2(fragmentEl, fragmentStyles);
|
|
29175
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
30985
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
29176
30986
|
fragmentEl.style.height = `${fragment.height}px`;
|
|
29177
30987
|
this.applySdtDataset(fragmentEl, block.attrs?.sdt);
|
|
29178
30988
|
this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
|
|
@@ -29207,7 +31017,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29207
31017
|
return this.createErrorPlaceholder(fragment.blockId, error);
|
|
29208
31018
|
}
|
|
29209
31019
|
}
|
|
29210
|
-
renderDrawingFragment(fragment) {
|
|
31020
|
+
renderDrawingFragment(fragment, context) {
|
|
29211
31021
|
try {
|
|
29212
31022
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
29213
31023
|
if (!lookup || lookup.block.kind !== "drawing" || lookup.measure.kind !== "drawing") {
|
|
@@ -29221,7 +31031,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29221
31031
|
const fragmentEl = this.doc.createElement("div");
|
|
29222
31032
|
fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
|
|
29223
31033
|
applyStyles$2(fragmentEl, fragmentStyles);
|
|
29224
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
31034
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
29225
31035
|
fragmentEl.style.height = `${fragment.height}px`;
|
|
29226
31036
|
fragmentEl.style.position = "absolute";
|
|
29227
31037
|
fragmentEl.style.overflow = "hidden";
|
|
@@ -29668,13 +31478,16 @@ const _DomPainter = class _DomPainter {
|
|
|
29668
31478
|
if (!this.doc) {
|
|
29669
31479
|
throw new Error("DomPainter: document is not available");
|
|
29670
31480
|
}
|
|
31481
|
+
const applyFragmentFrameWithSection = (el, frag) => {
|
|
31482
|
+
this.applyFragmentFrame(el, frag, context.section);
|
|
31483
|
+
};
|
|
29671
31484
|
return renderTableFragment({
|
|
29672
31485
|
doc: this.doc,
|
|
29673
31486
|
fragment,
|
|
29674
31487
|
context,
|
|
29675
31488
|
blockLookup: this.blockLookup,
|
|
29676
31489
|
renderLine: this.renderLine.bind(this),
|
|
29677
|
-
applyFragmentFrame:
|
|
31490
|
+
applyFragmentFrame: applyFragmentFrameWithSection,
|
|
29678
31491
|
applySdtDataset: this.applySdtDataset.bind(this),
|
|
29679
31492
|
applyStyles: applyStyles$2
|
|
29680
31493
|
});
|
|
@@ -29684,7 +31497,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29684
31497
|
* @returns Sanitized link data or null if invalid/missing
|
|
29685
31498
|
*/
|
|
29686
31499
|
extractLinkData(run) {
|
|
29687
|
-
if (run.kind === "tab") {
|
|
31500
|
+
if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak") {
|
|
29688
31501
|
return null;
|
|
29689
31502
|
}
|
|
29690
31503
|
const link = run.link;
|
|
@@ -29838,11 +31651,29 @@ const _DomPainter = class _DomPainter {
|
|
|
29838
31651
|
isImageRun(run) {
|
|
29839
31652
|
return run.kind === "image";
|
|
29840
31653
|
}
|
|
31654
|
+
/**
|
|
31655
|
+
* Type guard to check if a run is a line break run.
|
|
31656
|
+
*/
|
|
31657
|
+
isLineBreakRun(run) {
|
|
31658
|
+
return run.kind === "lineBreak";
|
|
31659
|
+
}
|
|
31660
|
+
/**
|
|
31661
|
+
* Type guard to check if a run is a break run.
|
|
31662
|
+
*/
|
|
31663
|
+
isBreakRun(run) {
|
|
31664
|
+
return run.kind === "break";
|
|
31665
|
+
}
|
|
29841
31666
|
renderRun(run, context, trackedConfig) {
|
|
29842
31667
|
if (this.isImageRun(run)) {
|
|
29843
31668
|
return this.renderImageRun(run);
|
|
29844
31669
|
}
|
|
29845
|
-
if (
|
|
31670
|
+
if (this.isLineBreakRun(run)) {
|
|
31671
|
+
return null;
|
|
31672
|
+
}
|
|
31673
|
+
if (this.isBreakRun(run)) {
|
|
31674
|
+
return null;
|
|
31675
|
+
}
|
|
31676
|
+
if (!("text" in run) || !run.text || !this.doc) {
|
|
29846
31677
|
return null;
|
|
29847
31678
|
}
|
|
29848
31679
|
const linkData = this.extractLinkData(run);
|
|
@@ -29866,8 +31697,21 @@ const _DomPainter = class _DomPainter {
|
|
|
29866
31697
|
}
|
|
29867
31698
|
}
|
|
29868
31699
|
applyRunStyles(elem, run, isActiveLink);
|
|
31700
|
+
const commentColor = getCommentHighlight(run);
|
|
31701
|
+
if (commentColor && !run.highlight) {
|
|
31702
|
+
elem.style.backgroundColor = commentColor;
|
|
31703
|
+
}
|
|
31704
|
+
const commentAnnotations = run.comments;
|
|
31705
|
+
if (commentAnnotations?.length) {
|
|
31706
|
+
elem.dataset.commentIds = commentAnnotations.map((c) => c.commentId).join(",");
|
|
31707
|
+
if (commentAnnotations.some((c) => c.internal)) {
|
|
31708
|
+
elem.dataset.commentInternal = "true";
|
|
31709
|
+
}
|
|
31710
|
+
elem.classList.add("superdoc-comment-highlight");
|
|
31711
|
+
}
|
|
29869
31712
|
elem.style.zIndex = "1";
|
|
29870
31713
|
applyRunDataAttributes(elem, run.dataAttrs);
|
|
31714
|
+
assertPmPositions(run, "paragraph text run");
|
|
29871
31715
|
if (run.pmStart != null) elem.dataset.pmStart = String(run.pmStart);
|
|
29872
31716
|
if (run.pmEnd != null) elem.dataset.pmEnd = String(run.pmEnd);
|
|
29873
31717
|
if (trackedConfig) {
|
|
@@ -29946,6 +31790,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29946
31790
|
img.style.marginRight = `${run.distRight}px`;
|
|
29947
31791
|
}
|
|
29948
31792
|
img.style.zIndex = "1";
|
|
31793
|
+
assertPmPositions(run, "inline image run");
|
|
29949
31794
|
if (run.pmStart != null) {
|
|
29950
31795
|
img.dataset.pmStart = String(run.pmStart);
|
|
29951
31796
|
}
|
|
@@ -29969,6 +31814,12 @@ const _DomPainter = class _DomPainter {
|
|
|
29969
31814
|
if (styleId) {
|
|
29970
31815
|
el.setAttribute("styleid", styleId);
|
|
29971
31816
|
}
|
|
31817
|
+
const alignment = block.attrs?.alignment;
|
|
31818
|
+
if (alignment === "center" || alignment === "right" || alignment === "justify") {
|
|
31819
|
+
el.style.textAlign = alignment === "justify" ? "justify" : alignment;
|
|
31820
|
+
} else {
|
|
31821
|
+
el.style.textAlign = "left";
|
|
31822
|
+
}
|
|
29972
31823
|
const lineRange = computeLinePmRange(block, line);
|
|
29973
31824
|
if (lineRange.pmStart != null) {
|
|
29974
31825
|
el.dataset.pmStart = String(lineRange.pmStart);
|
|
@@ -29976,9 +31827,9 @@ const _DomPainter = class _DomPainter {
|
|
|
29976
31827
|
if (lineRange.pmEnd != null) {
|
|
29977
31828
|
el.dataset.pmEnd = String(lineRange.pmEnd);
|
|
29978
31829
|
}
|
|
29979
|
-
const
|
|
31830
|
+
const runsForLine = sliceRunsForLine(block, line);
|
|
29980
31831
|
const trackedConfig = this.resolveTrackedChangesConfig(block);
|
|
29981
|
-
if (
|
|
31832
|
+
if (runsForLine.length === 0) {
|
|
29982
31833
|
const span = this.doc.createElement("span");
|
|
29983
31834
|
span.innerHTML = " ";
|
|
29984
31835
|
el.appendChild(span);
|
|
@@ -30026,49 +31877,115 @@ const _DomPainter = class _DomPainter {
|
|
|
30026
31877
|
const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
|
|
30027
31878
|
if (hasExplicitPositioning && line.segments) {
|
|
30028
31879
|
let cumulativeX = 0;
|
|
30029
|
-
|
|
30030
|
-
|
|
30031
|
-
|
|
30032
|
-
if (
|
|
30033
|
-
|
|
30034
|
-
|
|
30035
|
-
|
|
30036
|
-
|
|
30037
|
-
|
|
30038
|
-
|
|
31880
|
+
const segmentsByRun = /* @__PURE__ */ new Map();
|
|
31881
|
+
line.segments.forEach((segment) => {
|
|
31882
|
+
const list = segmentsByRun.get(segment.runIndex);
|
|
31883
|
+
if (list) {
|
|
31884
|
+
list.push(segment);
|
|
31885
|
+
} else {
|
|
31886
|
+
segmentsByRun.set(segment.runIndex, [segment]);
|
|
31887
|
+
}
|
|
31888
|
+
});
|
|
31889
|
+
const findImmediateNextSegmentX = (fromRunIndex) => {
|
|
31890
|
+
const nextRunIdx = fromRunIndex + 1;
|
|
31891
|
+
if (nextRunIdx <= line.toRun) {
|
|
31892
|
+
const nextSegments = segmentsByRun.get(nextRunIdx);
|
|
31893
|
+
if (nextSegments && nextSegments.length > 0) {
|
|
31894
|
+
const firstSegment = nextSegments[0];
|
|
31895
|
+
return firstSegment.x;
|
|
30039
31896
|
}
|
|
30040
|
-
return;
|
|
30041
31897
|
}
|
|
30042
|
-
|
|
30043
|
-
|
|
30044
|
-
|
|
30045
|
-
|
|
31898
|
+
return void 0;
|
|
31899
|
+
};
|
|
31900
|
+
for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
|
|
31901
|
+
const baseRun = block.runs[runIndex];
|
|
31902
|
+
if (!baseRun) continue;
|
|
31903
|
+
if (baseRun.kind === "tab") {
|
|
31904
|
+
const immediateNextX = findImmediateNextSegmentX(runIndex);
|
|
31905
|
+
const tabStartX = cumulativeX;
|
|
31906
|
+
const tabEndX = immediateNextX !== void 0 ? immediateNextX : tabStartX + (baseRun.width ?? 0);
|
|
31907
|
+
const actualTabWidth = tabEndX - tabStartX;
|
|
31908
|
+
const tabEl = this.doc.createElement("span");
|
|
31909
|
+
tabEl.style.position = "absolute";
|
|
31910
|
+
tabEl.style.left = `${tabStartX}px`;
|
|
31911
|
+
tabEl.style.top = "0px";
|
|
31912
|
+
tabEl.style.width = `${actualTabWidth}px`;
|
|
31913
|
+
tabEl.style.height = `${line.lineHeight}px`;
|
|
31914
|
+
tabEl.style.display = "inline-block";
|
|
31915
|
+
tabEl.style.visibility = "hidden";
|
|
31916
|
+
tabEl.style.pointerEvents = "none";
|
|
31917
|
+
tabEl.style.zIndex = "1";
|
|
30046
31918
|
if (styleId) {
|
|
30047
|
-
|
|
31919
|
+
tabEl.setAttribute("styleid", styleId);
|
|
30048
31920
|
}
|
|
30049
|
-
|
|
30050
|
-
if (
|
|
30051
|
-
|
|
30052
|
-
|
|
30053
|
-
|
|
31921
|
+
if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
|
|
31922
|
+
if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
|
|
31923
|
+
el.appendChild(tabEl);
|
|
31924
|
+
cumulativeX = tabEndX;
|
|
31925
|
+
continue;
|
|
31926
|
+
}
|
|
31927
|
+
if (this.isImageRun(baseRun)) {
|
|
31928
|
+
const elem = this.renderRun(baseRun, context, trackedConfig);
|
|
31929
|
+
if (elem) {
|
|
31930
|
+
if (styleId) {
|
|
31931
|
+
elem.setAttribute("styleid", styleId);
|
|
31932
|
+
}
|
|
31933
|
+
el.appendChild(elem);
|
|
30054
31934
|
}
|
|
30055
|
-
|
|
30056
|
-
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
30064
|
-
|
|
30065
|
-
|
|
31935
|
+
continue;
|
|
31936
|
+
}
|
|
31937
|
+
if (this.isLineBreakRun(baseRun)) {
|
|
31938
|
+
continue;
|
|
31939
|
+
}
|
|
31940
|
+
if (this.isBreakRun(baseRun)) {
|
|
31941
|
+
continue;
|
|
31942
|
+
}
|
|
31943
|
+
const runSegments = segmentsByRun.get(runIndex);
|
|
31944
|
+
if (!runSegments || runSegments.length === 0) {
|
|
31945
|
+
continue;
|
|
31946
|
+
}
|
|
31947
|
+
if (!("text" in baseRun)) {
|
|
31948
|
+
continue;
|
|
31949
|
+
}
|
|
31950
|
+
const baseText = baseRun.text ?? "";
|
|
31951
|
+
const runPmStart = baseRun.pmStart ?? null;
|
|
31952
|
+
const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
|
|
31953
|
+
runSegments.forEach((segment) => {
|
|
31954
|
+
const segmentText = baseText.slice(segment.fromChar, segment.toChar);
|
|
31955
|
+
if (!segmentText) return;
|
|
31956
|
+
const pmSliceStart = runPmStart != null ? runPmStart + segment.fromChar : void 0;
|
|
31957
|
+
const pmSliceEnd = runPmStart != null ? runPmStart + segment.toChar : fallbackPmEnd ?? void 0;
|
|
31958
|
+
const segmentRun = {
|
|
31959
|
+
...baseRun,
|
|
31960
|
+
text: segmentText,
|
|
31961
|
+
pmStart: pmSliceStart,
|
|
31962
|
+
pmEnd: pmSliceEnd
|
|
31963
|
+
};
|
|
31964
|
+
const elem = this.renderRun(segmentRun, context, trackedConfig);
|
|
31965
|
+
if (elem) {
|
|
31966
|
+
if (styleId) {
|
|
31967
|
+
elem.setAttribute("styleid", styleId);
|
|
31968
|
+
}
|
|
31969
|
+
const xPos = segment.x !== void 0 ? segment.x : cumulativeX;
|
|
31970
|
+
elem.style.position = "absolute";
|
|
31971
|
+
elem.style.left = `${xPos}px`;
|
|
31972
|
+
el.appendChild(elem);
|
|
31973
|
+
let width = segment.width ?? 0;
|
|
31974
|
+
if (width <= 0 && this.doc) {
|
|
31975
|
+
const measureEl = elem.cloneNode(true);
|
|
31976
|
+
measureEl.style.position = "absolute";
|
|
31977
|
+
measureEl.style.visibility = "hidden";
|
|
31978
|
+
measureEl.style.left = "-9999px";
|
|
31979
|
+
this.doc.body.appendChild(measureEl);
|
|
31980
|
+
width = measureEl.offsetWidth;
|
|
31981
|
+
this.doc.body.removeChild(measureEl);
|
|
31982
|
+
}
|
|
30066
31983
|
cumulativeX = xPos + width;
|
|
30067
31984
|
}
|
|
30068
|
-
}
|
|
30069
|
-
}
|
|
31985
|
+
});
|
|
31986
|
+
}
|
|
30070
31987
|
} else {
|
|
30071
|
-
|
|
31988
|
+
runsForLine.forEach((run) => {
|
|
30072
31989
|
const elem = this.renderRun(run, context, trackedConfig);
|
|
30073
31990
|
if (elem) {
|
|
30074
31991
|
if (styleId) {
|
|
@@ -30126,8 +32043,18 @@ const _DomPainter = class _DomPainter {
|
|
|
30126
32043
|
elem.dataset.trackChangeDate = meta.date;
|
|
30127
32044
|
}
|
|
30128
32045
|
}
|
|
30129
|
-
|
|
30130
|
-
|
|
32046
|
+
/**
|
|
32047
|
+
* Updates an existing fragment element's position and dimensions in place.
|
|
32048
|
+
* Used during incremental updates to efficiently reposition fragments without full re-render.
|
|
32049
|
+
*
|
|
32050
|
+
* @param el - The HTMLElement representing the fragment to update
|
|
32051
|
+
* @param fragment - The fragment data containing updated position and dimensions
|
|
32052
|
+
* @param section - The document section ('body', 'header', 'footer') containing this fragment.
|
|
32053
|
+
* Affects PM position validation - only body sections validate PM positions.
|
|
32054
|
+
* If undefined, defaults to 'body' section behavior.
|
|
32055
|
+
*/
|
|
32056
|
+
updateFragmentElement(el, fragment, section) {
|
|
32057
|
+
this.applyFragmentFrame(el, fragment, section);
|
|
30131
32058
|
if (fragment.kind === "image") {
|
|
30132
32059
|
el.style.height = `${fragment.height}px`;
|
|
30133
32060
|
}
|
|
@@ -30135,12 +32062,27 @@ const _DomPainter = class _DomPainter {
|
|
|
30135
32062
|
el.style.height = `${fragment.height}px`;
|
|
30136
32063
|
}
|
|
30137
32064
|
}
|
|
30138
|
-
|
|
32065
|
+
/**
|
|
32066
|
+
* Applies fragment positioning, dimensions, and metadata to an HTML element.
|
|
32067
|
+
* Sets CSS positioning, block ID, and PM position data attributes for paragraph fragments.
|
|
32068
|
+
*
|
|
32069
|
+
* @param el - The HTMLElement to apply fragment properties to
|
|
32070
|
+
* @param fragment - The fragment data containing position, dimensions, and PM position information
|
|
32071
|
+
* @param section - The document section ('body', 'header', 'footer') containing this fragment.
|
|
32072
|
+
* Controls PM position validation behavior:
|
|
32073
|
+
* - 'body' or undefined: PM positions are validated and required for paragraph fragments
|
|
32074
|
+
* - 'header' or 'footer': PM position validation is skipped (these sections have separate PM coordinate spaces)
|
|
32075
|
+
* When undefined, defaults to 'body' section behavior (validation enabled).
|
|
32076
|
+
*/
|
|
32077
|
+
applyFragmentFrame(el, fragment, section) {
|
|
30139
32078
|
el.style.left = `${fragment.x}px`;
|
|
30140
32079
|
el.style.top = `${fragment.y}px`;
|
|
30141
32080
|
el.style.width = `${fragment.width}px`;
|
|
30142
32081
|
el.dataset.blockId = fragment.blockId;
|
|
30143
32082
|
if (fragment.kind === "para") {
|
|
32083
|
+
if (section === "body" || section === void 0) {
|
|
32084
|
+
assertFragmentPmPositions(fragment, "paragraph fragment");
|
|
32085
|
+
}
|
|
30144
32086
|
if (fragment.pmStart != null) {
|
|
30145
32087
|
el.dataset.pmStart = String(fragment.pmStart);
|
|
30146
32088
|
} else {
|
|
@@ -30323,7 +32265,12 @@ const fragmentKey = (fragment) => {
|
|
|
30323
32265
|
if (fragment.kind === "drawing") {
|
|
30324
32266
|
return `drawing:${fragment.blockId}:${fragment.x}:${fragment.y}`;
|
|
30325
32267
|
}
|
|
30326
|
-
|
|
32268
|
+
if (fragment.kind === "table") {
|
|
32269
|
+
const partialKey = fragment.partialRow ? `:${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}` : "";
|
|
32270
|
+
return `table:${fragment.blockId}:${fragment.fromRow}:${fragment.toRow}${partialKey}`;
|
|
32271
|
+
}
|
|
32272
|
+
const _exhaustiveCheck = fragment;
|
|
32273
|
+
return _exhaustiveCheck;
|
|
30327
32274
|
};
|
|
30328
32275
|
const fragmentSignature = (fragment, lookup) => {
|
|
30329
32276
|
const base2 = lookup.get(fragment.blockId)?.version ?? "missing";
|
|
@@ -30365,6 +32312,20 @@ const fragmentSignature = (fragment, lookup) => {
|
|
|
30365
32312
|
fragment.zIndex ?? ""
|
|
30366
32313
|
].join("|");
|
|
30367
32314
|
}
|
|
32315
|
+
if (fragment.kind === "table") {
|
|
32316
|
+
const partialSig = fragment.partialRow ? `${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}-${fragment.partialRow.partialHeight}` : "";
|
|
32317
|
+
return [
|
|
32318
|
+
base2,
|
|
32319
|
+
fragment.fromRow,
|
|
32320
|
+
fragment.toRow,
|
|
32321
|
+
fragment.width,
|
|
32322
|
+
fragment.height,
|
|
32323
|
+
fragment.continuesFromPrev ? 1 : 0,
|
|
32324
|
+
fragment.continuesOnNext ? 1 : 0,
|
|
32325
|
+
fragment.repeatHeaderCount ?? 0,
|
|
32326
|
+
partialSig
|
|
32327
|
+
].join("|");
|
|
32328
|
+
}
|
|
30368
32329
|
return base2;
|
|
30369
32330
|
};
|
|
30370
32331
|
const deriveBlockVersion = (block) => {
|
|
@@ -30387,22 +32348,29 @@ const deriveBlockVersion = (block) => {
|
|
|
30387
32348
|
imgRun.pmEnd ?? ""
|
|
30388
32349
|
].join(",");
|
|
30389
32350
|
}
|
|
32351
|
+
if (run.kind === "lineBreak") {
|
|
32352
|
+
return ["linebreak", run.pmStart ?? "", run.pmEnd ?? ""].join(",");
|
|
32353
|
+
}
|
|
32354
|
+
if (run.kind === "tab") {
|
|
32355
|
+
return [run.text ?? "", "tab", run.pmStart ?? "", run.pmEnd ?? ""].join(",");
|
|
32356
|
+
}
|
|
32357
|
+
const textRun = run;
|
|
30390
32358
|
return [
|
|
30391
|
-
|
|
30392
|
-
|
|
30393
|
-
|
|
30394
|
-
|
|
30395
|
-
|
|
30396
|
-
|
|
32359
|
+
textRun.text ?? "",
|
|
32360
|
+
textRun.fontFamily,
|
|
32361
|
+
textRun.fontSize,
|
|
32362
|
+
textRun.bold ? 1 : 0,
|
|
32363
|
+
textRun.italic ? 1 : 0,
|
|
32364
|
+
textRun.color ?? "",
|
|
30397
32365
|
// Text decorations - ensures DOM updates when decoration properties change.
|
|
30398
|
-
|
|
30399
|
-
|
|
30400
|
-
|
|
30401
|
-
|
|
30402
|
-
|
|
30403
|
-
|
|
30404
|
-
|
|
30405
|
-
|
|
32366
|
+
textRun.underline?.style ?? "",
|
|
32367
|
+
textRun.underline?.color ?? "",
|
|
32368
|
+
textRun.strike ? 1 : 0,
|
|
32369
|
+
textRun.highlight ?? "",
|
|
32370
|
+
textRun.letterSpacing != null ? textRun.letterSpacing : "",
|
|
32371
|
+
textRun.pmStart ?? "",
|
|
32372
|
+
textRun.pmEnd ?? "",
|
|
32373
|
+
textRun.token ?? ""
|
|
30406
32374
|
].join(",");
|
|
30407
32375
|
}).join("|");
|
|
30408
32376
|
}
|
|
@@ -30453,16 +32421,57 @@ const deriveBlockVersion = (block) => {
|
|
|
30453
32421
|
}
|
|
30454
32422
|
if (block.kind === "table") {
|
|
30455
32423
|
const tableBlock = block;
|
|
30456
|
-
|
|
30457
|
-
|
|
30458
|
-
|
|
30459
|
-
|
|
30460
|
-
|
|
32424
|
+
const hashString = (seed, value) => {
|
|
32425
|
+
let hash22 = seed >>> 0;
|
|
32426
|
+
for (let i = 0; i < value.length; i++) {
|
|
32427
|
+
hash22 ^= value.charCodeAt(i);
|
|
32428
|
+
hash22 = Math.imul(hash22, 16777619);
|
|
32429
|
+
}
|
|
32430
|
+
return hash22 >>> 0;
|
|
32431
|
+
};
|
|
32432
|
+
const hashNumber = (seed, value) => {
|
|
32433
|
+
const n = Number.isFinite(value) ? value : 0;
|
|
32434
|
+
let hash22 = seed ^ n;
|
|
32435
|
+
hash22 = Math.imul(hash22, 16777619);
|
|
32436
|
+
hash22 ^= hash22 >>> 13;
|
|
32437
|
+
return hash22 >>> 0;
|
|
32438
|
+
};
|
|
32439
|
+
let hash2 = 2166136261;
|
|
32440
|
+
hash2 = hashString(hash2, block.id);
|
|
32441
|
+
hash2 = hashNumber(hash2, tableBlock.rows.length);
|
|
32442
|
+
hash2 = (tableBlock.columnWidths ?? []).reduce((acc, width) => hashNumber(acc, Math.round(width * 1e3)), hash2);
|
|
32443
|
+
const rows = tableBlock.rows ?? [];
|
|
32444
|
+
for (const row of rows) {
|
|
32445
|
+
if (!row || !Array.isArray(row.cells)) continue;
|
|
32446
|
+
hash2 = hashNumber(hash2, row.cells.length);
|
|
32447
|
+
for (const cell of row.cells) {
|
|
32448
|
+
if (!cell) continue;
|
|
32449
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
32450
|
+
hash2 = hashNumber(hash2, cellBlocks.length);
|
|
32451
|
+
hash2 = hashNumber(hash2, cell.rowSpan ?? 1);
|
|
32452
|
+
hash2 = hashNumber(hash2, cell.colSpan ?? 1);
|
|
32453
|
+
for (const cellBlock of cellBlocks) {
|
|
32454
|
+
hash2 = hashString(hash2, cellBlock?.kind ?? "unknown");
|
|
32455
|
+
if (cellBlock?.kind === "paragraph") {
|
|
32456
|
+
const runs = cellBlock.runs ?? [];
|
|
32457
|
+
hash2 = hashNumber(hash2, runs.length);
|
|
32458
|
+
for (const run of runs) {
|
|
32459
|
+
if ("text" in run && typeof run.text === "string") {
|
|
32460
|
+
hash2 = hashString(hash2, run.text);
|
|
32461
|
+
}
|
|
32462
|
+
hash2 = hashNumber(hash2, run.pmStart ?? -1);
|
|
32463
|
+
hash2 = hashNumber(hash2, run.pmEnd ?? -1);
|
|
32464
|
+
}
|
|
32465
|
+
}
|
|
32466
|
+
}
|
|
32467
|
+
}
|
|
32468
|
+
}
|
|
32469
|
+
return [block.id, tableBlock.rows.length, hash2.toString(16)].join("|");
|
|
30461
32470
|
}
|
|
30462
32471
|
return block.id;
|
|
30463
32472
|
};
|
|
30464
32473
|
const applyRunStyles = (element, run, isLink = false) => {
|
|
30465
|
-
if (run.kind === "tab" || run.kind === "image") {
|
|
32474
|
+
if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak" || run.kind === "break") {
|
|
30466
32475
|
return;
|
|
30467
32476
|
}
|
|
30468
32477
|
element.style.fontFamily = run.fontFamily;
|
|
@@ -30494,6 +32503,13 @@ const applyRunStyles = (element, run, isLink = false) => {
|
|
|
30494
32503
|
element.style.textDecorationLine = decorations.join(" ");
|
|
30495
32504
|
}
|
|
30496
32505
|
};
|
|
32506
|
+
const getCommentHighlight = (run) => {
|
|
32507
|
+
const comments = run.comments;
|
|
32508
|
+
if (!comments || comments.length === 0) return void 0;
|
|
32509
|
+
const primary = comments[0];
|
|
32510
|
+
const base2 = primary.internal ? COMMENT_INTERNAL_COLOR : COMMENT_EXTERNAL_COLOR;
|
|
32511
|
+
return `${base2}${COMMENT_INACTIVE_ALPHA}`;
|
|
32512
|
+
};
|
|
30497
32513
|
const applyRunDataAttributes = (element, dataAttrs) => {
|
|
30498
32514
|
if (!dataAttrs) return;
|
|
30499
32515
|
Object.entries(dataAttrs).forEach(([key2, value]) => {
|
|
@@ -30585,6 +32601,21 @@ const sliceRunsForLine = (block, line) => {
|
|
|
30585
32601
|
result.push(run);
|
|
30586
32602
|
continue;
|
|
30587
32603
|
}
|
|
32604
|
+
if (run.kind === "lineBreak") {
|
|
32605
|
+
result.push(run);
|
|
32606
|
+
continue;
|
|
32607
|
+
}
|
|
32608
|
+
if (run.kind === "break") {
|
|
32609
|
+
result.push(run);
|
|
32610
|
+
continue;
|
|
32611
|
+
}
|
|
32612
|
+
if (run.kind === "tab") {
|
|
32613
|
+
result.push(run);
|
|
32614
|
+
continue;
|
|
32615
|
+
}
|
|
32616
|
+
if (!("text" in run)) {
|
|
32617
|
+
continue;
|
|
32618
|
+
}
|
|
30588
32619
|
const text = run.text ?? "";
|
|
30589
32620
|
const isFirstRun = runIndex === line.fromRun;
|
|
30590
32621
|
const isLastRun = runIndex === line.toRun;
|
|
@@ -30598,19 +32629,14 @@ const sliceRunsForLine = (block, line) => {
|
|
|
30598
32629
|
if (!slice2) continue;
|
|
30599
32630
|
const pmSliceStart = runPmStart != null ? runPmStart + start2 : void 0;
|
|
30600
32631
|
const pmSliceEnd = runPmStart != null ? runPmStart + end2 : fallbackPmEnd ?? void 0;
|
|
30601
|
-
|
|
30602
|
-
|
|
30603
|
-
|
|
30604
|
-
|
|
30605
|
-
|
|
30606
|
-
|
|
30607
|
-
|
|
30608
|
-
|
|
30609
|
-
pmStart: pmSliceStart,
|
|
30610
|
-
pmEnd: pmSliceEnd
|
|
30611
|
-
};
|
|
30612
|
-
result.push(sliced);
|
|
30613
|
-
}
|
|
32632
|
+
const sliced = {
|
|
32633
|
+
...run,
|
|
32634
|
+
text: slice2,
|
|
32635
|
+
pmStart: pmSliceStart,
|
|
32636
|
+
pmEnd: pmSliceEnd,
|
|
32637
|
+
comments: run.comments ? [...run.comments] : void 0
|
|
32638
|
+
};
|
|
32639
|
+
result.push(sliced);
|
|
30614
32640
|
} else {
|
|
30615
32641
|
result.push(run);
|
|
30616
32642
|
}
|
|
@@ -30638,6 +32664,54 @@ const computeLinePmRange = (block, line) => {
|
|
|
30638
32664
|
}
|
|
30639
32665
|
continue;
|
|
30640
32666
|
}
|
|
32667
|
+
if (run.kind === "lineBreak") {
|
|
32668
|
+
const runPmStart2 = run.pmStart ?? null;
|
|
32669
|
+
const runPmEnd = run.pmEnd ?? null;
|
|
32670
|
+
if (runPmStart2 == null || runPmEnd == null) {
|
|
32671
|
+
continue;
|
|
32672
|
+
}
|
|
32673
|
+
if (pmStart == null) {
|
|
32674
|
+
pmStart = runPmStart2;
|
|
32675
|
+
}
|
|
32676
|
+
pmEnd = runPmEnd;
|
|
32677
|
+
if (runIndex === line.toRun) {
|
|
32678
|
+
break;
|
|
32679
|
+
}
|
|
32680
|
+
continue;
|
|
32681
|
+
}
|
|
32682
|
+
if (run.kind === "break") {
|
|
32683
|
+
const runPmStart2 = run.pmStart ?? null;
|
|
32684
|
+
const runPmEnd = run.pmEnd ?? null;
|
|
32685
|
+
if (runPmStart2 == null || runPmEnd == null) {
|
|
32686
|
+
continue;
|
|
32687
|
+
}
|
|
32688
|
+
if (pmStart == null) {
|
|
32689
|
+
pmStart = runPmStart2;
|
|
32690
|
+
}
|
|
32691
|
+
pmEnd = runPmEnd;
|
|
32692
|
+
if (runIndex === line.toRun) {
|
|
32693
|
+
break;
|
|
32694
|
+
}
|
|
32695
|
+
continue;
|
|
32696
|
+
}
|
|
32697
|
+
if (run.kind === "tab") {
|
|
32698
|
+
const runPmStart2 = run.pmStart ?? null;
|
|
32699
|
+
const runPmEnd = run.pmEnd ?? null;
|
|
32700
|
+
if (runPmStart2 == null || runPmEnd == null) {
|
|
32701
|
+
continue;
|
|
32702
|
+
}
|
|
32703
|
+
if (pmStart == null) {
|
|
32704
|
+
pmStart = runPmStart2;
|
|
32705
|
+
}
|
|
32706
|
+
pmEnd = runPmEnd;
|
|
32707
|
+
if (runIndex === line.toRun) {
|
|
32708
|
+
break;
|
|
32709
|
+
}
|
|
32710
|
+
continue;
|
|
32711
|
+
}
|
|
32712
|
+
if (!("text" in run)) {
|
|
32713
|
+
continue;
|
|
32714
|
+
}
|
|
30641
32715
|
const text = run.text ?? "";
|
|
30642
32716
|
const runLength = text.length;
|
|
30643
32717
|
const runPmStart = run.pmStart ?? null;
|
|
@@ -30676,6 +32750,15 @@ const resolveRunText = (run, context) => {
|
|
|
30676
32750
|
if (run.kind === "image") {
|
|
30677
32751
|
return "";
|
|
30678
32752
|
}
|
|
32753
|
+
if (run.kind === "lineBreak") {
|
|
32754
|
+
return "";
|
|
32755
|
+
}
|
|
32756
|
+
if (run.kind === "break") {
|
|
32757
|
+
return "";
|
|
32758
|
+
}
|
|
32759
|
+
if (!("text" in run)) {
|
|
32760
|
+
return "";
|
|
32761
|
+
}
|
|
30679
32762
|
if (!runToken) {
|
|
30680
32763
|
return run.text ?? "";
|
|
30681
32764
|
}
|
|
@@ -30842,6 +32925,9 @@ function isTabRun(run) {
|
|
|
30842
32925
|
function isImageRun(run) {
|
|
30843
32926
|
return run.kind === "image";
|
|
30844
32927
|
}
|
|
32928
|
+
function isLineBreakRun(run) {
|
|
32929
|
+
return run.kind === "lineBreak";
|
|
32930
|
+
}
|
|
30845
32931
|
async function measureBlock(block, constraints) {
|
|
30846
32932
|
const normalized = normalizeConstraints(constraints);
|
|
30847
32933
|
if (block.kind === "drawing") {
|
|
@@ -30870,6 +32956,7 @@ async function measureBlock(block, constraints) {
|
|
|
30870
32956
|
async function measureParagraphBlock(block, maxWidth) {
|
|
30871
32957
|
const ctx2 = getCanvasContext();
|
|
30872
32958
|
const wordLayout = block.attrs?.wordLayout;
|
|
32959
|
+
const WIDTH_FUDGE_PX = 0.5;
|
|
30873
32960
|
const lines = [];
|
|
30874
32961
|
const indent = block.attrs?.indent;
|
|
30875
32962
|
const spacing = block.attrs?.spacing;
|
|
@@ -30879,7 +32966,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30879
32966
|
const hanging = indent?.hanging ?? 0;
|
|
30880
32967
|
const firstLineOffset = firstLine - hanging;
|
|
30881
32968
|
const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
|
|
30882
|
-
|
|
32969
|
+
const initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
|
|
30883
32970
|
const tabStops = buildTabStopsPx(
|
|
30884
32971
|
indent,
|
|
30885
32972
|
block.attrs?.tabs,
|
|
@@ -30892,6 +32979,18 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30892
32979
|
line.bars = barTabStops.map((stop) => ({ x: stop.pos }));
|
|
30893
32980
|
}
|
|
30894
32981
|
};
|
|
32982
|
+
const dropCapDescriptor = block.attrs?.dropCapDescriptor;
|
|
32983
|
+
let dropCapMeasure = null;
|
|
32984
|
+
if (dropCapDescriptor) {
|
|
32985
|
+
if (!dropCapDescriptor.run || !dropCapDescriptor.run.text || !dropCapDescriptor.lines) {
|
|
32986
|
+
console.warn("Invalid drop cap descriptor - missing required fields:", dropCapDescriptor);
|
|
32987
|
+
} else {
|
|
32988
|
+
const dropCapMeasured = measureDropCap(ctx2, dropCapDescriptor, spacing);
|
|
32989
|
+
dropCapMeasure = dropCapMeasured;
|
|
32990
|
+
dropCapDescriptor.measuredWidth = dropCapMeasured.width;
|
|
32991
|
+
dropCapDescriptor.measuredHeight = dropCapMeasured.height;
|
|
32992
|
+
}
|
|
32993
|
+
}
|
|
30895
32994
|
if (block.runs.length === 0) {
|
|
30896
32995
|
const metrics = calculateTypographyMetrics(12, spacing);
|
|
30897
32996
|
const emptyLine = {
|
|
@@ -30911,6 +33010,13 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30911
33010
|
};
|
|
30912
33011
|
}
|
|
30913
33012
|
let currentLine = null;
|
|
33013
|
+
const getEffectiveWidth = (baseWidth) => {
|
|
33014
|
+
if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
|
|
33015
|
+
return Math.max(1, baseWidth - dropCapMeasure.width);
|
|
33016
|
+
}
|
|
33017
|
+
return baseWidth;
|
|
33018
|
+
};
|
|
33019
|
+
let lastFontSize = 12;
|
|
30914
33020
|
let tabStopCursor = 0;
|
|
30915
33021
|
let pendingTabAlignment = null;
|
|
30916
33022
|
let lastAppliedTabAlign = null;
|
|
@@ -30945,8 +33051,108 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30945
33051
|
lastAppliedTabAlign = { target, val };
|
|
30946
33052
|
pendingTabAlignment = null;
|
|
30947
33053
|
};
|
|
30948
|
-
|
|
30949
|
-
|
|
33054
|
+
const runsToProcess = [];
|
|
33055
|
+
for (const run of block.runs) {
|
|
33056
|
+
if (run.text && typeof run.text === "string" && run.text.includes("\n")) {
|
|
33057
|
+
const textRun = run;
|
|
33058
|
+
const segments = textRun.text.split("\n");
|
|
33059
|
+
let cursor = textRun.pmStart ?? 0;
|
|
33060
|
+
segments.forEach((seg, idx) => {
|
|
33061
|
+
runsToProcess.push({
|
|
33062
|
+
...textRun,
|
|
33063
|
+
text: seg,
|
|
33064
|
+
pmStart: cursor,
|
|
33065
|
+
pmEnd: cursor + seg.length
|
|
33066
|
+
});
|
|
33067
|
+
cursor += seg.length;
|
|
33068
|
+
if (idx !== segments.length - 1) {
|
|
33069
|
+
runsToProcess.push({
|
|
33070
|
+
kind: "break",
|
|
33071
|
+
breakType: "line",
|
|
33072
|
+
pmStart: cursor,
|
|
33073
|
+
pmEnd: cursor + 1,
|
|
33074
|
+
sdt: run.sdt
|
|
33075
|
+
});
|
|
33076
|
+
cursor += 1;
|
|
33077
|
+
}
|
|
33078
|
+
});
|
|
33079
|
+
} else {
|
|
33080
|
+
runsToProcess.push(run);
|
|
33081
|
+
}
|
|
33082
|
+
}
|
|
33083
|
+
for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
|
|
33084
|
+
const run = runsToProcess[runIndex];
|
|
33085
|
+
if (run.kind === "break") {
|
|
33086
|
+
if (currentLine) {
|
|
33087
|
+
const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
|
|
33088
|
+
const completedLine = { ...currentLine, ...metrics };
|
|
33089
|
+
addBarTabsToLine(completedLine);
|
|
33090
|
+
lines.push(completedLine);
|
|
33091
|
+
currentLine = null;
|
|
33092
|
+
} else {
|
|
33093
|
+
const textRunWithSize = block.runs.find(
|
|
33094
|
+
(r2) => r2.kind !== "tab" && r2.kind !== "lineBreak" && r2.kind !== "break" && !("src" in r2) && "fontSize" in r2
|
|
33095
|
+
);
|
|
33096
|
+
const fallbackSize = textRunWithSize?.fontSize ?? 12;
|
|
33097
|
+
const metrics = calculateTypographyMetrics(fallbackSize, spacing);
|
|
33098
|
+
const emptyLine = {
|
|
33099
|
+
fromRun: runIndex,
|
|
33100
|
+
fromChar: 0,
|
|
33101
|
+
toRun: runIndex,
|
|
33102
|
+
toChar: 0,
|
|
33103
|
+
width: 0,
|
|
33104
|
+
segments: [],
|
|
33105
|
+
...metrics
|
|
33106
|
+
};
|
|
33107
|
+
addBarTabsToLine(emptyLine);
|
|
33108
|
+
lines.push(emptyLine);
|
|
33109
|
+
}
|
|
33110
|
+
tabStopCursor = 0;
|
|
33111
|
+
pendingTabAlignment = null;
|
|
33112
|
+
lastAppliedTabAlign = null;
|
|
33113
|
+
continue;
|
|
33114
|
+
}
|
|
33115
|
+
if (isLineBreakRun(run)) {
|
|
33116
|
+
if (currentLine) {
|
|
33117
|
+
const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
|
|
33118
|
+
const completedLine = {
|
|
33119
|
+
...currentLine,
|
|
33120
|
+
...metrics
|
|
33121
|
+
};
|
|
33122
|
+
addBarTabsToLine(completedLine);
|
|
33123
|
+
lines.push(completedLine);
|
|
33124
|
+
} else {
|
|
33125
|
+
const metrics = calculateTypographyMetrics(lastFontSize, spacing);
|
|
33126
|
+
const emptyLine = {
|
|
33127
|
+
fromRun: runIndex,
|
|
33128
|
+
fromChar: 0,
|
|
33129
|
+
toRun: runIndex,
|
|
33130
|
+
toChar: 0,
|
|
33131
|
+
width: 0,
|
|
33132
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
33133
|
+
segments: [],
|
|
33134
|
+
...metrics
|
|
33135
|
+
};
|
|
33136
|
+
addBarTabsToLine(emptyLine);
|
|
33137
|
+
lines.push(emptyLine);
|
|
33138
|
+
}
|
|
33139
|
+
const hadPreviousLine = lines.length > 0;
|
|
33140
|
+
const nextLineMaxWidth = hadPreviousLine ? getEffectiveWidth(contentWidth) : getEffectiveWidth(initialAvailableWidth);
|
|
33141
|
+
currentLine = {
|
|
33142
|
+
fromRun: runIndex,
|
|
33143
|
+
fromChar: 0,
|
|
33144
|
+
toRun: runIndex,
|
|
33145
|
+
toChar: 0,
|
|
33146
|
+
width: 0,
|
|
33147
|
+
maxFontSize: lastFontSize,
|
|
33148
|
+
maxWidth: nextLineMaxWidth,
|
|
33149
|
+
segments: []
|
|
33150
|
+
};
|
|
33151
|
+
tabStopCursor = 0;
|
|
33152
|
+
pendingTabAlignment = null;
|
|
33153
|
+
lastAppliedTabAlign = null;
|
|
33154
|
+
continue;
|
|
33155
|
+
}
|
|
30950
33156
|
if (isTabRun(run)) {
|
|
30951
33157
|
if (!currentLine) {
|
|
30952
33158
|
currentLine = {
|
|
@@ -30957,7 +33163,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30957
33163
|
width: 0,
|
|
30958
33164
|
maxFontSize: 12,
|
|
30959
33165
|
// Default font size for tabs
|
|
30960
|
-
maxWidth:
|
|
33166
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
30961
33167
|
segments: []
|
|
30962
33168
|
};
|
|
30963
33169
|
}
|
|
@@ -31002,7 +33208,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31002
33208
|
width: imageWidth,
|
|
31003
33209
|
maxFontSize: imageHeight,
|
|
31004
33210
|
// Use image height for line height calculation
|
|
31005
|
-
maxWidth:
|
|
33211
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31006
33212
|
segments: [
|
|
31007
33213
|
{
|
|
31008
33214
|
runIndex,
|
|
@@ -31012,7 +33218,6 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31012
33218
|
}
|
|
31013
33219
|
]
|
|
31014
33220
|
};
|
|
31015
|
-
availableWidth = contentWidth;
|
|
31016
33221
|
continue;
|
|
31017
33222
|
}
|
|
31018
33223
|
if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
|
|
@@ -31032,7 +33237,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31032
33237
|
toChar: 1,
|
|
31033
33238
|
width: imageWidth,
|
|
31034
33239
|
maxFontSize: imageHeight,
|
|
31035
|
-
maxWidth: contentWidth,
|
|
33240
|
+
maxWidth: getEffectiveWidth(contentWidth),
|
|
31036
33241
|
segments: [
|
|
31037
33242
|
{
|
|
31038
33243
|
runIndex,
|
|
@@ -31042,7 +33247,6 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31042
33247
|
}
|
|
31043
33248
|
]
|
|
31044
33249
|
};
|
|
31045
|
-
availableWidth = contentWidth;
|
|
31046
33250
|
} else {
|
|
31047
33251
|
currentLine.toRun = runIndex;
|
|
31048
33252
|
currentLine.toChar = 1;
|
|
@@ -31058,6 +33262,10 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31058
33262
|
}
|
|
31059
33263
|
continue;
|
|
31060
33264
|
}
|
|
33265
|
+
if (!("text" in run) || !("fontSize" in run)) {
|
|
33266
|
+
continue;
|
|
33267
|
+
}
|
|
33268
|
+
lastFontSize = run.fontSize;
|
|
31061
33269
|
const { font } = buildFontString(run);
|
|
31062
33270
|
const tabSegments = run.text.split(" ");
|
|
31063
33271
|
let charPosInRun = 0;
|
|
@@ -31092,23 +33300,22 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31092
33300
|
toChar: wordEndNoSpace,
|
|
31093
33301
|
width: wordOnlyWidth,
|
|
31094
33302
|
maxFontSize: run.fontSize,
|
|
31095
|
-
maxWidth:
|
|
33303
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31096
33304
|
segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
|
|
31097
33305
|
};
|
|
31098
33306
|
const ls = run.letterSpacing ?? 0;
|
|
31099
|
-
if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
|
|
33307
|
+
if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
|
|
31100
33308
|
currentLine.toChar = wordEndWithSpace;
|
|
31101
33309
|
currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
|
|
31102
33310
|
charPosInRun = wordEndWithSpace;
|
|
31103
33311
|
} else {
|
|
31104
|
-
charPosInRun =
|
|
33312
|
+
charPosInRun = wordEndWithSpace;
|
|
31105
33313
|
}
|
|
31106
|
-
availableWidth = contentWidth;
|
|
31107
33314
|
continue;
|
|
31108
33315
|
}
|
|
31109
33316
|
const isTocEntry = block.attrs?.isTocEntry;
|
|
31110
33317
|
const boundarySpacing = currentLine.width > 0 ? run.letterSpacing ?? 0 : 0;
|
|
31111
|
-
if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth && currentLine.width > 0 && !isTocEntry) {
|
|
33318
|
+
if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
|
|
31112
33319
|
const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
|
|
31113
33320
|
const completedLine = {
|
|
31114
33321
|
...currentLine,
|
|
@@ -31125,19 +33332,19 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31125
33332
|
toChar: wordEndNoSpace,
|
|
31126
33333
|
width: wordOnlyWidth,
|
|
31127
33334
|
maxFontSize: run.fontSize,
|
|
31128
|
-
maxWidth: contentWidth,
|
|
33335
|
+
maxWidth: getEffectiveWidth(contentWidth),
|
|
31129
33336
|
segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
|
|
31130
33337
|
};
|
|
31131
|
-
if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
|
|
33338
|
+
if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
|
|
31132
33339
|
currentLine.toChar = wordEndWithSpace;
|
|
31133
33340
|
currentLine.width = roundValue(currentLine.width + spaceWidth + (run.letterSpacing ?? 0));
|
|
31134
33341
|
charPosInRun = wordEndWithSpace;
|
|
31135
33342
|
} else {
|
|
31136
|
-
charPosInRun =
|
|
33343
|
+
charPosInRun = wordEndWithSpace;
|
|
31137
33344
|
}
|
|
31138
33345
|
} else {
|
|
31139
33346
|
currentLine.toRun = runIndex;
|
|
31140
|
-
if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth) {
|
|
33347
|
+
if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX) {
|
|
31141
33348
|
currentLine.toChar = wordEndNoSpace;
|
|
31142
33349
|
currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
|
|
31143
33350
|
currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
|
|
@@ -31181,10 +33388,9 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31181
33388
|
toChar: charPosInRun,
|
|
31182
33389
|
width: 0,
|
|
31183
33390
|
maxFontSize: run.fontSize,
|
|
31184
|
-
maxWidth:
|
|
33391
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31185
33392
|
segments: []
|
|
31186
33393
|
};
|
|
31187
|
-
availableWidth = contentWidth;
|
|
31188
33394
|
}
|
|
31189
33395
|
const originX = currentLine.width;
|
|
31190
33396
|
const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
|
|
@@ -31257,12 +33463,41 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31257
33463
|
kind: "paragraph",
|
|
31258
33464
|
lines,
|
|
31259
33465
|
totalHeight,
|
|
31260
|
-
...markerInfo ? { marker: markerInfo } : {}
|
|
33466
|
+
...markerInfo ? { marker: markerInfo } : {},
|
|
33467
|
+
...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
|
|
31261
33468
|
};
|
|
31262
33469
|
}
|
|
31263
33470
|
async function measureTableBlock(block, constraints) {
|
|
31264
33471
|
const maxWidth = typeof constraints === "number" ? constraints : constraints.maxWidth;
|
|
31265
33472
|
let columnWidths;
|
|
33473
|
+
const scaleColumnWidths = (widths, targetWidth) => {
|
|
33474
|
+
const totalWidth2 = widths.reduce((a, b) => a + b, 0);
|
|
33475
|
+
if (totalWidth2 <= targetWidth || widths.length === 0) return widths;
|
|
33476
|
+
const scale = targetWidth / totalWidth2;
|
|
33477
|
+
const scaled = widths.map((w) => Math.max(1, Math.round(w * scale)));
|
|
33478
|
+
const sum = scaled.reduce((a, b) => a + b, 0);
|
|
33479
|
+
if (sum !== targetWidth) {
|
|
33480
|
+
const adjust = (delta) => {
|
|
33481
|
+
let idx = 0;
|
|
33482
|
+
const direction = delta > 0 ? 1 : -1;
|
|
33483
|
+
delta = Math.abs(delta);
|
|
33484
|
+
while (delta > 0 && scaled.length > 0) {
|
|
33485
|
+
const i = idx % scaled.length;
|
|
33486
|
+
if (direction > 0) {
|
|
33487
|
+
scaled[i] += 1;
|
|
33488
|
+
delta -= 1;
|
|
33489
|
+
} else if (scaled[i] > 1) {
|
|
33490
|
+
scaled[i] -= 1;
|
|
33491
|
+
delta -= 1;
|
|
33492
|
+
}
|
|
33493
|
+
idx += 1;
|
|
33494
|
+
if (idx > scaled.length * 2 && delta > 0) break;
|
|
33495
|
+
}
|
|
33496
|
+
};
|
|
33497
|
+
adjust(targetWidth - sum);
|
|
33498
|
+
}
|
|
33499
|
+
return scaled;
|
|
33500
|
+
};
|
|
31266
33501
|
const maxCellCount = Math.max(1, Math.max(...block.rows.map((r2) => r2.cells.length)));
|
|
31267
33502
|
if (block.columnWidths && block.columnWidths.length > 0) {
|
|
31268
33503
|
columnWidths = [...block.columnWidths];
|
|
@@ -31271,8 +33506,7 @@ async function measureTableBlock(block, constraints) {
|
|
|
31271
33506
|
if (hasExplicitWidth || hasFixedLayout) {
|
|
31272
33507
|
const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
|
|
31273
33508
|
if (totalWidth2 > maxWidth) {
|
|
31274
|
-
|
|
31275
|
-
columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
|
|
33509
|
+
columnWidths = scaleColumnWidths(columnWidths, maxWidth);
|
|
31276
33510
|
}
|
|
31277
33511
|
} else {
|
|
31278
33512
|
if (columnWidths.length < maxCellCount) {
|
|
@@ -31286,8 +33520,7 @@ async function measureTableBlock(block, constraints) {
|
|
|
31286
33520
|
}
|
|
31287
33521
|
const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
|
|
31288
33522
|
if (totalWidth2 > maxWidth) {
|
|
31289
|
-
|
|
31290
|
-
columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
|
|
33523
|
+
columnWidths = scaleColumnWidths(columnWidths, maxWidth);
|
|
31291
33524
|
}
|
|
31292
33525
|
}
|
|
31293
33526
|
} else {
|
|
@@ -31304,6 +33537,8 @@ async function measureTableBlock(block, constraints) {
|
|
|
31304
33537
|
};
|
|
31305
33538
|
const rowspanTracker = new Array(gridColumnCount).fill(0);
|
|
31306
33539
|
const rows = [];
|
|
33540
|
+
const rowBaseHeights = new Array(block.rows.length).fill(0);
|
|
33541
|
+
const spanConstraints = [];
|
|
31307
33542
|
for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
|
|
31308
33543
|
const row = block.rows[rowIndex];
|
|
31309
33544
|
const cellMeasures = [];
|
|
@@ -31350,6 +33585,11 @@ async function measureTableBlock(block, constraints) {
|
|
|
31350
33585
|
colSpan: colspan,
|
|
31351
33586
|
rowSpan: rowspan
|
|
31352
33587
|
});
|
|
33588
|
+
if (rowspan === 1) {
|
|
33589
|
+
rowBaseHeights[rowIndex] = Math.max(rowBaseHeights[rowIndex], totalCellHeight);
|
|
33590
|
+
} else {
|
|
33591
|
+
spanConstraints.push({ startRow: rowIndex, rowSpan: rowspan, requiredHeight: totalCellHeight });
|
|
33592
|
+
}
|
|
31353
33593
|
gridColIndex += colspan;
|
|
31354
33594
|
}
|
|
31355
33595
|
for (let col = gridColIndex; col < gridColumnCount; col++) {
|
|
@@ -31357,10 +33597,39 @@ async function measureTableBlock(block, constraints) {
|
|
|
31357
33597
|
rowspanTracker[col]--;
|
|
31358
33598
|
}
|
|
31359
33599
|
}
|
|
31360
|
-
|
|
31361
|
-
|
|
33600
|
+
rows.push({ cells: cellMeasures, height: 0 });
|
|
33601
|
+
}
|
|
33602
|
+
const rowHeights = [...rowBaseHeights];
|
|
33603
|
+
for (const constraint of spanConstraints) {
|
|
33604
|
+
const { startRow, rowSpan, requiredHeight } = constraint;
|
|
33605
|
+
if (rowSpan <= 0) continue;
|
|
33606
|
+
let currentHeight = 0;
|
|
33607
|
+
for (let i = 0; i < rowSpan && startRow + i < rowHeights.length; i++) {
|
|
33608
|
+
currentHeight += rowHeights[startRow + i];
|
|
33609
|
+
}
|
|
33610
|
+
if (currentHeight < requiredHeight) {
|
|
33611
|
+
const spanLength = Math.min(rowSpan, rowHeights.length - startRow);
|
|
33612
|
+
const increment = spanLength > 0 ? (requiredHeight - currentHeight) / spanLength : 0;
|
|
33613
|
+
for (let i = 0; i < spanLength; i++) {
|
|
33614
|
+
rowHeights[startRow + i] += increment;
|
|
33615
|
+
}
|
|
33616
|
+
}
|
|
31362
33617
|
}
|
|
31363
|
-
|
|
33618
|
+
block.rows.forEach((row, index2) => {
|
|
33619
|
+
const spec = row.attrs?.rowHeight;
|
|
33620
|
+
if (spec?.value != null && Number.isFinite(spec.value)) {
|
|
33621
|
+
const rule = spec.rule ?? "atLeast";
|
|
33622
|
+
if (rule === "exact") {
|
|
33623
|
+
rowHeights[index2] = spec.value;
|
|
33624
|
+
} else {
|
|
33625
|
+
rowHeights[index2] = Math.max(rowHeights[index2], spec.value);
|
|
33626
|
+
}
|
|
33627
|
+
}
|
|
33628
|
+
});
|
|
33629
|
+
for (let i = 0; i < rows.length; i++) {
|
|
33630
|
+
rows[i].height = Math.max(0, rowHeights[i]);
|
|
33631
|
+
}
|
|
33632
|
+
const totalHeight = rowHeights.reduce((sum, h) => sum + h, 0);
|
|
31364
33633
|
const totalWidth = columnWidths.reduce((a, b) => a + b, 0);
|
|
31365
33634
|
return {
|
|
31366
33635
|
kind: "table",
|
|
@@ -31537,7 +33806,7 @@ const getPrimaryRun = (paragraph) => {
|
|
|
31537
33806
|
};
|
|
31538
33807
|
};
|
|
31539
33808
|
const measureRunWidth = (text, font, ctx2, run) => {
|
|
31540
|
-
const letterSpacing = run.kind === "text" ? run.letterSpacing || 0 : 0;
|
|
33809
|
+
const letterSpacing = run.kind === "text" || run.kind === void 0 ? run.letterSpacing || 0 : 0;
|
|
31541
33810
|
const width = getMeasuredTextWidth(text, font, letterSpacing, ctx2);
|
|
31542
33811
|
return roundValue(width);
|
|
31543
33812
|
};
|
|
@@ -31566,13 +33835,37 @@ const resolveLineHeight = (spacing, baseLineHeight) => {
|
|
|
31566
33835
|
if (spacing.lineRule === "atLeast") {
|
|
31567
33836
|
return Math.max(baseLineHeight, raw);
|
|
31568
33837
|
}
|
|
31569
|
-
return raw;
|
|
33838
|
+
return Math.max(baseLineHeight, raw);
|
|
31570
33839
|
};
|
|
31571
33840
|
const sanitizePositive = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
31572
33841
|
const sanitizeDecimalSeparator = (value) => {
|
|
31573
33842
|
if (value === ",") return ",";
|
|
31574
33843
|
return DEFAULT_DECIMAL_SEPARATOR;
|
|
31575
33844
|
};
|
|
33845
|
+
const DROP_CAP_PADDING_PX = 4;
|
|
33846
|
+
const measureDropCap = (ctx2, descriptor, spacing) => {
|
|
33847
|
+
const { run, lines, mode } = descriptor;
|
|
33848
|
+
const { font } = buildFontString({
|
|
33849
|
+
fontFamily: run.fontFamily,
|
|
33850
|
+
fontSize: run.fontSize,
|
|
33851
|
+
bold: run.bold,
|
|
33852
|
+
italic: run.italic
|
|
33853
|
+
});
|
|
33854
|
+
ctx2.font = font;
|
|
33855
|
+
const metrics = ctx2.measureText(run.text);
|
|
33856
|
+
const advanceWidth = metrics.width;
|
|
33857
|
+
const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
|
|
33858
|
+
const textWidth = Math.max(advanceWidth, paintedWidth);
|
|
33859
|
+
const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
|
|
33860
|
+
const baseLineHeight = resolveLineHeight(spacing, run.fontSize * 1.2);
|
|
33861
|
+
const height = roundValue(baseLineHeight * lines);
|
|
33862
|
+
return {
|
|
33863
|
+
width,
|
|
33864
|
+
height,
|
|
33865
|
+
lines,
|
|
33866
|
+
mode
|
|
33867
|
+
};
|
|
33868
|
+
};
|
|
31576
33869
|
const resolveIndentLeft = (item) => {
|
|
31577
33870
|
const indentLeft = sanitizePositive(item.paragraph.attrs?.indent?.left);
|
|
31578
33871
|
if (indentLeft > 0) {
|
|
@@ -32711,10 +35004,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
|
|
|
32711
35004
|
const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, hit.pos));
|
|
32712
35005
|
try {
|
|
32713
35006
|
__privateGet(this, _editor3).view?.dispatch(tr);
|
|
32714
|
-
} catch
|
|
32715
|
-
if (process$1.env.NODE_ENV === "development") {
|
|
32716
|
-
console.warn("[PresentationEditor] Failed to dispatch selection at position:", hit.pos, error);
|
|
32717
|
-
}
|
|
35007
|
+
} catch {
|
|
32718
35008
|
}
|
|
32719
35009
|
}
|
|
32720
35010
|
__privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
|
|
@@ -35247,10 +37537,10 @@ computeHeaderFooterCaretRect_fn = function(pos) {
|
|
|
35247
37537
|
if (!lineInfo) return null;
|
|
35248
37538
|
const { line, index: index2 } = lineInfo;
|
|
35249
37539
|
const range = computeLinePmRange$1(block, line);
|
|
35250
|
-
if (range.pmStart == null) return null;
|
|
35251
|
-
const
|
|
35252
|
-
const
|
|
35253
|
-
const localX = hit.fragment.x + measureCharacterX(block, line,
|
|
37540
|
+
if (range.pmStart == null || range.pmEnd == null) return null;
|
|
37541
|
+
const pmCharsInLine = Math.max(1, range.pmEnd - range.pmStart);
|
|
37542
|
+
const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range.pmStart));
|
|
37543
|
+
const localX = hit.fragment.x + measureCharacterX(block, line, pmOffset);
|
|
35254
37544
|
const lineOffset = __privateMethod(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, hit.fragment.fromLine, index2);
|
|
35255
37545
|
const headerPageHeight = context.layout.pageSize?.h ?? context.region.height ?? 1;
|
|
35256
37546
|
const headerLocalY = hit.pageIndex * headerPageHeight + (hit.fragment.y + lineOffset);
|
|
@@ -35390,23 +37680,34 @@ normalizeClientPoint_fn = function(clientX, clientY) {
|
|
|
35390
37680
|
computeCaretLayoutRect_fn = function(pos) {
|
|
35391
37681
|
const layout = __privateGet(this, _layoutState).layout;
|
|
35392
37682
|
if (!layout) return null;
|
|
37683
|
+
const domResult = __privateMethod(this, _PresentationEditor_instances, computeCaretLayoutRectFromDOM_fn).call(this, pos);
|
|
37684
|
+
if (domResult) {
|
|
37685
|
+
return domResult;
|
|
37686
|
+
}
|
|
35393
37687
|
const hit = getFragmentAtPosition(layout, __privateGet(this, _layoutState).blocks, __privateGet(this, _layoutState).measures, pos);
|
|
35394
|
-
if (!hit)
|
|
37688
|
+
if (!hit) {
|
|
37689
|
+
return null;
|
|
37690
|
+
}
|
|
35395
37691
|
const block = hit.block;
|
|
35396
37692
|
const measure = hit.measure;
|
|
37693
|
+
if (hit.fragment.kind === "table" && block?.kind === "table" && measure?.kind === "table") {
|
|
37694
|
+
return __privateMethod(this, _PresentationEditor_instances, computeTableCaretLayoutRect_fn).call(this, pos, hit.fragment, block, measure, hit.pageIndex);
|
|
37695
|
+
}
|
|
35397
37696
|
if (!block || block.kind !== "paragraph" || measure?.kind !== "paragraph") return null;
|
|
35398
37697
|
if (hit.fragment.kind !== "para") {
|
|
35399
37698
|
return null;
|
|
35400
37699
|
}
|
|
35401
37700
|
const fragment = hit.fragment;
|
|
35402
37701
|
const lineInfo = __privateMethod(this, _PresentationEditor_instances, findLineContainingPos_fn).call(this, block, measure, fragment.fromLine, fragment.toLine, pos);
|
|
35403
|
-
if (!lineInfo)
|
|
37702
|
+
if (!lineInfo) {
|
|
37703
|
+
return null;
|
|
37704
|
+
}
|
|
35404
37705
|
const { line, index: index2 } = lineInfo;
|
|
35405
37706
|
const range = computeLinePmRange$1(block, line);
|
|
35406
|
-
if (range.pmStart == null) return null;
|
|
35407
|
-
const
|
|
35408
|
-
const
|
|
35409
|
-
const localX = fragment.x + measureCharacterX(block, line,
|
|
37707
|
+
if (range.pmStart == null || range.pmEnd == null) return null;
|
|
37708
|
+
const pmCharsInLine = Math.max(1, range.pmEnd - range.pmStart);
|
|
37709
|
+
const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range.pmStart));
|
|
37710
|
+
const localX = fragment.x + measureCharacterX(block, line, pmOffset);
|
|
35410
37711
|
const lineOffset = __privateMethod(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
|
|
35411
37712
|
const localY = fragment.y + lineOffset;
|
|
35412
37713
|
return {
|
|
@@ -35416,17 +37717,179 @@ computeCaretLayoutRect_fn = function(pos) {
|
|
|
35416
37717
|
height: line.lineHeight
|
|
35417
37718
|
};
|
|
35418
37719
|
};
|
|
37720
|
+
/**
|
|
37721
|
+
* Computes caret position using DOM-based positioning.
|
|
37722
|
+
* This matches how click-to-position mapping works and correctly handles
|
|
37723
|
+
* segment-based rendering with tab stops.
|
|
37724
|
+
*
|
|
37725
|
+
* Returns page-local coordinates (x, y relative to the page element).
|
|
37726
|
+
*/
|
|
37727
|
+
computeCaretLayoutRectFromDOM_fn = function(pos) {
|
|
37728
|
+
const zoom = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
37729
|
+
let targetPageEl = null;
|
|
37730
|
+
if (__privateGet(this, _layoutState).layout && __privateGet(this, _layoutState).blocks && __privateGet(this, _layoutState).measures) {
|
|
37731
|
+
const fragmentHit = getFragmentAtPosition(
|
|
37732
|
+
__privateGet(this, _layoutState).layout,
|
|
37733
|
+
__privateGet(this, _layoutState).blocks,
|
|
37734
|
+
__privateGet(this, _layoutState).measures,
|
|
37735
|
+
pos
|
|
37736
|
+
);
|
|
37737
|
+
if (fragmentHit) {
|
|
37738
|
+
const pageEl = __privateGet(this, _viewportHost).querySelector(
|
|
37739
|
+
`.superdoc-page[data-page-index="${fragmentHit.pageIndex}"]`
|
|
37740
|
+
);
|
|
37741
|
+
if (pageEl) {
|
|
37742
|
+
targetPageEl = pageEl;
|
|
37743
|
+
}
|
|
37744
|
+
}
|
|
37745
|
+
}
|
|
37746
|
+
const spanEls = Array.from(
|
|
37747
|
+
targetPageEl ? targetPageEl.querySelectorAll("span[data-pm-start][data-pm-end]") : __privateGet(this, _viewportHost).querySelectorAll("span[data-pm-start][data-pm-end]")
|
|
37748
|
+
);
|
|
37749
|
+
for (const spanEl of spanEls) {
|
|
37750
|
+
const pmStart = Number(spanEl.dataset.pmStart ?? "NaN");
|
|
37751
|
+
const pmEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
|
|
37752
|
+
if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
|
|
37753
|
+
if (pos < pmStart || pos > pmEnd) continue;
|
|
37754
|
+
const pageEl = spanEl.closest(".superdoc-page");
|
|
37755
|
+
if (!pageEl) continue;
|
|
37756
|
+
const pageIndex = Number(pageEl.dataset.pageIndex ?? "0");
|
|
37757
|
+
const pageRect = pageEl.getBoundingClientRect();
|
|
37758
|
+
const textNode = spanEl.firstChild;
|
|
37759
|
+
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
|
|
37760
|
+
const spanRect2 = spanEl.getBoundingClientRect();
|
|
37761
|
+
return {
|
|
37762
|
+
pageIndex,
|
|
37763
|
+
x: (spanRect2.left - pageRect.left) / zoom,
|
|
37764
|
+
y: (spanRect2.top - pageRect.top) / zoom,
|
|
37765
|
+
height: spanRect2.height / zoom
|
|
37766
|
+
};
|
|
37767
|
+
}
|
|
37768
|
+
const text = textNode.textContent ?? "";
|
|
37769
|
+
const charOffset = Math.max(0, Math.min(text.length, pos - pmStart));
|
|
37770
|
+
const range = document.createRange();
|
|
37771
|
+
try {
|
|
37772
|
+
range.setStart(textNode, charOffset);
|
|
37773
|
+
range.setEnd(textNode, charOffset);
|
|
37774
|
+
} catch (error) {
|
|
37775
|
+
if (process$1.env.NODE_ENV === "development") {
|
|
37776
|
+
console.warn("[PresentationEditor] Range.setStart/setEnd failed:", {
|
|
37777
|
+
error: error instanceof Error ? error.message : String(error),
|
|
37778
|
+
charOffset,
|
|
37779
|
+
textLength: text.length,
|
|
37780
|
+
pos,
|
|
37781
|
+
pmStart,
|
|
37782
|
+
pmEnd
|
|
37783
|
+
});
|
|
37784
|
+
}
|
|
37785
|
+
const spanRect2 = spanEl.getBoundingClientRect();
|
|
37786
|
+
return {
|
|
37787
|
+
pageIndex,
|
|
37788
|
+
x: (spanRect2.left - pageRect.left) / zoom,
|
|
37789
|
+
y: (spanRect2.top - pageRect.top) / zoom,
|
|
37790
|
+
height: spanRect2.height / zoom
|
|
37791
|
+
};
|
|
37792
|
+
}
|
|
37793
|
+
const rangeRect = range.getBoundingClientRect();
|
|
37794
|
+
const spanRect = spanEl.getBoundingClientRect();
|
|
37795
|
+
const lineEl = spanEl.closest(".superdoc-line");
|
|
37796
|
+
const lineRect = lineEl ? lineEl.getBoundingClientRect() : spanRect;
|
|
37797
|
+
const caretHeight = spanRect.height;
|
|
37798
|
+
const verticalOffset = (lineRect.height - caretHeight) / 2;
|
|
37799
|
+
const caretY = lineRect.top + verticalOffset;
|
|
37800
|
+
return {
|
|
37801
|
+
pageIndex,
|
|
37802
|
+
x: (rangeRect.left - pageRect.left) / zoom,
|
|
37803
|
+
y: (caretY - pageRect.top) / zoom,
|
|
37804
|
+
height: caretHeight / zoom
|
|
37805
|
+
};
|
|
37806
|
+
}
|
|
37807
|
+
return null;
|
|
37808
|
+
};
|
|
37809
|
+
/**
|
|
37810
|
+
* Computes caret position within a table cell using DOM-based positioning.
|
|
37811
|
+
* This uses the actual rendered DOM elements to get accurate positions,
|
|
37812
|
+
* matching how click-to-position mapping works.
|
|
37813
|
+
*/
|
|
37814
|
+
computeTableCaretLayoutRect_fn = function(pos, _fragment, _tableBlock, _tableMeasure, pageIndex) {
|
|
37815
|
+
const lineEls = Array.from(__privateGet(this, _viewportHost).querySelectorAll(".superdoc-line"));
|
|
37816
|
+
if (lineEls.length === 0) return null;
|
|
37817
|
+
for (const lineEl of lineEls) {
|
|
37818
|
+
const pmStart = Number(lineEl.dataset.pmStart ?? "NaN");
|
|
37819
|
+
const pmEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
|
|
37820
|
+
if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
|
|
37821
|
+
if (pos < pmStart || pos > pmEnd) continue;
|
|
37822
|
+
const spanEls = Array.from(lineEl.querySelectorAll("span[data-pm-start]"));
|
|
37823
|
+
for (const spanEl of spanEls) {
|
|
37824
|
+
const spanStart = Number(spanEl.dataset.pmStart ?? "NaN");
|
|
37825
|
+
const spanEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
|
|
37826
|
+
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
|
|
37827
|
+
if (pos < spanStart || pos > spanEnd) continue;
|
|
37828
|
+
const textNode = spanEl.firstChild;
|
|
37829
|
+
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
|
|
37830
|
+
const spanRect = spanEl.getBoundingClientRect();
|
|
37831
|
+
const viewportRect3 = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
37832
|
+
const zoom3 = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
37833
|
+
return {
|
|
37834
|
+
pageIndex,
|
|
37835
|
+
x: (spanRect.left - viewportRect3.left + __privateGet(this, _visibleHost).scrollLeft) / zoom3,
|
|
37836
|
+
y: (spanRect.top - viewportRect3.top + __privateGet(this, _visibleHost).scrollTop) / zoom3,
|
|
37837
|
+
height: spanRect.height / zoom3
|
|
37838
|
+
};
|
|
37839
|
+
}
|
|
37840
|
+
const text = textNode.textContent ?? "";
|
|
37841
|
+
const charOffset = Math.max(0, Math.min(text.length, pos - spanStart));
|
|
37842
|
+
const range = document.createRange();
|
|
37843
|
+
range.setStart(textNode, charOffset);
|
|
37844
|
+
range.setEnd(textNode, charOffset);
|
|
37845
|
+
const rangeRect = range.getBoundingClientRect();
|
|
37846
|
+
const viewportRect2 = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
37847
|
+
const zoom2 = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
37848
|
+
const lineRect2 = lineEl.getBoundingClientRect();
|
|
37849
|
+
return {
|
|
37850
|
+
pageIndex,
|
|
37851
|
+
x: (rangeRect.left - viewportRect2.left + __privateGet(this, _visibleHost).scrollLeft) / zoom2,
|
|
37852
|
+
y: (lineRect2.top - viewportRect2.top + __privateGet(this, _visibleHost).scrollTop) / zoom2,
|
|
37853
|
+
height: lineRect2.height / zoom2
|
|
37854
|
+
};
|
|
37855
|
+
}
|
|
37856
|
+
const lineRect = lineEl.getBoundingClientRect();
|
|
37857
|
+
const viewportRect = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
37858
|
+
const zoom = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
37859
|
+
return {
|
|
37860
|
+
pageIndex,
|
|
37861
|
+
x: (lineRect.left - viewportRect.left + __privateGet(this, _visibleHost).scrollLeft) / zoom,
|
|
37862
|
+
y: (lineRect.top - viewportRect.top + __privateGet(this, _visibleHost).scrollTop) / zoom,
|
|
37863
|
+
height: lineRect.height / zoom
|
|
37864
|
+
};
|
|
37865
|
+
}
|
|
37866
|
+
return null;
|
|
37867
|
+
};
|
|
35419
37868
|
findLineContainingPos_fn = function(block, measure, fromLine, toLine, pos) {
|
|
37869
|
+
const log2 = (...args) => {
|
|
37870
|
+
console.log("[LINE-SEARCH]", ...args);
|
|
37871
|
+
};
|
|
37872
|
+
log2("Searching for pos:", pos, "in lines", fromLine, "to", toLine);
|
|
35420
37873
|
if (measure.kind !== "paragraph" || block.kind !== "paragraph") return null;
|
|
35421
37874
|
for (let lineIndex = fromLine; lineIndex < toLine; lineIndex += 1) {
|
|
35422
37875
|
const line = measure.lines[lineIndex];
|
|
35423
37876
|
if (!line) continue;
|
|
35424
37877
|
const range = computeLinePmRange$1(block, line);
|
|
37878
|
+
log2("Line", lineIndex, ":", {
|
|
37879
|
+
pmStart: range.pmStart,
|
|
37880
|
+
pmEnd: range.pmEnd,
|
|
37881
|
+
fromRun: line.fromRun,
|
|
37882
|
+
toRun: line.toRun,
|
|
37883
|
+
fromChar: line.fromChar,
|
|
37884
|
+
toChar: line.toChar
|
|
37885
|
+
});
|
|
35425
37886
|
if (range.pmStart == null || range.pmEnd == null) continue;
|
|
35426
37887
|
if (pos >= range.pmStart && pos <= range.pmEnd) {
|
|
37888
|
+
log2("Found line", lineIndex, "for pos", pos);
|
|
35427
37889
|
return { line, index: lineIndex };
|
|
35428
37890
|
}
|
|
35429
37891
|
}
|
|
37892
|
+
log2("No line found for pos", pos);
|
|
35430
37893
|
return null;
|
|
35431
37894
|
};
|
|
35432
37895
|
lineHeightBeforeIndex_fn = function(lines, fromLine, targetIndex) {
|
|
@@ -48995,6 +51458,49 @@ const ShapeGroup = Node$1.create({
|
|
|
48995
51458
|
};
|
|
48996
51459
|
}
|
|
48997
51460
|
});
|
|
51461
|
+
const sharedAttributes = () => ({
|
|
51462
|
+
originalName: {
|
|
51463
|
+
default: null
|
|
51464
|
+
},
|
|
51465
|
+
originalXml: {
|
|
51466
|
+
default: null
|
|
51467
|
+
}
|
|
51468
|
+
});
|
|
51469
|
+
const hiddenRender = (type) => ["sd-passthrough", { "data-sd-passthrough": type, style: "display: none;" }];
|
|
51470
|
+
const PassthroughBlock = Node$1.create({
|
|
51471
|
+
name: "passthroughBlock",
|
|
51472
|
+
group: "block",
|
|
51473
|
+
atom: true,
|
|
51474
|
+
draggable: false,
|
|
51475
|
+
selectable: false,
|
|
51476
|
+
defining: true,
|
|
51477
|
+
parseDOM() {
|
|
51478
|
+
return [{ tag: 'sd-passthrough[data-sd-passthrough="block"]' }];
|
|
51479
|
+
},
|
|
51480
|
+
renderDOM() {
|
|
51481
|
+
return hiddenRender("block");
|
|
51482
|
+
},
|
|
51483
|
+
addAttributes() {
|
|
51484
|
+
return sharedAttributes();
|
|
51485
|
+
}
|
|
51486
|
+
});
|
|
51487
|
+
const PassthroughInline = Node$1.create({
|
|
51488
|
+
name: "passthroughInline",
|
|
51489
|
+
group: "inline",
|
|
51490
|
+
inline: true,
|
|
51491
|
+
atom: true,
|
|
51492
|
+
draggable: false,
|
|
51493
|
+
selectable: false,
|
|
51494
|
+
parseDOM() {
|
|
51495
|
+
return [{ tag: 'sd-passthrough[data-sd-passthrough="inline"]' }];
|
|
51496
|
+
},
|
|
51497
|
+
renderDOM() {
|
|
51498
|
+
return hiddenRender("inline");
|
|
51499
|
+
},
|
|
51500
|
+
addAttributes() {
|
|
51501
|
+
return sharedAttributes();
|
|
51502
|
+
}
|
|
51503
|
+
});
|
|
48998
51504
|
const TextStyle = Mark.create({
|
|
48999
51505
|
name: "textStyle",
|
|
49000
51506
|
addOptions() {
|
|
@@ -54905,7 +57411,9 @@ const getRichTextExtensions = () => {
|
|
|
54905
57411
|
AiPlugin,
|
|
54906
57412
|
Image,
|
|
54907
57413
|
NodeResizer,
|
|
54908
|
-
CustomSelection
|
|
57414
|
+
CustomSelection,
|
|
57415
|
+
PassthroughInline,
|
|
57416
|
+
PassthroughBlock
|
|
54909
57417
|
];
|
|
54910
57418
|
};
|
|
54911
57419
|
const getStarterExtensions = () => {
|
|
@@ -54977,7 +57485,9 @@ const getStarterExtensions = () => {
|
|
|
54977
57485
|
CustomSelection,
|
|
54978
57486
|
TextTransform,
|
|
54979
57487
|
VectorShape,
|
|
54980
|
-
ShapeGroup
|
|
57488
|
+
ShapeGroup,
|
|
57489
|
+
PassthroughInline,
|
|
57490
|
+
PassthroughBlock
|
|
54981
57491
|
];
|
|
54982
57492
|
};
|
|
54983
57493
|
export {
|