superdoc 1.0.0-beta.14 → 1.0.0-beta.15
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-DrsLL5TV.es.js → PdfViewer-CjlHzt9e.es.js} +1 -1
- package/dist/chunks/{PdfViewer-Cdc_EOZ9.cjs → PdfViewer-DltPlBWC.cjs} +1 -1
- package/dist/chunks/{index-9ZvcPlCg.cjs → index-BZnlco_f.cjs} +3 -3
- package/dist/chunks/{index-I4Ew0HDV-EPhjcu7T.cjs → index-Bds7gW4r-JPDW6c39.cjs} +1 -1
- package/dist/chunks/{index-I4Ew0HDV-Bht7-IGi.es.js → index-Bds7gW4r-Pk_xAuWe.es.js} +1 -1
- package/dist/chunks/{index-DB1DyDmZ.es.js → index-qg0AxQJC.es.js} +3 -3
- package/dist/chunks/{super-editor.es-DxAG4BVh.es.js → super-editor.es-CQTkj_nb.es.js} +2031 -472
- package/dist/chunks/{super-editor.es-DuS77THX.cjs → super-editor.es-CuAhqbzW.cjs} +2031 -472
- 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-qMoZOGGn.js} +412 -252
- package/dist/super-editor/chunks/{docx-zipper-B-CXiNSb.js → docx-zipper-QKiyORxV.js} +1 -1
- package/dist/super-editor/chunks/{editor-wC_gs8Bl.js → editor-D8ZdjC2V.js} +1633 -215
- package/dist/super-editor/chunks/{index-I4Ew0HDV.js → index-Bds7gW4r.js} +1 -1
- package/dist/super-editor/chunks/{toolbar-BR1GYvwW.js → toolbar-Spi7vpev.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 +2033 -474
- 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-qMoZOGGn.js";
|
|
16
|
+
import { D as DocxZipper } from "./docx-zipper-QKiyORxV.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.15";
|
|
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-Bds7gW4r.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.15");
|
|
14544
14565
|
if (!this.options.ydoc) return;
|
|
14545
14566
|
const metaMap = this.options.ydoc.getMap("meta");
|
|
14546
14567
|
let docVersion = metaMap.get("version");
|
|
@@ -16357,6 +16378,23 @@ const resolveColorFromAttributes = (attrs, themeColors) => {
|
|
|
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) {
|
|
@@ -18555,10 +18598,17 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
|
|
|
18555
18598
|
}
|
|
18556
18599
|
const resolvedExtended = resolved;
|
|
18557
18600
|
const resolvedAsRecord = resolved;
|
|
18601
|
+
let resolvedIndent = cloneIfObject(resolvedAsRecord.indent);
|
|
18602
|
+
const styleIdLower = typeof styleId === "string" ? styleId.toLowerCase() : "";
|
|
18603
|
+
const isHeadingStyle = typeof resolvedExtended.outlineLvl === "number" || styleIdLower.startsWith("heading ") || styleIdLower.startsWith("heading");
|
|
18604
|
+
const onlyFirstLineIndent = resolvedIndent && resolvedIndent.firstLine != null && resolvedIndent.hanging == null && resolvedIndent.left == null && resolvedIndent.right == null;
|
|
18605
|
+
if (isHeadingStyle && (!resolvedIndent || Object.keys(resolvedIndent).length === 0 || onlyFirstLineIndent)) {
|
|
18606
|
+
resolvedIndent = { firstLine: 0, hanging: 0, left: resolvedIndent?.left, right: resolvedIndent?.right };
|
|
18607
|
+
}
|
|
18558
18608
|
const hydrated = {
|
|
18559
18609
|
resolved,
|
|
18560
18610
|
spacing: cloneIfObject(resolvedAsRecord.spacing),
|
|
18561
|
-
indent:
|
|
18611
|
+
indent: resolvedIndent,
|
|
18562
18612
|
borders: cloneIfObject(resolvedExtended.borders),
|
|
18563
18613
|
shading: cloneIfObject(resolvedExtended.shading),
|
|
18564
18614
|
alignment: resolvedExtended.justification,
|
|
@@ -18666,6 +18716,12 @@ const cloneParagraphAttrs = (attrs) => {
|
|
|
18666
18716
|
}
|
|
18667
18717
|
if (attrs.shading) clone.shading = { ...attrs.shading };
|
|
18668
18718
|
if (attrs.tabs) clone.tabs = attrs.tabs.map((tab) => ({ ...tab }));
|
|
18719
|
+
if (attrs.dropCapDescriptor) {
|
|
18720
|
+
clone.dropCapDescriptor = {
|
|
18721
|
+
...attrs.dropCapDescriptor,
|
|
18722
|
+
run: { ...attrs.dropCapDescriptor.run }
|
|
18723
|
+
};
|
|
18724
|
+
}
|
|
18669
18725
|
return clone;
|
|
18670
18726
|
};
|
|
18671
18727
|
const buildStyleNodeFromAttrs = (attrs, spacing, indent) => {
|
|
@@ -18777,6 +18833,119 @@ const normalizeResolvedTabAlignment = (value) => {
|
|
|
18777
18833
|
return void 0;
|
|
18778
18834
|
}
|
|
18779
18835
|
};
|
|
18836
|
+
const DEFAULT_DROP_CAP_FONT_SIZE_PX = 64;
|
|
18837
|
+
const DEFAULT_DROP_CAP_FONT_FAMILY = "Times New Roman";
|
|
18838
|
+
const extractDropCapRunFromParagraph = (para) => {
|
|
18839
|
+
const content = para.content;
|
|
18840
|
+
if (!Array.isArray(content) || content.length === 0) {
|
|
18841
|
+
return null;
|
|
18842
|
+
}
|
|
18843
|
+
let text = "";
|
|
18844
|
+
let runProperties = {};
|
|
18845
|
+
let textStyleMarks = {};
|
|
18846
|
+
const MAX_RECURSION_DEPTH = 50;
|
|
18847
|
+
const extractTextAndStyle = (nodes, depth = 0) => {
|
|
18848
|
+
if (depth > MAX_RECURSION_DEPTH) {
|
|
18849
|
+
console.warn(`extractTextAndStyle exceeded max recursion depth (${MAX_RECURSION_DEPTH})`);
|
|
18850
|
+
return false;
|
|
18851
|
+
}
|
|
18852
|
+
for (const node of nodes) {
|
|
18853
|
+
if (!node) continue;
|
|
18854
|
+
if (node.type === "text" && typeof node.text === "string" && node.text.length > 0) {
|
|
18855
|
+
text = node.text;
|
|
18856
|
+
if (Array.isArray(node.marks)) {
|
|
18857
|
+
for (const mark of node.marks) {
|
|
18858
|
+
if (mark?.type === "textStyle" && mark.attrs) {
|
|
18859
|
+
textStyleMarks = { ...textStyleMarks, ...mark.attrs };
|
|
18860
|
+
}
|
|
18861
|
+
}
|
|
18862
|
+
}
|
|
18863
|
+
return true;
|
|
18864
|
+
}
|
|
18865
|
+
if (node.type === "run") {
|
|
18866
|
+
if (node.attrs?.runProperties && typeof node.attrs.runProperties === "object") {
|
|
18867
|
+
runProperties = { ...runProperties, ...node.attrs.runProperties };
|
|
18868
|
+
}
|
|
18869
|
+
if (Array.isArray(node.marks)) {
|
|
18870
|
+
for (const mark of node.marks) {
|
|
18871
|
+
if (mark?.type === "textStyle" && mark.attrs) {
|
|
18872
|
+
textStyleMarks = { ...textStyleMarks, ...mark.attrs };
|
|
18873
|
+
}
|
|
18874
|
+
}
|
|
18875
|
+
}
|
|
18876
|
+
if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
|
|
18877
|
+
return true;
|
|
18878
|
+
}
|
|
18879
|
+
}
|
|
18880
|
+
if (Array.isArray(node.content) && extractTextAndStyle(node.content, depth + 1)) {
|
|
18881
|
+
return true;
|
|
18882
|
+
}
|
|
18883
|
+
}
|
|
18884
|
+
return false;
|
|
18885
|
+
};
|
|
18886
|
+
extractTextAndStyle(content);
|
|
18887
|
+
if (!text) {
|
|
18888
|
+
return null;
|
|
18889
|
+
}
|
|
18890
|
+
const mergedStyle = { ...runProperties, ...textStyleMarks };
|
|
18891
|
+
let fontSizePx = DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
18892
|
+
const rawFontSize = mergedStyle.fontSize ?? mergedStyle["w:sz"] ?? mergedStyle.sz;
|
|
18893
|
+
if (rawFontSize != null) {
|
|
18894
|
+
if (typeof rawFontSize === "number") {
|
|
18895
|
+
const converted = rawFontSize > 100 ? ptToPx(rawFontSize / 2) : rawFontSize;
|
|
18896
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
18897
|
+
} else if (typeof rawFontSize === "string") {
|
|
18898
|
+
const numericPart = parseFloat(rawFontSize);
|
|
18899
|
+
if (Number.isFinite(numericPart)) {
|
|
18900
|
+
if (rawFontSize.endsWith("pt")) {
|
|
18901
|
+
const converted = ptToPx(numericPart);
|
|
18902
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
18903
|
+
} else if (rawFontSize.endsWith("px")) {
|
|
18904
|
+
fontSizePx = numericPart;
|
|
18905
|
+
} else {
|
|
18906
|
+
const converted = numericPart > 100 ? ptToPx(numericPart / 2) : numericPart;
|
|
18907
|
+
fontSizePx = converted ?? DEFAULT_DROP_CAP_FONT_SIZE_PX;
|
|
18908
|
+
}
|
|
18909
|
+
}
|
|
18910
|
+
}
|
|
18911
|
+
}
|
|
18912
|
+
let fontFamily = DEFAULT_DROP_CAP_FONT_FAMILY;
|
|
18913
|
+
const rawFontFamily = mergedStyle.fontFamily ?? mergedStyle["w:rFonts"] ?? mergedStyle.rFonts;
|
|
18914
|
+
if (typeof rawFontFamily === "string") {
|
|
18915
|
+
fontFamily = rawFontFamily;
|
|
18916
|
+
} else if (rawFontFamily && typeof rawFontFamily === "object") {
|
|
18917
|
+
const rFonts = rawFontFamily;
|
|
18918
|
+
const ascii = rFonts["w:ascii"] ?? rFonts.ascii;
|
|
18919
|
+
if (typeof ascii === "string") {
|
|
18920
|
+
fontFamily = ascii;
|
|
18921
|
+
}
|
|
18922
|
+
}
|
|
18923
|
+
const dropCapRun = {
|
|
18924
|
+
text,
|
|
18925
|
+
fontFamily,
|
|
18926
|
+
fontSize: fontSizePx
|
|
18927
|
+
};
|
|
18928
|
+
const bold = mergedStyle.bold ?? mergedStyle["w:b"] ?? mergedStyle.b;
|
|
18929
|
+
if (isTruthy(bold)) {
|
|
18930
|
+
dropCapRun.bold = true;
|
|
18931
|
+
}
|
|
18932
|
+
const italic = mergedStyle.italic ?? mergedStyle["w:i"] ?? mergedStyle.i;
|
|
18933
|
+
if (isTruthy(italic)) {
|
|
18934
|
+
dropCapRun.italic = true;
|
|
18935
|
+
}
|
|
18936
|
+
const color = mergedStyle.color ?? mergedStyle["w:color"] ?? mergedStyle.val;
|
|
18937
|
+
if (typeof color === "string" && color.length > 0 && color.toLowerCase() !== "auto") {
|
|
18938
|
+
dropCapRun.color = color.startsWith("#") ? color : `#${color}`;
|
|
18939
|
+
}
|
|
18940
|
+
const position = mergedStyle.position ?? mergedStyle["w:position"];
|
|
18941
|
+
if (position != null) {
|
|
18942
|
+
const posNum = pickNumber(position);
|
|
18943
|
+
if (posNum != null) {
|
|
18944
|
+
dropCapRun.position = ptToPx(posNum / 2);
|
|
18945
|
+
}
|
|
18946
|
+
}
|
|
18947
|
+
return dropCapRun;
|
|
18948
|
+
};
|
|
18780
18949
|
const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
|
|
18781
18950
|
if (numberingProps === null) {
|
|
18782
18951
|
return null;
|
|
@@ -19042,6 +19211,24 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
|
|
|
19042
19211
|
const dropCap = framePr["w:dropCap"] ?? framePr.dropCap;
|
|
19043
19212
|
if (dropCap != null && (typeof dropCap === "string" || typeof dropCap === "number" || typeof dropCap === "boolean")) {
|
|
19044
19213
|
paragraphAttrs.dropCap = dropCap;
|
|
19214
|
+
const dropCapMode = typeof dropCap === "string" ? dropCap.toLowerCase() : "drop";
|
|
19215
|
+
const linesValue = pickNumber(framePr["w:lines"] ?? framePr.lines);
|
|
19216
|
+
const wrapValue = asString(framePr["w:wrap"] ?? framePr.wrap);
|
|
19217
|
+
const dropCapRunInfo = extractDropCapRunFromParagraph(para);
|
|
19218
|
+
if (dropCapRunInfo) {
|
|
19219
|
+
const descriptor = {
|
|
19220
|
+
mode: dropCapMode === "margin" ? "margin" : "drop",
|
|
19221
|
+
lines: linesValue != null && linesValue > 0 ? linesValue : 3,
|
|
19222
|
+
run: dropCapRunInfo
|
|
19223
|
+
};
|
|
19224
|
+
if (wrapValue) {
|
|
19225
|
+
const normalizedWrap = wrapValue.toLowerCase();
|
|
19226
|
+
if (normalizedWrap === "around" || normalizedWrap === "notbeside" || normalizedWrap === "none" || normalizedWrap === "tight") {
|
|
19227
|
+
descriptor.wrap = normalizedWrap === "notbeside" ? "notBeside" : normalizedWrap;
|
|
19228
|
+
}
|
|
19229
|
+
}
|
|
19230
|
+
paragraphAttrs.dropCapDescriptor = descriptor;
|
|
19231
|
+
}
|
|
19045
19232
|
}
|
|
19046
19233
|
const frame = {};
|
|
19047
19234
|
const wrap = asString(framePr["w:wrap"] ?? framePr.wrap);
|
|
@@ -19815,13 +20002,26 @@ const dataAttrsCompatible = (a, b) => {
|
|
|
19815
20002
|
}
|
|
19816
20003
|
return true;
|
|
19817
20004
|
};
|
|
20005
|
+
const commentsCompatible = (a, b) => {
|
|
20006
|
+
const aComments = a.comments ?? [];
|
|
20007
|
+
const bComments = b.comments ?? [];
|
|
20008
|
+
if (aComments.length === 0 && bComments.length === 0) return true;
|
|
20009
|
+
if (aComments.length !== bComments.length) return false;
|
|
20010
|
+
const normalize2 = (c) => `${c.commentId ?? ""}::${c.importedId ?? ""}::${c.internal ? "1" : "0"}`;
|
|
20011
|
+
const aKeys = aComments.map(normalize2).sort();
|
|
20012
|
+
const bKeys = bComments.map(normalize2).sort();
|
|
20013
|
+
for (let i = 0; i < aKeys.length; i++) {
|
|
20014
|
+
if (aKeys[i] !== bKeys[i]) return false;
|
|
20015
|
+
}
|
|
20016
|
+
return true;
|
|
20017
|
+
};
|
|
19818
20018
|
function mergeAdjacentRuns(runs) {
|
|
19819
20019
|
if (runs.length <= 1) return runs;
|
|
19820
20020
|
const merged = [];
|
|
19821
20021
|
let current = runs[0];
|
|
19822
20022
|
for (let i = 1; i < runs.length; i++) {
|
|
19823
20023
|
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);
|
|
20024
|
+
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
20025
|
if (canMerge) {
|
|
19826
20026
|
const currText = current.text ?? "";
|
|
19827
20027
|
const nextText = next.text ?? "";
|
|
@@ -20303,6 +20503,22 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
|
|
|
20303
20503
|
id: nextId(),
|
|
20304
20504
|
attrs: node.attrs || {}
|
|
20305
20505
|
});
|
|
20506
|
+
} else {
|
|
20507
|
+
const lineBreakRun = { kind: "lineBreak", attrs: {} };
|
|
20508
|
+
const lbAttrs = {};
|
|
20509
|
+
if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
|
|
20510
|
+
if (attrs.clear) lbAttrs.clear = String(attrs.clear);
|
|
20511
|
+
if (Object.keys(lbAttrs).length > 0) {
|
|
20512
|
+
lineBreakRun.attrs = lbAttrs;
|
|
20513
|
+
} else {
|
|
20514
|
+
delete lineBreakRun.attrs;
|
|
20515
|
+
}
|
|
20516
|
+
const pos = positions.get(node);
|
|
20517
|
+
if (pos) {
|
|
20518
|
+
lineBreakRun.pmStart = pos.start;
|
|
20519
|
+
lineBreakRun.pmEnd = pos.end;
|
|
20520
|
+
}
|
|
20521
|
+
currentRuns.push(lineBreakRun);
|
|
20306
20522
|
}
|
|
20307
20523
|
return;
|
|
20308
20524
|
}
|
|
@@ -21327,7 +21543,39 @@ function toFlowBlocks(pmDoc, options) {
|
|
|
21327
21543
|
}
|
|
21328
21544
|
instrumentation?.log?.({ totalBlocks: blocks.length, blockCounts, bookmarks: bookmarks.size });
|
|
21329
21545
|
const hydratedBlocks = hydrateImageBlocks(blocks, options?.mediaFiles);
|
|
21330
|
-
|
|
21546
|
+
const mergedBlocks = mergeDropCapParagraphs(hydratedBlocks);
|
|
21547
|
+
return { blocks: mergedBlocks, bookmarks };
|
|
21548
|
+
}
|
|
21549
|
+
function mergeDropCapParagraphs(blocks) {
|
|
21550
|
+
const result = [];
|
|
21551
|
+
let i = 0;
|
|
21552
|
+
while (i < blocks.length) {
|
|
21553
|
+
const block = blocks[i];
|
|
21554
|
+
if (block.kind === "paragraph" && block.attrs?.dropCapDescriptor && i + 1 < blocks.length) {
|
|
21555
|
+
const dropCapBlock = block;
|
|
21556
|
+
const nextBlock = blocks[i + 1];
|
|
21557
|
+
if (nextBlock.kind === "paragraph") {
|
|
21558
|
+
const textBlock = nextBlock;
|
|
21559
|
+
const mergedBlock = {
|
|
21560
|
+
kind: "paragraph",
|
|
21561
|
+
id: textBlock.id,
|
|
21562
|
+
runs: textBlock.runs,
|
|
21563
|
+
attrs: {
|
|
21564
|
+
...textBlock.attrs,
|
|
21565
|
+
dropCapDescriptor: dropCapBlock.attrs?.dropCapDescriptor,
|
|
21566
|
+
// Clear the legacy dropCap flag on the merged block
|
|
21567
|
+
dropCap: void 0
|
|
21568
|
+
}
|
|
21569
|
+
};
|
|
21570
|
+
result.push(mergedBlock);
|
|
21571
|
+
i += 2;
|
|
21572
|
+
continue;
|
|
21573
|
+
}
|
|
21574
|
+
}
|
|
21575
|
+
result.push(block);
|
|
21576
|
+
i += 1;
|
|
21577
|
+
}
|
|
21578
|
+
return result;
|
|
21331
21579
|
}
|
|
21332
21580
|
function paragraphToFlowBlocks(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converterContext) {
|
|
21333
21581
|
return paragraphToFlowBlocks$1(
|
|
@@ -21402,7 +21650,7 @@ function getMeasurementContext() {
|
|
|
21402
21650
|
return measurementCtx;
|
|
21403
21651
|
}
|
|
21404
21652
|
function getRunFontString(run) {
|
|
21405
|
-
if (run.kind === "tab" || run.kind === "
|
|
21653
|
+
if (run.kind === "tab" || run.kind === "lineBreak" || "src" in run) {
|
|
21406
21654
|
return "normal normal 16px Arial";
|
|
21407
21655
|
}
|
|
21408
21656
|
const style = run.italic ? "italic" : "normal";
|
|
@@ -21421,7 +21669,11 @@ function sliceRunsForLine$1(block, line) {
|
|
|
21421
21669
|
result.push(run);
|
|
21422
21670
|
continue;
|
|
21423
21671
|
}
|
|
21424
|
-
if (
|
|
21672
|
+
if ("src" in run) {
|
|
21673
|
+
result.push(run);
|
|
21674
|
+
continue;
|
|
21675
|
+
}
|
|
21676
|
+
if (run.kind === "lineBreak") {
|
|
21425
21677
|
result.push(run);
|
|
21426
21678
|
continue;
|
|
21427
21679
|
}
|
|
@@ -21448,13 +21700,17 @@ function sliceRunsForLine$1(block, line) {
|
|
|
21448
21700
|
}
|
|
21449
21701
|
function measureCharacterX(block, line, charOffset) {
|
|
21450
21702
|
const ctx2 = getMeasurementContext();
|
|
21703
|
+
const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
|
|
21704
|
+
if (hasExplicitPositioning && line.segments && ctx2) {
|
|
21705
|
+
return measureCharacterXSegmentBased(block, line, charOffset, ctx2);
|
|
21706
|
+
}
|
|
21451
21707
|
if (!ctx2) {
|
|
21452
21708
|
const runs2 = sliceRunsForLine$1(block, line);
|
|
21453
21709
|
const charsInLine = Math.max(
|
|
21454
21710
|
1,
|
|
21455
21711
|
runs2.reduce((sum, run) => {
|
|
21456
21712
|
if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
|
|
21457
|
-
if (run.kind === "
|
|
21713
|
+
if ("src" in run || run.kind === "lineBreak") return sum;
|
|
21458
21714
|
return sum + (run.text ?? "").length;
|
|
21459
21715
|
}, 0)
|
|
21460
21716
|
);
|
|
@@ -21475,7 +21731,7 @@ function measureCharacterX(block, line, charOffset) {
|
|
|
21475
21731
|
currentCharOffset += runLength2;
|
|
21476
21732
|
continue;
|
|
21477
21733
|
}
|
|
21478
|
-
const text = run.kind === "
|
|
21734
|
+
const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
|
|
21479
21735
|
const runLength = text.length;
|
|
21480
21736
|
if (currentCharOffset + runLength >= charOffset) {
|
|
21481
21737
|
const offsetInRun = charOffset - currentCharOffset;
|
|
@@ -21492,6 +21748,47 @@ function measureCharacterX(block, line, charOffset) {
|
|
|
21492
21748
|
}
|
|
21493
21749
|
return currentX;
|
|
21494
21750
|
}
|
|
21751
|
+
function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
|
|
21752
|
+
if (block.kind !== "paragraph" || !line.segments) return 0;
|
|
21753
|
+
let lineCharCount = 0;
|
|
21754
|
+
for (const segment of line.segments) {
|
|
21755
|
+
const run = block.runs[segment.runIndex];
|
|
21756
|
+
if (!run) continue;
|
|
21757
|
+
const segmentChars = segment.toChar - segment.fromChar;
|
|
21758
|
+
if (lineCharCount + segmentChars >= charOffset) {
|
|
21759
|
+
const offsetInSegment = charOffset - lineCharCount;
|
|
21760
|
+
let segmentBaseX = segment.x;
|
|
21761
|
+
if (segmentBaseX === void 0) {
|
|
21762
|
+
segmentBaseX = 0;
|
|
21763
|
+
for (const prevSeg of line.segments) {
|
|
21764
|
+
if (prevSeg === segment) break;
|
|
21765
|
+
const prevRun = block.runs[prevSeg.runIndex];
|
|
21766
|
+
if (!prevRun) continue;
|
|
21767
|
+
if (prevSeg.x !== void 0) {
|
|
21768
|
+
segmentBaseX = prevSeg.x + (prevSeg.width ?? 0);
|
|
21769
|
+
} else {
|
|
21770
|
+
segmentBaseX += prevSeg.width ?? 0;
|
|
21771
|
+
}
|
|
21772
|
+
}
|
|
21773
|
+
}
|
|
21774
|
+
if (isTabRun$1(run)) {
|
|
21775
|
+
return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
|
|
21776
|
+
}
|
|
21777
|
+
if ("src" in run || run.kind === "lineBreak") {
|
|
21778
|
+
return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
|
|
21779
|
+
}
|
|
21780
|
+
const text = run.text ?? "";
|
|
21781
|
+
const segmentText = text.slice(segment.fromChar, segment.toChar);
|
|
21782
|
+
const textUpToTarget = segmentText.slice(0, offsetInSegment);
|
|
21783
|
+
ctx2.font = getRunFontString(run);
|
|
21784
|
+
const measured = ctx2.measureText(textUpToTarget);
|
|
21785
|
+
const spacingWidth = computeLetterSpacingWidth(run, offsetInSegment, segmentChars);
|
|
21786
|
+
return segmentBaseX + measured.width + spacingWidth;
|
|
21787
|
+
}
|
|
21788
|
+
lineCharCount += segmentChars;
|
|
21789
|
+
}
|
|
21790
|
+
return line.width;
|
|
21791
|
+
}
|
|
21495
21792
|
function findCharacterAtX(block, line, x, pmStart) {
|
|
21496
21793
|
const ctx2 = getMeasurementContext();
|
|
21497
21794
|
if (!ctx2) {
|
|
@@ -21500,7 +21797,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21500
21797
|
1,
|
|
21501
21798
|
runs2.reduce((sum, run) => {
|
|
21502
21799
|
if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
|
|
21503
|
-
if (run.kind === "
|
|
21800
|
+
if ("src" in run || run.kind === "lineBreak") return sum;
|
|
21504
21801
|
return sum + (run.text ?? "").length;
|
|
21505
21802
|
}, 0)
|
|
21506
21803
|
);
|
|
@@ -21535,7 +21832,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21535
21832
|
currentCharOffset += TAB_CHAR_LENGTH;
|
|
21536
21833
|
continue;
|
|
21537
21834
|
}
|
|
21538
|
-
const text = run.kind === "
|
|
21835
|
+
const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
|
|
21539
21836
|
const runLength = text.length;
|
|
21540
21837
|
if (runLength === 0) continue;
|
|
21541
21838
|
ctx2.font = getRunFontString(run);
|
|
@@ -21572,7 +21869,7 @@ function findCharacterAtX(block, line, x, pmStart) {
|
|
|
21572
21869
|
};
|
|
21573
21870
|
}
|
|
21574
21871
|
const computeLetterSpacingWidth = (run, precedingChars, runLength) => {
|
|
21575
|
-
if (isTabRun$1(run) || run
|
|
21872
|
+
if (isTabRun$1(run) || "src" in run || !("letterSpacing" in run) || !run.letterSpacing) {
|
|
21576
21873
|
return 0;
|
|
21577
21874
|
}
|
|
21578
21875
|
const maxGaps = Math.max(runLength - 1, 0);
|
|
@@ -21582,6 +21879,8 @@ const computeLetterSpacingWidth = (run, precedingChars, runLength) => {
|
|
|
21582
21879
|
const clamped = Math.min(Math.max(precedingChars, 0), maxGaps);
|
|
21583
21880
|
return clamped * run.letterSpacing;
|
|
21584
21881
|
};
|
|
21882
|
+
const log = (...args) => {
|
|
21883
|
+
};
|
|
21585
21884
|
const CLASS_NAMES$1 = {
|
|
21586
21885
|
page: "superdoc-page",
|
|
21587
21886
|
fragment: "superdoc-fragment",
|
|
@@ -21597,6 +21896,11 @@ function clickToPositionDom(domContainer, clientX, clientY) {
|
|
|
21597
21896
|
const pageLocalY = clientY - pageRect.top;
|
|
21598
21897
|
const viewX = pageRect.left + pageLocalX;
|
|
21599
21898
|
const viewY = pageRect.top + pageLocalY;
|
|
21899
|
+
log("Page found:", {
|
|
21900
|
+
pageIndex: pageEl.dataset.pageIndex,
|
|
21901
|
+
pageRect: { left: pageRect.left, top: pageRect.top, width: pageRect.width, height: pageRect.height },
|
|
21902
|
+
viewCoords: { viewX, viewY }
|
|
21903
|
+
});
|
|
21600
21904
|
let hitChain = [];
|
|
21601
21905
|
const doc2 = document;
|
|
21602
21906
|
if (typeof doc2.elementsFromPoint === "function") {
|
|
@@ -21608,15 +21912,62 @@ function clickToPositionDom(domContainer, clientX, clientY) {
|
|
|
21608
21912
|
if (!Array.isArray(hitChain)) {
|
|
21609
21913
|
return null;
|
|
21610
21914
|
}
|
|
21915
|
+
const hitChainData = hitChain.map((el) => {
|
|
21916
|
+
const rect = el.getBoundingClientRect();
|
|
21917
|
+
return {
|
|
21918
|
+
tag: el.tagName,
|
|
21919
|
+
classes: el.className,
|
|
21920
|
+
blockId: el.dataset?.blockId,
|
|
21921
|
+
pmStart: el.dataset?.pmStart,
|
|
21922
|
+
pmEnd: el.dataset?.pmEnd,
|
|
21923
|
+
rect: {
|
|
21924
|
+
top: Math.round(rect.top),
|
|
21925
|
+
bottom: Math.round(rect.bottom),
|
|
21926
|
+
left: Math.round(rect.left),
|
|
21927
|
+
right: Math.round(rect.right),
|
|
21928
|
+
height: Math.round(rect.height)
|
|
21929
|
+
}
|
|
21930
|
+
};
|
|
21931
|
+
});
|
|
21932
|
+
log("Hit chain elements:", JSON.stringify(hitChainData, null, 2));
|
|
21933
|
+
const allFragments = Array.from(pageEl.querySelectorAll(`.${CLASS_NAMES$1.fragment}`));
|
|
21934
|
+
const fragmentData = allFragments.map((el) => {
|
|
21935
|
+
const rect = el.getBoundingClientRect();
|
|
21936
|
+
return {
|
|
21937
|
+
blockId: el.dataset.blockId,
|
|
21938
|
+
pmStart: el.dataset.pmStart,
|
|
21939
|
+
pmEnd: el.dataset.pmEnd,
|
|
21940
|
+
rect: {
|
|
21941
|
+
top: Math.round(rect.top),
|
|
21942
|
+
bottom: Math.round(rect.bottom),
|
|
21943
|
+
left: Math.round(rect.left),
|
|
21944
|
+
right: Math.round(rect.right),
|
|
21945
|
+
height: Math.round(rect.height)
|
|
21946
|
+
}
|
|
21947
|
+
};
|
|
21948
|
+
});
|
|
21949
|
+
log("All fragments on page:", JSON.stringify(fragmentData, null, 2));
|
|
21611
21950
|
const fragmentEl = hitChain.find((el) => el.classList?.contains?.(CLASS_NAMES$1.fragment));
|
|
21612
21951
|
if (!fragmentEl) {
|
|
21613
21952
|
const fallbackFragment = pageEl.querySelector(`.${CLASS_NAMES$1.fragment}`);
|
|
21614
21953
|
if (!fallbackFragment) {
|
|
21615
21954
|
return null;
|
|
21616
21955
|
}
|
|
21617
|
-
|
|
21956
|
+
log("Using fallback fragment:", {
|
|
21957
|
+
blockId: fallbackFragment.dataset.blockId,
|
|
21958
|
+
pmStart: fallbackFragment.dataset.pmStart,
|
|
21959
|
+
pmEnd: fallbackFragment.dataset.pmEnd
|
|
21960
|
+
});
|
|
21961
|
+
const result2 = processFragment(fallbackFragment, viewX, viewY);
|
|
21962
|
+
return result2;
|
|
21618
21963
|
}
|
|
21619
|
-
|
|
21964
|
+
log("Fragment found:", {
|
|
21965
|
+
blockId: fragmentEl.dataset.blockId,
|
|
21966
|
+
pmStart: fragmentEl.dataset.pmStart,
|
|
21967
|
+
pmEnd: fragmentEl.dataset.pmEnd
|
|
21968
|
+
});
|
|
21969
|
+
const result = processFragment(fragmentEl, viewX, viewY);
|
|
21970
|
+
return result;
|
|
21620
21971
|
}
|
|
21621
21972
|
function findPageElement(domContainer, clientX, clientY) {
|
|
21622
21973
|
if (domContainer.classList?.contains?.(CLASS_NAMES$1.page)) {
|
|
@@ -21648,7 +21999,20 @@ function findPageElement(domContainer, clientX, clientY) {
|
|
|
21648
21999
|
return null;
|
|
21649
22000
|
}
|
|
21650
22001
|
function processFragment(fragmentEl, viewX, viewY) {
|
|
22002
|
+
log("processFragment:", { viewX, viewY, blockId: fragmentEl.dataset.blockId });
|
|
21651
22003
|
const lineEls = Array.from(fragmentEl.querySelectorAll(`.${CLASS_NAMES$1.line}`));
|
|
22004
|
+
log(
|
|
22005
|
+
"Lines in fragment:",
|
|
22006
|
+
lineEls.map((el, i) => {
|
|
22007
|
+
const rect = el.getBoundingClientRect();
|
|
22008
|
+
return {
|
|
22009
|
+
index: i,
|
|
22010
|
+
pmStart: el.dataset.pmStart,
|
|
22011
|
+
pmEnd: el.dataset.pmEnd,
|
|
22012
|
+
rect: { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right }
|
|
22013
|
+
};
|
|
22014
|
+
})
|
|
22015
|
+
);
|
|
21652
22016
|
if (lineEls.length === 0) {
|
|
21653
22017
|
return null;
|
|
21654
22018
|
}
|
|
@@ -21658,10 +22022,30 @@ function processFragment(fragmentEl, viewX, viewY) {
|
|
|
21658
22022
|
}
|
|
21659
22023
|
const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
|
|
21660
22024
|
const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
|
|
22025
|
+
const lineRect = lineEl.getBoundingClientRect();
|
|
22026
|
+
log("Selected line:", {
|
|
22027
|
+
pmStart: lineStart,
|
|
22028
|
+
pmEnd: lineEnd,
|
|
22029
|
+
rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
|
|
22030
|
+
});
|
|
21661
22031
|
if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
|
|
21662
22032
|
return null;
|
|
21663
22033
|
}
|
|
21664
22034
|
const spanEls = Array.from(lineEl.querySelectorAll("span"));
|
|
22035
|
+
log(
|
|
22036
|
+
"Spans in line:",
|
|
22037
|
+
spanEls.map((el, i) => {
|
|
22038
|
+
const rect = el.getBoundingClientRect();
|
|
22039
|
+
return {
|
|
22040
|
+
index: i,
|
|
22041
|
+
pmStart: el.dataset.pmStart,
|
|
22042
|
+
pmEnd: el.dataset.pmEnd,
|
|
22043
|
+
text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
|
|
22044
|
+
visibility: el.style.visibility,
|
|
22045
|
+
rect: { left: rect.left, right: rect.right, width: rect.width }
|
|
22046
|
+
};
|
|
22047
|
+
})
|
|
22048
|
+
);
|
|
21665
22049
|
if (spanEls.length === 0) {
|
|
21666
22050
|
return lineStart;
|
|
21667
22051
|
}
|
|
@@ -21679,6 +22063,14 @@ function processFragment(fragmentEl, viewX, viewY) {
|
|
|
21679
22063
|
}
|
|
21680
22064
|
const spanStart = Number(targetSpan.dataset.pmStart ?? "NaN");
|
|
21681
22065
|
const spanEnd = Number(targetSpan.dataset.pmEnd ?? "NaN");
|
|
22066
|
+
const targetRect = targetSpan.getBoundingClientRect();
|
|
22067
|
+
log("Target span:", {
|
|
22068
|
+
pmStart: spanStart,
|
|
22069
|
+
pmEnd: spanEnd,
|
|
22070
|
+
text: targetSpan.textContent?.substring(0, 30),
|
|
22071
|
+
visibility: targetSpan.style.visibility,
|
|
22072
|
+
rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width }
|
|
22073
|
+
});
|
|
21682
22074
|
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
|
|
21683
22075
|
return null;
|
|
21684
22076
|
}
|
|
@@ -21698,28 +22090,53 @@ function findLineAtY(lineEls, viewY) {
|
|
|
21698
22090
|
if (lineEls.length === 0) {
|
|
21699
22091
|
return null;
|
|
21700
22092
|
}
|
|
21701
|
-
for (
|
|
22093
|
+
for (let i = 0; i < lineEls.length; i++) {
|
|
22094
|
+
const lineEl = lineEls[i];
|
|
21702
22095
|
const rect = lineEl.getBoundingClientRect();
|
|
21703
22096
|
if (viewY >= rect.top && viewY <= rect.bottom) {
|
|
22097
|
+
log("findLineAtY: Found line at index", i, {
|
|
22098
|
+
pmStart: lineEl.dataset.pmStart,
|
|
22099
|
+
pmEnd: lineEl.dataset.pmEnd,
|
|
22100
|
+
rect: { top: rect.top, bottom: rect.bottom },
|
|
22101
|
+
viewY
|
|
22102
|
+
});
|
|
21704
22103
|
return lineEl;
|
|
21705
22104
|
}
|
|
21706
22105
|
}
|
|
21707
|
-
|
|
22106
|
+
const lastLine = lineEls[lineEls.length - 1];
|
|
22107
|
+
log("findLineAtY: Y beyond all lines, using last line:", {
|
|
22108
|
+
pmStart: lastLine.dataset.pmStart,
|
|
22109
|
+
pmEnd: lastLine.dataset.pmEnd,
|
|
22110
|
+
viewY
|
|
22111
|
+
});
|
|
22112
|
+
return lastLine;
|
|
21708
22113
|
}
|
|
21709
22114
|
function findSpanAtX(spanEls, viewX) {
|
|
21710
22115
|
if (spanEls.length === 0) {
|
|
21711
22116
|
return null;
|
|
21712
22117
|
}
|
|
21713
22118
|
let targetSpan = spanEls[0];
|
|
21714
|
-
for (
|
|
22119
|
+
for (let i = 0; i < spanEls.length; i++) {
|
|
22120
|
+
const span = spanEls[i];
|
|
21715
22121
|
const rect = span.getBoundingClientRect();
|
|
21716
22122
|
if (viewX >= rect.left && viewX <= rect.right) {
|
|
22123
|
+
log("findSpanAtX: Found containing span at index", i, {
|
|
22124
|
+
pmStart: span.dataset.pmStart,
|
|
22125
|
+
pmEnd: span.dataset.pmEnd,
|
|
22126
|
+
rect: { left: rect.left, right: rect.right },
|
|
22127
|
+
viewX
|
|
22128
|
+
});
|
|
21717
22129
|
return span;
|
|
21718
22130
|
}
|
|
21719
22131
|
if (viewX > rect.right) {
|
|
21720
22132
|
targetSpan = span;
|
|
21721
22133
|
}
|
|
21722
22134
|
}
|
|
22135
|
+
log("findSpanAtX: No containing span, using nearest:", {
|
|
22136
|
+
pmStart: targetSpan.dataset.pmStart,
|
|
22137
|
+
pmEnd: targetSpan.dataset.pmEnd,
|
|
22138
|
+
viewX
|
|
22139
|
+
});
|
|
21723
22140
|
return targetSpan;
|
|
21724
22141
|
}
|
|
21725
22142
|
function findCharIndexAtX(textNode, span, targetX) {
|
|
@@ -21849,7 +22266,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21849
22266
|
zones.push(zone);
|
|
21850
22267
|
},
|
|
21851
22268
|
getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber) {
|
|
21852
|
-
|
|
22269
|
+
const result = zones.filter((zone) => {
|
|
21853
22270
|
if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
|
|
21854
22271
|
return false;
|
|
21855
22272
|
}
|
|
@@ -21857,8 +22274,10 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21857
22274
|
const lineBottom = lineY + lineHeight;
|
|
21858
22275
|
const zoneTop = zone.bounds.y - zone.distances.top;
|
|
21859
22276
|
const zoneBottom = zone.bounds.y + zone.bounds.height + zone.distances.bottom;
|
|
21860
|
-
|
|
22277
|
+
const overlaps = lineBottom > zoneTop && lineTop < zoneBottom;
|
|
22278
|
+
return overlaps;
|
|
21861
22279
|
});
|
|
22280
|
+
return result;
|
|
21862
22281
|
},
|
|
21863
22282
|
computeAvailableWidth(lineY, lineHeight, baseWidth, columnIndex, pageNumber) {
|
|
21864
22283
|
const exclusions = this.getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber);
|
|
@@ -21871,6 +22290,8 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21871
22290
|
}
|
|
21872
22291
|
const leftFloats = [];
|
|
21873
22292
|
const rightFloats = [];
|
|
22293
|
+
const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
|
|
22294
|
+
const columnCenter = columnOrigin + baseWidth / 2;
|
|
21874
22295
|
for (const zone of wrappingZones) {
|
|
21875
22296
|
if (zone.wrapMode === "left") {
|
|
21876
22297
|
leftFloats.push(zone);
|
|
@@ -21878,7 +22299,7 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21878
22299
|
rightFloats.push(zone);
|
|
21879
22300
|
} else if (zone.wrapMode === "both" || zone.wrapMode === "largest") {
|
|
21880
22301
|
const zoneCenter = zone.bounds.x + zone.bounds.width / 2;
|
|
21881
|
-
if (zoneCenter <
|
|
22302
|
+
if (zoneCenter < columnCenter) {
|
|
21882
22303
|
leftFloats.push(zone);
|
|
21883
22304
|
} else {
|
|
21884
22305
|
rightFloats.push(zone);
|
|
@@ -21890,7 +22311,6 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
|
|
|
21890
22311
|
const boundary = zone.bounds.x + zone.bounds.width + zone.distances.left + zone.distances.right;
|
|
21891
22312
|
leftBoundary = Math.max(leftBoundary, boundary);
|
|
21892
22313
|
}
|
|
21893
|
-
const columnOrigin = marginLeft + columnIndex * (columns.width + columns.gap);
|
|
21894
22314
|
const columnRightEdge = columnOrigin + baseWidth;
|
|
21895
22315
|
let rightBoundary = columnRightEdge;
|
|
21896
22316
|
for (const zone of rightFloats) {
|
|
@@ -22213,9 +22633,6 @@ const extractBlockPmRange = (block) => {
|
|
|
22213
22633
|
pmEnd: end2 ?? (start2 != null ? start2 + 1 : void 0)
|
|
22214
22634
|
};
|
|
22215
22635
|
};
|
|
22216
|
-
const anchorDebugLog = (...args) => {
|
|
22217
|
-
return;
|
|
22218
|
-
};
|
|
22219
22636
|
function layoutParagraphBlock(ctx2, anchors) {
|
|
22220
22637
|
const { block, measure, columnWidth, ensurePage, advanceColumn, columnX, floatManager } = ctx2;
|
|
22221
22638
|
const remeasureParagraph2 = ctx2.remeasureParagraph;
|
|
@@ -22224,23 +22641,45 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22224
22641
|
for (const entry of anchors.anchoredDrawings) {
|
|
22225
22642
|
if (anchors.placedAnchoredIds.has(entry.block.id)) continue;
|
|
22226
22643
|
const state = ensurePage();
|
|
22227
|
-
const baseAnchorY = state.cursorY;
|
|
22228
|
-
const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
|
|
22229
22644
|
const vRelativeFrom = entry.block.anchor?.vRelativeFrom;
|
|
22230
|
-
const
|
|
22231
|
-
const
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22645
|
+
const alignV = entry.block.anchor?.alignV;
|
|
22646
|
+
const offsetV = entry.block.anchor?.offsetV ?? 0;
|
|
22647
|
+
const imageHeight = entry.measure.height;
|
|
22648
|
+
const contentTop = state.topMargin;
|
|
22649
|
+
const contentBottom = state.contentBottom;
|
|
22650
|
+
const contentHeight = Math.max(0, contentBottom - contentTop);
|
|
22651
|
+
let anchorY;
|
|
22652
|
+
if (vRelativeFrom === "margin") {
|
|
22653
|
+
if (alignV === "top") {
|
|
22654
|
+
anchorY = contentTop + offsetV;
|
|
22655
|
+
} else if (alignV === "bottom") {
|
|
22656
|
+
anchorY = contentBottom - imageHeight + offsetV;
|
|
22657
|
+
} else if (alignV === "center") {
|
|
22658
|
+
anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
|
|
22659
|
+
} else {
|
|
22660
|
+
anchorY = contentTop + offsetV;
|
|
22661
|
+
}
|
|
22662
|
+
} else if (vRelativeFrom === "page") {
|
|
22663
|
+
if (alignV === "top") {
|
|
22664
|
+
anchorY = offsetV;
|
|
22665
|
+
} else if (alignV === "bottom") {
|
|
22666
|
+
const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
|
|
22667
|
+
anchorY = pageHeight - imageHeight + offsetV;
|
|
22668
|
+
} else if (alignV === "center") {
|
|
22669
|
+
const pageHeight = contentBottom + (anchors.pageMargins.bottom ?? 0);
|
|
22670
|
+
anchorY = (pageHeight - imageHeight) / 2 + offsetV;
|
|
22671
|
+
} else {
|
|
22672
|
+
anchorY = offsetV;
|
|
22673
|
+
}
|
|
22674
|
+
} else if (vRelativeFrom === "paragraph") {
|
|
22675
|
+
const baseAnchorY = state.cursorY;
|
|
22676
|
+
const firstLineHeight = measure.lines?.[0]?.lineHeight ?? 0;
|
|
22677
|
+
const paragraphAdjustment = firstLineHeight / 2;
|
|
22678
|
+
anchorY = baseAnchorY + paragraphAdjustment + offsetV;
|
|
22679
|
+
} else {
|
|
22680
|
+
const baseAnchorY = state.cursorY;
|
|
22681
|
+
anchorY = baseAnchorY + offsetV;
|
|
22682
|
+
}
|
|
22244
22683
|
floatManager.registerDrawing(entry.block, entry.measure, anchorY, state.columnIndex, state.page.number);
|
|
22245
22684
|
const anchorX = entry.block.anchor ? computeAnchorX(
|
|
22246
22685
|
entry.block.anchor,
|
|
@@ -22280,7 +22719,7 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22280
22719
|
kind: "image",
|
|
22281
22720
|
blockId: entry.block.id,
|
|
22282
22721
|
x: anchorX,
|
|
22283
|
-
y: anchorY
|
|
22722
|
+
y: anchorY,
|
|
22284
22723
|
width: entry.measure.width,
|
|
22285
22724
|
height: entry.measure.height,
|
|
22286
22725
|
isAnchored: true,
|
|
@@ -22296,7 +22735,7 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22296
22735
|
blockId: entry.block.id,
|
|
22297
22736
|
drawingKind: entry.block.drawingKind,
|
|
22298
22737
|
x: anchorX,
|
|
22299
|
-
y: anchorY
|
|
22738
|
+
y: anchorY,
|
|
22300
22739
|
width: entry.measure.width,
|
|
22301
22740
|
height: entry.measure.height,
|
|
22302
22741
|
geometry: entry.measure.geometry,
|
|
@@ -22357,7 +22796,39 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22357
22796
|
state.lastParagraphStyleId = styleId;
|
|
22358
22797
|
return;
|
|
22359
22798
|
}
|
|
22799
|
+
let narrowestWidth = columnWidth;
|
|
22800
|
+
let narrowestOffsetX = 0;
|
|
22360
22801
|
let didRemeasureForFloats = false;
|
|
22802
|
+
if (typeof remeasureParagraph2 === "function") {
|
|
22803
|
+
const tempState = ensurePage();
|
|
22804
|
+
let tempY = tempState.cursorY;
|
|
22805
|
+
if (!appliedSpacingBefore && spacingBefore > 0) {
|
|
22806
|
+
const prevTrailing = tempState.trailingSpacing ?? 0;
|
|
22807
|
+
const neededSpacingBefore = Math.max(spacingBefore - prevTrailing, 0);
|
|
22808
|
+
tempY += neededSpacingBefore;
|
|
22809
|
+
}
|
|
22810
|
+
for (let i = 0; i < lines.length; i++) {
|
|
22811
|
+
const lineY = tempY;
|
|
22812
|
+
const lineHeight = lines[i]?.lineHeight || 0;
|
|
22813
|
+
const { width: availableWidth, offsetX: computedOffset } = floatManager.computeAvailableWidth(
|
|
22814
|
+
lineY,
|
|
22815
|
+
lineHeight,
|
|
22816
|
+
columnWidth,
|
|
22817
|
+
tempState.columnIndex,
|
|
22818
|
+
tempState.page.number
|
|
22819
|
+
);
|
|
22820
|
+
if (availableWidth < narrowestWidth) {
|
|
22821
|
+
narrowestWidth = availableWidth;
|
|
22822
|
+
narrowestOffsetX = computedOffset;
|
|
22823
|
+
}
|
|
22824
|
+
tempY += lineHeight;
|
|
22825
|
+
}
|
|
22826
|
+
if (narrowestWidth < columnWidth) {
|
|
22827
|
+
const newMeasure = remeasureParagraph2(block, narrowestWidth);
|
|
22828
|
+
lines = normalizeLines(newMeasure);
|
|
22829
|
+
didRemeasureForFloats = true;
|
|
22830
|
+
}
|
|
22831
|
+
}
|
|
22361
22832
|
while (fromLine < lines.length) {
|
|
22362
22833
|
let state = ensurePage();
|
|
22363
22834
|
if (state.trailingSpacing == null) state.trailingSpacing = 0;
|
|
@@ -22402,23 +22873,9 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22402
22873
|
}
|
|
22403
22874
|
let effectiveColumnWidth = columnWidth;
|
|
22404
22875
|
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
|
-
}
|
|
22876
|
+
if (didRemeasureForFloats) {
|
|
22877
|
+
effectiveColumnWidth = narrowestWidth;
|
|
22878
|
+
offsetX = narrowestOffsetX;
|
|
22422
22879
|
}
|
|
22423
22880
|
const slice2 = sliceLines(lines, fromLine, state.contentBottom - state.cursorY);
|
|
22424
22881
|
const fragmentHeight = slice2.height;
|
|
@@ -22432,15 +22889,6 @@ function layoutParagraphBlock(ctx2, anchors) {
|
|
|
22432
22889
|
width: effectiveColumnWidth,
|
|
22433
22890
|
...computeFragmentPmRange(block, lines, fromLine, slice2.toLine)
|
|
22434
22891
|
};
|
|
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
22892
|
if (measure.marker && fromLine === 0) {
|
|
22445
22893
|
fragment.markerWidth = measure.marker.markerWidth;
|
|
22446
22894
|
}
|
|
@@ -22653,9 +23101,32 @@ function layoutTableBlock({
|
|
|
22653
23101
|
state.page.fragments.push(fragment);
|
|
22654
23102
|
state.cursorY += height;
|
|
22655
23103
|
}
|
|
23104
|
+
function isPageRelativeAnchor(block) {
|
|
23105
|
+
const vRelativeFrom = block.anchor?.vRelativeFrom;
|
|
23106
|
+
return vRelativeFrom === "margin" || vRelativeFrom === "page";
|
|
23107
|
+
}
|
|
23108
|
+
function collectPreRegisteredAnchors(blocks, measures) {
|
|
23109
|
+
const result = [];
|
|
23110
|
+
const len = Math.min(blocks.length, measures.length);
|
|
23111
|
+
for (let i = 0; i < len; i += 1) {
|
|
23112
|
+
const block = blocks[i];
|
|
23113
|
+
const measure = measures[i];
|
|
23114
|
+
const isImage = block.kind === "image" && measure?.kind === "image";
|
|
23115
|
+
const isDrawing = block.kind === "drawing" && measure?.kind === "drawing";
|
|
23116
|
+
if (!isImage && !isDrawing) continue;
|
|
23117
|
+
const drawingBlock = block;
|
|
23118
|
+
const drawingMeasure = measure;
|
|
23119
|
+
if (!drawingBlock.anchor?.isAnchored) continue;
|
|
23120
|
+
if (isPageRelativeAnchor(drawingBlock)) {
|
|
23121
|
+
result.push({ block: drawingBlock, measure: drawingMeasure });
|
|
23122
|
+
}
|
|
23123
|
+
}
|
|
23124
|
+
return result;
|
|
23125
|
+
}
|
|
22656
23126
|
function collectAnchoredDrawings(blocks, measures) {
|
|
22657
23127
|
const map2 = /* @__PURE__ */ new Map();
|
|
22658
|
-
|
|
23128
|
+
const len = Math.min(blocks.length, measures.length);
|
|
23129
|
+
for (let i = 0; i < len; i += 1) {
|
|
22659
23130
|
if (blocks[i].kind === "paragraph") ;
|
|
22660
23131
|
}
|
|
22661
23132
|
const nearestPrevParagraph = (fromIndex) => {
|
|
@@ -22665,12 +23136,12 @@ function collectAnchoredDrawings(blocks, measures) {
|
|
|
22665
23136
|
return null;
|
|
22666
23137
|
};
|
|
22667
23138
|
const nearestNextParagraph = (fromIndex) => {
|
|
22668
|
-
for (let i = fromIndex + 1; i <
|
|
23139
|
+
for (let i = fromIndex + 1; i < len; i += 1) {
|
|
22669
23140
|
if (blocks[i].kind === "paragraph") return i;
|
|
22670
23141
|
}
|
|
22671
23142
|
return null;
|
|
22672
23143
|
};
|
|
22673
|
-
for (let i = 0; i <
|
|
23144
|
+
for (let i = 0; i < len; i += 1) {
|
|
22674
23145
|
const block = blocks[i];
|
|
22675
23146
|
const measure = measures[i];
|
|
22676
23147
|
const isImage = block.kind === "image" && measure?.kind === "image";
|
|
@@ -22678,7 +23149,12 @@ function collectAnchoredDrawings(blocks, measures) {
|
|
|
22678
23149
|
if (!isImage && !isDrawing) continue;
|
|
22679
23150
|
const drawingBlock = block;
|
|
22680
23151
|
const drawingMeasure = measure;
|
|
22681
|
-
if (!drawingBlock.anchor?.isAnchored)
|
|
23152
|
+
if (!drawingBlock.anchor?.isAnchored) {
|
|
23153
|
+
continue;
|
|
23154
|
+
}
|
|
23155
|
+
if (isPageRelativeAnchor(drawingBlock)) {
|
|
23156
|
+
continue;
|
|
23157
|
+
}
|
|
22682
23158
|
let anchorParaIndex = nearestPrevParagraph(i);
|
|
22683
23159
|
if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
|
|
22684
23160
|
if (anchorParaIndex == null) continue;
|
|
@@ -23274,6 +23750,54 @@ function layoutDocument(blocks, measures, options = {}) {
|
|
|
23274
23750
|
};
|
|
23275
23751
|
const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
|
|
23276
23752
|
const placedAnchoredIds = /* @__PURE__ */ new Set();
|
|
23753
|
+
const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
|
|
23754
|
+
const preRegisteredPositions = /* @__PURE__ */ new Map();
|
|
23755
|
+
for (const entry of preRegisteredAnchors) {
|
|
23756
|
+
const state = paginator.ensurePage();
|
|
23757
|
+
const vRelativeFrom = entry.block.anchor?.vRelativeFrom ?? "paragraph";
|
|
23758
|
+
const alignV = entry.block.anchor?.alignV ?? "top";
|
|
23759
|
+
const offsetV = entry.block.anchor?.offsetV ?? 0;
|
|
23760
|
+
const imageHeight = entry.measure.height ?? 0;
|
|
23761
|
+
const contentTop = state.topMargin;
|
|
23762
|
+
const contentBottom = state.contentBottom;
|
|
23763
|
+
const contentHeight = Math.max(0, contentBottom - contentTop);
|
|
23764
|
+
let anchorY;
|
|
23765
|
+
if (vRelativeFrom === "margin") {
|
|
23766
|
+
if (alignV === "top") {
|
|
23767
|
+
anchorY = contentTop + offsetV;
|
|
23768
|
+
} else if (alignV === "bottom") {
|
|
23769
|
+
anchorY = contentBottom - imageHeight + offsetV;
|
|
23770
|
+
} else if (alignV === "center") {
|
|
23771
|
+
anchorY = contentTop + (contentHeight - imageHeight) / 2 + offsetV;
|
|
23772
|
+
} else {
|
|
23773
|
+
anchorY = contentTop + offsetV;
|
|
23774
|
+
}
|
|
23775
|
+
} else if (vRelativeFrom === "page") {
|
|
23776
|
+
if (alignV === "top") {
|
|
23777
|
+
anchorY = offsetV;
|
|
23778
|
+
} else if (alignV === "bottom") {
|
|
23779
|
+
const pageHeight = contentBottom + margins.bottom;
|
|
23780
|
+
anchorY = pageHeight - imageHeight + offsetV;
|
|
23781
|
+
} else if (alignV === "center") {
|
|
23782
|
+
const pageHeight = contentBottom + margins.bottom;
|
|
23783
|
+
anchorY = (pageHeight - imageHeight) / 2 + offsetV;
|
|
23784
|
+
} else {
|
|
23785
|
+
anchorY = offsetV;
|
|
23786
|
+
}
|
|
23787
|
+
} else {
|
|
23788
|
+
anchorY = contentTop + offsetV;
|
|
23789
|
+
}
|
|
23790
|
+
const anchorX = entry.block.anchor ? computeAnchorX(
|
|
23791
|
+
entry.block.anchor,
|
|
23792
|
+
state.columnIndex,
|
|
23793
|
+
normalizeColumns(activeColumns, contentWidth),
|
|
23794
|
+
entry.measure.width,
|
|
23795
|
+
{ left: margins.left, right: margins.right },
|
|
23796
|
+
activePageSize.w
|
|
23797
|
+
) : margins.left;
|
|
23798
|
+
floatManager.registerDrawing(entry.block, entry.measure, anchorY, state.columnIndex, state.page.number);
|
|
23799
|
+
preRegisteredPositions.set(entry.block.id, { anchorX, anchorY, pageNumber: state.page.number });
|
|
23800
|
+
}
|
|
23277
23801
|
for (let index2 = 0; index2 < blocks.length; index2 += 1) {
|
|
23278
23802
|
const block = blocks[index2];
|
|
23279
23803
|
const measure = measures[index2];
|
|
@@ -23433,6 +23957,52 @@ function layoutDocument(blocks, measures, options = {}) {
|
|
|
23433
23957
|
if (measure.kind !== "image") {
|
|
23434
23958
|
throw new Error(`layoutDocument: expected image measure for block ${block.id}`);
|
|
23435
23959
|
}
|
|
23960
|
+
const preRegPos = preRegisteredPositions.get(block.id);
|
|
23961
|
+
if (preRegPos && Number.isFinite(preRegPos.anchorX) && Number.isFinite(preRegPos.anchorY) && Number.isFinite(preRegPos.pageNumber)) {
|
|
23962
|
+
const state = paginator.ensurePage();
|
|
23963
|
+
const imgBlock = block;
|
|
23964
|
+
const imgMeasure = measure;
|
|
23965
|
+
const pageContentHeight = Math.max(0, state.contentBottom - state.topMargin);
|
|
23966
|
+
const relativeFrom = imgBlock.anchor?.hRelativeFrom ?? "column";
|
|
23967
|
+
const cols = getCurrentColumns();
|
|
23968
|
+
let maxWidth;
|
|
23969
|
+
if (relativeFrom === "page") {
|
|
23970
|
+
maxWidth = cols.count === 1 ? activePageSize.w - margins.left - margins.right : activePageSize.w;
|
|
23971
|
+
} else if (relativeFrom === "margin") {
|
|
23972
|
+
maxWidth = activePageSize.w - margins.left - margins.right;
|
|
23973
|
+
} else {
|
|
23974
|
+
maxWidth = cols.width;
|
|
23975
|
+
}
|
|
23976
|
+
const aspectRatio = imgMeasure.width > 0 && imgMeasure.height > 0 ? imgMeasure.width / imgMeasure.height : 1;
|
|
23977
|
+
const minWidth = 20;
|
|
23978
|
+
const minHeight = minWidth / aspectRatio;
|
|
23979
|
+
const metadata = {
|
|
23980
|
+
originalWidth: imgMeasure.width,
|
|
23981
|
+
originalHeight: imgMeasure.height,
|
|
23982
|
+
maxWidth,
|
|
23983
|
+
maxHeight: pageContentHeight,
|
|
23984
|
+
aspectRatio,
|
|
23985
|
+
minWidth,
|
|
23986
|
+
minHeight
|
|
23987
|
+
};
|
|
23988
|
+
const fragment = {
|
|
23989
|
+
kind: "image",
|
|
23990
|
+
blockId: imgBlock.id,
|
|
23991
|
+
x: preRegPos.anchorX,
|
|
23992
|
+
y: preRegPos.anchorY,
|
|
23993
|
+
width: imgMeasure.width,
|
|
23994
|
+
height: imgMeasure.height,
|
|
23995
|
+
isAnchored: true,
|
|
23996
|
+
zIndex: imgBlock.anchor?.behindDoc ? 0 : 1,
|
|
23997
|
+
metadata
|
|
23998
|
+
};
|
|
23999
|
+
const attrs = imgBlock.attrs;
|
|
24000
|
+
if (attrs?.pmStart != null) fragment.pmStart = attrs.pmStart;
|
|
24001
|
+
if (attrs?.pmEnd != null) fragment.pmEnd = attrs.pmEnd;
|
|
24002
|
+
state.page.fragments.push(fragment);
|
|
24003
|
+
placedAnchoredIds.add(imgBlock.id);
|
|
24004
|
+
continue;
|
|
24005
|
+
}
|
|
23436
24006
|
layoutImageBlock({
|
|
23437
24007
|
block,
|
|
23438
24008
|
measure,
|
|
@@ -23628,7 +24198,7 @@ const hashRuns = (block) => {
|
|
|
23628
24198
|
const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
|
|
23629
24199
|
const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
|
|
23630
24200
|
const runsHash = block.runs.map((run) => {
|
|
23631
|
-
const text = normalizeText(run.kind === "
|
|
24201
|
+
const text = normalizeText("src" in run || run.kind === "lineBreak" ? "" : run.text ?? "");
|
|
23632
24202
|
const bold = "bold" in run ? run.bold : false;
|
|
23633
24203
|
const italic = "italic" in run ? run.italic : false;
|
|
23634
24204
|
const color = "color" in run ? run.color : void 0;
|
|
@@ -23897,7 +24467,13 @@ const FeatureFlags = {
|
|
|
23897
24467
|
* Logs cache hits, misses, invalidations, and bucket selection.
|
|
23898
24468
|
* Should be disabled in production (only enabled for debugging).
|
|
23899
24469
|
*/
|
|
23900
|
-
DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false)
|
|
24470
|
+
DEBUG_HF_CACHE: isEnabled("SD_DEBUG_HF_CACHE", false),
|
|
24471
|
+
/**
|
|
24472
|
+
* Enable debug logging for layout version tracking.
|
|
24473
|
+
* Logs stale layout reads, geometry fallbacks, PM transactions, and layout completions.
|
|
24474
|
+
* Should be disabled in production (only enabled for debugging).
|
|
24475
|
+
*/
|
|
24476
|
+
DEBUG_LAYOUT_VERSION: isEnabled("SD_DEBUG_LAYOUT_VERSION", false)
|
|
23901
24477
|
};
|
|
23902
24478
|
const PageTokenLogger = {
|
|
23903
24479
|
/**
|
|
@@ -24282,7 +24858,7 @@ function fontString(run) {
|
|
|
24282
24858
|
return `${italic}${bold}${size}px ${family}`.trim();
|
|
24283
24859
|
}
|
|
24284
24860
|
function runText(run) {
|
|
24285
|
-
return run.kind === "
|
|
24861
|
+
return "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
|
|
24286
24862
|
}
|
|
24287
24863
|
function measureRunSliceWidth(run, fromChar, toChar) {
|
|
24288
24864
|
const context = getCtx();
|
|
@@ -24444,7 +25020,7 @@ const paragraphBlocksEqual = (a, b) => {
|
|
|
24444
25020
|
for (let i = 0; i < a.runs.length; i += 1) {
|
|
24445
25021
|
const runA = a.runs[i];
|
|
24446
25022
|
const runB = b.runs[i];
|
|
24447
|
-
if ((runA.kind === "
|
|
25023
|
+
if (("src" in runA || runA.kind === "lineBreak" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" ? "" : 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
25024
|
return false;
|
|
24449
25025
|
}
|
|
24450
25026
|
}
|
|
@@ -24564,7 +25140,7 @@ function computeHeaderFooterContentHash(blocks) {
|
|
|
24564
25140
|
parts.push(block.id);
|
|
24565
25141
|
if (block.kind === "paragraph") {
|
|
24566
25142
|
for (const run of block.runs) {
|
|
24567
|
-
if (run.kind !== "
|
|
25143
|
+
if (!("src" in run) && run.kind !== "lineBreak") {
|
|
24568
25144
|
parts.push(run.text ?? "");
|
|
24569
25145
|
}
|
|
24570
25146
|
if ("bold" in run && run.bold) parts.push("b");
|
|
@@ -24993,6 +25569,23 @@ async function remeasureAffectedBlocks(blocks, measures, affectedBlockIds, const
|
|
|
24993
25569
|
}
|
|
24994
25570
|
return updatedMeasures;
|
|
24995
25571
|
}
|
|
25572
|
+
var Priority = /* @__PURE__ */ ((Priority2) => {
|
|
25573
|
+
Priority2[Priority2["P0"] = 0] = "P0";
|
|
25574
|
+
Priority2[Priority2["P1"] = 1] = "P1";
|
|
25575
|
+
Priority2[Priority2["P2"] = 2] = "P2";
|
|
25576
|
+
Priority2[Priority2["P3"] = 3] = "P3";
|
|
25577
|
+
return Priority2;
|
|
25578
|
+
})(Priority || {});
|
|
25579
|
+
({
|
|
25580
|
+
/** P0: No debounce for synchronous cursor positioning */
|
|
25581
|
+
[Priority.P0]: 0,
|
|
25582
|
+
/** P1: One animation frame (~60fps) for viewport layout */
|
|
25583
|
+
[Priority.P1]: 16,
|
|
25584
|
+
/** P2: Typing burst threshold for adjacent pages layout */
|
|
25585
|
+
[Priority.P2]: 50,
|
|
25586
|
+
/** P3: Heavy debounce for full document layout */
|
|
25587
|
+
[Priority.P3]: 150
|
|
25588
|
+
});
|
|
24996
25589
|
const isAtomicFragment = (fragment) => {
|
|
24997
25590
|
return fragment.kind === "drawing" || fragment.kind === "image";
|
|
24998
25591
|
};
|
|
@@ -25080,6 +25673,111 @@ const hitTestAtomicFragment = (pageHit, blocks, measures, point) => {
|
|
|
25080
25673
|
}
|
|
25081
25674
|
return null;
|
|
25082
25675
|
};
|
|
25676
|
+
const hitTestTableFragment = (pageHit, blocks, measures, point) => {
|
|
25677
|
+
for (const fragment of pageHit.page.fragments) {
|
|
25678
|
+
if (fragment.kind !== "table") continue;
|
|
25679
|
+
const tableFragment = fragment;
|
|
25680
|
+
const withinX = point.x >= tableFragment.x && point.x <= tableFragment.x + tableFragment.width;
|
|
25681
|
+
const withinY = point.y >= tableFragment.y && point.y <= tableFragment.y + tableFragment.height;
|
|
25682
|
+
if (!withinX || !withinY) continue;
|
|
25683
|
+
const blockIndex = blocks.findIndex((block2) => block2.id === tableFragment.blockId);
|
|
25684
|
+
if (blockIndex === -1) continue;
|
|
25685
|
+
const block = blocks[blockIndex];
|
|
25686
|
+
const measure = measures[blockIndex];
|
|
25687
|
+
if (!block || block.kind !== "table" || !measure || measure.kind !== "table") continue;
|
|
25688
|
+
const tableBlock = block;
|
|
25689
|
+
const tableMeasure = measure;
|
|
25690
|
+
const localX = point.x - tableFragment.x;
|
|
25691
|
+
const localY = point.y - tableFragment.y;
|
|
25692
|
+
let rowY = 0;
|
|
25693
|
+
let rowIndex = -1;
|
|
25694
|
+
if (tableMeasure.rows.length === 0 || tableBlock.rows.length === 0) continue;
|
|
25695
|
+
for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableMeasure.rows.length; r2++) {
|
|
25696
|
+
const rowMeasure2 = tableMeasure.rows[r2];
|
|
25697
|
+
if (localY >= rowY && localY < rowY + rowMeasure2.height) {
|
|
25698
|
+
rowIndex = r2;
|
|
25699
|
+
break;
|
|
25700
|
+
}
|
|
25701
|
+
rowY += rowMeasure2.height;
|
|
25702
|
+
}
|
|
25703
|
+
if (rowIndex === -1) {
|
|
25704
|
+
rowIndex = Math.min(tableFragment.toRow - 1, tableMeasure.rows.length - 1);
|
|
25705
|
+
if (rowIndex < tableFragment.fromRow) continue;
|
|
25706
|
+
}
|
|
25707
|
+
const rowMeasure = tableMeasure.rows[rowIndex];
|
|
25708
|
+
const row = tableBlock.rows[rowIndex];
|
|
25709
|
+
if (!rowMeasure || !row) continue;
|
|
25710
|
+
let colX = 0;
|
|
25711
|
+
let colIndex = -1;
|
|
25712
|
+
if (rowMeasure.cells.length === 0 || row.cells.length === 0) continue;
|
|
25713
|
+
for (let c = 0; c < rowMeasure.cells.length; c++) {
|
|
25714
|
+
const cellMeasure2 = rowMeasure.cells[c];
|
|
25715
|
+
if (localX >= colX && localX < colX + cellMeasure2.width) {
|
|
25716
|
+
colIndex = c;
|
|
25717
|
+
break;
|
|
25718
|
+
}
|
|
25719
|
+
colX += cellMeasure2.width;
|
|
25720
|
+
}
|
|
25721
|
+
if (colIndex === -1) {
|
|
25722
|
+
colIndex = rowMeasure.cells.length - 1;
|
|
25723
|
+
if (colIndex < 0) continue;
|
|
25724
|
+
}
|
|
25725
|
+
const cellMeasure = rowMeasure.cells[colIndex];
|
|
25726
|
+
const cell = row.cells[colIndex];
|
|
25727
|
+
if (!cellMeasure || !cell) continue;
|
|
25728
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
25729
|
+
const rawMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
|
|
25730
|
+
const cellBlockMeasures = (Array.isArray(rawMeasures) ? rawMeasures : []).filter(
|
|
25731
|
+
(m) => m != null && typeof m === "object" && "kind" in m
|
|
25732
|
+
);
|
|
25733
|
+
let blockStartY = 0;
|
|
25734
|
+
const getBlockHeight = (m) => {
|
|
25735
|
+
if (!m) return 0;
|
|
25736
|
+
if ("totalHeight" in m && typeof m.totalHeight === "number") {
|
|
25737
|
+
return m.totalHeight;
|
|
25738
|
+
}
|
|
25739
|
+
if ("height" in m && typeof m.height === "number") {
|
|
25740
|
+
return m.height;
|
|
25741
|
+
}
|
|
25742
|
+
return 0;
|
|
25743
|
+
};
|
|
25744
|
+
for (let i = 0; i < cellBlocks.length && i < cellBlockMeasures.length; i++) {
|
|
25745
|
+
const cellBlock = cellBlocks[i];
|
|
25746
|
+
const cellBlockMeasure = cellBlockMeasures[i];
|
|
25747
|
+
if (cellBlock?.kind !== "paragraph" || cellBlockMeasure?.kind !== "paragraph") {
|
|
25748
|
+
blockStartY += getBlockHeight(cellBlockMeasure);
|
|
25749
|
+
continue;
|
|
25750
|
+
}
|
|
25751
|
+
const blockHeight = getBlockHeight(cellBlockMeasure);
|
|
25752
|
+
const blockEndY = blockStartY + blockHeight;
|
|
25753
|
+
const padding = cell.attrs?.padding ?? { top: 2, left: 4 };
|
|
25754
|
+
const cellLocalX = localX - colX - (padding.left ?? 4);
|
|
25755
|
+
const cellLocalY = localY - rowY - (padding.top ?? 2);
|
|
25756
|
+
const paragraphBlock = cellBlock;
|
|
25757
|
+
const paragraphMeasure = cellBlockMeasure;
|
|
25758
|
+
const isWithinBlock = cellLocalY >= blockStartY && cellLocalY < blockEndY;
|
|
25759
|
+
const isLastParagraph = i === Math.min(cellBlocks.length, cellBlockMeasures.length) - 1;
|
|
25760
|
+
if (isWithinBlock || isLastParagraph) {
|
|
25761
|
+
const unclampedLocalY = cellLocalY - blockStartY;
|
|
25762
|
+
const localYWithinBlock = Math.max(0, Math.min(unclampedLocalY, Math.max(blockHeight, 0)));
|
|
25763
|
+
return {
|
|
25764
|
+
fragment: tableFragment,
|
|
25765
|
+
block: tableBlock,
|
|
25766
|
+
measure: tableMeasure,
|
|
25767
|
+
pageIndex: pageHit.pageIndex,
|
|
25768
|
+
cellRowIndex: rowIndex,
|
|
25769
|
+
cellColIndex: colIndex,
|
|
25770
|
+
cellBlock: paragraphBlock,
|
|
25771
|
+
cellMeasure: paragraphMeasure,
|
|
25772
|
+
localX: Math.max(0, cellLocalX),
|
|
25773
|
+
localY: Math.max(0, localYWithinBlock)
|
|
25774
|
+
};
|
|
25775
|
+
}
|
|
25776
|
+
blockStartY = blockEndY;
|
|
25777
|
+
}
|
|
25778
|
+
}
|
|
25779
|
+
return null;
|
|
25780
|
+
};
|
|
25083
25781
|
function clickToPosition(layout, blocks, measures, containerPoint, domContainer, clientX, clientY) {
|
|
25084
25782
|
logClickStage("log", "entry", {
|
|
25085
25783
|
pages: layout.pages.length
|
|
@@ -25174,6 +25872,49 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
|
|
|
25174
25872
|
// lineIndex is now already absolute (within measure.lines), no need to add fragment.fromLine
|
|
25175
25873
|
};
|
|
25176
25874
|
}
|
|
25875
|
+
const tableHit = hitTestTableFragment(pageHit, blocks, measures, pageRelativePoint);
|
|
25876
|
+
if (tableHit) {
|
|
25877
|
+
const { cellBlock, cellMeasure, localX, localY, pageIndex } = tableHit;
|
|
25878
|
+
const lineIndex = findLineIndexAtY(cellMeasure, localY, 0, cellMeasure.lines.length);
|
|
25879
|
+
if (lineIndex != null) {
|
|
25880
|
+
const line = cellMeasure.lines[lineIndex];
|
|
25881
|
+
const isRTL = isRtlBlock(cellBlock);
|
|
25882
|
+
const pos = mapPointToPm(cellBlock, line, localX, isRTL);
|
|
25883
|
+
if (pos != null) {
|
|
25884
|
+
logClickStage("log", "success", {
|
|
25885
|
+
blockId: tableHit.fragment.blockId,
|
|
25886
|
+
column: determineColumn(layout, tableHit.fragment.x)
|
|
25887
|
+
});
|
|
25888
|
+
return {
|
|
25889
|
+
pos,
|
|
25890
|
+
blockId: tableHit.fragment.blockId,
|
|
25891
|
+
pageIndex,
|
|
25892
|
+
column: determineColumn(layout, tableHit.fragment.x),
|
|
25893
|
+
lineIndex
|
|
25894
|
+
};
|
|
25895
|
+
}
|
|
25896
|
+
}
|
|
25897
|
+
const firstRun = cellBlock.runs?.[0];
|
|
25898
|
+
if (firstRun && firstRun.pmStart != null) {
|
|
25899
|
+
logClickStage("log", "success", {
|
|
25900
|
+
blockId: tableHit.fragment.blockId,
|
|
25901
|
+
pos: firstRun.pmStart,
|
|
25902
|
+
column: determineColumn(layout, tableHit.fragment.x)
|
|
25903
|
+
});
|
|
25904
|
+
return {
|
|
25905
|
+
pos: firstRun.pmStart,
|
|
25906
|
+
blockId: tableHit.fragment.blockId,
|
|
25907
|
+
pageIndex,
|
|
25908
|
+
column: determineColumn(layout, tableHit.fragment.x),
|
|
25909
|
+
lineIndex: 0
|
|
25910
|
+
};
|
|
25911
|
+
}
|
|
25912
|
+
logClickStage("warn", "table-cell-no-position", {
|
|
25913
|
+
blockId: tableHit.fragment.blockId,
|
|
25914
|
+
cellRow: tableHit.cellRowIndex,
|
|
25915
|
+
cellCol: tableHit.cellColIndex
|
|
25916
|
+
});
|
|
25917
|
+
}
|
|
25177
25918
|
const atomicHit = hitTestAtomicFragment(pageHit, blocks, measures, pageRelativePoint);
|
|
25178
25919
|
if (atomicHit && isAtomicFragment(atomicHit.fragment)) {
|
|
25179
25920
|
const { fragment, block, pageIndex } = atomicHit;
|
|
@@ -25285,6 +26026,44 @@ function getFragmentAtPosition(layout, blocks, measures, pos) {
|
|
|
25285
26026
|
}
|
|
25286
26027
|
continue;
|
|
25287
26028
|
}
|
|
26029
|
+
if (fragment.kind === "table") {
|
|
26030
|
+
if (block.kind !== "table" || measure.kind !== "table") continue;
|
|
26031
|
+
const tableBlock = block;
|
|
26032
|
+
const tableFragment = fragment;
|
|
26033
|
+
let tableMinPos = null;
|
|
26034
|
+
let tableMaxPos = null;
|
|
26035
|
+
for (let r2 = tableFragment.fromRow; r2 < tableFragment.toRow && r2 < tableBlock.rows.length; r2++) {
|
|
26036
|
+
const row = tableBlock.rows[r2];
|
|
26037
|
+
for (const cell of row.cells) {
|
|
26038
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
26039
|
+
for (const cellBlock of cellBlocks) {
|
|
26040
|
+
if (cellBlock?.kind === "paragraph") {
|
|
26041
|
+
const paraBlock = cellBlock;
|
|
26042
|
+
for (const run of paraBlock.runs ?? []) {
|
|
26043
|
+
if (run.pmStart != null) {
|
|
26044
|
+
if (tableMinPos === null || run.pmStart < tableMinPos) tableMinPos = run.pmStart;
|
|
26045
|
+
if (tableMaxPos === null || run.pmStart > tableMaxPos) tableMaxPos = run.pmStart;
|
|
26046
|
+
}
|
|
26047
|
+
if (run.pmEnd != null) {
|
|
26048
|
+
if (tableMinPos === null || run.pmEnd < tableMinPos) tableMinPos = run.pmEnd;
|
|
26049
|
+
if (tableMaxPos === null || run.pmEnd > tableMaxPos) tableMaxPos = run.pmEnd;
|
|
26050
|
+
}
|
|
26051
|
+
}
|
|
26052
|
+
}
|
|
26053
|
+
}
|
|
26054
|
+
}
|
|
26055
|
+
}
|
|
26056
|
+
if (tableMinPos != null && tableMaxPos != null && pos >= tableMinPos && pos <= tableMaxPos) {
|
|
26057
|
+
return {
|
|
26058
|
+
fragment,
|
|
26059
|
+
block,
|
|
26060
|
+
measure,
|
|
26061
|
+
pageIndex,
|
|
26062
|
+
pageY: 0
|
|
26063
|
+
};
|
|
26064
|
+
}
|
|
26065
|
+
continue;
|
|
26066
|
+
}
|
|
25288
26067
|
if (isAtomicFragment(fragment)) {
|
|
25289
26068
|
const { pmStart, pmEnd } = getAtomicPmRange(fragment, block);
|
|
25290
26069
|
const start2 = pmStart ?? pmEnd;
|
|
@@ -25332,7 +26111,7 @@ function computeLinePmRange$1(block, line) {
|
|
|
25332
26111
|
for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
|
|
25333
26112
|
const run = block.runs[runIndex];
|
|
25334
26113
|
if (!run) continue;
|
|
25335
|
-
const text = run.kind === "
|
|
26114
|
+
const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
|
|
25336
26115
|
const runLength = text.length;
|
|
25337
26116
|
const runPmStart = run.pmStart ?? null;
|
|
25338
26117
|
const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
|
|
@@ -27728,16 +28507,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27728
28507
|
opacity: 0.8;
|
|
27729
28508
|
}
|
|
27730
28509
|
|
|
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
28510
|
/* Print mode: show URLs after links */
|
|
27742
28511
|
@media print {
|
|
27743
28512
|
.superdoc-link::after {
|
|
@@ -27750,11 +28519,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27750
28519
|
.superdoc-link[href^="#"]::after {
|
|
27751
28520
|
content: "";
|
|
27752
28521
|
}
|
|
27753
|
-
|
|
27754
|
-
/* Don't show URL for external link indicator */
|
|
27755
|
-
.superdoc-link[target="_blank"]::after {
|
|
27756
|
-
content: " (" attr(href) ")";
|
|
27757
|
-
}
|
|
27758
28522
|
}
|
|
27759
28523
|
|
|
27760
28524
|
/* High contrast mode support */
|
|
@@ -27772,13 +28536,6 @@ const LINK_AND_TOC_STYLES = `
|
|
|
27772
28536
|
}
|
|
27773
28537
|
}
|
|
27774
28538
|
|
|
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
28539
|
/* Screen reader only content (WCAG SC 1.3.1) */
|
|
27783
28540
|
.sr-only {
|
|
27784
28541
|
position: absolute;
|
|
@@ -28233,7 +28990,100 @@ const renderTableFragment = (deps) => {
|
|
|
28233
28990
|
}
|
|
28234
28991
|
return container;
|
|
28235
28992
|
};
|
|
28993
|
+
const isDevelopment = () => {
|
|
28994
|
+
if (typeof process$1 !== "undefined" && typeof process$1.env !== "undefined") {
|
|
28995
|
+
return process$1.env.NODE_ENV === "development";
|
|
28996
|
+
}
|
|
28997
|
+
return false;
|
|
28998
|
+
};
|
|
28999
|
+
class ValidationStatsCollector {
|
|
29000
|
+
constructor() {
|
|
29001
|
+
this.stats = {
|
|
29002
|
+
totalSpans: 0,
|
|
29003
|
+
validSpans: 0,
|
|
29004
|
+
missingPmStart: 0,
|
|
29005
|
+
missingPmEnd: 0,
|
|
29006
|
+
missingBoth: 0
|
|
29007
|
+
};
|
|
29008
|
+
}
|
|
29009
|
+
record(hasPmStart, hasPmEnd) {
|
|
29010
|
+
this.stats.totalSpans++;
|
|
29011
|
+
if (hasPmStart && hasPmEnd) {
|
|
29012
|
+
this.stats.validSpans++;
|
|
29013
|
+
} else if (!hasPmStart && !hasPmEnd) {
|
|
29014
|
+
this.stats.missingBoth++;
|
|
29015
|
+
} else if (!hasPmStart) {
|
|
29016
|
+
this.stats.missingPmStart++;
|
|
29017
|
+
} else {
|
|
29018
|
+
this.stats.missingPmEnd++;
|
|
29019
|
+
}
|
|
29020
|
+
}
|
|
29021
|
+
getStats() {
|
|
29022
|
+
return { ...this.stats };
|
|
29023
|
+
}
|
|
29024
|
+
reset() {
|
|
29025
|
+
this.stats = {
|
|
29026
|
+
totalSpans: 0,
|
|
29027
|
+
validSpans: 0,
|
|
29028
|
+
missingPmStart: 0,
|
|
29029
|
+
missingPmEnd: 0,
|
|
29030
|
+
missingBoth: 0
|
|
29031
|
+
};
|
|
29032
|
+
}
|
|
29033
|
+
getCoveragePercent() {
|
|
29034
|
+
if (this.stats.totalSpans === 0) return 100;
|
|
29035
|
+
return this.stats.validSpans / this.stats.totalSpans * 100;
|
|
29036
|
+
}
|
|
29037
|
+
logSummary() {
|
|
29038
|
+
if (!isDevelopment()) return;
|
|
29039
|
+
const coverage = this.getCoveragePercent();
|
|
29040
|
+
const s2 = this.stats;
|
|
29041
|
+
if (coverage < 100) {
|
|
29042
|
+
console.warn("[PmPositionValidation] PM position coverage:", {
|
|
29043
|
+
coverage: `${coverage.toFixed(1)}%`,
|
|
29044
|
+
totalSpans: s2.totalSpans,
|
|
29045
|
+
validSpans: s2.validSpans,
|
|
29046
|
+
missingPmStart: s2.missingPmStart,
|
|
29047
|
+
missingPmEnd: s2.missingPmEnd,
|
|
29048
|
+
missingBoth: s2.missingBoth
|
|
29049
|
+
});
|
|
29050
|
+
}
|
|
29051
|
+
}
|
|
29052
|
+
}
|
|
29053
|
+
const globalValidationStats = new ValidationStatsCollector();
|
|
29054
|
+
function assertPmPositions(run, context) {
|
|
29055
|
+
const hasPmStart = run.pmStart != null;
|
|
29056
|
+
const hasPmEnd = run.pmEnd != null;
|
|
29057
|
+
globalValidationStats.record(hasPmStart, hasPmEnd);
|
|
29058
|
+
if (!isDevelopment()) return;
|
|
29059
|
+
if (!hasPmStart || !hasPmEnd) {
|
|
29060
|
+
const textPreview = run.text ? run.text.substring(0, 20) + (run.text.length > 20 ? "..." : "") : "(no text)";
|
|
29061
|
+
console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
|
|
29062
|
+
hasPmStart,
|
|
29063
|
+
hasPmEnd,
|
|
29064
|
+
textPreview,
|
|
29065
|
+
fallback: "Will use PM DOM coordinates for cursor positioning"
|
|
29066
|
+
});
|
|
29067
|
+
}
|
|
29068
|
+
}
|
|
29069
|
+
function assertFragmentPmPositions(fragment, context) {
|
|
29070
|
+
const hasPmStart = fragment.pmStart != null;
|
|
29071
|
+
const hasPmEnd = fragment.pmEnd != null;
|
|
29072
|
+
globalValidationStats.record(hasPmStart, hasPmEnd);
|
|
29073
|
+
if (!isDevelopment()) return;
|
|
29074
|
+
if (!hasPmStart || !hasPmEnd) {
|
|
29075
|
+
console.warn(`[PmPositionValidation] Missing PM positions in ${context}:`, {
|
|
29076
|
+
fragmentKind: fragment.kind ?? "unknown",
|
|
29077
|
+
hasPmStart,
|
|
29078
|
+
hasPmEnd,
|
|
29079
|
+
fallback: "Will use PM DOM coordinates for cursor positioning"
|
|
29080
|
+
});
|
|
29081
|
+
}
|
|
29082
|
+
}
|
|
28236
29083
|
const LIST_MARKER_GAP$1 = 8;
|
|
29084
|
+
const COMMENT_EXTERNAL_COLOR = "#B1124B";
|
|
29085
|
+
const COMMENT_INTERNAL_COLOR = "#078383";
|
|
29086
|
+
const COMMENT_INACTIVE_ALPHA = "22";
|
|
28237
29087
|
const LINK_DATASET_KEYS = {
|
|
28238
29088
|
blocked: "linkBlocked",
|
|
28239
29089
|
docLocation: "linkDocLocation",
|
|
@@ -28890,7 +29740,7 @@ const _DomPainter = class _DomPainter {
|
|
|
28890
29740
|
current.element = replacement;
|
|
28891
29741
|
current.signature = fragmentSignature(fragment, this.blockLookup);
|
|
28892
29742
|
}
|
|
28893
|
-
this.updateFragmentElement(current.element, fragment);
|
|
29743
|
+
this.updateFragmentElement(current.element, fragment, contextBase.section);
|
|
28894
29744
|
current.fragment = fragment;
|
|
28895
29745
|
current.key = key2;
|
|
28896
29746
|
current.context = contextBase;
|
|
@@ -28958,10 +29808,10 @@ const _DomPainter = class _DomPainter {
|
|
|
28958
29808
|
return this.renderListItemFragment(fragment, context);
|
|
28959
29809
|
}
|
|
28960
29810
|
if (fragment.kind === "image") {
|
|
28961
|
-
return this.renderImageFragment(fragment);
|
|
29811
|
+
return this.renderImageFragment(fragment, context);
|
|
28962
29812
|
}
|
|
28963
29813
|
if (fragment.kind === "drawing") {
|
|
28964
|
-
return this.renderDrawingFragment(fragment);
|
|
29814
|
+
return this.renderDrawingFragment(fragment, context);
|
|
28965
29815
|
}
|
|
28966
29816
|
if (fragment.kind === "table") {
|
|
28967
29817
|
return this.renderTableFragment(fragment, context);
|
|
@@ -28994,7 +29844,7 @@ const _DomPainter = class _DomPainter {
|
|
|
28994
29844
|
const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
|
|
28995
29845
|
const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
|
|
28996
29846
|
applyStyles$2(fragmentEl, styles);
|
|
28997
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
29847
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
28998
29848
|
if (isTocEntry) {
|
|
28999
29849
|
fragmentEl.classList.add("superdoc-toc-entry");
|
|
29000
29850
|
}
|
|
@@ -29012,8 +29862,32 @@ const _DomPainter = class _DomPainter {
|
|
|
29012
29862
|
}
|
|
29013
29863
|
this.applySdtDataset(fragmentEl, block.attrs?.sdt);
|
|
29014
29864
|
this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
|
|
29865
|
+
const dropCapDescriptor = block.attrs?.dropCapDescriptor;
|
|
29866
|
+
const dropCapMeasure = measure.dropCap;
|
|
29867
|
+
if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
|
|
29868
|
+
const dropCapEl = this.renderDropCap(dropCapDescriptor, dropCapMeasure);
|
|
29869
|
+
fragmentEl.appendChild(dropCapEl);
|
|
29870
|
+
}
|
|
29871
|
+
if (fragmentEl.style.paddingLeft) fragmentEl.style.removeProperty("padding-left");
|
|
29872
|
+
if (fragmentEl.style.paddingRight) fragmentEl.style.removeProperty("padding-right");
|
|
29873
|
+
if (fragmentEl.style.textIndent) fragmentEl.style.removeProperty("text-indent");
|
|
29874
|
+
const paraIndent = block.attrs?.indent;
|
|
29875
|
+
const paraIndentLeft = paraIndent?.left ?? 0;
|
|
29876
|
+
const paraIndentRight = paraIndent?.right ?? 0;
|
|
29877
|
+
const firstLineOffset = (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
|
|
29015
29878
|
lines.forEach((line, index2) => {
|
|
29016
29879
|
const lineEl = this.renderLine(block, line, context);
|
|
29880
|
+
if (paraIndentLeft) {
|
|
29881
|
+
lineEl.style.paddingLeft = `${paraIndentLeft}px`;
|
|
29882
|
+
}
|
|
29883
|
+
if (paraIndentRight) {
|
|
29884
|
+
lineEl.style.paddingRight = `${paraIndentRight}px`;
|
|
29885
|
+
}
|
|
29886
|
+
if (!fragment.continuesFromPrev && index2 === 0 && firstLineOffset) {
|
|
29887
|
+
lineEl.style.textIndent = `${firstLineOffset}px`;
|
|
29888
|
+
} else if (firstLineOffset) {
|
|
29889
|
+
lineEl.style.textIndent = "0px";
|
|
29890
|
+
}
|
|
29017
29891
|
if (index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker) {
|
|
29018
29892
|
const markerContainer = this.doc.createElement("span");
|
|
29019
29893
|
markerContainer.style.display = "inline-block";
|
|
@@ -29024,6 +29898,12 @@ const _DomPainter = class _DomPainter {
|
|
|
29024
29898
|
markerEl.style.textAlign = wordLayout.marker.justification ?? "right";
|
|
29025
29899
|
markerEl.style.paddingRight = `${LIST_MARKER_GAP$1}px`;
|
|
29026
29900
|
markerEl.style.pointerEvents = "none";
|
|
29901
|
+
const indentLeft = paraIndentLeft;
|
|
29902
|
+
const hanging = paraIndent?.hanging ?? 0;
|
|
29903
|
+
const textStartX = indentLeft - hanging;
|
|
29904
|
+
const markerLeftX = textStartX - fragment.markerWidth;
|
|
29905
|
+
markerEl.style.position = "relative";
|
|
29906
|
+
markerEl.style.left = `${markerLeftX}px`;
|
|
29027
29907
|
markerEl.style.fontFamily = wordLayout.marker.run.fontFamily;
|
|
29028
29908
|
markerEl.style.fontSize = `${wordLayout.marker.run.fontSize}px`;
|
|
29029
29909
|
markerEl.style.fontWeight = wordLayout.marker.run.bold ? "bold" : "";
|
|
@@ -29082,6 +29962,53 @@ const _DomPainter = class _DomPainter {
|
|
|
29082
29962
|
}
|
|
29083
29963
|
return el;
|
|
29084
29964
|
}
|
|
29965
|
+
/**
|
|
29966
|
+
* Renders a drop cap element as a floated span at the start of a paragraph.
|
|
29967
|
+
*
|
|
29968
|
+
* Drop caps are large initial letters that span multiple lines of text.
|
|
29969
|
+
* This method creates a floated element with the drop cap letter styled
|
|
29970
|
+
* according to the descriptor's run properties.
|
|
29971
|
+
*
|
|
29972
|
+
* @param descriptor - The drop cap descriptor with text and styling info
|
|
29973
|
+
* @param measure - The measured dimensions of the drop cap
|
|
29974
|
+
* @returns HTMLElement containing the rendered drop cap
|
|
29975
|
+
*/
|
|
29976
|
+
renderDropCap(descriptor, measure) {
|
|
29977
|
+
const doc2 = this.doc;
|
|
29978
|
+
const { run, mode } = descriptor;
|
|
29979
|
+
const dropCapEl = doc2.createElement("span");
|
|
29980
|
+
dropCapEl.classList.add("superdoc-drop-cap");
|
|
29981
|
+
dropCapEl.textContent = run.text;
|
|
29982
|
+
dropCapEl.style.fontFamily = run.fontFamily;
|
|
29983
|
+
dropCapEl.style.fontSize = `${run.fontSize}px`;
|
|
29984
|
+
if (run.bold) {
|
|
29985
|
+
dropCapEl.style.fontWeight = "bold";
|
|
29986
|
+
}
|
|
29987
|
+
if (run.italic) {
|
|
29988
|
+
dropCapEl.style.fontStyle = "italic";
|
|
29989
|
+
}
|
|
29990
|
+
if (run.color) {
|
|
29991
|
+
dropCapEl.style.color = run.color;
|
|
29992
|
+
}
|
|
29993
|
+
if (mode === "drop") {
|
|
29994
|
+
dropCapEl.style.float = "left";
|
|
29995
|
+
dropCapEl.style.marginRight = "4px";
|
|
29996
|
+
dropCapEl.style.lineHeight = "1";
|
|
29997
|
+
} else if (mode === "margin") {
|
|
29998
|
+
dropCapEl.style.position = "absolute";
|
|
29999
|
+
dropCapEl.style.left = "0";
|
|
30000
|
+
dropCapEl.style.lineHeight = "1";
|
|
30001
|
+
}
|
|
30002
|
+
if (run.position && run.position !== 0) {
|
|
30003
|
+
dropCapEl.style.position = dropCapEl.style.position || "relative";
|
|
30004
|
+
dropCapEl.style.top = `${run.position}px`;
|
|
30005
|
+
}
|
|
30006
|
+
if (measure) {
|
|
30007
|
+
dropCapEl.style.width = `${measure.width}px`;
|
|
30008
|
+
dropCapEl.style.height = `${measure.height}px`;
|
|
30009
|
+
}
|
|
30010
|
+
return dropCapEl;
|
|
30011
|
+
}
|
|
29085
30012
|
renderListItemFragment(fragment, context) {
|
|
29086
30013
|
try {
|
|
29087
30014
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
@@ -29159,7 +30086,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29159
30086
|
return this.createErrorPlaceholder(fragment.blockId, error);
|
|
29160
30087
|
}
|
|
29161
30088
|
}
|
|
29162
|
-
renderImageFragment(fragment) {
|
|
30089
|
+
renderImageFragment(fragment, context) {
|
|
29163
30090
|
try {
|
|
29164
30091
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
29165
30092
|
if (!lookup || lookup.block.kind !== "image" || lookup.measure.kind !== "image") {
|
|
@@ -29172,7 +30099,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29172
30099
|
const fragmentEl = this.doc.createElement("div");
|
|
29173
30100
|
fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-image-fragment");
|
|
29174
30101
|
applyStyles$2(fragmentEl, fragmentStyles);
|
|
29175
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
30102
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
29176
30103
|
fragmentEl.style.height = `${fragment.height}px`;
|
|
29177
30104
|
this.applySdtDataset(fragmentEl, block.attrs?.sdt);
|
|
29178
30105
|
this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
|
|
@@ -29207,7 +30134,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29207
30134
|
return this.createErrorPlaceholder(fragment.blockId, error);
|
|
29208
30135
|
}
|
|
29209
30136
|
}
|
|
29210
|
-
renderDrawingFragment(fragment) {
|
|
30137
|
+
renderDrawingFragment(fragment, context) {
|
|
29211
30138
|
try {
|
|
29212
30139
|
const lookup = this.blockLookup.get(fragment.blockId);
|
|
29213
30140
|
if (!lookup || lookup.block.kind !== "drawing" || lookup.measure.kind !== "drawing") {
|
|
@@ -29221,7 +30148,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29221
30148
|
const fragmentEl = this.doc.createElement("div");
|
|
29222
30149
|
fragmentEl.classList.add(CLASS_NAMES.fragment, "superdoc-drawing-fragment");
|
|
29223
30150
|
applyStyles$2(fragmentEl, fragmentStyles);
|
|
29224
|
-
this.applyFragmentFrame(fragmentEl, fragment);
|
|
30151
|
+
this.applyFragmentFrame(fragmentEl, fragment, context.section);
|
|
29225
30152
|
fragmentEl.style.height = `${fragment.height}px`;
|
|
29226
30153
|
fragmentEl.style.position = "absolute";
|
|
29227
30154
|
fragmentEl.style.overflow = "hidden";
|
|
@@ -29668,13 +30595,16 @@ const _DomPainter = class _DomPainter {
|
|
|
29668
30595
|
if (!this.doc) {
|
|
29669
30596
|
throw new Error("DomPainter: document is not available");
|
|
29670
30597
|
}
|
|
30598
|
+
const applyFragmentFrameWithSection = (el, frag) => {
|
|
30599
|
+
this.applyFragmentFrame(el, frag, context.section);
|
|
30600
|
+
};
|
|
29671
30601
|
return renderTableFragment({
|
|
29672
30602
|
doc: this.doc,
|
|
29673
30603
|
fragment,
|
|
29674
30604
|
context,
|
|
29675
30605
|
blockLookup: this.blockLookup,
|
|
29676
30606
|
renderLine: this.renderLine.bind(this),
|
|
29677
|
-
applyFragmentFrame:
|
|
30607
|
+
applyFragmentFrame: applyFragmentFrameWithSection,
|
|
29678
30608
|
applySdtDataset: this.applySdtDataset.bind(this),
|
|
29679
30609
|
applyStyles: applyStyles$2
|
|
29680
30610
|
});
|
|
@@ -29684,7 +30614,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29684
30614
|
* @returns Sanitized link data or null if invalid/missing
|
|
29685
30615
|
*/
|
|
29686
30616
|
extractLinkData(run) {
|
|
29687
|
-
if (run.kind === "tab") {
|
|
30617
|
+
if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak") {
|
|
29688
30618
|
return null;
|
|
29689
30619
|
}
|
|
29690
30620
|
const link = run.link;
|
|
@@ -29838,10 +30768,19 @@ const _DomPainter = class _DomPainter {
|
|
|
29838
30768
|
isImageRun(run) {
|
|
29839
30769
|
return run.kind === "image";
|
|
29840
30770
|
}
|
|
30771
|
+
/**
|
|
30772
|
+
* Type guard to check if a run is a line break run.
|
|
30773
|
+
*/
|
|
30774
|
+
isLineBreakRun(run) {
|
|
30775
|
+
return run.kind === "lineBreak";
|
|
30776
|
+
}
|
|
29841
30777
|
renderRun(run, context, trackedConfig) {
|
|
29842
30778
|
if (this.isImageRun(run)) {
|
|
29843
30779
|
return this.renderImageRun(run);
|
|
29844
30780
|
}
|
|
30781
|
+
if (this.isLineBreakRun(run)) {
|
|
30782
|
+
return null;
|
|
30783
|
+
}
|
|
29845
30784
|
if (!run.text || !this.doc) {
|
|
29846
30785
|
return null;
|
|
29847
30786
|
}
|
|
@@ -29866,8 +30805,21 @@ const _DomPainter = class _DomPainter {
|
|
|
29866
30805
|
}
|
|
29867
30806
|
}
|
|
29868
30807
|
applyRunStyles(elem, run, isActiveLink);
|
|
30808
|
+
const commentColor = getCommentHighlight(run);
|
|
30809
|
+
if (commentColor && !run.highlight) {
|
|
30810
|
+
elem.style.backgroundColor = commentColor;
|
|
30811
|
+
}
|
|
30812
|
+
const commentAnnotations = run.comments;
|
|
30813
|
+
if (commentAnnotations?.length) {
|
|
30814
|
+
elem.dataset.commentIds = commentAnnotations.map((c) => c.commentId).join(",");
|
|
30815
|
+
if (commentAnnotations.some((c) => c.internal)) {
|
|
30816
|
+
elem.dataset.commentInternal = "true";
|
|
30817
|
+
}
|
|
30818
|
+
elem.classList.add("superdoc-comment-highlight");
|
|
30819
|
+
}
|
|
29869
30820
|
elem.style.zIndex = "1";
|
|
29870
30821
|
applyRunDataAttributes(elem, run.dataAttrs);
|
|
30822
|
+
assertPmPositions(run, "paragraph text run");
|
|
29871
30823
|
if (run.pmStart != null) elem.dataset.pmStart = String(run.pmStart);
|
|
29872
30824
|
if (run.pmEnd != null) elem.dataset.pmEnd = String(run.pmEnd);
|
|
29873
30825
|
if (trackedConfig) {
|
|
@@ -29946,6 +30898,7 @@ const _DomPainter = class _DomPainter {
|
|
|
29946
30898
|
img.style.marginRight = `${run.distRight}px`;
|
|
29947
30899
|
}
|
|
29948
30900
|
img.style.zIndex = "1";
|
|
30901
|
+
assertPmPositions(run, "inline image run");
|
|
29949
30902
|
if (run.pmStart != null) {
|
|
29950
30903
|
img.dataset.pmStart = String(run.pmStart);
|
|
29951
30904
|
}
|
|
@@ -29976,9 +30929,9 @@ const _DomPainter = class _DomPainter {
|
|
|
29976
30929
|
if (lineRange.pmEnd != null) {
|
|
29977
30930
|
el.dataset.pmEnd = String(lineRange.pmEnd);
|
|
29978
30931
|
}
|
|
29979
|
-
const
|
|
30932
|
+
const runsForLine = sliceRunsForLine(block, line);
|
|
29980
30933
|
const trackedConfig = this.resolveTrackedChangesConfig(block);
|
|
29981
|
-
if (
|
|
30934
|
+
if (runsForLine.length === 0) {
|
|
29982
30935
|
const span = this.doc.createElement("span");
|
|
29983
30936
|
span.innerHTML = " ";
|
|
29984
30937
|
el.appendChild(span);
|
|
@@ -30026,49 +30979,109 @@ const _DomPainter = class _DomPainter {
|
|
|
30026
30979
|
const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
|
|
30027
30980
|
if (hasExplicitPositioning && line.segments) {
|
|
30028
30981
|
let cumulativeX = 0;
|
|
30029
|
-
|
|
30030
|
-
|
|
30031
|
-
|
|
30032
|
-
if (
|
|
30033
|
-
|
|
30034
|
-
|
|
30035
|
-
|
|
30036
|
-
|
|
30037
|
-
|
|
30038
|
-
|
|
30982
|
+
const segmentsByRun = /* @__PURE__ */ new Map();
|
|
30983
|
+
line.segments.forEach((segment) => {
|
|
30984
|
+
const list = segmentsByRun.get(segment.runIndex);
|
|
30985
|
+
if (list) {
|
|
30986
|
+
list.push(segment);
|
|
30987
|
+
} else {
|
|
30988
|
+
segmentsByRun.set(segment.runIndex, [segment]);
|
|
30989
|
+
}
|
|
30990
|
+
});
|
|
30991
|
+
const findImmediateNextSegmentX = (fromRunIndex) => {
|
|
30992
|
+
const nextRunIdx = fromRunIndex + 1;
|
|
30993
|
+
if (nextRunIdx <= line.toRun) {
|
|
30994
|
+
const nextSegments = segmentsByRun.get(nextRunIdx);
|
|
30995
|
+
if (nextSegments && nextSegments.length > 0) {
|
|
30996
|
+
const firstSegment = nextSegments[0];
|
|
30997
|
+
return firstSegment.x;
|
|
30039
30998
|
}
|
|
30040
|
-
return;
|
|
30041
30999
|
}
|
|
30042
|
-
|
|
30043
|
-
|
|
30044
|
-
|
|
30045
|
-
|
|
31000
|
+
return void 0;
|
|
31001
|
+
};
|
|
31002
|
+
for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
|
|
31003
|
+
const baseRun = block.runs[runIndex];
|
|
31004
|
+
if (!baseRun) continue;
|
|
31005
|
+
if (baseRun.kind === "tab") {
|
|
31006
|
+
const immediateNextX = findImmediateNextSegmentX(runIndex);
|
|
31007
|
+
const tabStartX = cumulativeX;
|
|
31008
|
+
const tabEndX = immediateNextX !== void 0 ? immediateNextX : tabStartX + (baseRun.width ?? 0);
|
|
31009
|
+
const actualTabWidth = tabEndX - tabStartX;
|
|
31010
|
+
const tabEl = this.doc.createElement("span");
|
|
31011
|
+
tabEl.style.position = "absolute";
|
|
31012
|
+
tabEl.style.left = `${tabStartX}px`;
|
|
31013
|
+
tabEl.style.top = "0px";
|
|
31014
|
+
tabEl.style.width = `${actualTabWidth}px`;
|
|
31015
|
+
tabEl.style.height = `${line.lineHeight}px`;
|
|
31016
|
+
tabEl.style.display = "inline-block";
|
|
31017
|
+
tabEl.style.visibility = "hidden";
|
|
31018
|
+
tabEl.style.pointerEvents = "none";
|
|
31019
|
+
tabEl.style.zIndex = "1";
|
|
30046
31020
|
if (styleId) {
|
|
30047
|
-
|
|
31021
|
+
tabEl.setAttribute("styleid", styleId);
|
|
30048
31022
|
}
|
|
30049
|
-
|
|
30050
|
-
if (
|
|
30051
|
-
|
|
30052
|
-
|
|
30053
|
-
|
|
31023
|
+
if (baseRun.pmStart != null) tabEl.dataset.pmStart = String(baseRun.pmStart);
|
|
31024
|
+
if (baseRun.pmEnd != null) tabEl.dataset.pmEnd = String(baseRun.pmEnd);
|
|
31025
|
+
el.appendChild(tabEl);
|
|
31026
|
+
cumulativeX = tabEndX;
|
|
31027
|
+
continue;
|
|
31028
|
+
}
|
|
31029
|
+
if (this.isImageRun(baseRun)) {
|
|
31030
|
+
const elem = this.renderRun(baseRun, context, trackedConfig);
|
|
31031
|
+
if (elem) {
|
|
31032
|
+
if (styleId) {
|
|
31033
|
+
elem.setAttribute("styleid", styleId);
|
|
31034
|
+
}
|
|
31035
|
+
el.appendChild(elem);
|
|
30054
31036
|
}
|
|
30055
|
-
|
|
30056
|
-
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
30064
|
-
|
|
30065
|
-
|
|
31037
|
+
continue;
|
|
31038
|
+
}
|
|
31039
|
+
if (this.isLineBreakRun(baseRun)) {
|
|
31040
|
+
continue;
|
|
31041
|
+
}
|
|
31042
|
+
const runSegments = segmentsByRun.get(runIndex);
|
|
31043
|
+
if (!runSegments || runSegments.length === 0) {
|
|
31044
|
+
continue;
|
|
31045
|
+
}
|
|
31046
|
+
const baseText = baseRun.text ?? "";
|
|
31047
|
+
const runPmStart = baseRun.pmStart ?? null;
|
|
31048
|
+
const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
|
|
31049
|
+
runSegments.forEach((segment) => {
|
|
31050
|
+
const segmentText = baseText.slice(segment.fromChar, segment.toChar);
|
|
31051
|
+
if (!segmentText) return;
|
|
31052
|
+
const pmSliceStart = runPmStart != null ? runPmStart + segment.fromChar : void 0;
|
|
31053
|
+
const pmSliceEnd = runPmStart != null ? runPmStart + segment.toChar : fallbackPmEnd ?? void 0;
|
|
31054
|
+
const segmentRun = {
|
|
31055
|
+
...baseRun,
|
|
31056
|
+
text: segmentText,
|
|
31057
|
+
pmStart: pmSliceStart,
|
|
31058
|
+
pmEnd: pmSliceEnd
|
|
31059
|
+
};
|
|
31060
|
+
const elem = this.renderRun(segmentRun, context, trackedConfig);
|
|
31061
|
+
if (elem) {
|
|
31062
|
+
if (styleId) {
|
|
31063
|
+
elem.setAttribute("styleid", styleId);
|
|
31064
|
+
}
|
|
31065
|
+
const xPos = segment.x !== void 0 ? segment.x : cumulativeX;
|
|
31066
|
+
elem.style.position = "absolute";
|
|
31067
|
+
elem.style.left = `${xPos}px`;
|
|
31068
|
+
el.appendChild(elem);
|
|
31069
|
+
let width = segment.width ?? 0;
|
|
31070
|
+
if (width <= 0 && this.doc) {
|
|
31071
|
+
const measureEl = elem.cloneNode(true);
|
|
31072
|
+
measureEl.style.position = "absolute";
|
|
31073
|
+
measureEl.style.visibility = "hidden";
|
|
31074
|
+
measureEl.style.left = "-9999px";
|
|
31075
|
+
this.doc.body.appendChild(measureEl);
|
|
31076
|
+
width = measureEl.offsetWidth;
|
|
31077
|
+
this.doc.body.removeChild(measureEl);
|
|
31078
|
+
}
|
|
30066
31079
|
cumulativeX = xPos + width;
|
|
30067
31080
|
}
|
|
30068
|
-
}
|
|
30069
|
-
}
|
|
31081
|
+
});
|
|
31082
|
+
}
|
|
30070
31083
|
} else {
|
|
30071
|
-
|
|
31084
|
+
runsForLine.forEach((run) => {
|
|
30072
31085
|
const elem = this.renderRun(run, context, trackedConfig);
|
|
30073
31086
|
if (elem) {
|
|
30074
31087
|
if (styleId) {
|
|
@@ -30126,8 +31139,18 @@ const _DomPainter = class _DomPainter {
|
|
|
30126
31139
|
elem.dataset.trackChangeDate = meta.date;
|
|
30127
31140
|
}
|
|
30128
31141
|
}
|
|
30129
|
-
|
|
30130
|
-
|
|
31142
|
+
/**
|
|
31143
|
+
* Updates an existing fragment element's position and dimensions in place.
|
|
31144
|
+
* Used during incremental updates to efficiently reposition fragments without full re-render.
|
|
31145
|
+
*
|
|
31146
|
+
* @param el - The HTMLElement representing the fragment to update
|
|
31147
|
+
* @param fragment - The fragment data containing updated position and dimensions
|
|
31148
|
+
* @param section - The document section ('body', 'header', 'footer') containing this fragment.
|
|
31149
|
+
* Affects PM position validation - only body sections validate PM positions.
|
|
31150
|
+
* If undefined, defaults to 'body' section behavior.
|
|
31151
|
+
*/
|
|
31152
|
+
updateFragmentElement(el, fragment, section) {
|
|
31153
|
+
this.applyFragmentFrame(el, fragment, section);
|
|
30131
31154
|
if (fragment.kind === "image") {
|
|
30132
31155
|
el.style.height = `${fragment.height}px`;
|
|
30133
31156
|
}
|
|
@@ -30135,12 +31158,27 @@ const _DomPainter = class _DomPainter {
|
|
|
30135
31158
|
el.style.height = `${fragment.height}px`;
|
|
30136
31159
|
}
|
|
30137
31160
|
}
|
|
30138
|
-
|
|
31161
|
+
/**
|
|
31162
|
+
* Applies fragment positioning, dimensions, and metadata to an HTML element.
|
|
31163
|
+
* Sets CSS positioning, block ID, and PM position data attributes for paragraph fragments.
|
|
31164
|
+
*
|
|
31165
|
+
* @param el - The HTMLElement to apply fragment properties to
|
|
31166
|
+
* @param fragment - The fragment data containing position, dimensions, and PM position information
|
|
31167
|
+
* @param section - The document section ('body', 'header', 'footer') containing this fragment.
|
|
31168
|
+
* Controls PM position validation behavior:
|
|
31169
|
+
* - 'body' or undefined: PM positions are validated and required for paragraph fragments
|
|
31170
|
+
* - 'header' or 'footer': PM position validation is skipped (these sections have separate PM coordinate spaces)
|
|
31171
|
+
* When undefined, defaults to 'body' section behavior (validation enabled).
|
|
31172
|
+
*/
|
|
31173
|
+
applyFragmentFrame(el, fragment, section) {
|
|
30139
31174
|
el.style.left = `${fragment.x}px`;
|
|
30140
31175
|
el.style.top = `${fragment.y}px`;
|
|
30141
31176
|
el.style.width = `${fragment.width}px`;
|
|
30142
31177
|
el.dataset.blockId = fragment.blockId;
|
|
30143
31178
|
if (fragment.kind === "para") {
|
|
31179
|
+
if (section === "body" || section === void 0) {
|
|
31180
|
+
assertFragmentPmPositions(fragment, "paragraph fragment");
|
|
31181
|
+
}
|
|
30144
31182
|
if (fragment.pmStart != null) {
|
|
30145
31183
|
el.dataset.pmStart = String(fragment.pmStart);
|
|
30146
31184
|
} else {
|
|
@@ -30387,22 +31425,29 @@ const deriveBlockVersion = (block) => {
|
|
|
30387
31425
|
imgRun.pmEnd ?? ""
|
|
30388
31426
|
].join(",");
|
|
30389
31427
|
}
|
|
31428
|
+
if (run.kind === "lineBreak") {
|
|
31429
|
+
return ["linebreak", run.pmStart ?? "", run.pmEnd ?? ""].join(",");
|
|
31430
|
+
}
|
|
31431
|
+
if (run.kind === "tab") {
|
|
31432
|
+
return [run.text ?? "", "tab", run.pmStart ?? "", run.pmEnd ?? ""].join(",");
|
|
31433
|
+
}
|
|
31434
|
+
const textRun = run;
|
|
30390
31435
|
return [
|
|
30391
|
-
|
|
30392
|
-
|
|
30393
|
-
|
|
30394
|
-
|
|
30395
|
-
|
|
30396
|
-
|
|
31436
|
+
textRun.text ?? "",
|
|
31437
|
+
textRun.fontFamily,
|
|
31438
|
+
textRun.fontSize,
|
|
31439
|
+
textRun.bold ? 1 : 0,
|
|
31440
|
+
textRun.italic ? 1 : 0,
|
|
31441
|
+
textRun.color ?? "",
|
|
30397
31442
|
// Text decorations - ensures DOM updates when decoration properties change.
|
|
30398
|
-
|
|
30399
|
-
|
|
30400
|
-
|
|
30401
|
-
|
|
30402
|
-
|
|
30403
|
-
|
|
30404
|
-
|
|
30405
|
-
|
|
31443
|
+
textRun.underline?.style ?? "",
|
|
31444
|
+
textRun.underline?.color ?? "",
|
|
31445
|
+
textRun.strike ? 1 : 0,
|
|
31446
|
+
textRun.highlight ?? "",
|
|
31447
|
+
textRun.letterSpacing != null ? textRun.letterSpacing : "",
|
|
31448
|
+
textRun.pmStart ?? "",
|
|
31449
|
+
textRun.pmEnd ?? "",
|
|
31450
|
+
textRun.token ?? ""
|
|
30406
31451
|
].join(",");
|
|
30407
31452
|
}).join("|");
|
|
30408
31453
|
}
|
|
@@ -30453,16 +31498,57 @@ const deriveBlockVersion = (block) => {
|
|
|
30453
31498
|
}
|
|
30454
31499
|
if (block.kind === "table") {
|
|
30455
31500
|
const tableBlock = block;
|
|
30456
|
-
|
|
30457
|
-
|
|
30458
|
-
|
|
30459
|
-
|
|
30460
|
-
|
|
31501
|
+
const hashString = (seed, value) => {
|
|
31502
|
+
let hash22 = seed >>> 0;
|
|
31503
|
+
for (let i = 0; i < value.length; i++) {
|
|
31504
|
+
hash22 ^= value.charCodeAt(i);
|
|
31505
|
+
hash22 = Math.imul(hash22, 16777619);
|
|
31506
|
+
}
|
|
31507
|
+
return hash22 >>> 0;
|
|
31508
|
+
};
|
|
31509
|
+
const hashNumber = (seed, value) => {
|
|
31510
|
+
const n = Number.isFinite(value) ? value : 0;
|
|
31511
|
+
let hash22 = seed ^ n;
|
|
31512
|
+
hash22 = Math.imul(hash22, 16777619);
|
|
31513
|
+
hash22 ^= hash22 >>> 13;
|
|
31514
|
+
return hash22 >>> 0;
|
|
31515
|
+
};
|
|
31516
|
+
let hash2 = 2166136261;
|
|
31517
|
+
hash2 = hashString(hash2, block.id);
|
|
31518
|
+
hash2 = hashNumber(hash2, tableBlock.rows.length);
|
|
31519
|
+
hash2 = (tableBlock.columnWidths ?? []).reduce((acc, width) => hashNumber(acc, Math.round(width * 1e3)), hash2);
|
|
31520
|
+
const rows = tableBlock.rows ?? [];
|
|
31521
|
+
for (const row of rows) {
|
|
31522
|
+
if (!row || !Array.isArray(row.cells)) continue;
|
|
31523
|
+
hash2 = hashNumber(hash2, row.cells.length);
|
|
31524
|
+
for (const cell of row.cells) {
|
|
31525
|
+
if (!cell) continue;
|
|
31526
|
+
const cellBlocks = cell.blocks ?? (cell.paragraph ? [cell.paragraph] : []);
|
|
31527
|
+
hash2 = hashNumber(hash2, cellBlocks.length);
|
|
31528
|
+
hash2 = hashNumber(hash2, cell.rowSpan ?? 1);
|
|
31529
|
+
hash2 = hashNumber(hash2, cell.colSpan ?? 1);
|
|
31530
|
+
for (const cellBlock of cellBlocks) {
|
|
31531
|
+
hash2 = hashString(hash2, cellBlock?.kind ?? "unknown");
|
|
31532
|
+
if (cellBlock?.kind === "paragraph") {
|
|
31533
|
+
const runs = cellBlock.runs ?? [];
|
|
31534
|
+
hash2 = hashNumber(hash2, runs.length);
|
|
31535
|
+
for (const run of runs) {
|
|
31536
|
+
if ("text" in run && typeof run.text === "string") {
|
|
31537
|
+
hash2 = hashString(hash2, run.text);
|
|
31538
|
+
}
|
|
31539
|
+
hash2 = hashNumber(hash2, run.pmStart ?? -1);
|
|
31540
|
+
hash2 = hashNumber(hash2, run.pmEnd ?? -1);
|
|
31541
|
+
}
|
|
31542
|
+
}
|
|
31543
|
+
}
|
|
31544
|
+
}
|
|
31545
|
+
}
|
|
31546
|
+
return [block.id, tableBlock.rows.length, hash2.toString(16)].join("|");
|
|
30461
31547
|
}
|
|
30462
31548
|
return block.id;
|
|
30463
31549
|
};
|
|
30464
31550
|
const applyRunStyles = (element, run, isLink = false) => {
|
|
30465
|
-
if (run.kind === "tab" || run.kind === "image") {
|
|
31551
|
+
if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak") {
|
|
30466
31552
|
return;
|
|
30467
31553
|
}
|
|
30468
31554
|
element.style.fontFamily = run.fontFamily;
|
|
@@ -30494,6 +31580,13 @@ const applyRunStyles = (element, run, isLink = false) => {
|
|
|
30494
31580
|
element.style.textDecorationLine = decorations.join(" ");
|
|
30495
31581
|
}
|
|
30496
31582
|
};
|
|
31583
|
+
const getCommentHighlight = (run) => {
|
|
31584
|
+
const comments = run.comments;
|
|
31585
|
+
if (!comments || comments.length === 0) return void 0;
|
|
31586
|
+
const primary = comments[0];
|
|
31587
|
+
const base2 = primary.internal ? COMMENT_INTERNAL_COLOR : COMMENT_EXTERNAL_COLOR;
|
|
31588
|
+
return `${base2}${COMMENT_INACTIVE_ALPHA}`;
|
|
31589
|
+
};
|
|
30497
31590
|
const applyRunDataAttributes = (element, dataAttrs) => {
|
|
30498
31591
|
if (!dataAttrs) return;
|
|
30499
31592
|
Object.entries(dataAttrs).forEach(([key2, value]) => {
|
|
@@ -30585,6 +31678,10 @@ const sliceRunsForLine = (block, line) => {
|
|
|
30585
31678
|
result.push(run);
|
|
30586
31679
|
continue;
|
|
30587
31680
|
}
|
|
31681
|
+
if (run.kind === "lineBreak") {
|
|
31682
|
+
result.push(run);
|
|
31683
|
+
continue;
|
|
31684
|
+
}
|
|
30588
31685
|
const text = run.text ?? "";
|
|
30589
31686
|
const isFirstRun = runIndex === line.fromRun;
|
|
30590
31687
|
const isLastRun = runIndex === line.toRun;
|
|
@@ -30607,7 +31704,8 @@ const sliceRunsForLine = (block, line) => {
|
|
|
30607
31704
|
...run,
|
|
30608
31705
|
text: slice2,
|
|
30609
31706
|
pmStart: pmSliceStart,
|
|
30610
|
-
pmEnd: pmSliceEnd
|
|
31707
|
+
pmEnd: pmSliceEnd,
|
|
31708
|
+
comments: run.comments ? [...run.comments] : void 0
|
|
30611
31709
|
};
|
|
30612
31710
|
result.push(sliced);
|
|
30613
31711
|
}
|
|
@@ -30638,6 +31736,21 @@ const computeLinePmRange = (block, line) => {
|
|
|
30638
31736
|
}
|
|
30639
31737
|
continue;
|
|
30640
31738
|
}
|
|
31739
|
+
if (run.kind === "lineBreak") {
|
|
31740
|
+
const runPmStart2 = run.pmStart ?? null;
|
|
31741
|
+
const runPmEnd = run.pmEnd ?? null;
|
|
31742
|
+
if (runPmStart2 == null || runPmEnd == null) {
|
|
31743
|
+
continue;
|
|
31744
|
+
}
|
|
31745
|
+
if (pmStart == null) {
|
|
31746
|
+
pmStart = runPmStart2;
|
|
31747
|
+
}
|
|
31748
|
+
pmEnd = runPmEnd;
|
|
31749
|
+
if (runIndex === line.toRun) {
|
|
31750
|
+
break;
|
|
31751
|
+
}
|
|
31752
|
+
continue;
|
|
31753
|
+
}
|
|
30641
31754
|
const text = run.text ?? "";
|
|
30642
31755
|
const runLength = text.length;
|
|
30643
31756
|
const runPmStart = run.pmStart ?? null;
|
|
@@ -30676,6 +31789,9 @@ const resolveRunText = (run, context) => {
|
|
|
30676
31789
|
if (run.kind === "image") {
|
|
30677
31790
|
return "";
|
|
30678
31791
|
}
|
|
31792
|
+
if (run.kind === "lineBreak") {
|
|
31793
|
+
return "";
|
|
31794
|
+
}
|
|
30679
31795
|
if (!runToken) {
|
|
30680
31796
|
return run.text ?? "";
|
|
30681
31797
|
}
|
|
@@ -30842,6 +31958,9 @@ function isTabRun(run) {
|
|
|
30842
31958
|
function isImageRun(run) {
|
|
30843
31959
|
return run.kind === "image";
|
|
30844
31960
|
}
|
|
31961
|
+
function isLineBreakRun(run) {
|
|
31962
|
+
return run.kind === "lineBreak";
|
|
31963
|
+
}
|
|
30845
31964
|
async function measureBlock(block, constraints) {
|
|
30846
31965
|
const normalized = normalizeConstraints(constraints);
|
|
30847
31966
|
if (block.kind === "drawing") {
|
|
@@ -30879,7 +31998,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30879
31998
|
const hanging = indent?.hanging ?? 0;
|
|
30880
31999
|
const firstLineOffset = firstLine - hanging;
|
|
30881
32000
|
const contentWidth = Math.max(1, maxWidth - indentLeft - indentRight);
|
|
30882
|
-
|
|
32001
|
+
const initialAvailableWidth = Math.max(1, contentWidth - firstLineOffset);
|
|
30883
32002
|
const tabStops = buildTabStopsPx(
|
|
30884
32003
|
indent,
|
|
30885
32004
|
block.attrs?.tabs,
|
|
@@ -30892,6 +32011,18 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30892
32011
|
line.bars = barTabStops.map((stop) => ({ x: stop.pos }));
|
|
30893
32012
|
}
|
|
30894
32013
|
};
|
|
32014
|
+
const dropCapDescriptor = block.attrs?.dropCapDescriptor;
|
|
32015
|
+
let dropCapMeasure = null;
|
|
32016
|
+
if (dropCapDescriptor) {
|
|
32017
|
+
if (!dropCapDescriptor.run || !dropCapDescriptor.run.text || !dropCapDescriptor.lines) {
|
|
32018
|
+
console.warn("Invalid drop cap descriptor - missing required fields:", dropCapDescriptor);
|
|
32019
|
+
} else {
|
|
32020
|
+
const dropCapMeasured = measureDropCap(ctx2, dropCapDescriptor, spacing);
|
|
32021
|
+
dropCapMeasure = dropCapMeasured;
|
|
32022
|
+
dropCapDescriptor.measuredWidth = dropCapMeasured.width;
|
|
32023
|
+
dropCapDescriptor.measuredHeight = dropCapMeasured.height;
|
|
32024
|
+
}
|
|
32025
|
+
}
|
|
30895
32026
|
if (block.runs.length === 0) {
|
|
30896
32027
|
const metrics = calculateTypographyMetrics(12, spacing);
|
|
30897
32028
|
const emptyLine = {
|
|
@@ -30911,6 +32042,13 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30911
32042
|
};
|
|
30912
32043
|
}
|
|
30913
32044
|
let currentLine = null;
|
|
32045
|
+
const getEffectiveWidth = (baseWidth) => {
|
|
32046
|
+
if (dropCapMeasure && lines.length < dropCapMeasure.lines && dropCapMeasure.mode === "drop") {
|
|
32047
|
+
return Math.max(1, baseWidth - dropCapMeasure.width);
|
|
32048
|
+
}
|
|
32049
|
+
return baseWidth;
|
|
32050
|
+
};
|
|
32051
|
+
let lastFontSize = 12;
|
|
30914
32052
|
let tabStopCursor = 0;
|
|
30915
32053
|
let pendingTabAlignment = null;
|
|
30916
32054
|
let lastAppliedTabAlign = null;
|
|
@@ -30947,6 +32085,47 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30947
32085
|
};
|
|
30948
32086
|
for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
|
|
30949
32087
|
const run = block.runs[runIndex];
|
|
32088
|
+
if (isLineBreakRun(run)) {
|
|
32089
|
+
if (currentLine) {
|
|
32090
|
+
const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
|
|
32091
|
+
const completedLine = {
|
|
32092
|
+
...currentLine,
|
|
32093
|
+
...metrics
|
|
32094
|
+
};
|
|
32095
|
+
addBarTabsToLine(completedLine);
|
|
32096
|
+
lines.push(completedLine);
|
|
32097
|
+
} else {
|
|
32098
|
+
const metrics = calculateTypographyMetrics(lastFontSize, spacing);
|
|
32099
|
+
const emptyLine = {
|
|
32100
|
+
fromRun: runIndex,
|
|
32101
|
+
fromChar: 0,
|
|
32102
|
+
toRun: runIndex,
|
|
32103
|
+
toChar: 0,
|
|
32104
|
+
width: 0,
|
|
32105
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
32106
|
+
segments: [],
|
|
32107
|
+
...metrics
|
|
32108
|
+
};
|
|
32109
|
+
addBarTabsToLine(emptyLine);
|
|
32110
|
+
lines.push(emptyLine);
|
|
32111
|
+
}
|
|
32112
|
+
const hadPreviousLine = lines.length > 0;
|
|
32113
|
+
const nextLineMaxWidth = hadPreviousLine ? getEffectiveWidth(contentWidth) : getEffectiveWidth(initialAvailableWidth);
|
|
32114
|
+
currentLine = {
|
|
32115
|
+
fromRun: runIndex,
|
|
32116
|
+
fromChar: 0,
|
|
32117
|
+
toRun: runIndex,
|
|
32118
|
+
toChar: 0,
|
|
32119
|
+
width: 0,
|
|
32120
|
+
maxFontSize: lastFontSize,
|
|
32121
|
+
maxWidth: nextLineMaxWidth,
|
|
32122
|
+
segments: []
|
|
32123
|
+
};
|
|
32124
|
+
tabStopCursor = 0;
|
|
32125
|
+
pendingTabAlignment = null;
|
|
32126
|
+
lastAppliedTabAlign = null;
|
|
32127
|
+
continue;
|
|
32128
|
+
}
|
|
30950
32129
|
if (isTabRun(run)) {
|
|
30951
32130
|
if (!currentLine) {
|
|
30952
32131
|
currentLine = {
|
|
@@ -30957,7 +32136,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
30957
32136
|
width: 0,
|
|
30958
32137
|
maxFontSize: 12,
|
|
30959
32138
|
// Default font size for tabs
|
|
30960
|
-
maxWidth:
|
|
32139
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
30961
32140
|
segments: []
|
|
30962
32141
|
};
|
|
30963
32142
|
}
|
|
@@ -31002,7 +32181,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31002
32181
|
width: imageWidth,
|
|
31003
32182
|
maxFontSize: imageHeight,
|
|
31004
32183
|
// Use image height for line height calculation
|
|
31005
|
-
maxWidth:
|
|
32184
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31006
32185
|
segments: [
|
|
31007
32186
|
{
|
|
31008
32187
|
runIndex,
|
|
@@ -31012,7 +32191,6 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31012
32191
|
}
|
|
31013
32192
|
]
|
|
31014
32193
|
};
|
|
31015
|
-
availableWidth = contentWidth;
|
|
31016
32194
|
continue;
|
|
31017
32195
|
}
|
|
31018
32196
|
if (currentLine.width + imageWidth > currentLine.maxWidth && currentLine.width > 0) {
|
|
@@ -31032,7 +32210,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31032
32210
|
toChar: 1,
|
|
31033
32211
|
width: imageWidth,
|
|
31034
32212
|
maxFontSize: imageHeight,
|
|
31035
|
-
maxWidth: contentWidth,
|
|
32213
|
+
maxWidth: getEffectiveWidth(contentWidth),
|
|
31036
32214
|
segments: [
|
|
31037
32215
|
{
|
|
31038
32216
|
runIndex,
|
|
@@ -31042,7 +32220,6 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31042
32220
|
}
|
|
31043
32221
|
]
|
|
31044
32222
|
};
|
|
31045
|
-
availableWidth = contentWidth;
|
|
31046
32223
|
} else {
|
|
31047
32224
|
currentLine.toRun = runIndex;
|
|
31048
32225
|
currentLine.toChar = 1;
|
|
@@ -31058,6 +32235,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31058
32235
|
}
|
|
31059
32236
|
continue;
|
|
31060
32237
|
}
|
|
32238
|
+
lastFontSize = run.fontSize;
|
|
31061
32239
|
const { font } = buildFontString(run);
|
|
31062
32240
|
const tabSegments = run.text.split(" ");
|
|
31063
32241
|
let charPosInRun = 0;
|
|
@@ -31092,7 +32270,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31092
32270
|
toChar: wordEndNoSpace,
|
|
31093
32271
|
width: wordOnlyWidth,
|
|
31094
32272
|
maxFontSize: run.fontSize,
|
|
31095
|
-
maxWidth:
|
|
32273
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31096
32274
|
segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
|
|
31097
32275
|
};
|
|
31098
32276
|
const ls = run.letterSpacing ?? 0;
|
|
@@ -31103,7 +32281,6 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31103
32281
|
} else {
|
|
31104
32282
|
charPosInRun = wordEndNoSpace;
|
|
31105
32283
|
}
|
|
31106
|
-
availableWidth = contentWidth;
|
|
31107
32284
|
continue;
|
|
31108
32285
|
}
|
|
31109
32286
|
const isTocEntry = block.attrs?.isTocEntry;
|
|
@@ -31125,7 +32302,7 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31125
32302
|
toChar: wordEndNoSpace,
|
|
31126
32303
|
width: wordOnlyWidth,
|
|
31127
32304
|
maxFontSize: run.fontSize,
|
|
31128
|
-
maxWidth: contentWidth,
|
|
32305
|
+
maxWidth: getEffectiveWidth(contentWidth),
|
|
31129
32306
|
segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
|
|
31130
32307
|
};
|
|
31131
32308
|
if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
|
|
@@ -31181,10 +32358,9 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31181
32358
|
toChar: charPosInRun,
|
|
31182
32359
|
width: 0,
|
|
31183
32360
|
maxFontSize: run.fontSize,
|
|
31184
|
-
maxWidth:
|
|
32361
|
+
maxWidth: getEffectiveWidth(initialAvailableWidth),
|
|
31185
32362
|
segments: []
|
|
31186
32363
|
};
|
|
31187
|
-
availableWidth = contentWidth;
|
|
31188
32364
|
}
|
|
31189
32365
|
const originX = currentLine.width;
|
|
31190
32366
|
const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
|
|
@@ -31257,7 +32433,8 @@ async function measureParagraphBlock(block, maxWidth) {
|
|
|
31257
32433
|
kind: "paragraph",
|
|
31258
32434
|
lines,
|
|
31259
32435
|
totalHeight,
|
|
31260
|
-
...markerInfo ? { marker: markerInfo } : {}
|
|
32436
|
+
...markerInfo ? { marker: markerInfo } : {},
|
|
32437
|
+
...dropCapMeasure ? { dropCap: dropCapMeasure } : {}
|
|
31261
32438
|
};
|
|
31262
32439
|
}
|
|
31263
32440
|
async function measureTableBlock(block, constraints) {
|
|
@@ -31537,7 +32714,7 @@ const getPrimaryRun = (paragraph) => {
|
|
|
31537
32714
|
};
|
|
31538
32715
|
};
|
|
31539
32716
|
const measureRunWidth = (text, font, ctx2, run) => {
|
|
31540
|
-
const letterSpacing = run.kind === "text" ? run.letterSpacing || 0 : 0;
|
|
32717
|
+
const letterSpacing = run.kind === "text" || run.kind === void 0 ? run.letterSpacing || 0 : 0;
|
|
31541
32718
|
const width = getMeasuredTextWidth(text, font, letterSpacing, ctx2);
|
|
31542
32719
|
return roundValue(width);
|
|
31543
32720
|
};
|
|
@@ -31573,6 +32750,30 @@ const sanitizeDecimalSeparator = (value) => {
|
|
|
31573
32750
|
if (value === ",") return ",";
|
|
31574
32751
|
return DEFAULT_DECIMAL_SEPARATOR;
|
|
31575
32752
|
};
|
|
32753
|
+
const DROP_CAP_PADDING_PX = 4;
|
|
32754
|
+
const measureDropCap = (ctx2, descriptor, spacing) => {
|
|
32755
|
+
const { run, lines, mode } = descriptor;
|
|
32756
|
+
const { font } = buildFontString({
|
|
32757
|
+
fontFamily: run.fontFamily,
|
|
32758
|
+
fontSize: run.fontSize,
|
|
32759
|
+
bold: run.bold,
|
|
32760
|
+
italic: run.italic
|
|
32761
|
+
});
|
|
32762
|
+
ctx2.font = font;
|
|
32763
|
+
const metrics = ctx2.measureText(run.text);
|
|
32764
|
+
const advanceWidth = metrics.width;
|
|
32765
|
+
const paintedWidth = (metrics.actualBoundingBoxLeft || 0) + (metrics.actualBoundingBoxRight || 0);
|
|
32766
|
+
const textWidth = Math.max(advanceWidth, paintedWidth);
|
|
32767
|
+
const width = roundValue(textWidth + DROP_CAP_PADDING_PX);
|
|
32768
|
+
const baseLineHeight = resolveLineHeight(spacing, run.fontSize * 1.2);
|
|
32769
|
+
const height = roundValue(baseLineHeight * lines);
|
|
32770
|
+
return {
|
|
32771
|
+
width,
|
|
32772
|
+
height,
|
|
32773
|
+
lines,
|
|
32774
|
+
mode
|
|
32775
|
+
};
|
|
32776
|
+
};
|
|
31576
32777
|
const resolveIndentLeft = (item) => {
|
|
31577
32778
|
const indentLeft = sanitizePositive(item.paragraph.attrs?.indent?.left);
|
|
31578
32779
|
if (indentLeft > 0) {
|
|
@@ -32711,10 +33912,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
|
|
|
32711
33912
|
const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, hit.pos));
|
|
32712
33913
|
try {
|
|
32713
33914
|
__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
|
-
}
|
|
33915
|
+
} catch {
|
|
32718
33916
|
}
|
|
32719
33917
|
}
|
|
32720
33918
|
__privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
|
|
@@ -35247,10 +36445,10 @@ computeHeaderFooterCaretRect_fn = function(pos) {
|
|
|
35247
36445
|
if (!lineInfo) return null;
|
|
35248
36446
|
const { line, index: index2 } = lineInfo;
|
|
35249
36447
|
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,
|
|
36448
|
+
if (range.pmStart == null || range.pmEnd == null) return null;
|
|
36449
|
+
const pmCharsInLine = Math.max(1, range.pmEnd - range.pmStart);
|
|
36450
|
+
const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range.pmStart));
|
|
36451
|
+
const localX = hit.fragment.x + measureCharacterX(block, line, pmOffset);
|
|
35254
36452
|
const lineOffset = __privateMethod(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, hit.fragment.fromLine, index2);
|
|
35255
36453
|
const headerPageHeight = context.layout.pageSize?.h ?? context.region.height ?? 1;
|
|
35256
36454
|
const headerLocalY = hit.pageIndex * headerPageHeight + (hit.fragment.y + lineOffset);
|
|
@@ -35390,23 +36588,34 @@ normalizeClientPoint_fn = function(clientX, clientY) {
|
|
|
35390
36588
|
computeCaretLayoutRect_fn = function(pos) {
|
|
35391
36589
|
const layout = __privateGet(this, _layoutState).layout;
|
|
35392
36590
|
if (!layout) return null;
|
|
36591
|
+
const domResult = __privateMethod(this, _PresentationEditor_instances, computeCaretLayoutRectFromDOM_fn).call(this, pos);
|
|
36592
|
+
if (domResult) {
|
|
36593
|
+
return domResult;
|
|
36594
|
+
}
|
|
35393
36595
|
const hit = getFragmentAtPosition(layout, __privateGet(this, _layoutState).blocks, __privateGet(this, _layoutState).measures, pos);
|
|
35394
|
-
if (!hit)
|
|
36596
|
+
if (!hit) {
|
|
36597
|
+
return null;
|
|
36598
|
+
}
|
|
35395
36599
|
const block = hit.block;
|
|
35396
36600
|
const measure = hit.measure;
|
|
36601
|
+
if (hit.fragment.kind === "table" && block?.kind === "table" && measure?.kind === "table") {
|
|
36602
|
+
return __privateMethod(this, _PresentationEditor_instances, computeTableCaretLayoutRect_fn).call(this, pos, hit.fragment, block, measure, hit.pageIndex);
|
|
36603
|
+
}
|
|
35397
36604
|
if (!block || block.kind !== "paragraph" || measure?.kind !== "paragraph") return null;
|
|
35398
36605
|
if (hit.fragment.kind !== "para") {
|
|
35399
36606
|
return null;
|
|
35400
36607
|
}
|
|
35401
36608
|
const fragment = hit.fragment;
|
|
35402
36609
|
const lineInfo = __privateMethod(this, _PresentationEditor_instances, findLineContainingPos_fn).call(this, block, measure, fragment.fromLine, fragment.toLine, pos);
|
|
35403
|
-
if (!lineInfo)
|
|
36610
|
+
if (!lineInfo) {
|
|
36611
|
+
return null;
|
|
36612
|
+
}
|
|
35404
36613
|
const { line, index: index2 } = lineInfo;
|
|
35405
36614
|
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,
|
|
36615
|
+
if (range.pmStart == null || range.pmEnd == null) return null;
|
|
36616
|
+
const pmCharsInLine = Math.max(1, range.pmEnd - range.pmStart);
|
|
36617
|
+
const pmOffset = Math.max(0, Math.min(pmCharsInLine, pos - range.pmStart));
|
|
36618
|
+
const localX = fragment.x + measureCharacterX(block, line, pmOffset);
|
|
35410
36619
|
const lineOffset = __privateMethod(this, _PresentationEditor_instances, lineHeightBeforeIndex_fn).call(this, measure.lines, fragment.fromLine, index2);
|
|
35411
36620
|
const localY = fragment.y + lineOffset;
|
|
35412
36621
|
return {
|
|
@@ -35416,17 +36625,179 @@ computeCaretLayoutRect_fn = function(pos) {
|
|
|
35416
36625
|
height: line.lineHeight
|
|
35417
36626
|
};
|
|
35418
36627
|
};
|
|
36628
|
+
/**
|
|
36629
|
+
* Computes caret position using DOM-based positioning.
|
|
36630
|
+
* This matches how click-to-position mapping works and correctly handles
|
|
36631
|
+
* segment-based rendering with tab stops.
|
|
36632
|
+
*
|
|
36633
|
+
* Returns page-local coordinates (x, y relative to the page element).
|
|
36634
|
+
*/
|
|
36635
|
+
computeCaretLayoutRectFromDOM_fn = function(pos) {
|
|
36636
|
+
const zoom = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
36637
|
+
let targetPageEl = null;
|
|
36638
|
+
if (__privateGet(this, _layoutState).layout && __privateGet(this, _layoutState).blocks && __privateGet(this, _layoutState).measures) {
|
|
36639
|
+
const fragmentHit = getFragmentAtPosition(
|
|
36640
|
+
__privateGet(this, _layoutState).layout,
|
|
36641
|
+
__privateGet(this, _layoutState).blocks,
|
|
36642
|
+
__privateGet(this, _layoutState).measures,
|
|
36643
|
+
pos
|
|
36644
|
+
);
|
|
36645
|
+
if (fragmentHit) {
|
|
36646
|
+
const pageEl = __privateGet(this, _viewportHost).querySelector(
|
|
36647
|
+
`.superdoc-page[data-page-index="${fragmentHit.pageIndex}"]`
|
|
36648
|
+
);
|
|
36649
|
+
if (pageEl) {
|
|
36650
|
+
targetPageEl = pageEl;
|
|
36651
|
+
}
|
|
36652
|
+
}
|
|
36653
|
+
}
|
|
36654
|
+
const spanEls = Array.from(
|
|
36655
|
+
targetPageEl ? targetPageEl.querySelectorAll("span[data-pm-start][data-pm-end]") : __privateGet(this, _viewportHost).querySelectorAll("span[data-pm-start][data-pm-end]")
|
|
36656
|
+
);
|
|
36657
|
+
for (const spanEl of spanEls) {
|
|
36658
|
+
const pmStart = Number(spanEl.dataset.pmStart ?? "NaN");
|
|
36659
|
+
const pmEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
|
|
36660
|
+
if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
|
|
36661
|
+
if (pos < pmStart || pos > pmEnd) continue;
|
|
36662
|
+
const pageEl = spanEl.closest(".superdoc-page");
|
|
36663
|
+
if (!pageEl) continue;
|
|
36664
|
+
const pageIndex = Number(pageEl.dataset.pageIndex ?? "0");
|
|
36665
|
+
const pageRect = pageEl.getBoundingClientRect();
|
|
36666
|
+
const textNode = spanEl.firstChild;
|
|
36667
|
+
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
|
|
36668
|
+
const spanRect2 = spanEl.getBoundingClientRect();
|
|
36669
|
+
return {
|
|
36670
|
+
pageIndex,
|
|
36671
|
+
x: (spanRect2.left - pageRect.left) / zoom,
|
|
36672
|
+
y: (spanRect2.top - pageRect.top) / zoom,
|
|
36673
|
+
height: spanRect2.height / zoom
|
|
36674
|
+
};
|
|
36675
|
+
}
|
|
36676
|
+
const text = textNode.textContent ?? "";
|
|
36677
|
+
const charOffset = Math.max(0, Math.min(text.length, pos - pmStart));
|
|
36678
|
+
const range = document.createRange();
|
|
36679
|
+
try {
|
|
36680
|
+
range.setStart(textNode, charOffset);
|
|
36681
|
+
range.setEnd(textNode, charOffset);
|
|
36682
|
+
} catch (error) {
|
|
36683
|
+
if (process$1.env.NODE_ENV === "development") {
|
|
36684
|
+
console.warn("[PresentationEditor] Range.setStart/setEnd failed:", {
|
|
36685
|
+
error: error instanceof Error ? error.message : String(error),
|
|
36686
|
+
charOffset,
|
|
36687
|
+
textLength: text.length,
|
|
36688
|
+
pos,
|
|
36689
|
+
pmStart,
|
|
36690
|
+
pmEnd
|
|
36691
|
+
});
|
|
36692
|
+
}
|
|
36693
|
+
const spanRect2 = spanEl.getBoundingClientRect();
|
|
36694
|
+
return {
|
|
36695
|
+
pageIndex,
|
|
36696
|
+
x: (spanRect2.left - pageRect.left) / zoom,
|
|
36697
|
+
y: (spanRect2.top - pageRect.top) / zoom,
|
|
36698
|
+
height: spanRect2.height / zoom
|
|
36699
|
+
};
|
|
36700
|
+
}
|
|
36701
|
+
const rangeRect = range.getBoundingClientRect();
|
|
36702
|
+
const spanRect = spanEl.getBoundingClientRect();
|
|
36703
|
+
const lineEl = spanEl.closest(".superdoc-line");
|
|
36704
|
+
const lineRect = lineEl ? lineEl.getBoundingClientRect() : spanRect;
|
|
36705
|
+
const caretHeight = spanRect.height;
|
|
36706
|
+
const verticalOffset = (lineRect.height - caretHeight) / 2;
|
|
36707
|
+
const caretY = lineRect.top + verticalOffset;
|
|
36708
|
+
return {
|
|
36709
|
+
pageIndex,
|
|
36710
|
+
x: (rangeRect.left - pageRect.left) / zoom,
|
|
36711
|
+
y: (caretY - pageRect.top) / zoom,
|
|
36712
|
+
height: caretHeight / zoom
|
|
36713
|
+
};
|
|
36714
|
+
}
|
|
36715
|
+
return null;
|
|
36716
|
+
};
|
|
36717
|
+
/**
|
|
36718
|
+
* Computes caret position within a table cell using DOM-based positioning.
|
|
36719
|
+
* This uses the actual rendered DOM elements to get accurate positions,
|
|
36720
|
+
* matching how click-to-position mapping works.
|
|
36721
|
+
*/
|
|
36722
|
+
computeTableCaretLayoutRect_fn = function(pos, _fragment, _tableBlock, _tableMeasure, pageIndex) {
|
|
36723
|
+
const lineEls = Array.from(__privateGet(this, _viewportHost).querySelectorAll(".superdoc-line"));
|
|
36724
|
+
if (lineEls.length === 0) return null;
|
|
36725
|
+
for (const lineEl of lineEls) {
|
|
36726
|
+
const pmStart = Number(lineEl.dataset.pmStart ?? "NaN");
|
|
36727
|
+
const pmEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
|
|
36728
|
+
if (!Number.isFinite(pmStart) || !Number.isFinite(pmEnd)) continue;
|
|
36729
|
+
if (pos < pmStart || pos > pmEnd) continue;
|
|
36730
|
+
const spanEls = Array.from(lineEl.querySelectorAll("span[data-pm-start]"));
|
|
36731
|
+
for (const spanEl of spanEls) {
|
|
36732
|
+
const spanStart = Number(spanEl.dataset.pmStart ?? "NaN");
|
|
36733
|
+
const spanEnd = Number(spanEl.dataset.pmEnd ?? "NaN");
|
|
36734
|
+
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
|
|
36735
|
+
if (pos < spanStart || pos > spanEnd) continue;
|
|
36736
|
+
const textNode = spanEl.firstChild;
|
|
36737
|
+
if (!textNode || textNode.nodeType !== Node.TEXT_NODE) {
|
|
36738
|
+
const spanRect = spanEl.getBoundingClientRect();
|
|
36739
|
+
const viewportRect3 = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
36740
|
+
const zoom3 = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
36741
|
+
return {
|
|
36742
|
+
pageIndex,
|
|
36743
|
+
x: (spanRect.left - viewportRect3.left + __privateGet(this, _visibleHost).scrollLeft) / zoom3,
|
|
36744
|
+
y: (spanRect.top - viewportRect3.top + __privateGet(this, _visibleHost).scrollTop) / zoom3,
|
|
36745
|
+
height: spanRect.height / zoom3
|
|
36746
|
+
};
|
|
36747
|
+
}
|
|
36748
|
+
const text = textNode.textContent ?? "";
|
|
36749
|
+
const charOffset = Math.max(0, Math.min(text.length, pos - spanStart));
|
|
36750
|
+
const range = document.createRange();
|
|
36751
|
+
range.setStart(textNode, charOffset);
|
|
36752
|
+
range.setEnd(textNode, charOffset);
|
|
36753
|
+
const rangeRect = range.getBoundingClientRect();
|
|
36754
|
+
const viewportRect2 = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
36755
|
+
const zoom2 = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
36756
|
+
const lineRect2 = lineEl.getBoundingClientRect();
|
|
36757
|
+
return {
|
|
36758
|
+
pageIndex,
|
|
36759
|
+
x: (rangeRect.left - viewportRect2.left + __privateGet(this, _visibleHost).scrollLeft) / zoom2,
|
|
36760
|
+
y: (lineRect2.top - viewportRect2.top + __privateGet(this, _visibleHost).scrollTop) / zoom2,
|
|
36761
|
+
height: lineRect2.height / zoom2
|
|
36762
|
+
};
|
|
36763
|
+
}
|
|
36764
|
+
const lineRect = lineEl.getBoundingClientRect();
|
|
36765
|
+
const viewportRect = __privateGet(this, _viewportHost).getBoundingClientRect();
|
|
36766
|
+
const zoom = __privateGet(this, _layoutOptions).zoom ?? 1;
|
|
36767
|
+
return {
|
|
36768
|
+
pageIndex,
|
|
36769
|
+
x: (lineRect.left - viewportRect.left + __privateGet(this, _visibleHost).scrollLeft) / zoom,
|
|
36770
|
+
y: (lineRect.top - viewportRect.top + __privateGet(this, _visibleHost).scrollTop) / zoom,
|
|
36771
|
+
height: lineRect.height / zoom
|
|
36772
|
+
};
|
|
36773
|
+
}
|
|
36774
|
+
return null;
|
|
36775
|
+
};
|
|
35419
36776
|
findLineContainingPos_fn = function(block, measure, fromLine, toLine, pos) {
|
|
36777
|
+
const log2 = (...args) => {
|
|
36778
|
+
console.log("[LINE-SEARCH]", ...args);
|
|
36779
|
+
};
|
|
36780
|
+
log2("Searching for pos:", pos, "in lines", fromLine, "to", toLine);
|
|
35420
36781
|
if (measure.kind !== "paragraph" || block.kind !== "paragraph") return null;
|
|
35421
36782
|
for (let lineIndex = fromLine; lineIndex < toLine; lineIndex += 1) {
|
|
35422
36783
|
const line = measure.lines[lineIndex];
|
|
35423
36784
|
if (!line) continue;
|
|
35424
36785
|
const range = computeLinePmRange$1(block, line);
|
|
36786
|
+
log2("Line", lineIndex, ":", {
|
|
36787
|
+
pmStart: range.pmStart,
|
|
36788
|
+
pmEnd: range.pmEnd,
|
|
36789
|
+
fromRun: line.fromRun,
|
|
36790
|
+
toRun: line.toRun,
|
|
36791
|
+
fromChar: line.fromChar,
|
|
36792
|
+
toChar: line.toChar
|
|
36793
|
+
});
|
|
35425
36794
|
if (range.pmStart == null || range.pmEnd == null) continue;
|
|
35426
36795
|
if (pos >= range.pmStart && pos <= range.pmEnd) {
|
|
36796
|
+
log2("Found line", lineIndex, "for pos", pos);
|
|
35427
36797
|
return { line, index: lineIndex };
|
|
35428
36798
|
}
|
|
35429
36799
|
}
|
|
36800
|
+
log2("No line found for pos", pos);
|
|
35430
36801
|
return null;
|
|
35431
36802
|
};
|
|
35432
36803
|
lineHeightBeforeIndex_fn = function(lines, fromLine, targetIndex) {
|
|
@@ -48995,6 +50366,49 @@ const ShapeGroup = Node$1.create({
|
|
|
48995
50366
|
};
|
|
48996
50367
|
}
|
|
48997
50368
|
});
|
|
50369
|
+
const sharedAttributes = () => ({
|
|
50370
|
+
originalName: {
|
|
50371
|
+
default: null
|
|
50372
|
+
},
|
|
50373
|
+
originalXml: {
|
|
50374
|
+
default: null
|
|
50375
|
+
}
|
|
50376
|
+
});
|
|
50377
|
+
const hiddenRender = (type) => ["sd-passthrough", { "data-sd-passthrough": type, style: "display: none;" }];
|
|
50378
|
+
const PassthroughBlock = Node$1.create({
|
|
50379
|
+
name: "passthroughBlock",
|
|
50380
|
+
group: "block",
|
|
50381
|
+
atom: true,
|
|
50382
|
+
draggable: false,
|
|
50383
|
+
selectable: false,
|
|
50384
|
+
defining: true,
|
|
50385
|
+
parseDOM() {
|
|
50386
|
+
return [{ tag: 'sd-passthrough[data-sd-passthrough="block"]' }];
|
|
50387
|
+
},
|
|
50388
|
+
renderDOM() {
|
|
50389
|
+
return hiddenRender("block");
|
|
50390
|
+
},
|
|
50391
|
+
addAttributes() {
|
|
50392
|
+
return sharedAttributes();
|
|
50393
|
+
}
|
|
50394
|
+
});
|
|
50395
|
+
const PassthroughInline = Node$1.create({
|
|
50396
|
+
name: "passthroughInline",
|
|
50397
|
+
group: "inline",
|
|
50398
|
+
inline: true,
|
|
50399
|
+
atom: true,
|
|
50400
|
+
draggable: false,
|
|
50401
|
+
selectable: false,
|
|
50402
|
+
parseDOM() {
|
|
50403
|
+
return [{ tag: 'sd-passthrough[data-sd-passthrough="inline"]' }];
|
|
50404
|
+
},
|
|
50405
|
+
renderDOM() {
|
|
50406
|
+
return hiddenRender("inline");
|
|
50407
|
+
},
|
|
50408
|
+
addAttributes() {
|
|
50409
|
+
return sharedAttributes();
|
|
50410
|
+
}
|
|
50411
|
+
});
|
|
48998
50412
|
const TextStyle = Mark.create({
|
|
48999
50413
|
name: "textStyle",
|
|
49000
50414
|
addOptions() {
|
|
@@ -54905,7 +56319,9 @@ const getRichTextExtensions = () => {
|
|
|
54905
56319
|
AiPlugin,
|
|
54906
56320
|
Image,
|
|
54907
56321
|
NodeResizer,
|
|
54908
|
-
CustomSelection
|
|
56322
|
+
CustomSelection,
|
|
56323
|
+
PassthroughInline,
|
|
56324
|
+
PassthroughBlock
|
|
54909
56325
|
];
|
|
54910
56326
|
};
|
|
54911
56327
|
const getStarterExtensions = () => {
|
|
@@ -54977,7 +56393,9 @@ const getStarterExtensions = () => {
|
|
|
54977
56393
|
CustomSelection,
|
|
54978
56394
|
TextTransform,
|
|
54979
56395
|
VectorShape,
|
|
54980
|
-
ShapeGroup
|
|
56396
|
+
ShapeGroup,
|
|
56397
|
+
PassthroughInline,
|
|
56398
|
+
PassthroughBlock
|
|
54981
56399
|
];
|
|
54982
56400
|
};
|
|
54983
56401
|
export {
|