superdoc 1.0.0-beta.15 → 1.0.0-beta.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/chunks/{PdfViewer-DltPlBWC.cjs → PdfViewer-93eWvs8z.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-CjlHzt9e.es.js → PdfViewer-ODeuH1gb.es.js} +1 -1
  3. package/dist/chunks/{index-qg0AxQJC.es.js → index-DW5_UKLM.es.js} +3 -3
  4. package/dist/chunks/{index-Bds7gW4r-Pk_xAuWe.es.js → index-DexFffM7-Cbdy0Zy6.es.js} +1 -1
  5. package/dist/chunks/{index-Bds7gW4r-JPDW6c39.cjs → index-DexFffM7-XZD_g6eY.cjs} +1 -1
  6. package/dist/chunks/{index-BZnlco_f.cjs → index-RquHXtgI.cjs} +3 -3
  7. package/dist/chunks/{super-editor.es-CuAhqbzW.cjs → super-editor.es-BLKWkx5G.cjs} +1223 -131
  8. package/dist/chunks/{super-editor.es-CQTkj_nb.es.js → super-editor.es-Dg5uoFkw.es.js} +1223 -131
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-qMoZOGGn.js → converter-C_R_BK8X.js} +1 -1
  11. package/dist/super-editor/chunks/{docx-zipper-QKiyORxV.js → docx-zipper-BvQAYmi1.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-D8ZdjC2V.js → editor-DFFvalb1.js} +1224 -132
  13. package/dist/super-editor/chunks/{index-Bds7gW4r.js → index-DexFffM7.js} +1 -1
  14. package/dist/super-editor/chunks/{toolbar-Spi7vpev.js → toolbar-DLPfegtw.js} +2 -2
  15. package/dist/super-editor/converter.es.js +1 -1
  16. package/dist/super-editor/docx-zipper.es.js +2 -2
  17. package/dist/super-editor/editor.es.js +3 -3
  18. package/dist/super-editor/file-zipper.es.js +1 -1
  19. package/dist/super-editor/super-editor.es.js +6 -6
  20. package/dist/super-editor/toolbar.es.js +2 -2
  21. package/dist/super-editor.cjs +1 -1
  22. package/dist/super-editor.es.js +1 -1
  23. package/dist/superdoc.cjs +2 -2
  24. package/dist/superdoc.es.js +2 -2
  25. package/dist/superdoc.umd.js +1225 -133
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -12,8 +12,8 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
12
12
  var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _headerLayoutResults, _footerLayoutResults, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _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-qMoZOGGn.js";
16
- import { D as DocxZipper } from "./docx-zipper-QKiyORxV.js";
15
+ import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as ListHelpers, O as updateNumberingProperties, Q as changeListLevel, U as findParentNode, V as isList, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as calculateResolvedParagraphProperties, ar as encodeCSSFromPPr, as as twipsToPixels$2, at as resolveRunProperties, au as encodeCSSFromRPr, av as generateOrderedListIndex, aw as docxNumberingHelpers, ax as InputRule, ay as convertSizeToCSS, az as SelectionRange, aA as Transform, aB as findParentNodeClosestToPos, aC as isInTable$1, aD as generateDocxRandomId, aE as insertNewRelationship, aF as inchesToPixels, aG as kebabCase, aH as getUnderlineCssString } from "./converter-C_R_BK8X.js";
16
+ import { D as DocxZipper } from "./docx-zipper-BvQAYmi1.js";
17
17
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
18
18
  var GOOD_LEAF_SIZE = 200;
19
19
  var RopeSequence = function RopeSequence2() {
@@ -13574,7 +13574,7 @@ const isHeadless = (editor) => {
13574
13574
  const shouldSkipNodeView = (editor) => {
13575
13575
  return isHeadless(editor);
13576
13576
  };
13577
- const summaryVersion = "1.0.0-beta.15";
13577
+ const summaryVersion = "1.0.0-beta.16";
13578
13578
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
13579
13579
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
13580
13580
  function mapAttributes(attrs) {
@@ -14356,7 +14356,7 @@ const _Editor = class _Editor extends EventEmitter {
14356
14356
  { default: remarkStringify },
14357
14357
  { default: remarkGfm }
14358
14358
  ] = await Promise.all([
14359
- import("./index-Bds7gW4r.js"),
14359
+ import("./index-DexFffM7.js"),
14360
14360
  import("./index-DRCvimau.js"),
14361
14361
  import("./index-C_x_N6Uh.js"),
14362
14362
  import("./index-D_sWOSiG.js"),
@@ -14561,7 +14561,7 @@ const _Editor = class _Editor extends EventEmitter {
14561
14561
  * Process collaboration migrations
14562
14562
  */
14563
14563
  processCollaborationMigrations() {
14564
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.15");
14564
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.16");
14565
14565
  if (!this.options.ydoc) return;
14566
14566
  const metaMap = this.options.ydoc.getMap("meta");
14567
14567
  let docVersion = metaMap.get("version");
@@ -15724,7 +15724,7 @@ const pickLang = (value) => {
15724
15724
  const normalized = value.trim().toLowerCase();
15725
15725
  return normalized || void 0;
15726
15726
  };
15727
- const normalizeColor = (value) => {
15727
+ const normalizeColor$1 = (value) => {
15728
15728
  if (typeof value !== "string") return void 0;
15729
15729
  const trimmed = value.trim();
15730
15730
  if (!trimmed || trimmed === "auto" || trimmed === "none") return void 0;
@@ -16364,14 +16364,14 @@ const resolveThemeColor = (attrs, themeColors) => {
16364
16364
  const resolveColorFromAttributes = (attrs, themeColors) => {
16365
16365
  if (!attrs) return void 0;
16366
16366
  if (typeof attrs.color === "string") {
16367
- const normalized = normalizeColor(attrs.color);
16367
+ const normalized = normalizeColor$1(attrs.color);
16368
16368
  if (normalized) {
16369
16369
  return normalized;
16370
16370
  }
16371
16371
  }
16372
16372
  const theme = resolveThemeColor(attrs, themeColors);
16373
16373
  if (theme) {
16374
- return normalizeColor(theme);
16374
+ return normalizeColor$1(theme);
16375
16375
  }
16376
16376
  return void 0;
16377
16377
  };
@@ -16806,13 +16806,8 @@ const MAX_BORDER_SIZE_PX = 100;
16806
16806
  const borderSizeToPx = (size) => {
16807
16807
  if (!isFiniteNumber(size)) return void 0;
16808
16808
  if (size <= 0) return 0;
16809
- let pixelValue;
16810
- if (size < EIGHTHS_PER_POINT) {
16811
- pixelValue = size;
16812
- } else {
16813
- const points = size / EIGHTHS_PER_POINT;
16814
- pixelValue = points * PX_PER_PT;
16815
- }
16809
+ const points = size / EIGHTHS_PER_POINT;
16810
+ const pixelValue = points * PX_PER_PT;
16816
16811
  return Math.min(MAX_BORDER_SIZE_PX, Math.max(MIN_BORDER_SIZE_PX, pixelValue));
16817
16812
  };
16818
16813
  const normalizeColorWithDefault = (color) => {
@@ -16951,7 +16946,7 @@ const normalizeBorderSide = (value) => {
16951
16946
  if (style === "none") return void 0;
16952
16947
  const width = pickNumber(raw.size);
16953
16948
  const widthPx = borderSizeToPx(width);
16954
- const color = normalizeColor(raw.color);
16949
+ const color = normalizeColor$1(raw.color);
16955
16950
  const space = pickNumber(raw.space);
16956
16951
  if (!style && widthPx == null && space == null && !color) {
16957
16952
  return void 0;
@@ -17007,7 +17002,7 @@ const normalizeParagraphShading = (value) => {
17007
17002
  return Object.keys(shading).length > 0 ? shading : void 0;
17008
17003
  };
17009
17004
  const normalizeShadingColor = (value) => {
17010
- const normalized = normalizeColor(value);
17005
+ const normalized = normalizeColor$1(value);
17011
17006
  if (!normalized) return void 0;
17012
17007
  if (normalized.toLowerCase() === "#auto") {
17013
17008
  return void 0;
@@ -18170,11 +18165,11 @@ const buildMarkerLayout = ({
18170
18165
  baselineOffsetPx: markerRun.baselineShift ?? 0,
18171
18166
  gutterWidthPx: markerBoxWidthPx,
18172
18167
  justification: numbering.lvlJc ?? "left",
18173
- suffix: normalizeSuffix(numbering.suffix) ?? "tab",
18168
+ suffix: normalizeSuffix$1(numbering.suffix) ?? "tab",
18174
18169
  run: markerRun,
18175
18170
  path: numbering.path
18176
18171
  });
18177
- const normalizeSuffix = (suffix) => {
18172
+ const normalizeSuffix$1 = (suffix) => {
18178
18173
  if (suffix === "tab" || suffix === "space" || suffix === "nothing") {
18179
18174
  return suffix;
18180
18175
  }
@@ -18628,6 +18623,154 @@ const cloneIfObject = (value) => {
18628
18623
  };
18629
18624
  const { resolveSpacingIndent } = Engines;
18630
18625
  const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
18626
+ const asOoxmlElement = (value) => {
18627
+ if (!value || typeof value !== "object") return void 0;
18628
+ const element = value;
18629
+ if (element.name == null && element.attributes == null && element.elements == null) return void 0;
18630
+ return element;
18631
+ };
18632
+ const findChild = (parent, name) => {
18633
+ return parent?.elements?.find((child) => child?.name === name);
18634
+ };
18635
+ const getAttribute = (element, key2) => {
18636
+ if (!element?.attributes) return void 0;
18637
+ const attrs = element.attributes;
18638
+ return attrs[key2] ?? attrs[key2.startsWith("w:") ? key2.slice(2) : `w:${key2}`];
18639
+ };
18640
+ const parseNumberAttr = (value) => {
18641
+ if (value == null) return void 0;
18642
+ const num = typeof value === "number" ? value : Number.parseInt(String(value), 10);
18643
+ return Number.isFinite(num) ? num : void 0;
18644
+ };
18645
+ const normalizeNumFmt = (value) => {
18646
+ if (typeof value !== "string") return void 0;
18647
+ switch (value) {
18648
+ case "decimal":
18649
+ return "decimal";
18650
+ case "lowerLetter":
18651
+ return "lowerLetter";
18652
+ case "upperLetter":
18653
+ return "upperLetter";
18654
+ case "lowerRoman":
18655
+ return "lowerRoman";
18656
+ case "upperRoman":
18657
+ return "upperRoman";
18658
+ case "bullet":
18659
+ return "bullet";
18660
+ default:
18661
+ return void 0;
18662
+ }
18663
+ };
18664
+ const normalizeSuffix = (value) => {
18665
+ if (typeof value !== "string") return void 0;
18666
+ if (value === "tab" || value === "space" || value === "nothing") {
18667
+ return value;
18668
+ }
18669
+ return void 0;
18670
+ };
18671
+ const normalizeJustification = (value) => {
18672
+ if (typeof value !== "string") return void 0;
18673
+ if (value === "start") return "left";
18674
+ if (value === "end") return "right";
18675
+ if (value === "left" || value === "center" || value === "right") return value;
18676
+ return void 0;
18677
+ };
18678
+ const extractIndentFromLevel = (lvl) => {
18679
+ const pPr = findChild(lvl, "w:pPr");
18680
+ const ind = findChild(pPr, "w:ind");
18681
+ if (!ind) return void 0;
18682
+ const left2 = parseNumberAttr(getAttribute(ind, "w:left"));
18683
+ const right2 = parseNumberAttr(getAttribute(ind, "w:right"));
18684
+ const firstLine = parseNumberAttr(getAttribute(ind, "w:firstLine"));
18685
+ const hanging = parseNumberAttr(getAttribute(ind, "w:hanging"));
18686
+ const indent = {};
18687
+ if (left2 != null) indent.left = left2;
18688
+ if (right2 != null) indent.right = right2;
18689
+ if (firstLine != null) indent.firstLine = firstLine;
18690
+ if (hanging != null) indent.hanging = hanging;
18691
+ return Object.keys(indent).length ? indent : void 0;
18692
+ };
18693
+ const normalizeColor = (value) => {
18694
+ if (typeof value !== "string") return void 0;
18695
+ const trimmed = value.trim();
18696
+ if (!trimmed || trimmed.toLowerCase() === "auto") return void 0;
18697
+ const upper = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
18698
+ return `#${upper.toUpperCase()}`;
18699
+ };
18700
+ const extractMarkerRun = (lvl) => {
18701
+ const rPr = findChild(lvl, "w:rPr");
18702
+ if (!rPr) return void 0;
18703
+ const run = {};
18704
+ const rFonts = findChild(rPr, "w:rFonts");
18705
+ const font = getAttribute(rFonts, "w:ascii") ?? getAttribute(rFonts, "w:hAnsi") ?? getAttribute(rFonts, "w:eastAsia");
18706
+ if (typeof font === "string" && font.trim()) {
18707
+ run.fontFamily = font;
18708
+ }
18709
+ const sz = parseNumberAttr(getAttribute(findChild(rPr, "w:sz"), "w:val")) ?? parseNumberAttr(getAttribute(findChild(rPr, "w:szCs"), "w:val"));
18710
+ if (sz != null) {
18711
+ run.fontSize = sz / 2;
18712
+ }
18713
+ const color = normalizeColor(getAttribute(findChild(rPr, "w:color"), "w:val"));
18714
+ if (color) run.color = color;
18715
+ if (findChild(rPr, "w:b")) run.bold = true;
18716
+ if (findChild(rPr, "w:i")) run.italic = true;
18717
+ const spacingTwips = parseNumberAttr(getAttribute(findChild(rPr, "w:spacing"), "w:val"));
18718
+ if (spacingTwips != null && Number.isFinite(spacingTwips)) {
18719
+ run.letterSpacing = twipsToPx$1(spacingTwips);
18720
+ }
18721
+ return Object.keys(run).length ? run : void 0;
18722
+ };
18723
+ const findNumFmtElement = (lvl) => {
18724
+ if (!lvl) return void 0;
18725
+ const direct = findChild(lvl, "w:numFmt");
18726
+ if (direct) return direct;
18727
+ const alternate = findChild(lvl, "mc:AlternateContent");
18728
+ const choice = findChild(alternate, "mc:Choice");
18729
+ if (choice) {
18730
+ return findChild(choice, "w:numFmt");
18731
+ }
18732
+ return void 0;
18733
+ };
18734
+ const resolveNumberingFromContext = (numId, ilvl, numbering) => {
18735
+ const definitions = numbering?.definitions;
18736
+ const abstracts = numbering?.abstracts;
18737
+ if (!definitions || !abstracts) return void 0;
18738
+ const numDef = asOoxmlElement(definitions[String(numId)]);
18739
+ if (!numDef) return void 0;
18740
+ const abstractId = getAttribute(findChild(numDef, "w:abstractNumId"), "w:val");
18741
+ if (abstractId == null) return void 0;
18742
+ const abstract = asOoxmlElement(abstracts[String(abstractId)]);
18743
+ if (!abstract) return void 0;
18744
+ let levelDef = abstract.elements?.find(
18745
+ (el) => el?.name === "w:lvl" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
18746
+ );
18747
+ const override = numDef.elements?.find(
18748
+ (el) => el?.name === "w:lvlOverride" && parseNumberAttr(el.attributes?.["w:ilvl"]) === ilvl
18749
+ );
18750
+ const overrideLvl = findChild(override, "w:lvl");
18751
+ if (overrideLvl) {
18752
+ levelDef = overrideLvl;
18753
+ }
18754
+ const startOverride = parseNumberAttr(getAttribute(findChild(override, "w:startOverride"), "w:val"));
18755
+ if (!levelDef) return void 0;
18756
+ const numFmtEl = findNumFmtElement(levelDef);
18757
+ const lvlText = getAttribute(findChild(levelDef, "w:lvlText"), "w:val");
18758
+ const start2 = startOverride ?? parseNumberAttr(getAttribute(findChild(levelDef, "w:start"), "w:val"));
18759
+ const suffix = normalizeSuffix(getAttribute(findChild(levelDef, "w:suff"), "w:val"));
18760
+ const lvlJc = normalizeJustification(getAttribute(findChild(levelDef, "w:lvlJc"), "w:val"));
18761
+ const indent = extractIndentFromLevel(levelDef);
18762
+ const markerRun = extractMarkerRun(levelDef);
18763
+ const numFmt = normalizeNumFmt(getAttribute(numFmtEl, "w:val"));
18764
+ return {
18765
+ format: numFmt,
18766
+ lvlText,
18767
+ start: start2,
18768
+ suffix,
18769
+ lvlJc,
18770
+ resolvedLevelIndent: indent,
18771
+ resolvedMarkerRpr: markerRun
18772
+ };
18773
+ };
18631
18774
  const isTruthy = (value) => {
18632
18775
  if (value === true || value === 1) return true;
18633
18776
  if (typeof value === "string") {
@@ -19260,6 +19403,30 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
19260
19403
  const ilvl = Number.isFinite(numberingProps.ilvl) ? Math.max(0, Math.floor(Number(numberingProps.ilvl))) : 0;
19261
19404
  const listRendering = normalizeListRenderingAttrs(attrs.listRendering);
19262
19405
  const numericNumId = typeof numId === "number" ? numId : void 0;
19406
+ const resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
19407
+ if (resolvedLevel) {
19408
+ if (resolvedLevel.format && numberingProps.format == null) {
19409
+ numberingProps.format = resolvedLevel.format;
19410
+ }
19411
+ if (resolvedLevel.lvlText && numberingProps.lvlText == null) {
19412
+ numberingProps.lvlText = resolvedLevel.lvlText;
19413
+ }
19414
+ if (resolvedLevel.start != null && numberingProps.start == null) {
19415
+ numberingProps.start = resolvedLevel.start;
19416
+ }
19417
+ if (resolvedLevel.suffix && numberingProps.suffix == null) {
19418
+ numberingProps.suffix = resolvedLevel.suffix;
19419
+ }
19420
+ if (resolvedLevel.lvlJc && numberingProps.lvlJc == null) {
19421
+ numberingProps.lvlJc = resolvedLevel.lvlJc;
19422
+ }
19423
+ if (resolvedLevel.resolvedLevelIndent && !numberingProps.resolvedLevelIndent) {
19424
+ numberingProps.resolvedLevelIndent = resolvedLevel.resolvedLevelIndent;
19425
+ }
19426
+ if (resolvedLevel.resolvedMarkerRpr && !numberingProps.resolvedMarkerRpr) {
19427
+ numberingProps.resolvedMarkerRpr = resolvedLevel.resolvedMarkerRpr;
19428
+ }
19429
+ }
19263
19430
  let counterValue = 1;
19264
19431
  if (listCounterContext && typeof numericNumId === "number") {
19265
19432
  counterValue = listCounterContext.incrementListCounter(numericNumId, ilvl);
@@ -20485,41 +20652,45 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
20485
20652
  }
20486
20653
  return;
20487
20654
  }
20488
- if (node.type === "hardBreak") {
20489
- flushParagraph();
20490
- blocks.push({
20491
- kind: "pageBreak",
20492
- id: nextId(),
20493
- attrs: node.attrs || {}
20494
- });
20495
- return;
20496
- }
20497
- if (node.type === "lineBreak") {
20655
+ if (node.type === "hardBreak" || node.type === "lineBreak") {
20498
20656
  const attrs = node.attrs ?? {};
20499
- if (attrs.lineBreakType === "column") {
20657
+ const breakType = attrs.pageBreakType ?? attrs.lineBreakType ?? "line";
20658
+ if (breakType === "page") {
20659
+ flushParagraph();
20660
+ blocks.push({
20661
+ kind: "pageBreak",
20662
+ id: nextId(),
20663
+ attrs: node.attrs || {}
20664
+ });
20665
+ return;
20666
+ }
20667
+ if (breakType === "column") {
20500
20668
  flushParagraph();
20501
20669
  blocks.push({
20502
20670
  kind: "columnBreak",
20503
20671
  id: nextId(),
20504
20672
  attrs: node.attrs || {}
20505
20673
  });
20674
+ return;
20675
+ }
20676
+ const lineBreakRun = { kind: "lineBreak", attrs: {} };
20677
+ const lbAttrs = {};
20678
+ if (attrs.lineBreakType) lbAttrs.lineBreakType = String(attrs.lineBreakType);
20679
+ if (attrs.clear) lbAttrs.clear = String(attrs.clear);
20680
+ if (Object.keys(lbAttrs).length > 0) {
20681
+ lineBreakRun.attrs = lbAttrs;
20506
20682
  } 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);
20683
+ delete lineBreakRun.attrs;
20684
+ }
20685
+ const pos = positions.get(node);
20686
+ if (pos) {
20687
+ lineBreakRun.pmStart = pos.start;
20688
+ lineBreakRun.pmEnd = pos.end;
20522
20689
  }
20690
+ if (activeSdt) {
20691
+ lineBreakRun.sdt = activeSdt;
20692
+ }
20693
+ currentRuns.push(lineBreakRun);
20523
20694
  return;
20524
20695
  }
20525
20696
  };
@@ -21112,6 +21283,22 @@ const normalizeTableWidth = (value) => {
21112
21283
  };
21113
21284
  const isTableRowNode = (node) => node.type === "tableRow" || node.type === "table_row";
21114
21285
  const isTableCellNode = (node) => node.type === "tableCell" || node.type === "table_cell" || node.type === "tableHeader" || node.type === "table_header";
21286
+ const normalizeRowHeight = (rowProps) => {
21287
+ if (!rowProps || typeof rowProps !== "object") return void 0;
21288
+ const rawRowHeight = rowProps.rowHeight;
21289
+ if (!rawRowHeight || typeof rawRowHeight !== "object") return void 0;
21290
+ const heightObj = rawRowHeight;
21291
+ const rawValue = pickNumber(heightObj.value ?? heightObj.val);
21292
+ if (rawValue == null) return void 0;
21293
+ const rawRule = heightObj.rule ?? heightObj.hRule;
21294
+ const rule = rawRule === "exact" || rawRule === "atLeast" || rawRule === "auto" ? rawRule : "atLeast";
21295
+ const isLikelyTwips = rawValue >= 300 || Math.abs(rawValue % 15) < 1e-6;
21296
+ const valuePx = isLikelyTwips ? twipsToPx$1(rawValue) : rawValue;
21297
+ return {
21298
+ value: valuePx,
21299
+ rule
21300
+ };
21301
+ };
21115
21302
  const parseTableCell = (args) => {
21116
21303
  const { cellNode, rowIndex, cellIndex, context, defaultCellPadding } = args;
21117
21304
  if (!isTableCellNode(cellNode) || !Array.isArray(cellNode.content)) {
@@ -21149,8 +21336,9 @@ const parseTableCell = (args) => {
21149
21336
  const padding = extractCellPadding(cellNode.attrs ?? {}) ?? (defaultCellPadding ? { ...defaultCellPadding } : void 0);
21150
21337
  if (padding) cellAttrs.padding = padding;
21151
21338
  const verticalAlign = cellNode.attrs?.verticalAlign;
21152
- if (verticalAlign === "top" || verticalAlign === "middle" || verticalAlign === "bottom") {
21153
- cellAttrs.verticalAlign = verticalAlign;
21339
+ const normalizedVerticalAlign = verticalAlign === "middle" ? "center" : verticalAlign === "center" ? "center" : verticalAlign;
21340
+ if (normalizedVerticalAlign === "top" || normalizedVerticalAlign === "center" || normalizedVerticalAlign === "bottom") {
21341
+ cellAttrs.verticalAlign = normalizedVerticalAlign;
21154
21342
  }
21155
21343
  const background = cellNode.attrs?.background;
21156
21344
  if (background && typeof background.color === "string") {
@@ -21193,15 +21381,89 @@ const parseTableRow = (args) => {
21193
21381
  });
21194
21382
  if (cells.length === 0) return null;
21195
21383
  const rowProps = rowNode.attrs?.tableRowProperties;
21384
+ const rowHeight = normalizeRowHeight(rowProps);
21196
21385
  const attrs = rowProps && typeof rowProps === "object" ? {
21197
- tableRowProperties: rowProps
21198
- } : void 0;
21386
+ tableRowProperties: rowProps,
21387
+ ...rowHeight ? { rowHeight } : {}
21388
+ } : rowHeight ? { rowHeight } : void 0;
21199
21389
  return {
21200
21390
  id: context.nextBlockId(`row-${rowIndex}`),
21201
21391
  cells,
21202
21392
  attrs
21203
21393
  };
21204
21394
  };
21395
+ function extractFloatingTableAnchorWrap(node) {
21396
+ const tableProperties = node.attrs?.tableProperties;
21397
+ const floatingProps = tableProperties?.floatingTableProperties;
21398
+ if (!floatingProps) {
21399
+ return {};
21400
+ }
21401
+ const hasPositioning = floatingProps.tblpX !== void 0 || floatingProps.tblpY !== void 0 || floatingProps.tblpXSpec !== void 0 || floatingProps.tblpYSpec !== void 0 || floatingProps.horzAnchor !== void 0 || floatingProps.vertAnchor !== void 0;
21402
+ if (!hasPositioning) {
21403
+ return {};
21404
+ }
21405
+ const mapHorzAnchor = (val) => {
21406
+ switch (val) {
21407
+ case "page":
21408
+ return "page";
21409
+ case "margin":
21410
+ return "margin";
21411
+ case "text":
21412
+ default:
21413
+ return "column";
21414
+ }
21415
+ };
21416
+ const mapVertAnchor = (val) => {
21417
+ switch (val) {
21418
+ case "page":
21419
+ return "page";
21420
+ case "margin":
21421
+ return "margin";
21422
+ case "text":
21423
+ default:
21424
+ return "paragraph";
21425
+ }
21426
+ };
21427
+ const anchor = {
21428
+ isAnchored: true,
21429
+ hRelativeFrom: mapHorzAnchor(floatingProps.horzAnchor),
21430
+ vRelativeFrom: mapVertAnchor(floatingProps.vertAnchor)
21431
+ };
21432
+ if (floatingProps.tblpXSpec) {
21433
+ anchor.alignH = floatingProps.tblpXSpec;
21434
+ }
21435
+ if (floatingProps.tblpYSpec) {
21436
+ anchor.alignV = floatingProps.tblpYSpec;
21437
+ }
21438
+ if (floatingProps.tblpX !== void 0) {
21439
+ anchor.offsetH = twipsToPx$1(floatingProps.tblpX);
21440
+ }
21441
+ if (floatingProps.tblpY !== void 0) {
21442
+ anchor.offsetV = twipsToPx$1(floatingProps.tblpY);
21443
+ }
21444
+ const hasDistances = floatingProps.leftFromText !== void 0 || floatingProps.rightFromText !== void 0 || floatingProps.topFromText !== void 0 || floatingProps.bottomFromText !== void 0;
21445
+ const wrap = {
21446
+ type: "Square",
21447
+ // Floating tables with text distances use square wrapping
21448
+ wrapText: "bothSides"
21449
+ // Default to text on both sides
21450
+ };
21451
+ if (hasDistances) {
21452
+ if (floatingProps.topFromText !== void 0) {
21453
+ wrap.distTop = twipsToPx$1(floatingProps.topFromText);
21454
+ }
21455
+ if (floatingProps.bottomFromText !== void 0) {
21456
+ wrap.distBottom = twipsToPx$1(floatingProps.bottomFromText);
21457
+ }
21458
+ if (floatingProps.leftFromText !== void 0) {
21459
+ wrap.distLeft = twipsToPx$1(floatingProps.leftFromText);
21460
+ }
21461
+ if (floatingProps.rightFromText !== void 0) {
21462
+ wrap.distRight = twipsToPx$1(floatingProps.rightFromText);
21463
+ }
21464
+ }
21465
+ return { anchor, wrap };
21466
+ }
21205
21467
  function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSize, _styleContext, trackedChanges, bookmarks, hyperlinkConfig, themeColors, paragraphToFlowBlocks2, converterContext) {
21206
21468
  if (!Array.isArray(node.content) || node.content.length === 0) return null;
21207
21469
  if (!paragraphToFlowBlocks2) return null;
@@ -21266,6 +21528,10 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
21266
21528
  if (tableLayout) {
21267
21529
  tableAttrs.tableLayout = tableLayout;
21268
21530
  }
21531
+ const tableProperties = node.attrs?.tableProperties;
21532
+ if (tableProperties && typeof tableProperties === "object") {
21533
+ tableAttrs.tableProperties = tableProperties;
21534
+ }
21269
21535
  let columnWidths = void 0;
21270
21536
  const twipsToPixels2 = (twips) => {
21271
21537
  const PIXELS_PER_INCH2 = 96;
@@ -21309,12 +21575,15 @@ function tableNodeToBlock$1(node, nextBlockId, positions, defaultFont, defaultSi
21309
21575
  columnWidths = void 0;
21310
21576
  }
21311
21577
  }
21578
+ const { anchor, wrap } = extractFloatingTableAnchorWrap(node);
21312
21579
  const tableBlock = {
21313
21580
  kind: "table",
21314
21581
  id: nextBlockId("table"),
21315
21582
  rows,
21316
21583
  attrs: Object.keys(tableAttrs).length > 0 ? tableAttrs : void 0,
21317
- columnWidths
21584
+ columnWidths,
21585
+ ...anchor ? { anchor } : {},
21586
+ ...wrap ? { wrap } : {}
21318
21587
  };
21319
21588
  return tableBlock;
21320
21589
  }
@@ -21650,7 +21919,7 @@ function getMeasurementContext() {
21650
21919
  return measurementCtx;
21651
21920
  }
21652
21921
  function getRunFontString(run) {
21653
- if (run.kind === "tab" || run.kind === "lineBreak" || "src" in run) {
21922
+ if (run.kind === "tab" || run.kind === "lineBreak" || run.kind === "break" || "src" in run) {
21654
21923
  return "normal normal 16px Arial";
21655
21924
  }
21656
21925
  const style = run.italic ? "italic" : "normal";
@@ -21677,6 +21946,10 @@ function sliceRunsForLine$1(block, line) {
21677
21946
  result.push(run);
21678
21947
  continue;
21679
21948
  }
21949
+ if (run.kind === "break") {
21950
+ result.push(run);
21951
+ continue;
21952
+ }
21680
21953
  const text = run.text ?? "";
21681
21954
  const isFirstRun = runIndex === line.fromRun;
21682
21955
  const isLastRun = runIndex === line.toRun;
@@ -21710,7 +21983,7 @@ function measureCharacterX(block, line, charOffset) {
21710
21983
  1,
21711
21984
  runs2.reduce((sum, run) => {
21712
21985
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
21713
- if ("src" in run || run.kind === "lineBreak") return sum;
21986
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
21714
21987
  return sum + (run.text ?? "").length;
21715
21988
  }, 0)
21716
21989
  );
@@ -21731,7 +22004,7 @@ function measureCharacterX(block, line, charOffset) {
21731
22004
  currentCharOffset += runLength2;
21732
22005
  continue;
21733
22006
  }
21734
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
22007
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
21735
22008
  const runLength = text.length;
21736
22009
  if (currentCharOffset + runLength >= charOffset) {
21737
22010
  const offsetInRun = charOffset - currentCharOffset;
@@ -21774,7 +22047,7 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
21774
22047
  if (isTabRun$1(run)) {
21775
22048
  return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
21776
22049
  }
21777
- if ("src" in run || run.kind === "lineBreak") {
22050
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") {
21778
22051
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
21779
22052
  }
21780
22053
  const text = run.text ?? "";
@@ -21797,7 +22070,7 @@ function findCharacterAtX(block, line, x, pmStart) {
21797
22070
  1,
21798
22071
  runs2.reduce((sum, run) => {
21799
22072
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
21800
- if ("src" in run || run.kind === "lineBreak") return sum;
22073
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
21801
22074
  return sum + (run.text ?? "").length;
21802
22075
  }, 0)
21803
22076
  );
@@ -21832,7 +22105,7 @@ function findCharacterAtX(block, line, x, pmStart) {
21832
22105
  currentCharOffset += TAB_CHAR_LENGTH;
21833
22106
  continue;
21834
22107
  }
21835
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
22108
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
21836
22109
  const runLength = text.length;
21837
22110
  if (runLength === 0) continue;
21838
22111
  ctx2.font = getRunFontString(run);
@@ -22265,6 +22538,40 @@ function createFloatingObjectManager(columns, margins, pageWidth) {
22265
22538
  };
22266
22539
  zones.push(zone);
22267
22540
  },
22541
+ registerTable(tableBlock, measure, anchorY, columnIndex, pageNumber) {
22542
+ if (!tableBlock.anchor?.isAnchored) {
22543
+ return;
22544
+ }
22545
+ const { wrap, anchor } = tableBlock;
22546
+ const wrapType = wrap?.type ?? "None";
22547
+ if (wrapType === "None") {
22548
+ return;
22549
+ }
22550
+ const tableWidth = measure.totalWidth ?? 0;
22551
+ const tableHeight = measure.totalHeight ?? 0;
22552
+ const x = computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth);
22553
+ const y = anchorY + (anchor.offsetV ?? 0);
22554
+ const zone = {
22555
+ imageBlockId: tableBlock.id,
22556
+ // Reusing imageBlockId field for table id
22557
+ pageNumber,
22558
+ columnIndex,
22559
+ bounds: {
22560
+ x,
22561
+ y,
22562
+ width: tableWidth,
22563
+ height: tableHeight
22564
+ },
22565
+ distances: {
22566
+ top: wrap?.distTop ?? 0,
22567
+ bottom: wrap?.distBottom ?? 0,
22568
+ left: wrap?.distLeft ?? 0,
22569
+ right: wrap?.distRight ?? 0
22570
+ },
22571
+ wrapMode: computeTableWrapMode(wrap)
22572
+ };
22573
+ zones.push(zone);
22574
+ },
22268
22575
  getExclusionsForLine(lineY, lineHeight, columnIndex, pageNumber) {
22269
22576
  const result = zones.filter((zone) => {
22270
22577
  if (zone.pageNumber !== pageNumber || zone.columnIndex !== columnIndex) {
@@ -22372,6 +22679,49 @@ function computeWrapMode(wrap, _anchor) {
22372
22679
  if (wrapText === "largest") return "largest";
22373
22680
  return "both";
22374
22681
  }
22682
+ function computeTableAnchorX(anchor, columnIndex, columns, tableWidth, margins, pageWidth) {
22683
+ const alignH = anchor.alignH ?? "left";
22684
+ const offsetH = anchor.offsetH ?? 0;
22685
+ const marginLeft = Math.max(0, margins?.left ?? 0);
22686
+ const marginRight = Math.max(0, margins?.right ?? 0);
22687
+ const contentWidth = pageWidth != null ? Math.max(1, pageWidth - (marginLeft + marginRight)) : columns.width;
22688
+ const contentLeft = marginLeft;
22689
+ const columnLeft = contentLeft + columnIndex * (columns.width + columns.gap);
22690
+ const relativeFrom = anchor.hRelativeFrom ?? "column";
22691
+ let baseX;
22692
+ let availableWidth;
22693
+ if (relativeFrom === "page") {
22694
+ if (columns.count === 1) {
22695
+ baseX = contentLeft;
22696
+ availableWidth = contentWidth;
22697
+ } else {
22698
+ baseX = 0;
22699
+ availableWidth = pageWidth != null ? pageWidth : contentWidth;
22700
+ }
22701
+ } else if (relativeFrom === "margin") {
22702
+ baseX = contentLeft;
22703
+ availableWidth = contentWidth;
22704
+ } else {
22705
+ baseX = columnLeft;
22706
+ availableWidth = columns.width;
22707
+ }
22708
+ let effectiveAlignH = alignH;
22709
+ if (alignH === "inside") effectiveAlignH = "left";
22710
+ if (alignH === "outside") effectiveAlignH = "right";
22711
+ const result = effectiveAlignH === "left" ? baseX + offsetH : effectiveAlignH === "right" ? baseX + availableWidth - tableWidth - offsetH : effectiveAlignH === "center" ? baseX + (availableWidth - tableWidth) / 2 + offsetH : baseX;
22712
+ return result;
22713
+ }
22714
+ function computeTableWrapMode(wrap) {
22715
+ if (!wrap) return "none";
22716
+ if (wrap.type === "None") {
22717
+ return "none";
22718
+ }
22719
+ const wrapText = wrap.wrapText ?? "bothSides";
22720
+ if (wrapText === "left") return "right";
22721
+ if (wrapText === "right") return "left";
22722
+ if (wrapText === "largest") return "largest";
22723
+ return "both";
22724
+ }
22375
22725
  function computeNextSectionPropsAtBreak(blocks) {
22376
22726
  const nextSectionPropsAtBreak = /* @__PURE__ */ new Map();
22377
22727
  const docxBreakIndexes = [];
@@ -23068,6 +23418,206 @@ function generateColumnBoundaries(measure) {
23068
23418
  }
23069
23419
  return boundaries;
23070
23420
  }
23421
+ function countHeaderRows(block) {
23422
+ let count = 0;
23423
+ for (let i = 0; i < block.rows.length; i++) {
23424
+ const row = block.rows[i];
23425
+ const repeatHeader = row.attrs?.tableRowProperties?.repeatHeader;
23426
+ if (repeatHeader === true) {
23427
+ count++;
23428
+ } else {
23429
+ break;
23430
+ }
23431
+ }
23432
+ return count;
23433
+ }
23434
+ function sumRowHeights(rows, fromRow, toRow) {
23435
+ let total = 0;
23436
+ for (let i = fromRow; i < toRow && i < rows.length; i++) {
23437
+ total += rows[i].height;
23438
+ }
23439
+ return total;
23440
+ }
23441
+ function calculateFragmentHeight(fragment, measure, _headerCount) {
23442
+ let height = 0;
23443
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
23444
+ height += sumRowHeights(measure.rows, 0, fragment.repeatHeaderCount);
23445
+ }
23446
+ height += sumRowHeights(measure.rows, fragment.fromRow, fragment.toRow);
23447
+ return height;
23448
+ }
23449
+ const MIN_PARTIAL_ROW_HEIGHT = 20;
23450
+ function getCellLines(cell) {
23451
+ if (cell.blocks && cell.blocks.length > 0) {
23452
+ const allLines = [];
23453
+ for (const block of cell.blocks) {
23454
+ if (block.kind === "paragraph") {
23455
+ if (block.kind === "paragraph" && "lines" in block) {
23456
+ const paraBlock = block;
23457
+ if (paraBlock.lines) {
23458
+ allLines.push(...paraBlock.lines);
23459
+ }
23460
+ }
23461
+ }
23462
+ }
23463
+ return allLines;
23464
+ }
23465
+ if (cell.paragraph?.lines) {
23466
+ return cell.paragraph.lines;
23467
+ }
23468
+ return [];
23469
+ }
23470
+ function getCellPadding(cellIdx, blockRow) {
23471
+ const padding = blockRow?.cells?.[cellIdx]?.attrs?.padding ?? {};
23472
+ return {
23473
+ top: padding.top ?? 2,
23474
+ bottom: padding.bottom ?? 2,
23475
+ left: padding.left ?? 4,
23476
+ right: padding.right ?? 4
23477
+ };
23478
+ }
23479
+ function getCellTotalLines(cell) {
23480
+ return getCellLines(cell).length;
23481
+ }
23482
+ function computePartialRow(rowIndex, blockRow, measure, availableHeight, fromLineByCell) {
23483
+ const row = measure.rows[rowIndex];
23484
+ if (!row) {
23485
+ throw new Error(`Invalid rowIndex ${rowIndex}: measure.rows has ${measure.rows.length} rows`);
23486
+ }
23487
+ const cellCount = row.cells.length;
23488
+ const startLines = fromLineByCell || new Array(cellCount).fill(0);
23489
+ const toLineByCell = [];
23490
+ const heightByCell = [];
23491
+ const cellPaddings = row.cells.map((_, idx) => getCellPadding(idx, blockRow));
23492
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
23493
+ const cell = row.cells[cellIdx];
23494
+ const startLine = startLines[cellIdx] || 0;
23495
+ const cellPadding = cellPaddings[cellIdx];
23496
+ const availableForLines = Math.max(0, availableHeight - (cellPadding.top + cellPadding.bottom));
23497
+ const lines = getCellLines(cell);
23498
+ let cumulativeHeight = 0;
23499
+ let cutLine = startLine;
23500
+ for (let i = startLine; i < lines.length; i++) {
23501
+ const lineHeight = lines[i].lineHeight || 0;
23502
+ if (cumulativeHeight + lineHeight > availableForLines) {
23503
+ break;
23504
+ }
23505
+ cumulativeHeight += lineHeight;
23506
+ cutLine = i + 1;
23507
+ }
23508
+ toLineByCell.push(cutLine);
23509
+ heightByCell.push(cumulativeHeight);
23510
+ }
23511
+ const positiveHeights = heightByCell.filter((h) => h > 0);
23512
+ const minHeight = positiveHeights.length > 0 ? Math.min(...positiveHeights) : 0;
23513
+ let actualPartialHeight = 0;
23514
+ let maxPaddingTotal = 0;
23515
+ for (let cellIdx = 0; cellIdx < cellCount; cellIdx++) {
23516
+ const cell = row.cells[cellIdx];
23517
+ const startLine = startLines[cellIdx] || 0;
23518
+ const lines = getCellLines(cell);
23519
+ const cellPadding = cellPaddings[cellIdx];
23520
+ const paddingTotal = cellPadding.top + cellPadding.bottom;
23521
+ maxPaddingTotal = Math.max(maxPaddingTotal, paddingTotal);
23522
+ let cumulativeHeight = 0;
23523
+ let cutLine = startLine;
23524
+ for (let i = startLine; i < lines.length; i++) {
23525
+ const lineHeight = lines[i].lineHeight || 0;
23526
+ if (cumulativeHeight + lineHeight > minHeight) {
23527
+ break;
23528
+ }
23529
+ cumulativeHeight += lineHeight;
23530
+ cutLine = i + 1;
23531
+ }
23532
+ toLineByCell[cellIdx] = cutLine;
23533
+ actualPartialHeight = Math.max(actualPartialHeight, cumulativeHeight + paddingTotal);
23534
+ }
23535
+ const madeProgress = toLineByCell.some((cutLine, idx) => cutLine > (startLines[idx] || 0));
23536
+ const isFirstPart = startLines.every((l) => l === 0);
23537
+ const allCellsExhausted = toLineByCell.every((cutLine, idx) => {
23538
+ const totalLines = getCellTotalLines(row.cells[idx]);
23539
+ return cutLine >= totalLines;
23540
+ });
23541
+ const isLastPart = allCellsExhausted || !madeProgress;
23542
+ if (actualPartialHeight === 0 && isFirstPart) {
23543
+ actualPartialHeight = maxPaddingTotal;
23544
+ }
23545
+ return {
23546
+ rowIndex,
23547
+ fromLineByCell: startLines,
23548
+ toLineByCell,
23549
+ isFirstPart,
23550
+ isLastPart,
23551
+ partialHeight: actualPartialHeight
23552
+ };
23553
+ }
23554
+ function findSplitPoint(block, measure, startRow, availableHeight, fullPageHeight, _pendingPartialRow) {
23555
+ let accumulatedHeight = 0;
23556
+ let lastFitRow = startRow;
23557
+ for (let i = startRow; i < block.rows.length; i++) {
23558
+ const row = block.rows[i];
23559
+ const rowHeight = measure.rows[i]?.height || 0;
23560
+ const cantSplit = row.attrs?.tableRowProperties?.cantSplit === true;
23561
+ if (accumulatedHeight + rowHeight <= availableHeight) {
23562
+ accumulatedHeight += rowHeight;
23563
+ lastFitRow = i + 1;
23564
+ } else {
23565
+ const remainingHeight = availableHeight - accumulatedHeight;
23566
+ if (fullPageHeight && rowHeight > fullPageHeight) {
23567
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
23568
+ return { endRow: i + 1, partialRow };
23569
+ }
23570
+ if (cantSplit) {
23571
+ if (lastFitRow === startRow) {
23572
+ return { endRow: startRow, partialRow: null };
23573
+ }
23574
+ return { endRow: lastFitRow, partialRow: null };
23575
+ }
23576
+ if (remainingHeight >= MIN_PARTIAL_ROW_HEIGHT) {
23577
+ const partialRow = computePartialRow(i, block.rows[i], measure, remainingHeight);
23578
+ const hasContent = partialRow.toLineByCell.some(
23579
+ (cutLine, idx) => cutLine > (partialRow.fromLineByCell[idx] || 0)
23580
+ );
23581
+ if (hasContent) {
23582
+ return { endRow: i + 1, partialRow };
23583
+ }
23584
+ }
23585
+ return { endRow: lastFitRow, partialRow: null };
23586
+ }
23587
+ }
23588
+ return { endRow: block.rows.length, partialRow: null };
23589
+ }
23590
+ function generateFragmentMetadata(measure, _fromRow, _toRow, _repeatHeaderCount) {
23591
+ return {
23592
+ columnBoundaries: generateColumnBoundaries(measure),
23593
+ coordinateSystem: "fragment"
23594
+ };
23595
+ }
23596
+ function layoutMonolithicTable(context) {
23597
+ let state = context.ensurePage();
23598
+ if (state.cursorY + context.measure.totalHeight > state.contentBottom && state.page.fragments.length > 0) {
23599
+ state = context.advanceColumn(state);
23600
+ }
23601
+ state = context.ensurePage();
23602
+ const height = Math.min(context.measure.totalHeight, state.contentBottom - state.cursorY);
23603
+ const metadata = {
23604
+ columnBoundaries: generateColumnBoundaries(context.measure),
23605
+ coordinateSystem: "fragment"
23606
+ };
23607
+ const fragment = {
23608
+ kind: "table",
23609
+ blockId: context.block.id,
23610
+ fromRow: 0,
23611
+ toRow: context.block.rows.length,
23612
+ x: context.columnX(state.columnIndex),
23613
+ y: state.cursorY,
23614
+ width: Math.min(context.columnWidth, context.measure.totalWidth || context.columnWidth),
23615
+ height,
23616
+ metadata
23617
+ };
23618
+ state.page.fragments.push(fragment);
23619
+ state.cursorY += height;
23620
+ }
23071
23621
  function layoutTableBlock({
23072
23622
  block,
23073
23623
  measure,
@@ -23076,30 +23626,176 @@ function layoutTableBlock({
23076
23626
  advanceColumn,
23077
23627
  columnX
23078
23628
  }) {
23629
+ if (block.anchor?.isAnchored) {
23630
+ return;
23631
+ }
23632
+ const tableProps = block.attrs?.tableProperties;
23633
+ const floatingProps = tableProps?.floatingTableProperties;
23634
+ if (floatingProps && Object.keys(floatingProps).length > 0) {
23635
+ layoutMonolithicTable({ block, measure, columnWidth, ensurePage, advanceColumn, columnX });
23636
+ return;
23637
+ }
23638
+ const headerCount = countHeaderRows(block);
23639
+ const headerHeight = headerCount > 0 ? sumRowHeights(measure.rows, 0, headerCount) : 0;
23079
23640
  let state = ensurePage();
23080
- if (state.cursorY + measure.totalHeight > state.contentBottom && state.page.fragments.length > 0) {
23081
- state = advanceColumn(state);
23641
+ let currentRow = 0;
23642
+ let isTableContinuation = false;
23643
+ let pendingPartialRow = null;
23644
+ while (currentRow < block.rows.length || pendingPartialRow !== null) {
23645
+ state = ensurePage();
23646
+ const availableHeight = state.contentBottom - state.cursorY;
23647
+ let repeatHeaderCount = 0;
23648
+ if (currentRow === 0 && !pendingPartialRow) {
23649
+ repeatHeaderCount = 0;
23650
+ } else {
23651
+ if (headerCount > 0 && headerHeight <= availableHeight) {
23652
+ repeatHeaderCount = headerCount;
23653
+ } else if (headerCount > 0 && headerHeight > availableHeight) {
23654
+ repeatHeaderCount = 0;
23655
+ }
23656
+ }
23657
+ const availableForBody = repeatHeaderCount > 0 ? availableHeight - headerHeight : availableHeight;
23658
+ const fullPageHeight = state.contentBottom;
23659
+ if (pendingPartialRow !== null) {
23660
+ const rowIndex = pendingPartialRow.rowIndex;
23661
+ const fromLineByCell = pendingPartialRow.toLineByCell;
23662
+ const continuationPartialRow = computePartialRow(
23663
+ rowIndex,
23664
+ block.rows[rowIndex],
23665
+ measure,
23666
+ availableForBody,
23667
+ fromLineByCell
23668
+ );
23669
+ const madeProgress = continuationPartialRow.toLineByCell.some(
23670
+ (toLine, idx) => toLine > (fromLineByCell[idx] || 0)
23671
+ );
23672
+ const hasRemainingLinesAfterContinuation = continuationPartialRow.toLineByCell.some(
23673
+ (toLine, idx) => {
23674
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
23675
+ return toLine < totalLines;
23676
+ }
23677
+ );
23678
+ const hadRemainingLinesBefore = fromLineByCell.some((fromLine, idx) => {
23679
+ const totalLines = getCellTotalLines(measure.rows[rowIndex].cells[idx]);
23680
+ return fromLine < totalLines;
23681
+ });
23682
+ const fragmentHeight2 = continuationPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23683
+ if (fragmentHeight2 > 0) {
23684
+ const fragment2 = {
23685
+ kind: "table",
23686
+ blockId: block.id,
23687
+ fromRow: rowIndex,
23688
+ toRow: rowIndex + 1,
23689
+ x: columnX(state.columnIndex),
23690
+ y: state.cursorY,
23691
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23692
+ height: fragmentHeight2,
23693
+ continuesFromPrev: true,
23694
+ continuesOnNext: hasRemainingLinesAfterContinuation || rowIndex + 1 < block.rows.length,
23695
+ repeatHeaderCount,
23696
+ partialRow: continuationPartialRow,
23697
+ metadata: generateFragmentMetadata(measure)
23698
+ };
23699
+ state.page.fragments.push(fragment2);
23700
+ state.cursorY += fragmentHeight2;
23701
+ }
23702
+ const rowComplete = !hasRemainingLinesAfterContinuation;
23703
+ if (rowComplete) {
23704
+ currentRow = rowIndex + 1;
23705
+ pendingPartialRow = null;
23706
+ } else if (!madeProgress && hadRemainingLinesBefore) {
23707
+ state = advanceColumn(state);
23708
+ } else {
23709
+ state = advanceColumn(state);
23710
+ pendingPartialRow = continuationPartialRow;
23711
+ }
23712
+ isTableContinuation = true;
23713
+ continue;
23714
+ }
23715
+ const bodyStartRow = currentRow;
23716
+ const { endRow, partialRow } = findSplitPoint(block, measure, bodyStartRow, availableForBody, fullPageHeight);
23717
+ if (endRow === bodyStartRow && partialRow === null && state.page.fragments.length > 0) {
23718
+ state = advanceColumn(state);
23719
+ continue;
23720
+ }
23721
+ if (endRow === bodyStartRow && partialRow === null) {
23722
+ const forcedPartialRow = computePartialRow(bodyStartRow, block.rows[bodyStartRow], measure, availableForBody);
23723
+ const forcedEndRow = bodyStartRow + 1;
23724
+ const fragmentHeight2 = forcedPartialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23725
+ const fragment2 = {
23726
+ kind: "table",
23727
+ blockId: block.id,
23728
+ fromRow: bodyStartRow,
23729
+ toRow: forcedEndRow,
23730
+ x: columnX(state.columnIndex),
23731
+ y: state.cursorY,
23732
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23733
+ height: fragmentHeight2,
23734
+ continuesFromPrev: isTableContinuation,
23735
+ continuesOnNext: !forcedPartialRow.isLastPart || forcedEndRow < block.rows.length,
23736
+ repeatHeaderCount,
23737
+ partialRow: forcedPartialRow,
23738
+ metadata: generateFragmentMetadata(measure)
23739
+ };
23740
+ state.page.fragments.push(fragment2);
23741
+ state.cursorY += fragmentHeight2;
23742
+ pendingPartialRow = forcedPartialRow;
23743
+ isTableContinuation = true;
23744
+ continue;
23745
+ }
23746
+ let fragmentHeight;
23747
+ if (partialRow) {
23748
+ const fullRowsHeight = sumRowHeights(measure.rows, bodyStartRow, endRow - 1);
23749
+ fragmentHeight = fullRowsHeight + partialRow.partialHeight + (repeatHeaderCount > 0 ? headerHeight : 0);
23750
+ } else {
23751
+ fragmentHeight = calculateFragmentHeight(
23752
+ { fromRow: bodyStartRow, toRow: endRow, repeatHeaderCount },
23753
+ measure
23754
+ );
23755
+ }
23756
+ const fragment = {
23757
+ kind: "table",
23758
+ blockId: block.id,
23759
+ fromRow: bodyStartRow,
23760
+ toRow: endRow,
23761
+ x: columnX(state.columnIndex),
23762
+ y: state.cursorY,
23763
+ width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23764
+ height: fragmentHeight,
23765
+ continuesFromPrev: isTableContinuation,
23766
+ continuesOnNext: endRow < block.rows.length || (partialRow ? !partialRow.isLastPart : false),
23767
+ repeatHeaderCount,
23768
+ partialRow: partialRow || void 0,
23769
+ metadata: generateFragmentMetadata(measure)
23770
+ };
23771
+ state.page.fragments.push(fragment);
23772
+ state.cursorY += fragmentHeight;
23773
+ if (partialRow && !partialRow.isLastPart) {
23774
+ pendingPartialRow = partialRow;
23775
+ currentRow = partialRow.rowIndex;
23776
+ } else {
23777
+ currentRow = endRow;
23778
+ pendingPartialRow = null;
23779
+ }
23780
+ isTableContinuation = true;
23082
23781
  }
23083
- state = ensurePage();
23084
- const height = Math.min(measure.totalHeight, state.contentBottom - state.cursorY);
23782
+ }
23783
+ function createAnchoredTableFragment(block, measure, x, y) {
23085
23784
  const metadata = {
23086
23785
  columnBoundaries: generateColumnBoundaries(measure),
23087
23786
  coordinateSystem: "fragment"
23088
- // rowBoundaries omitted - not needed for column resize, reduces DOM overhead
23089
23787
  };
23090
- const fragment = {
23788
+ return {
23091
23789
  kind: "table",
23092
23790
  blockId: block.id,
23093
23791
  fromRow: 0,
23094
23792
  toRow: block.rows.length,
23095
- x: columnX(state.columnIndex),
23096
- y: state.cursorY,
23097
- width: Math.min(columnWidth, measure.totalWidth || columnWidth),
23098
- height,
23793
+ x,
23794
+ y,
23795
+ width: measure.totalWidth ?? 0,
23796
+ height: measure.totalHeight ?? 0,
23099
23797
  metadata
23100
23798
  };
23101
- state.page.fragments.push(fragment);
23102
- state.cursorY += height;
23103
23799
  }
23104
23800
  function isPageRelativeAnchor(block) {
23105
23801
  const vRelativeFrom = block.anchor?.vRelativeFrom;
@@ -23126,9 +23822,6 @@ function collectPreRegisteredAnchors(blocks, measures) {
23126
23822
  function collectAnchoredDrawings(blocks, measures) {
23127
23823
  const map2 = /* @__PURE__ */ new Map();
23128
23824
  const len = Math.min(blocks.length, measures.length);
23129
- for (let i = 0; i < len; i += 1) {
23130
- if (blocks[i].kind === "paragraph") ;
23131
- }
23132
23825
  const nearestPrevParagraph = (fromIndex) => {
23133
23826
  for (let i = fromIndex - 1; i >= 0; i -= 1) {
23134
23827
  if (blocks[i].kind === "paragraph") return i;
@@ -23164,6 +23857,36 @@ function collectAnchoredDrawings(blocks, measures) {
23164
23857
  }
23165
23858
  return map2;
23166
23859
  }
23860
+ function collectAnchoredTables(blocks, measures) {
23861
+ const map2 = /* @__PURE__ */ new Map();
23862
+ const nearestPrevParagraph = (fromIndex) => {
23863
+ for (let i = fromIndex - 1; i >= 0; i -= 1) {
23864
+ if (blocks[i].kind === "paragraph") return i;
23865
+ }
23866
+ return null;
23867
+ };
23868
+ const nearestNextParagraph = (fromIndex) => {
23869
+ for (let i = fromIndex + 1; i < blocks.length; i += 1) {
23870
+ if (blocks[i].kind === "paragraph") return i;
23871
+ }
23872
+ return null;
23873
+ };
23874
+ for (let i = 0; i < blocks.length; i += 1) {
23875
+ const block = blocks[i];
23876
+ const measure = measures[i];
23877
+ if (block.kind !== "table" || measure?.kind !== "table") continue;
23878
+ const tableBlock = block;
23879
+ const tableMeasure = measure;
23880
+ if (!tableBlock.anchor?.isAnchored) continue;
23881
+ let anchorParaIndex = nearestPrevParagraph(i);
23882
+ if (anchorParaIndex == null) anchorParaIndex = nearestNextParagraph(i);
23883
+ if (anchorParaIndex == null) continue;
23884
+ const list = map2.get(anchorParaIndex) ?? [];
23885
+ list.push({ block: tableBlock, measure: tableMeasure });
23886
+ map2.set(anchorParaIndex, list);
23887
+ }
23888
+ return map2;
23889
+ }
23167
23890
  function createPaginator(opts) {
23168
23891
  const states = [];
23169
23892
  const pages = [];
@@ -23749,7 +24472,9 @@ function layoutDocument(blocks, measures, options = {}) {
23749
24472
  cachedColumnsState.state = null;
23750
24473
  };
23751
24474
  const anchoredByParagraph = collectAnchoredDrawings(blocks, measures);
24475
+ const anchoredTablesByParagraph = collectAnchoredTables(blocks, measures);
23752
24476
  const placedAnchoredIds = /* @__PURE__ */ new Set();
24477
+ const placedAnchoredTableIds = /* @__PURE__ */ new Set();
23753
24478
  const preRegisteredAnchors = collectPreRegisteredAnchors(blocks, measures);
23754
24479
  const preRegisteredPositions = /* @__PURE__ */ new Map();
23755
24480
  for (const entry of preRegisteredAnchors) {
@@ -23927,6 +24652,19 @@ function layoutDocument(blocks, measures, options = {}) {
23927
24652
  }
23928
24653
  }
23929
24654
  const anchorsForPara = anchoredByParagraph.get(index2);
24655
+ const tablesForPara = anchoredTablesByParagraph.get(index2);
24656
+ if (tablesForPara) {
24657
+ const state = paginator.ensurePage();
24658
+ for (const { block: tableBlock, measure: tableMeasure } of tablesForPara) {
24659
+ if (placedAnchoredTableIds.has(tableBlock.id)) continue;
24660
+ floatManager.registerTable(tableBlock, tableMeasure, state.cursorY, state.columnIndex, state.page.number);
24661
+ const anchorX = tableBlock.anchor?.offsetH ?? columnX(state.columnIndex);
24662
+ const anchorY = state.cursorY + (tableBlock.anchor?.offsetV ?? 0);
24663
+ const tableFragment = createAnchoredTableFragment(tableBlock, tableMeasure, anchorX, anchorY);
24664
+ state.page.fragments.push(tableFragment);
24665
+ placedAnchoredTableIds.add(tableBlock.id);
24666
+ }
24667
+ }
23930
24668
  layoutParagraphBlock(
23931
24669
  {
23932
24670
  block,
@@ -24198,7 +24936,9 @@ const hashRuns = (block) => {
24198
24936
  const trackedMode = block.attrs && "trackedChangesMode" in block.attrs && block.attrs.trackedChangesMode || "review";
24199
24937
  const trackedEnabled = resolveTrackedChangesEnabled(block.attrs, true);
24200
24938
  const runsHash = block.runs.map((run) => {
24201
- const text = normalizeText("src" in run || run.kind === "lineBreak" ? "" : run.text ?? "");
24939
+ const text = normalizeText(
24940
+ "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? ""
24941
+ );
24202
24942
  const bold = "bold" in run ? run.bold : false;
24203
24943
  const italic = "italic" in run ? run.italic : false;
24204
24944
  const color = "color" in run ? run.color : void 0;
@@ -24858,7 +25598,7 @@ function fontString(run) {
24858
25598
  return `${italic}${bold}${size}px ${family}`.trim();
24859
25599
  }
24860
25600
  function runText(run) {
24861
- return "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
25601
+ return "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
24862
25602
  }
24863
25603
  function measureRunSliceWidth(run, fromChar, toChar) {
24864
25604
  const context = getCtx();
@@ -25020,7 +25760,7 @@ const paragraphBlocksEqual = (a, b) => {
25020
25760
  for (let i = 0; i < a.runs.length; i += 1) {
25021
25761
  const runA = a.runs[i];
25022
25762
  const runB = b.runs[i];
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)) {
25763
+ if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
25024
25764
  return false;
25025
25765
  }
25026
25766
  }
@@ -25140,7 +25880,7 @@ function computeHeaderFooterContentHash(blocks) {
25140
25880
  parts.push(block.id);
25141
25881
  if (block.kind === "paragraph") {
25142
25882
  for (const run of block.runs) {
25143
- if (!("src" in run) && run.kind !== "lineBreak") {
25883
+ if (!("src" in run) && run.kind !== "lineBreak" && run.kind !== "break") {
25144
25884
  parts.push(run.text ?? "");
25145
25885
  }
25146
25886
  if ("bold" in run && run.bold) parts.push("b");
@@ -26111,7 +26851,7 @@ function computeLinePmRange$1(block, line) {
26111
26851
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
26112
26852
  const run = block.runs[runIndex];
26113
26853
  if (!run) continue;
26114
- const text = "src" in run || run.kind === "lineBreak" ? "" : run.text ?? "";
26854
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
26115
26855
  const runLength = text.length;
26116
26856
  const runPmStart = run.pmStart ?? null;
26117
26857
  const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -28719,7 +29459,20 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
28719
29459
  };
28720
29460
  };
28721
29461
  const renderTableCell = (deps) => {
28722
- const { doc: doc2, x, y, rowHeight, cellMeasure, cell, borders, renderLine, context, applySdtDataset } = deps;
29462
+ const {
29463
+ doc: doc2,
29464
+ x,
29465
+ y,
29466
+ rowHeight,
29467
+ cellMeasure,
29468
+ cell,
29469
+ borders,
29470
+ renderLine,
29471
+ context,
29472
+ applySdtDataset,
29473
+ fromLine,
29474
+ toLine
29475
+ } = deps;
28723
29476
  const cellEl = doc2.createElement("div");
28724
29477
  cellEl.style.position = "absolute";
28725
29478
  cellEl.style.left = `${x}px`;
@@ -28727,6 +29480,7 @@ const renderTableCell = (deps) => {
28727
29480
  cellEl.style.width = `${cellMeasure.width}px`;
28728
29481
  cellEl.style.height = `${rowHeight}px`;
28729
29482
  cellEl.style.boxSizing = "border-box";
29483
+ cellEl.style.overflow = "hidden";
28730
29484
  if (borders) {
28731
29485
  applyCellBorders(cellEl, borders);
28732
29486
  }
@@ -28740,36 +29494,87 @@ const renderTableCell = (deps) => {
28740
29494
  }
28741
29495
  let contentElement;
28742
29496
  const attrs = cell?.attrs;
28743
- const padding = attrs?.padding || { top: 2, left: 4, right: 4 };
29497
+ const padding = attrs?.padding || { top: 2, left: 4, right: 4, bottom: 2 };
28744
29498
  const paddingLeft = padding.left ?? 4;
28745
29499
  const paddingTop = padding.top ?? 2;
28746
29500
  const paddingRight = padding.right ?? 4;
29501
+ const paddingBottom = padding.bottom ?? 2;
28747
29502
  const cellBlocks = cell?.blocks ?? (cell?.paragraph ? [cell.paragraph] : []);
28748
- const blockMeasures = cellMeasure.blocks ?? (cellMeasure.paragraph ? [cellMeasure.paragraph] : []);
29503
+ const blockMeasures = cellMeasure?.blocks ?? (cellMeasure?.paragraph ? [cellMeasure.paragraph] : []);
28749
29504
  if (cellBlocks.length > 0 && blockMeasures.length > 0) {
28750
29505
  const content = doc2.createElement("div");
28751
29506
  content.style.position = "absolute";
28752
29507
  content.style.left = `${x + paddingLeft}px`;
28753
29508
  content.style.top = `${y + paddingTop}px`;
28754
- content.style.width = `${Math.max(0, cellMeasure.width - paddingLeft - paddingRight)}px`;
28755
- let blockY = 0;
29509
+ const contentWidth = Math.max(0, cellMeasure.width - paddingLeft - paddingRight);
29510
+ const contentHeight = Math.max(0, rowHeight - paddingTop - paddingBottom);
29511
+ content.style.width = `${contentWidth + 1}px`;
29512
+ content.style.height = `${contentHeight}px`;
29513
+ content.style.display = "flex";
29514
+ content.style.flexDirection = "column";
29515
+ content.style.overflowX = "visible";
29516
+ content.style.overflowY = "hidden";
29517
+ if (cell?.attrs?.verticalAlign === "center") {
29518
+ content.style.justifyContent = "center";
29519
+ } else if (cell?.attrs?.verticalAlign === "bottom") {
29520
+ content.style.justifyContent = "flex-end";
29521
+ } else {
29522
+ content.style.justifyContent = "flex-start";
29523
+ }
29524
+ const blockLineCounts = [];
29525
+ for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
29526
+ const bm = blockMeasures[i];
29527
+ if (bm.kind === "paragraph") {
29528
+ blockLineCounts.push(bm.lines?.length || 0);
29529
+ } else {
29530
+ blockLineCounts.push(0);
29531
+ }
29532
+ }
29533
+ const totalLines = blockLineCounts.reduce((a, b) => a + b, 0);
29534
+ const globalFromLine = fromLine ?? 0;
29535
+ const globalToLine = toLine === -1 || toLine === void 0 ? totalLines : toLine;
29536
+ let cumulativeLineCount = 0;
28756
29537
  for (let i = 0; i < Math.min(blockMeasures.length, cellBlocks.length); i++) {
28757
29538
  const blockMeasure = blockMeasures[i];
28758
29539
  const block = cellBlocks[i];
28759
29540
  if (blockMeasure.kind === "paragraph" && block?.kind === "paragraph") {
29541
+ const lines = blockMeasure.lines;
29542
+ const blockLineCount = lines?.length || 0;
29543
+ const blockStartGlobal = cumulativeLineCount;
29544
+ const blockEndGlobal = cumulativeLineCount + blockLineCount;
29545
+ if (blockEndGlobal <= globalFromLine) {
29546
+ cumulativeLineCount += blockLineCount;
29547
+ continue;
29548
+ }
29549
+ if (blockStartGlobal >= globalToLine) {
29550
+ cumulativeLineCount += blockLineCount;
29551
+ continue;
29552
+ }
29553
+ const localStartLine = Math.max(0, globalFromLine - blockStartGlobal);
29554
+ const localEndLine = Math.min(blockLineCount, globalToLine - blockStartGlobal);
28760
29555
  const paraWrapper = doc2.createElement("div");
28761
- paraWrapper.style.position = "absolute";
28762
- paraWrapper.style.top = `${blockY}px`;
29556
+ paraWrapper.style.position = "relative";
28763
29557
  paraWrapper.style.left = "0";
28764
29558
  paraWrapper.style.width = "100%";
28765
29559
  applySdtDataset(paraWrapper, block.attrs?.sdt);
28766
- const lines = blockMeasure.lines;
28767
- lines.forEach((line) => {
29560
+ let renderedHeight = 0;
29561
+ for (let lineIdx = localStartLine; lineIdx < localEndLine && lineIdx < lines.length; lineIdx++) {
29562
+ const line = lines[lineIdx];
28768
29563
  const lineEl = renderLine(block, line, { ...context, section: "body" });
28769
29564
  paraWrapper.appendChild(lineEl);
28770
- });
29565
+ renderedHeight += line.lineHeight;
29566
+ }
29567
+ const renderedEntireBlock = localStartLine === 0 && localEndLine >= blockLineCount;
29568
+ if (renderedEntireBlock && blockMeasure.totalHeight && blockMeasure.totalHeight > renderedHeight) {
29569
+ renderedHeight = blockMeasure.totalHeight;
29570
+ }
28771
29571
  content.appendChild(paraWrapper);
28772
- blockY += blockMeasure.totalHeight;
29572
+ if (renderedHeight > 0) {
29573
+ paraWrapper.style.height = `${renderedHeight}px`;
29574
+ }
29575
+ cumulativeLineCount += blockLineCount;
29576
+ } else {
29577
+ cumulativeLineCount += 0;
28773
29578
  }
28774
29579
  }
28775
29580
  contentElement = content;
@@ -28790,7 +29595,10 @@ const renderTableRow = (deps) => {
28790
29595
  allRowHeights,
28791
29596
  context,
28792
29597
  renderLine,
28793
- applySdtDataset
29598
+ applySdtDataset,
29599
+ continuesFromPrev,
29600
+ continuesOnNext,
29601
+ partialRow
28794
29602
  } = deps;
28795
29603
  const calculateXPosition = (gridColumnStart) => {
28796
29604
  let x = 0;
@@ -28823,25 +29631,57 @@ const renderTableRow = (deps) => {
28823
29631
  const isLastRow = rowIndex === totalRows - 1;
28824
29632
  const isFirstCol = gridColIndex === 0;
28825
29633
  const isLastCol = gridColIndex === totalCols - 1;
29634
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
29635
+ const treatAsLastRow = isLastRow || continuesOnNext;
28826
29636
  resolvedBorders = {
28827
- // For top: use cell's if defined, otherwise use table's top for first row
28828
- top: cellBordersAttr.top ?? borderValueToSpec(isFirstRow ? tableBorders.top : tableBorders.insideH),
28829
- // For bottom: use cell's if defined, otherwise use table's bottom for last row only
28830
- bottom: cellBordersAttr.bottom ?? borderValueToSpec(isLastRow ? tableBorders.bottom : void 0),
29637
+ // For top: use cell's if defined, otherwise use table's top border for first row OR continuation
29638
+ top: cellBordersAttr.top ?? borderValueToSpec(treatAsFirstRow ? tableBorders.top : tableBorders.insideH),
29639
+ // For bottom: use cell's if defined, otherwise use table's bottom border for last row OR before continuation
29640
+ bottom: cellBordersAttr.bottom ?? borderValueToSpec(treatAsLastRow ? tableBorders.bottom : void 0),
28831
29641
  // For left: use cell's if defined, otherwise use table's left for first col
28832
29642
  left: cellBordersAttr.left ?? borderValueToSpec(isFirstCol ? tableBorders.left : tableBorders.insideV),
28833
29643
  // For right: use cell's if defined, otherwise use table's right for last col only
28834
29644
  right: cellBordersAttr.right ?? borderValueToSpec(isLastCol ? tableBorders.right : void 0)
28835
29645
  };
28836
29646
  } else if (hasExplicitBorders) {
28837
- resolvedBorders = cellBordersAttr;
29647
+ resolvedBorders = {
29648
+ top: cellBordersAttr.top,
29649
+ bottom: cellBordersAttr.bottom,
29650
+ left: cellBordersAttr.left,
29651
+ right: cellBordersAttr.right
29652
+ };
28838
29653
  } else if (tableBorders) {
28839
- resolvedBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
29654
+ const isFirstRow = rowIndex === 0;
29655
+ const isLastRow = rowIndex === totalRows - 1;
29656
+ const treatAsFirstRow = isFirstRow || continuesFromPrev;
29657
+ const treatAsLastRow = isLastRow || continuesOnNext;
29658
+ const baseBorders = resolveTableCellBorders(tableBorders, rowIndex, gridColIndex, totalRows, totalCols);
29659
+ if (baseBorders) {
29660
+ resolvedBorders = {
29661
+ // If this is a continuation (continuesFromPrev), use table's top border
29662
+ top: treatAsFirstRow ? borderValueToSpec(tableBorders.top) : baseBorders.top,
29663
+ // If this continues on next (continuesOnNext), use table's bottom border
29664
+ bottom: treatAsLastRow ? borderValueToSpec(tableBorders.bottom) : baseBorders.bottom,
29665
+ left: baseBorders.left,
29666
+ right: baseBorders.right
29667
+ };
29668
+ } else {
29669
+ resolvedBorders = void 0;
29670
+ }
28840
29671
  } else {
28841
29672
  resolvedBorders = void 0;
28842
29673
  }
28843
29674
  const rowSpan = cellMeasure.rowSpan ?? 1;
28844
- const cellHeight = rowSpan > 1 ? calculateRowspanHeight(rowIndex, rowSpan) : rowMeasure.height;
29675
+ let cellHeight;
29676
+ if (partialRow) {
29677
+ cellHeight = partialRow.partialHeight;
29678
+ } else if (rowSpan > 1) {
29679
+ cellHeight = calculateRowspanHeight(rowIndex, rowSpan);
29680
+ } else {
29681
+ cellHeight = rowMeasure.height;
29682
+ }
29683
+ const fromLine = partialRow?.fromLineByCell?.[cellIndex];
29684
+ const toLine = partialRow?.toLineByCell?.[cellIndex];
28845
29685
  const { cellElement, contentElement } = renderTableCell({
28846
29686
  doc: doc2,
28847
29687
  x,
@@ -28852,7 +29692,9 @@ const renderTableRow = (deps) => {
28852
29692
  borders: resolvedBorders,
28853
29693
  renderLine,
28854
29694
  context,
28855
- applySdtDataset
29695
+ applySdtDataset,
29696
+ fromLine,
29697
+ toLine
28856
29698
  });
28857
29699
  container.appendChild(cellElement);
28858
29700
  if (contentElement) {
@@ -28966,11 +29808,46 @@ const renderTableFragment = (deps) => {
28966
29808
  if (borderCollapse === "separate" && block.attrs?.cellSpacing) {
28967
29809
  container.style.borderSpacing = `${block.attrs.cellSpacing}px`;
28968
29810
  }
28969
- const allRowHeights = measure.rows.map((r2) => r2.height);
29811
+ const allRowHeights = measure.rows.map((r2, idx) => {
29812
+ if (fragment.partialRow && fragment.partialRow.rowIndex === idx) {
29813
+ return fragment.partialRow.partialHeight;
29814
+ }
29815
+ return r2?.height ?? 0;
29816
+ });
28970
29817
  let y = 0;
29818
+ if (fragment.repeatHeaderCount && fragment.repeatHeaderCount > 0) {
29819
+ for (let r2 = 0; r2 < fragment.repeatHeaderCount; r2 += 1) {
29820
+ const rowMeasure = measure.rows[r2];
29821
+ if (!rowMeasure) break;
29822
+ renderTableRow({
29823
+ doc: doc2,
29824
+ container,
29825
+ rowIndex: r2,
29826
+ y,
29827
+ rowMeasure,
29828
+ row: block.rows[r2],
29829
+ totalRows: block.rows.length,
29830
+ tableBorders,
29831
+ columnWidths: measure.columnWidths,
29832
+ allRowHeights,
29833
+ context,
29834
+ renderLine,
29835
+ applySdtDataset,
29836
+ // Headers are always rendered as-is (no border suppression)
29837
+ continuesFromPrev: false,
29838
+ continuesOnNext: false
29839
+ });
29840
+ y += rowMeasure.height;
29841
+ }
29842
+ }
28971
29843
  for (let r2 = fragment.fromRow; r2 < fragment.toRow; r2 += 1) {
28972
29844
  const rowMeasure = measure.rows[r2];
28973
29845
  if (!rowMeasure) break;
29846
+ const isFirstRenderedBodyRow = r2 === fragment.fromRow;
29847
+ const isLastRenderedBodyRow = r2 === fragment.toRow - 1;
29848
+ const isPartialRow = fragment.partialRow && fragment.partialRow.rowIndex === r2;
29849
+ const partialRowData = isPartialRow ? fragment.partialRow : void 0;
29850
+ const actualRowHeight = partialRowData ? partialRowData.partialHeight : rowMeasure.height;
28974
29851
  renderTableRow({
28975
29852
  doc: doc2,
28976
29853
  container,
@@ -28984,9 +29861,15 @@ const renderTableFragment = (deps) => {
28984
29861
  allRowHeights,
28985
29862
  context,
28986
29863
  renderLine,
28987
- applySdtDataset
29864
+ applySdtDataset,
29865
+ // Draw top border if table continues from previous fragment (MS Word behavior)
29866
+ continuesFromPrev: isFirstRenderedBodyRow && fragment.continuesFromPrev === true,
29867
+ // Draw bottom border if table continues on next fragment (MS Word behavior)
29868
+ continuesOnNext: isLastRenderedBodyRow && fragment.continuesOnNext === true,
29869
+ // Pass partial row data for mid-row splits
29870
+ partialRow: partialRowData
28988
29871
  });
28989
- y += rowMeasure.height;
29872
+ y += actualRowHeight;
28990
29873
  }
28991
29874
  return container;
28992
29875
  };
@@ -30774,6 +31657,12 @@ const _DomPainter = class _DomPainter {
30774
31657
  isLineBreakRun(run) {
30775
31658
  return run.kind === "lineBreak";
30776
31659
  }
31660
+ /**
31661
+ * Type guard to check if a run is a break run.
31662
+ */
31663
+ isBreakRun(run) {
31664
+ return run.kind === "break";
31665
+ }
30777
31666
  renderRun(run, context, trackedConfig) {
30778
31667
  if (this.isImageRun(run)) {
30779
31668
  return this.renderImageRun(run);
@@ -30781,7 +31670,10 @@ const _DomPainter = class _DomPainter {
30781
31670
  if (this.isLineBreakRun(run)) {
30782
31671
  return null;
30783
31672
  }
30784
- if (!run.text || !this.doc) {
31673
+ if (this.isBreakRun(run)) {
31674
+ return null;
31675
+ }
31676
+ if (!("text" in run) || !run.text || !this.doc) {
30785
31677
  return null;
30786
31678
  }
30787
31679
  const linkData = this.extractLinkData(run);
@@ -30922,6 +31814,12 @@ const _DomPainter = class _DomPainter {
30922
31814
  if (styleId) {
30923
31815
  el.setAttribute("styleid", styleId);
30924
31816
  }
31817
+ const alignment = block.attrs?.alignment;
31818
+ if (alignment === "center" || alignment === "right" || alignment === "justify") {
31819
+ el.style.textAlign = alignment === "justify" ? "justify" : alignment;
31820
+ } else {
31821
+ el.style.textAlign = "left";
31822
+ }
30925
31823
  const lineRange = computeLinePmRange(block, line);
30926
31824
  if (lineRange.pmStart != null) {
30927
31825
  el.dataset.pmStart = String(lineRange.pmStart);
@@ -31039,10 +31937,16 @@ const _DomPainter = class _DomPainter {
31039
31937
  if (this.isLineBreakRun(baseRun)) {
31040
31938
  continue;
31041
31939
  }
31940
+ if (this.isBreakRun(baseRun)) {
31941
+ continue;
31942
+ }
31042
31943
  const runSegments = segmentsByRun.get(runIndex);
31043
31944
  if (!runSegments || runSegments.length === 0) {
31044
31945
  continue;
31045
31946
  }
31947
+ if (!("text" in baseRun)) {
31948
+ continue;
31949
+ }
31046
31950
  const baseText = baseRun.text ?? "";
31047
31951
  const runPmStart = baseRun.pmStart ?? null;
31048
31952
  const fallbackPmEnd = runPmStart != null && baseRun.pmEnd == null ? runPmStart + baseText.length : baseRun.pmEnd ?? null;
@@ -31361,7 +32265,12 @@ const fragmentKey = (fragment) => {
31361
32265
  if (fragment.kind === "drawing") {
31362
32266
  return `drawing:${fragment.blockId}:${fragment.x}:${fragment.y}`;
31363
32267
  }
31364
- return `${fragment.kind}:${fragment.blockId}`;
32268
+ if (fragment.kind === "table") {
32269
+ const partialKey = fragment.partialRow ? `:${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}` : "";
32270
+ return `table:${fragment.blockId}:${fragment.fromRow}:${fragment.toRow}${partialKey}`;
32271
+ }
32272
+ const _exhaustiveCheck = fragment;
32273
+ return _exhaustiveCheck;
31365
32274
  };
31366
32275
  const fragmentSignature = (fragment, lookup) => {
31367
32276
  const base2 = lookup.get(fragment.blockId)?.version ?? "missing";
@@ -31403,6 +32312,20 @@ const fragmentSignature = (fragment, lookup) => {
31403
32312
  fragment.zIndex ?? ""
31404
32313
  ].join("|");
31405
32314
  }
32315
+ if (fragment.kind === "table") {
32316
+ const partialSig = fragment.partialRow ? `${fragment.partialRow.fromLineByCell.join(",")}-${fragment.partialRow.toLineByCell.join(",")}-${fragment.partialRow.partialHeight}` : "";
32317
+ return [
32318
+ base2,
32319
+ fragment.fromRow,
32320
+ fragment.toRow,
32321
+ fragment.width,
32322
+ fragment.height,
32323
+ fragment.continuesFromPrev ? 1 : 0,
32324
+ fragment.continuesOnNext ? 1 : 0,
32325
+ fragment.repeatHeaderCount ?? 0,
32326
+ partialSig
32327
+ ].join("|");
32328
+ }
31406
32329
  return base2;
31407
32330
  };
31408
32331
  const deriveBlockVersion = (block) => {
@@ -31548,7 +32471,7 @@ const deriveBlockVersion = (block) => {
31548
32471
  return block.id;
31549
32472
  };
31550
32473
  const applyRunStyles = (element, run, isLink = false) => {
31551
- if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak") {
32474
+ if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak" || run.kind === "break") {
31552
32475
  return;
31553
32476
  }
31554
32477
  element.style.fontFamily = run.fontFamily;
@@ -31682,6 +32605,17 @@ const sliceRunsForLine = (block, line) => {
31682
32605
  result.push(run);
31683
32606
  continue;
31684
32607
  }
32608
+ if (run.kind === "break") {
32609
+ result.push(run);
32610
+ continue;
32611
+ }
32612
+ if (run.kind === "tab") {
32613
+ result.push(run);
32614
+ continue;
32615
+ }
32616
+ if (!("text" in run)) {
32617
+ continue;
32618
+ }
31685
32619
  const text = run.text ?? "";
31686
32620
  const isFirstRun = runIndex === line.fromRun;
31687
32621
  const isLastRun = runIndex === line.toRun;
@@ -31695,20 +32629,14 @@ const sliceRunsForLine = (block, line) => {
31695
32629
  if (!slice2) continue;
31696
32630
  const pmSliceStart = runPmStart != null ? runPmStart + start2 : void 0;
31697
32631
  const pmSliceEnd = runPmStart != null ? runPmStart + end2 : fallbackPmEnd ?? void 0;
31698
- if (run.kind === "tab") {
31699
- if (slice2.includes(" ")) {
31700
- result.push(run);
31701
- }
31702
- } else {
31703
- const sliced = {
31704
- ...run,
31705
- text: slice2,
31706
- pmStart: pmSliceStart,
31707
- pmEnd: pmSliceEnd,
31708
- comments: run.comments ? [...run.comments] : void 0
31709
- };
31710
- result.push(sliced);
31711
- }
32632
+ const sliced = {
32633
+ ...run,
32634
+ text: slice2,
32635
+ pmStart: pmSliceStart,
32636
+ pmEnd: pmSliceEnd,
32637
+ comments: run.comments ? [...run.comments] : void 0
32638
+ };
32639
+ result.push(sliced);
31712
32640
  } else {
31713
32641
  result.push(run);
31714
32642
  }
@@ -31751,6 +32679,39 @@ const computeLinePmRange = (block, line) => {
31751
32679
  }
31752
32680
  continue;
31753
32681
  }
32682
+ if (run.kind === "break") {
32683
+ const runPmStart2 = run.pmStart ?? null;
32684
+ const runPmEnd = run.pmEnd ?? null;
32685
+ if (runPmStart2 == null || runPmEnd == null) {
32686
+ continue;
32687
+ }
32688
+ if (pmStart == null) {
32689
+ pmStart = runPmStart2;
32690
+ }
32691
+ pmEnd = runPmEnd;
32692
+ if (runIndex === line.toRun) {
32693
+ break;
32694
+ }
32695
+ continue;
32696
+ }
32697
+ if (run.kind === "tab") {
32698
+ const runPmStart2 = run.pmStart ?? null;
32699
+ const runPmEnd = run.pmEnd ?? null;
32700
+ if (runPmStart2 == null || runPmEnd == null) {
32701
+ continue;
32702
+ }
32703
+ if (pmStart == null) {
32704
+ pmStart = runPmStart2;
32705
+ }
32706
+ pmEnd = runPmEnd;
32707
+ if (runIndex === line.toRun) {
32708
+ break;
32709
+ }
32710
+ continue;
32711
+ }
32712
+ if (!("text" in run)) {
32713
+ continue;
32714
+ }
31754
32715
  const text = run.text ?? "";
31755
32716
  const runLength = text.length;
31756
32717
  const runPmStart = run.pmStart ?? null;
@@ -31792,6 +32753,12 @@ const resolveRunText = (run, context) => {
31792
32753
  if (run.kind === "lineBreak") {
31793
32754
  return "";
31794
32755
  }
32756
+ if (run.kind === "break") {
32757
+ return "";
32758
+ }
32759
+ if (!("text" in run)) {
32760
+ return "";
32761
+ }
31795
32762
  if (!runToken) {
31796
32763
  return run.text ?? "";
31797
32764
  }
@@ -31989,6 +32956,7 @@ async function measureBlock(block, constraints) {
31989
32956
  async function measureParagraphBlock(block, maxWidth) {
31990
32957
  const ctx2 = getCanvasContext();
31991
32958
  const wordLayout = block.attrs?.wordLayout;
32959
+ const WIDTH_FUDGE_PX = 0.5;
31992
32960
  const lines = [];
31993
32961
  const indent = block.attrs?.indent;
31994
32962
  const spacing = block.attrs?.spacing;
@@ -32083,8 +33051,67 @@ async function measureParagraphBlock(block, maxWidth) {
32083
33051
  lastAppliedTabAlign = { target, val };
32084
33052
  pendingTabAlignment = null;
32085
33053
  };
32086
- for (let runIndex = 0; runIndex < block.runs.length; runIndex++) {
32087
- const run = block.runs[runIndex];
33054
+ const runsToProcess = [];
33055
+ for (const run of block.runs) {
33056
+ if (run.text && typeof run.text === "string" && run.text.includes("\n")) {
33057
+ const textRun = run;
33058
+ const segments = textRun.text.split("\n");
33059
+ let cursor = textRun.pmStart ?? 0;
33060
+ segments.forEach((seg, idx) => {
33061
+ runsToProcess.push({
33062
+ ...textRun,
33063
+ text: seg,
33064
+ pmStart: cursor,
33065
+ pmEnd: cursor + seg.length
33066
+ });
33067
+ cursor += seg.length;
33068
+ if (idx !== segments.length - 1) {
33069
+ runsToProcess.push({
33070
+ kind: "break",
33071
+ breakType: "line",
33072
+ pmStart: cursor,
33073
+ pmEnd: cursor + 1,
33074
+ sdt: run.sdt
33075
+ });
33076
+ cursor += 1;
33077
+ }
33078
+ });
33079
+ } else {
33080
+ runsToProcess.push(run);
33081
+ }
33082
+ }
33083
+ for (let runIndex = 0; runIndex < runsToProcess.length; runIndex++) {
33084
+ const run = runsToProcess[runIndex];
33085
+ if (run.kind === "break") {
33086
+ if (currentLine) {
33087
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
33088
+ const completedLine = { ...currentLine, ...metrics };
33089
+ addBarTabsToLine(completedLine);
33090
+ lines.push(completedLine);
33091
+ currentLine = null;
33092
+ } else {
33093
+ const textRunWithSize = block.runs.find(
33094
+ (r2) => r2.kind !== "tab" && r2.kind !== "lineBreak" && r2.kind !== "break" && !("src" in r2) && "fontSize" in r2
33095
+ );
33096
+ const fallbackSize = textRunWithSize?.fontSize ?? 12;
33097
+ const metrics = calculateTypographyMetrics(fallbackSize, spacing);
33098
+ const emptyLine = {
33099
+ fromRun: runIndex,
33100
+ fromChar: 0,
33101
+ toRun: runIndex,
33102
+ toChar: 0,
33103
+ width: 0,
33104
+ segments: [],
33105
+ ...metrics
33106
+ };
33107
+ addBarTabsToLine(emptyLine);
33108
+ lines.push(emptyLine);
33109
+ }
33110
+ tabStopCursor = 0;
33111
+ pendingTabAlignment = null;
33112
+ lastAppliedTabAlign = null;
33113
+ continue;
33114
+ }
32088
33115
  if (isLineBreakRun(run)) {
32089
33116
  if (currentLine) {
32090
33117
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
@@ -32235,6 +33262,9 @@ async function measureParagraphBlock(block, maxWidth) {
32235
33262
  }
32236
33263
  continue;
32237
33264
  }
33265
+ if (!("text" in run) || !("fontSize" in run)) {
33266
+ continue;
33267
+ }
32238
33268
  lastFontSize = run.fontSize;
32239
33269
  const { font } = buildFontString(run);
32240
33270
  const tabSegments = run.text.split(" ");
@@ -32274,18 +33304,18 @@ async function measureParagraphBlock(block, maxWidth) {
32274
33304
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
32275
33305
  };
32276
33306
  const ls = run.letterSpacing ?? 0;
32277
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
33307
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
32278
33308
  currentLine.toChar = wordEndWithSpace;
32279
33309
  currentLine.width = roundValue(currentLine.width + spaceWidth + ls);
32280
33310
  charPosInRun = wordEndWithSpace;
32281
33311
  } else {
32282
- charPosInRun = wordEndNoSpace;
33312
+ charPosInRun = wordEndWithSpace;
32283
33313
  }
32284
33314
  continue;
32285
33315
  }
32286
33316
  const isTocEntry = block.attrs?.isTocEntry;
32287
33317
  const boundarySpacing = currentLine.width > 0 ? run.letterSpacing ?? 0 : 0;
32288
- if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth && currentLine.width > 0 && !isTocEntry) {
33318
+ if (currentLine.width + boundarySpacing + wordOnlyWidth > currentLine.maxWidth - WIDTH_FUDGE_PX && currentLine.width > 0 && !isTocEntry) {
32289
33319
  const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing);
32290
33320
  const completedLine = {
32291
33321
  ...currentLine,
@@ -32305,16 +33335,16 @@ async function measureParagraphBlock(block, maxWidth) {
32305
33335
  maxWidth: getEffectiveWidth(contentWidth),
32306
33336
  segments: [{ runIndex, fromChar: wordStartChar, toChar: wordEndNoSpace, width: wordOnlyWidth }]
32307
33337
  };
32308
- if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth) {
33338
+ if (!isLastWord && currentLine.width + spaceWidth <= currentLine.maxWidth - WIDTH_FUDGE_PX) {
32309
33339
  currentLine.toChar = wordEndWithSpace;
32310
33340
  currentLine.width = roundValue(currentLine.width + spaceWidth + (run.letterSpacing ?? 0));
32311
33341
  charPosInRun = wordEndWithSpace;
32312
33342
  } else {
32313
- charPosInRun = wordEndNoSpace;
33343
+ charPosInRun = wordEndWithSpace;
32314
33344
  }
32315
33345
  } else {
32316
33346
  currentLine.toRun = runIndex;
32317
- if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth) {
33347
+ if (!isLastWord && currentLine.width + boundarySpacing + wordOnlyWidth + spaceWidth > currentLine.maxWidth - WIDTH_FUDGE_PX) {
32318
33348
  currentLine.toChar = wordEndNoSpace;
32319
33349
  currentLine.width = roundValue(currentLine.width + boundarySpacing + wordOnlyWidth);
32320
33350
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
@@ -32440,6 +33470,34 @@ async function measureParagraphBlock(block, maxWidth) {
32440
33470
  async function measureTableBlock(block, constraints) {
32441
33471
  const maxWidth = typeof constraints === "number" ? constraints : constraints.maxWidth;
32442
33472
  let columnWidths;
33473
+ const scaleColumnWidths = (widths, targetWidth) => {
33474
+ const totalWidth2 = widths.reduce((a, b) => a + b, 0);
33475
+ if (totalWidth2 <= targetWidth || widths.length === 0) return widths;
33476
+ const scale = targetWidth / totalWidth2;
33477
+ const scaled = widths.map((w) => Math.max(1, Math.round(w * scale)));
33478
+ const sum = scaled.reduce((a, b) => a + b, 0);
33479
+ if (sum !== targetWidth) {
33480
+ const adjust = (delta) => {
33481
+ let idx = 0;
33482
+ const direction = delta > 0 ? 1 : -1;
33483
+ delta = Math.abs(delta);
33484
+ while (delta > 0 && scaled.length > 0) {
33485
+ const i = idx % scaled.length;
33486
+ if (direction > 0) {
33487
+ scaled[i] += 1;
33488
+ delta -= 1;
33489
+ } else if (scaled[i] > 1) {
33490
+ scaled[i] -= 1;
33491
+ delta -= 1;
33492
+ }
33493
+ idx += 1;
33494
+ if (idx > scaled.length * 2 && delta > 0) break;
33495
+ }
33496
+ };
33497
+ adjust(targetWidth - sum);
33498
+ }
33499
+ return scaled;
33500
+ };
32443
33501
  const maxCellCount = Math.max(1, Math.max(...block.rows.map((r2) => r2.cells.length)));
32444
33502
  if (block.columnWidths && block.columnWidths.length > 0) {
32445
33503
  columnWidths = [...block.columnWidths];
@@ -32448,8 +33506,7 @@ async function measureTableBlock(block, constraints) {
32448
33506
  if (hasExplicitWidth || hasFixedLayout) {
32449
33507
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
32450
33508
  if (totalWidth2 > maxWidth) {
32451
- const scale = maxWidth / totalWidth2;
32452
- columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
33509
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
32453
33510
  }
32454
33511
  } else {
32455
33512
  if (columnWidths.length < maxCellCount) {
@@ -32463,8 +33520,7 @@ async function measureTableBlock(block, constraints) {
32463
33520
  }
32464
33521
  const totalWidth2 = columnWidths.reduce((a, b) => a + b, 0);
32465
33522
  if (totalWidth2 > maxWidth) {
32466
- const scale = maxWidth / totalWidth2;
32467
- columnWidths = columnWidths.map((w) => Math.max(1, Math.floor(w * scale)));
33523
+ columnWidths = scaleColumnWidths(columnWidths, maxWidth);
32468
33524
  }
32469
33525
  }
32470
33526
  } else {
@@ -32481,6 +33537,8 @@ async function measureTableBlock(block, constraints) {
32481
33537
  };
32482
33538
  const rowspanTracker = new Array(gridColumnCount).fill(0);
32483
33539
  const rows = [];
33540
+ const rowBaseHeights = new Array(block.rows.length).fill(0);
33541
+ const spanConstraints = [];
32484
33542
  for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex++) {
32485
33543
  const row = block.rows[rowIndex];
32486
33544
  const cellMeasures = [];
@@ -32527,6 +33585,11 @@ async function measureTableBlock(block, constraints) {
32527
33585
  colSpan: colspan,
32528
33586
  rowSpan: rowspan
32529
33587
  });
33588
+ if (rowspan === 1) {
33589
+ rowBaseHeights[rowIndex] = Math.max(rowBaseHeights[rowIndex], totalCellHeight);
33590
+ } else {
33591
+ spanConstraints.push({ startRow: rowIndex, rowSpan: rowspan, requiredHeight: totalCellHeight });
33592
+ }
32530
33593
  gridColIndex += colspan;
32531
33594
  }
32532
33595
  for (let col = gridColIndex; col < gridColumnCount; col++) {
@@ -32534,10 +33597,39 @@ async function measureTableBlock(block, constraints) {
32534
33597
  rowspanTracker[col]--;
32535
33598
  }
32536
33599
  }
32537
- const rowHeight = Math.max(0, ...cellMeasures.map((c) => c.height));
32538
- rows.push({ cells: cellMeasures, height: rowHeight });
33600
+ rows.push({ cells: cellMeasures, height: 0 });
33601
+ }
33602
+ const rowHeights = [...rowBaseHeights];
33603
+ for (const constraint of spanConstraints) {
33604
+ const { startRow, rowSpan, requiredHeight } = constraint;
33605
+ if (rowSpan <= 0) continue;
33606
+ let currentHeight = 0;
33607
+ for (let i = 0; i < rowSpan && startRow + i < rowHeights.length; i++) {
33608
+ currentHeight += rowHeights[startRow + i];
33609
+ }
33610
+ if (currentHeight < requiredHeight) {
33611
+ const spanLength = Math.min(rowSpan, rowHeights.length - startRow);
33612
+ const increment = spanLength > 0 ? (requiredHeight - currentHeight) / spanLength : 0;
33613
+ for (let i = 0; i < spanLength; i++) {
33614
+ rowHeights[startRow + i] += increment;
33615
+ }
33616
+ }
33617
+ }
33618
+ block.rows.forEach((row, index2) => {
33619
+ const spec = row.attrs?.rowHeight;
33620
+ if (spec?.value != null && Number.isFinite(spec.value)) {
33621
+ const rule = spec.rule ?? "atLeast";
33622
+ if (rule === "exact") {
33623
+ rowHeights[index2] = spec.value;
33624
+ } else {
33625
+ rowHeights[index2] = Math.max(rowHeights[index2], spec.value);
33626
+ }
33627
+ }
33628
+ });
33629
+ for (let i = 0; i < rows.length; i++) {
33630
+ rows[i].height = Math.max(0, rowHeights[i]);
32539
33631
  }
32540
- const totalHeight = rows.reduce((sum, r2) => sum + r2.height, 0);
33632
+ const totalHeight = rowHeights.reduce((sum, h) => sum + h, 0);
32541
33633
  const totalWidth = columnWidths.reduce((a, b) => a + b, 0);
32542
33634
  return {
32543
33635
  kind: "table",
@@ -32743,7 +33835,7 @@ const resolveLineHeight = (spacing, baseLineHeight) => {
32743
33835
  if (spacing.lineRule === "atLeast") {
32744
33836
  return Math.max(baseLineHeight, raw);
32745
33837
  }
32746
- return raw;
33838
+ return Math.max(baseLineHeight, raw);
32747
33839
  };
32748
33840
  const sanitizePositive = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
32749
33841
  const sanitizeDecimalSeparator = (value) => {