@stll/folio-core 0.28.1 → 0.30.0

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 (125) hide show
  1. package/dist/controller/folioEditor.d.ts +28 -1
  2. package/dist/controller/folioEditor.js +37 -26
  3. package/dist/controller/fontReadiness.js +28 -24
  4. package/dist/controller/hiddenEditorManager.d.ts +2 -7
  5. package/dist/controller/layoutPipeline.js +33 -3
  6. package/dist/controller/noteEditorManager.d.ts +3 -6
  7. package/dist/docx/metafileSvg.d.ts +12 -0
  8. package/dist/docx/metafileSvg.js +462 -0
  9. package/dist/docx/paragraphTextBoxEnrichment.js +55 -4
  10. package/dist/docx/parser.d.ts +2 -2
  11. package/dist/docx/parser.js +26 -0
  12. package/dist/docx/runParser.js +2 -1
  13. package/dist/docx/serializer/runSerializer.js +14 -2
  14. package/dist/docx/styleParser.js +2 -1
  15. package/dist/docx/textBoxParser.js +14 -0
  16. package/dist/docx/vmlImageParser.js +72 -152
  17. package/dist/docx/vmlPreview.d.ts +31 -0
  18. package/dist/docx/vmlPreview.js +535 -0
  19. package/dist/docx/wrapTypes.d.ts +2 -36
  20. package/dist/docx/wrapTypes.js +1 -39
  21. package/dist/fonts/fontAlternates.d.ts +8 -0
  22. package/dist/fonts/fontAlternates.js +16 -0
  23. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  24. package/dist/layout-bridge/convert/footnoteLayout.js +34 -3
  25. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  26. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -0
  27. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -2
  28. package/dist/layout-bridge/convert/toFlowBlocks.js +136 -120
  29. package/dist/layout-bridge/dom/noteStoryDom.d.ts +1 -1
  30. package/dist/layout-bridge/engine/selectionRects.js +3 -1
  31. package/dist/layout-engine/index.js +65 -32
  32. package/dist/layout-engine/justifiedLineFit.d.ts +7 -0
  33. package/dist/layout-engine/justifiedLineFit.js +6 -0
  34. package/dist/layout-engine/keep-together.js +15 -10
  35. package/dist/layout-engine/measure/complexScriptFormatting.d.ts +6 -1
  36. package/dist/layout-engine/measure/complexScriptFormatting.js +11 -2
  37. package/dist/layout-engine/measure/floatingTablePosition.d.ts +16 -1
  38. package/dist/layout-engine/measure/floatingTablePosition.js +29 -6
  39. package/dist/layout-engine/measure/lineBreakProvider.js +67 -8
  40. package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
  41. package/dist/layout-engine/measure/listMarkerWidth.js +23 -10
  42. package/dist/layout-engine/measure/measureBlocks.d.ts +15 -0
  43. package/dist/layout-engine/measure/measureBlocks.js +197 -30
  44. package/dist/layout-engine/measure/measureContainer.js +20 -24
  45. package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
  46. package/dist/layout-engine/measure/measureHelpers.js +14 -8
  47. package/dist/layout-engine/measure/measureParagraph.js +111 -37
  48. package/dist/layout-engine/measure/measureTypes.d.ts +3 -0
  49. package/dist/layout-engine/measure/tabCalculator.d.ts +123 -0
  50. package/dist/layout-engine/measure/tabCalculator.js +144 -0
  51. package/dist/layout-engine/measure/tableCellFlow.d.ts +21 -1
  52. package/dist/layout-engine/measure/tableCellFlow.js +45 -8
  53. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +10 -2
  54. package/dist/layout-engine/measure/tableInlinePlacement.js +17 -15
  55. package/dist/layout-engine/paginator.d.ts +26 -2
  56. package/dist/layout-engine/paginator.js +76 -14
  57. package/dist/layout-engine/paragraphSpacing.d.ts +3 -1
  58. package/dist/layout-engine/paragraphSpacing.js +4 -3
  59. package/dist/layout-engine/renderedBreakReconciliation.d.ts +14 -3
  60. package/dist/layout-engine/renderedBreakReconciliation.js +45 -14
  61. package/dist/layout-engine/section-breaks.d.ts +3 -1
  62. package/dist/layout-engine/section-breaks.js +6 -2
  63. package/dist/layout-engine/types.d.ts +18 -1
  64. package/dist/layout-engine/types.js +1 -1
  65. package/dist/layout-painter/imageLayout.d.ts +1 -1
  66. package/dist/layout-painter/renderPage.js +6 -1
  67. package/dist/layout-painter/renderParagraph.js +169 -82
  68. package/dist/layout-painter/renderTable.d.ts +1 -1
  69. package/dist/layout-painter/renderTable.js +18 -7
  70. package/dist/layout-painter/renderTextBox.d.ts +1 -1
  71. package/dist/layout-painter/renderTextBox.js +6 -1
  72. package/dist/markdown/renderParagraph.js +7 -2
  73. package/dist/model.d.ts +3 -3
  74. package/dist/model.js +2 -2
  75. package/dist/paged-layout/sectionBlockWidths.d.ts +14 -0
  76. package/dist/paged-layout/sectionBlockWidths.js +103 -14
  77. package/dist/prosemirror/attrs/index.js +14 -2
  78. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +8 -0
  79. package/dist/prosemirror/bookmarkBoundaryAttrs.js +66 -0
  80. package/dist/prosemirror/conversion/fromProseDoc.js +176 -54
  81. package/dist/prosemirror/conversion/toProseDoc.js +179 -64
  82. package/dist/prosemirror/extensions/StarterKit.js +11 -3
  83. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +8 -4
  84. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  85. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +9 -5
  86. package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +10 -23
  87. package/dist/prosemirror/extensions/features/pasteCleanup.js +77 -22
  88. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +9 -5
  89. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.d.ts +9 -0
  90. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +67 -0
  91. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +10 -4
  92. package/dist/prosemirror/extensions/nodes/FieldExtension.js +77 -59
  93. package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
  94. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.d.ts +4 -1
  95. package/dist/prosemirror/extensions/nodes/TextBoxAnchorExtension.js +4 -3
  96. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +6 -2
  97. package/dist/prosemirror/listMarker.d.ts +58 -0
  98. package/dist/prosemirror/listMarker.js +185 -0
  99. package/dist/prosemirror/numberedRefFields.d.ts +24 -0
  100. package/dist/prosemirror/numberedRefFields.js +276 -0
  101. package/dist/prosemirror/paraText.js +56 -17
  102. package/dist/prosemirror/plugins/anonymizationDecorations.js +1 -1
  103. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -1
  104. package/dist/prosemirror/plugins/pmTextScan.js +28 -7
  105. package/dist/prosemirror/plugins/templateDirectives.js +2 -2
  106. package/dist/prosemirror/schema/index.d.ts +2 -2
  107. package/dist/prosemirror/schema/nodes.d.ts +17 -1
  108. package/dist/prosemirror/utils/tabCalculator.d.ts +2 -123
  109. package/dist/prosemirror/utils/tabCalculator.js +1 -140
  110. package/dist/prosemirror/validation.js +93 -0
  111. package/dist/render-dom/RemoteSelectionOverlay.d.ts +4 -4
  112. package/dist/types/documentEnumValues.d.ts +4 -1
  113. package/dist/types/documentEnumValues.js +12 -1
  114. package/dist/types/editor-story.d.ts +8 -0
  115. package/dist/types/editor-story.js +0 -0
  116. package/dist/types/remote-selection.d.ts +11 -0
  117. package/dist/types/remote-selection.js +0 -0
  118. package/dist/types/wrap.d.ts +36 -0
  119. package/dist/types/wrap.js +40 -0
  120. package/dist/utils/fontResolver.d.ts +1 -1
  121. package/dist/utils/fontResolver.js +42 -2
  122. package/dist/utils/formatToStyle.js +4 -2
  123. package/dist/utils/horizontalScale.d.ts +28 -0
  124. package/dist/utils/horizontalScale.js +42 -0
  125. package/package.json +2 -2
@@ -2,7 +2,7 @@ import { measureParagraph } from "../layout-engine/measure/measureParagraph.js";
2
2
  import { buildTableCellFloatingZones, getTableCellContentWidth, getTableCellFloatingImages } from "../layout-engine/measure/tableCellFloating.js";
3
3
  import { createTableCellFlowState, finishTableCellFlow, placeTableCellBlock } from "../layout-engine/measure/tableCellFlow.js";
4
4
  import { buildTableCellGrid, buildTableCellPlacements, getSourceCellAt } from "../layout-engine/measure/tableCellGrid.js";
5
- import { resolveTableInlinePlacement } from "../layout-engine/measure/tableInlinePlacement.js";
5
+ import { resolveTableInlineOffset, resolveTableInlinePlacement } from "../layout-engine/measure/tableInlinePlacement.js";
6
6
  import { isFloatingImageRun, isFloatingTextBoxBlock, resolveTableCellPadding, tableColumnsArePinned } from "../layout-engine/types.js";
7
7
  import { applySanitizedImageSrc } from "../utils/sanitizeImageSrc.js";
8
8
  import { emuToPixels } from "../utils/units.js";
@@ -134,7 +134,7 @@ function renderCellContent({ cell, cellMeasure, context, doc, contentWidthOverri
134
134
  } else if (block?.kind === "table" && measure?.kind === "table") {
135
135
  const tableBlock = block;
136
136
  const tableMeasure = measure;
137
- const nestedTableEl = renderNestedTable(tableBlock, tableMeasure, context, doc);
137
+ const nestedTableEl = renderNestedTable(tableBlock, tableMeasure, context, doc, contentWidth);
138
138
  nestedTableEl.style.position = "relative";
139
139
  const placement = placeTableCellBlock(flowState, tableBlock, tableMeasure);
140
140
  if (placement.leadingSpacing > 0) {
@@ -224,13 +224,18 @@ function tableHasFloatingCellContent(block) {
224
224
  /**
225
225
  * Render a nested table (within a cell)
226
226
  */
227
- function renderNestedTable(block, measure, context, doc) {
227
+ function renderNestedTable(block, measure, context, doc, frameWidth = context.contentWidth ?? measure.totalWidth) {
228
228
  const tableEl = doc.createElement("div");
229
229
  tableEl.className = `${TABLE_CLASS_NAMES.table} layout-nested-table`;
230
230
  tableEl.style.position = "relative";
231
231
  tableEl.style.width = `${measure.totalWidth}px`;
232
232
  tableEl.style.display = "block";
233
233
  const placement = resolveTableInlinePlacement(block);
234
+ const tableInlineOffset = resolveTableInlineOffset({
235
+ table: block,
236
+ frameWidth,
237
+ tableWidth: measure.totalWidth
238
+ });
234
239
  if (placement.alignment === "center") {
235
240
  tableEl.style.marginLeft = "auto";
236
241
  tableEl.style.marginRight = "auto";
@@ -277,7 +282,13 @@ function renderNestedTable(block, measure, context, doc) {
277
282
  bidi: block.bidi === true,
278
283
  columnsPinned,
279
284
  cellGrid,
280
- cellPlacements
285
+ cellPlacements,
286
+ inlineOffset: resolveTableInlineOffset({
287
+ table: block,
288
+ rowJustification: row.justification,
289
+ frameWidth,
290
+ tableWidth: measure.totalWidth
291
+ }) - tableInlineOffset
281
292
  });
282
293
  tableEl.append(rowEl);
283
294
  y += rowMeasure.height;
@@ -433,11 +444,11 @@ function renderTableCell({ cell, cellMeasure, x, width, rowHeight, borderFlags,
433
444
  return cellEl;
434
445
  }
435
446
  const hasVisibleBorder = (border) => border !== void 0 && border.style !== "none" && border.style !== "nil";
436
- function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, contentClip, pageContentPosition }) {
447
+ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows, context, doc, rowYPositions, isFirstRowInFragment, bidi = false, columnsPinned = false, cellGrid, cellPlacements, contentClip, pageContentPosition, inlineOffset = 0 }) {
437
448
  const rowEl = doc.createElement("div");
438
449
  rowEl.className = TABLE_CLASS_NAMES.row;
439
450
  rowEl.style.position = "absolute";
440
- rowEl.style.left = "0";
451
+ rowEl.style.left = `${inlineOffset}px`;
441
452
  rowEl.style.top = `${y}px`;
442
453
  rowEl.style.width = "100%";
443
454
  rowEl.style.height = `${rowMeasure.height}px`;
@@ -484,7 +495,7 @@ function renderTableRow({ row, rowMeasure, rowIndex, y, columnWidths, totalRows,
484
495
  ...contentClip ? { contentClip } : {},
485
496
  ...pageContentPosition ? { pageContentPosition: {
486
497
  geometry: pageContentPosition.geometry,
487
- x: pageContentPosition.x + cellLeft,
498
+ x: pageContentPosition.x + inlineOffset + cellLeft,
488
499
  y: pageContentPosition.y
489
500
  } } : {}
490
501
  });
@@ -12,7 +12,7 @@ declare const TEXTBOX_CLASS_NAMES: {
12
12
  */
13
13
  type RenderTextBoxFragmentOptions = {
14
14
  document?: Document;
15
- renderTable?: (block: TableBlock, measure: TableMeasure, context: RenderContext, document: Document) => HTMLElement;
15
+ renderTable?: (block: TableBlock, measure: TableMeasure, context: RenderContext, document: Document, frameWidth?: number) => HTMLElement;
16
16
  };
17
17
  /**
18
18
  * Render a text box fragment to DOM
@@ -36,6 +36,11 @@ function renderTextBoxFragment(fragment, block, measure, context, options = {})
36
36
  }
37
37
  const margins = block.margins ?? DEFAULT_TEXTBOX_MARGINS;
38
38
  containerEl.style.padding = `${margins.top}px ${margins.right}px ${margins.bottom}px ${margins.left}px`;
39
+ if (block.verticalAlign === "middle" || block.verticalAlign === "bottom") {
40
+ containerEl.style.display = "flex";
41
+ containerEl.style.flexDirection = "column";
42
+ containerEl.style.justifyContent = block.verticalAlign === "middle" ? "center" : "flex-end";
43
+ }
39
44
  containerEl.dataset["blockId"] = String(fragment.blockId);
40
45
  if (fragment.pmStart !== void 0) containerEl.dataset["pmStart"] = String(fragment.pmStart);
41
46
  if (fragment.pmEnd !== void 0) containerEl.dataset["pmEnd"] = String(fragment.pmEnd);
@@ -48,7 +53,7 @@ function renderTextBoxFragment(fragment, block, measure, context, options = {})
48
53
  if (!contentBlock || !contentMeasure || !placement) continue;
49
54
  if (contentBlock.kind === "table" && contentMeasure.kind === "table") {
50
55
  if (!options.renderTable) panic("renderTextBoxFragment: a nested table renderer is required for table content");
51
- const tableEl = options.renderTable(contentBlock, contentMeasure, context, doc);
56
+ const tableEl = options.renderTable(contentBlock, contentMeasure, context, doc, innerWidth);
52
57
  tableEl.style.marginTop = `${placement.leadingSpacing}px`;
53
58
  containerEl.append(tableEl);
54
59
  continue;
@@ -1,4 +1,4 @@
1
- import { resolveListTemplate } from "../layout-bridge/convert/toFlowBlocks.js";
1
+ import { resolveListTemplate } from "../prosemirror/listMarker.js";
2
2
  import { isHeadingStyle, parseHeadingLevel } from "./headings.js";
3
3
  import { renderParagraphInline } from "./renderRuns.js";
4
4
  //#region src/markdown/renderParagraph.ts
@@ -58,7 +58,12 @@ function resolveTemplateMarker(ctx, list) {
58
58
  for (let i = level + 1; i < counters.length; i += 1) counters[i] = 0;
59
59
  ctx.listCounters.set(list.numId, counters);
60
60
  const levelFormats = list.levelNumFmts ?? (list.numFmt ? [list.numFmt] : void 0);
61
- return resolveListTemplate(list.marker, counters, levelFormats, list.isLegal).trim();
61
+ return resolveListTemplate({
62
+ template: list.marker,
63
+ counters,
64
+ levelFormats,
65
+ forceDecimal: list.isLegal
66
+ }).trim();
62
67
  }
63
68
  //#endregion
64
69
  export { renderParagraph };
package/dist/model.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { document_d_exports } from "./types/document.js";
2
2
  import { DeriveBlockIdInput, FolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
3
- import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "./types/documentEnumValues.js";
3
+ import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
4
4
  import { types_d_exports } from "./layout-engine/types.js";
5
5
  import { measureTypes_d_exports } from "./layout-engine/measure/measureTypes.js";
6
6
  export * from "@stll/docx-core/model";
7
7
  declare namespace model_d_exports {
8
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
8
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
9
9
  }
10
10
  //#endregion
11
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
11
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, DeriveBlockIdInput, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, FolioBlockId, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_d_exports as Layout, type measureTypes_d_exports as Measure, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, OutlineStyleAttr, OutlineStyleCssAlias, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
package/dist/model.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { types_exports } from "./layout-engine/types.js";
2
2
  import { deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
3
- import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "./types/documentEnumValues.js";
4
- export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId };
3
+ import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, normalizeShapeTextAnchor } from "./types/documentEnumValues.js";
4
+ export { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, types_exports as Layout, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, OUTLINE_STYLE_CSS_ALIASES, OUTLINE_STYLE_CSS_ALIAS_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TEXT_ANCHOR_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES, deriveBlockId, getFolioParaIdFromBlockId, getSequentialFolioBlockIdIndex, isFolioBlockId, isSequentialFolioBlockId, normalizeShapeTextAnchor };
@@ -6,14 +6,28 @@ type ComputePerBlockMeasureInput = {
6
6
  bodyConfig: SectionLayoutConfig;
7
7
  finalConfig: SectionLayoutConfig;
8
8
  };
9
+ type PerBlockPhysicalPageGeometry = {
10
+ pageHeights: number[];
11
+ pageWidths: number[];
12
+ marginTops: number[];
13
+ marginLefts: number[];
14
+ marginRights: number[];
15
+ marginBottoms: number[];
16
+ };
9
17
  type PerBlockMeasureInputs = {
10
18
  widths: number[];
19
+ /** Authored section top, retained for section-relative text-box semantics. */
11
20
  marginTops: number[];
12
21
  pageHeights: number[];
13
22
  pageWidths: number[];
14
23
  marginLefts: number[];
15
24
  marginRights: number[];
16
25
  marginBottoms: number[];
26
+ /** Absolute page X of the active column's content origin. */
27
+ contentLefts: number[];
28
+ columnIndices: number[];
29
+ columnCounts: number[];
30
+ physicalPageGeometry: PerBlockPhysicalPageGeometry;
17
31
  };
18
32
  /**
19
33
  * Compute per-block measurement widths by scanning for section breaks.
@@ -1,5 +1,18 @@
1
1
  import { collectSectionConfigs } from "../layout-engine/index.js";
2
+ import { hasPageBreakBefore } from "../layout-engine/keep-together.js";
3
+ import { calculateColumnLefts, calculateColumnWidths } from "../layout-engine/paginator.js";
4
+ import { normalizeSectionBreakType } from "../layout-engine/section-breaks.js";
2
5
  //#region src/paged-layout/sectionBlockWidths.ts
6
+ function resolvePreBlockPageTransition(block, config) {
7
+ if (!hasPageBreakBefore(block)) return { type: "none" };
8
+ return {
9
+ type: "physicalPage",
10
+ geometry: {
11
+ pageSize: config.pageSize,
12
+ margins: config.margins
13
+ }
14
+ };
15
+ }
3
16
  const SINGLE_COLUMN_LAYOUT = {
4
17
  count: 1,
5
18
  gap: 0
@@ -20,40 +33,105 @@ function computePerBlockWidths({ blocks, bodyConfig, finalConfig }) {
20
33
  }).widths;
21
34
  }
22
35
  function computePerBlockMeasureInputs({ blocks, bodyConfig, finalConfig }) {
23
- function colWidth(cw, cols, columnIndex) {
24
- if (cols.count <= 1) return cw;
25
- const authoredWidth = cols.widths?.[columnIndex];
26
- if (authoredWidth !== void 0) return authoredWidth;
27
- return Math.floor((cw - (cols.count - 1) * cols.gap) / cols.count);
28
- }
29
- function contentWidth(config) {
30
- return config.pageSize.w - config.margins.left - config.margins.right;
31
- }
32
36
  const { configs: sectionConfigs, breakIndices } = collectSectionConfigs(blocks, bodyConfig, finalConfig);
33
37
  let sectionIdx = 0;
34
38
  let columnIndex = 0;
39
+ let measuredSectionIdx = -1;
40
+ let activeColumns = SINGLE_COLUMN_LAYOUT;
41
+ let activeColumnWidths = [];
42
+ let activeContentLefts = [];
43
+ let columnGeometryDirty = true;
35
44
  const widths = [];
36
45
  const marginTops = [];
46
+ const physicalMarginTops = [];
37
47
  const pageHeights = [];
38
48
  const pageWidths = [];
39
49
  const marginLefts = [];
40
50
  const marginRights = [];
41
51
  const marginBottoms = [];
52
+ const physicalPageHeights = [];
53
+ const physicalPageWidths = [];
54
+ const physicalMarginLefts = [];
55
+ const physicalMarginRights = [];
56
+ const physicalMarginBottoms = [];
57
+ const contentLefts = [];
58
+ const columnIndices = [];
59
+ const columnCounts = [];
60
+ const initialConfig = sectionConfigs[0] ?? finalConfig;
61
+ let physicalPageGeometry = {
62
+ pageSize: initialConfig.pageSize,
63
+ margins: initialConfig.margins
64
+ };
65
+ let hasPhysicalPageContent = false;
42
66
  for (let i = 0; i < blocks.length; i++) {
43
67
  const config = sectionConfigs[sectionIdx] ?? finalConfig;
44
- const columns = config.columns ?? SINGLE_COLUMN_LAYOUT;
45
- widths.push(colWidth(contentWidth(config), columns, columnIndex));
68
+ const block = blocks[i];
69
+ const preBlockTransition = resolvePreBlockPageTransition(block, config);
70
+ switch (preBlockTransition.type) {
71
+ case "physicalPage":
72
+ physicalPageGeometry = preBlockTransition.geometry;
73
+ hasPhysicalPageContent = false;
74
+ columnGeometryDirty = true;
75
+ columnIndex = 0;
76
+ break;
77
+ case "none": break;
78
+ default:
79
+ }
80
+ if (measuredSectionIdx !== sectionIdx || columnGeometryDirty) {
81
+ activeColumns = config.columns ?? SINGLE_COLUMN_LAYOUT;
82
+ activeColumnWidths = calculateColumnWidths(physicalPageGeometry.pageSize.w, physicalPageGeometry.margins.left, physicalPageGeometry.margins.right, activeColumns);
83
+ activeContentLefts = calculateColumnLefts(physicalPageGeometry.margins.left, activeColumnWidths, activeColumns);
84
+ measuredSectionIdx = sectionIdx;
85
+ columnGeometryDirty = false;
86
+ }
87
+ widths.push(activeColumnWidths[columnIndex] ?? activeColumnWidths[0] ?? 0);
88
+ contentLefts.push(activeContentLefts[columnIndex] ?? physicalPageGeometry.margins.left);
89
+ columnIndices.push(columnIndex);
90
+ columnCounts.push(activeColumns.count);
46
91
  marginTops.push(config.margins.top);
92
+ physicalMarginTops.push(physicalPageGeometry.margins.top);
47
93
  pageHeights.push(config.pageSize.h);
48
94
  pageWidths.push(config.pageSize.w);
49
95
  marginLefts.push(config.margins.left);
50
96
  marginRights.push(config.margins.right);
51
97
  marginBottoms.push(config.margins.bottom);
98
+ physicalPageHeights.push(physicalPageGeometry.pageSize.h);
99
+ physicalPageWidths.push(physicalPageGeometry.pageSize.w);
100
+ physicalMarginLefts.push(physicalPageGeometry.margins.left);
101
+ physicalMarginRights.push(physicalPageGeometry.margins.right);
102
+ physicalMarginBottoms.push(physicalPageGeometry.margins.bottom);
52
103
  if (sectionIdx < breakIndices.length && i === breakIndices[sectionIdx]) {
104
+ const sectionBreak = block;
105
+ const nextConfig = sectionConfigs[sectionIdx + 1] ?? finalConfig;
106
+ if (!(sectionBreak?.kind === "sectionBreak" && normalizeSectionBreakType(sectionBreak.type) === "continuous" && hasPhysicalPageContent && Math.round(nextConfig.pageSize.w) === Math.round(physicalPageGeometry.pageSize.w) && Math.round(nextConfig.pageSize.h) === Math.round(physicalPageGeometry.pageSize.h))) {
107
+ physicalPageGeometry = {
108
+ pageSize: nextConfig.pageSize,
109
+ margins: nextConfig.margins
110
+ };
111
+ hasPhysicalPageContent = false;
112
+ }
113
+ columnGeometryDirty = true;
53
114
  sectionIdx++;
54
115
  columnIndex = 0;
55
- } else if (blocks[i]?.kind === "pageBreak") columnIndex = 0;
56
- else if (blocks[i]?.kind === "columnBreak") columnIndex = (columnIndex + 1) % columns.count;
116
+ } else if (block.kind === "pageBreak") {
117
+ physicalPageGeometry = {
118
+ pageSize: config.pageSize,
119
+ margins: config.margins
120
+ };
121
+ hasPhysicalPageContent = false;
122
+ columnGeometryDirty = true;
123
+ columnIndex = 0;
124
+ } else if (block.kind === "columnBreak") {
125
+ if (columnIndex + 1 >= activeColumns.count) {
126
+ physicalPageGeometry = {
127
+ pageSize: config.pageSize,
128
+ margins: config.margins
129
+ };
130
+ hasPhysicalPageContent = false;
131
+ columnGeometryDirty = true;
132
+ }
133
+ columnIndex = (columnIndex + 1) % activeColumns.count;
134
+ } else hasPhysicalPageContent = true;
57
135
  }
58
136
  return {
59
137
  widths,
@@ -62,7 +140,18 @@ function computePerBlockMeasureInputs({ blocks, bodyConfig, finalConfig }) {
62
140
  pageWidths,
63
141
  marginLefts,
64
142
  marginRights,
65
- marginBottoms
143
+ marginBottoms,
144
+ contentLefts,
145
+ columnIndices,
146
+ columnCounts,
147
+ physicalPageGeometry: {
148
+ pageHeights: physicalPageHeights,
149
+ pageWidths: physicalPageWidths,
150
+ marginTops: physicalMarginTops,
151
+ marginLefts: physicalMarginLefts,
152
+ marginRights: physicalMarginRights,
153
+ marginBottoms: physicalMarginBottoms
154
+ }
66
155
  };
67
156
  }
68
157
  //#endregion
@@ -1,4 +1,5 @@
1
1
  import { EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, OUTLINE_STYLE_ATTR_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "../../types/documentEnumValues.js";
2
+ import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
2
3
  import { isParagraphDirection } from "../paragraphDirection.js";
3
4
  import { TRACKED_CHANGE_PROVENANCE_VALUES } from "../schema/marks.js";
4
5
  import { panic } from "better-result";
@@ -276,6 +277,7 @@ const readTableAttrs = (node) => {
276
277
  "insideH",
277
278
  "insideV"
278
279
  ]);
280
+ optionalOneOf(attrs, "_resolvedJustification", "table.attrs._resolvedJustification", issues, TABLE_JUSTIFICATION_VALUES);
279
281
  optionalBoolean(attrs, "_resolvedBidi", "table.attrs._resolvedBidi", issues);
280
282
  optionalRecord(attrs, "_originalFormatting", "table.attrs._originalFormatting", issues);
281
283
  return attrsResult(attrs, issues);
@@ -289,6 +291,7 @@ const readTableRowAttrs = (node) => {
289
291
  optionalOneOf(attrs, "heightRule", "tableRow.attrs.heightRule", issues, TABLE_ROW_HEIGHT_RULE_VALUES);
290
292
  optionalBoolean(attrs, "isHeader", "tableRow.attrs.isHeader", issues);
291
293
  optionalBoolean(attrs, "hidden", "tableRow.attrs.hidden", issues);
294
+ optionalOneOf(attrs, "_resolvedJustification", "tableRow.attrs._resolvedJustification", issues, TABLE_JUSTIFICATION_VALUES);
292
295
  optionalRecord(attrs, "_originalFormatting", "tableRow.attrs._originalFormatting", issues);
293
296
  optionalTableRowRevision(attrs, "trIns", issues);
294
297
  optionalTableRowRevision(attrs, "trDel", issues);
@@ -371,10 +374,11 @@ const expectImageAttrs = (node) => expectCachedNodeAttrs(node, imageAttrsCache,
371
374
  const readFieldAttrs = (node) => {
372
375
  const attrs = attrsRecord(node.attrs);
373
376
  const issues = [];
374
- expectNodeType(node, "field", issues);
377
+ expectNodeTypeOneOf(node, ["field", "structuredField"], issues);
375
378
  requiredOneOf(attrs, "fieldType", "field.attrs.fieldType", issues, FIELD_TYPE_VALUES);
376
379
  requiredString(attrs, "instruction", "field.attrs.instruction", issues);
377
380
  requiredString(attrs, "displayText", "field.attrs.displayText", issues);
381
+ optionalString(attrs, "_numberedRefBaseline", "field.attrs._numberedRefBaseline", issues);
378
382
  requiredOneOf(attrs, "fieldKind", "field.attrs.fieldKind", issues, FIELD_KINDS);
379
383
  optionalBoolean(attrs, "fldLock", "field.attrs.fldLock", issues);
380
384
  optionalBoolean(attrs, "dirty", "field.attrs.dirty", issues);
@@ -594,7 +598,15 @@ const readCharacterSpacingMarkAttrs = (mark) => {
594
598
  optionalNumber(attrs, "position", "characterSpacing.attrs.position", issues);
595
599
  optionalNumber(attrs, "scale", "characterSpacing.attrs.scale", issues);
596
600
  optionalNumber(attrs, "kerning", "characterSpacing.attrs.kerning", issues);
597
- return attrsResult(attrs, issues);
601
+ const result = attrsResult(attrs, issues);
602
+ if (!result.ok) return result;
603
+ const { scale, ...rest } = result.value;
604
+ const horizontalScale = normalizeHorizontalScalePercent(scale);
605
+ result.value = {
606
+ ...rest,
607
+ ...horizontalScale !== void 0 ? { scale: horizontalScale } : {}
608
+ };
609
+ return result;
598
610
  };
599
611
  const expectCharacterSpacingMarkAttrs = (mark) => expectCachedMarkAttrs(mark, characterSpacingAttrsCache, readCharacterSpacingMarkAttrs, "character spacing attrs");
600
612
  const readEmphasisMarkAttrs = (mark) => {
@@ -0,0 +1,8 @@
1
+ import { BookmarkBoundaryAttrs } from "./schema/nodes.js";
2
+ import { ReadProseMirrorAttrsResult } from "./attrs/index.js";
3
+ import { Node } from "prosemirror-model";
4
+ //#region src/prosemirror/bookmarkBoundaryAttrs.d.ts
5
+ declare const readBookmarkBoundaryAttrs: (node: Node) => ReadProseMirrorAttrsResult<BookmarkBoundaryAttrs>;
6
+ declare const expectBookmarkBoundaryAttrs: (node: Node) => BookmarkBoundaryAttrs;
7
+ //#endregion
8
+ export { expectBookmarkBoundaryAttrs, readBookmarkBoundaryAttrs };
@@ -0,0 +1,66 @@
1
+ import { panic } from "better-result";
2
+ //#region src/prosemirror/bookmarkBoundaryAttrs.ts
3
+ const attrsCache = /* @__PURE__ */ new WeakMap();
4
+ const readBookmarkBoundaryAttrs = (node) => {
5
+ const issues = [];
6
+ if (node.type.name !== "bookmarkBoundary") issues.push({
7
+ path: "bookmarkBoundary.type.name",
8
+ message: `Expected bookmarkBoundary, got ${node.type.name}.`
9
+ });
10
+ const type = node.attrs["type"];
11
+ if (type !== "start" && type !== "end") issues.push({
12
+ path: "bookmarkBoundary.attrs.type",
13
+ message: "Expected \"start\" or \"end\"."
14
+ });
15
+ const id = node.attrs["id"];
16
+ if (typeof id !== "number" || !Number.isInteger(id) || id < 0) issues.push({
17
+ path: "bookmarkBoundary.attrs.id",
18
+ message: "Expected a non-negative integer."
19
+ });
20
+ const name = node.attrs["name"];
21
+ if (type === "start" && (typeof name !== "string" || name.length === 0)) issues.push({
22
+ path: "bookmarkBoundary.attrs.name",
23
+ message: "Expected a non-empty string for a bookmark start."
24
+ });
25
+ const colFirst = node.attrs["colFirst"];
26
+ if (colFirst !== void 0 && colFirst !== null && (typeof colFirst !== "number" || !Number.isInteger(colFirst) || colFirst < 0)) issues.push({
27
+ path: "bookmarkBoundary.attrs.colFirst",
28
+ message: "Expected a non-negative integer."
29
+ });
30
+ const colLast = node.attrs["colLast"];
31
+ if (colLast !== void 0 && colLast !== null && (typeof colLast !== "number" || !Number.isInteger(colLast) || colLast < 0)) issues.push({
32
+ path: "bookmarkBoundary.attrs.colLast",
33
+ message: "Expected a non-negative integer."
34
+ });
35
+ if (issues.length > 0 || typeof id !== "number") return {
36
+ ok: false,
37
+ issues
38
+ };
39
+ if (type === "start" && typeof name === "string") return {
40
+ ok: true,
41
+ value: {
42
+ type,
43
+ id,
44
+ name,
45
+ ...typeof colFirst === "number" ? { colFirst } : {},
46
+ ...typeof colLast === "number" ? { colLast } : {}
47
+ }
48
+ };
49
+ return {
50
+ ok: true,
51
+ value: {
52
+ type: "end",
53
+ id
54
+ }
55
+ };
56
+ };
57
+ const expectBookmarkBoundaryAttrs = (node) => {
58
+ const cached = attrsCache.get(node);
59
+ if (cached) return cached;
60
+ const result = readBookmarkBoundaryAttrs(node);
61
+ if (!result.ok) panic(`Invalid ProseMirror bookmark boundary attrs:\n${result.issues.map((issue) => `${issue.path}: ${issue.message}`).join("\n")}`);
62
+ attrsCache.set(node, result.value);
63
+ return result.value;
64
+ };
65
+ //#endregion
66
+ export { expectBookmarkBoundaryAttrs, readBookmarkBoundaryAttrs };