ooxml-core 1.8.4 → 1.9.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.
- package/dist/PptxHandler-AT7FVG5Q.mjs +2 -0
- package/dist/{PptxHandler-BL4B7CZO.mjs → PptxHandler-EX4WBIQQ.mjs} +2 -2
- package/dist/PptxHandler-VFSCECPL.cjs +11 -0
- package/dist/automation/index.cjs +6652 -4002
- package/dist/automation/index.mjs +6652 -4002
- package/dist/chunk-AT66SA5M.cjs +44423 -0
- package/dist/{chunk-TTPZITQN.mjs → chunk-FIELY5PI.mjs} +1 -1
- package/dist/{chunk-ZAP5WLEN.mjs → chunk-IGOA57LE.mjs} +1 -1
- package/dist/chunk-LCS3J3QI.mjs +87604 -0
- package/dist/{chunk-NIHPA63A.mjs → chunk-M76PHYRR.mjs} +54 -37
- package/dist/chunk-OB277ZGE.mjs +44107 -0
- package/dist/{chunk-GAGSCAR3.mjs → chunk-OXHMZS7B.mjs} +552 -178
- package/dist/chunk-SWF7KVL5.cjs +87610 -0
- package/dist/{chunk-Z7IQR4S4.mjs → chunk-WSO4T2LJ.mjs} +246 -21
- package/dist/docx/block-parser.d.ts.map +1 -1
- package/dist/docx/cell-blocks.d.ts +4 -0
- package/dist/docx/cell-blocks.d.ts.map +1 -0
- package/dist/docx/document-paragraphs.d.ts.map +1 -1
- package/dist/docx/document-parts.d.ts +2 -0
- package/dist/docx/document-parts.d.ts.map +1 -1
- package/dist/docx/embedded.cjs +189 -20
- package/dist/docx/embedded.mjs +189 -20
- package/dist/docx/index.cjs +219 -24
- package/dist/docx/index.mjs +219 -24
- package/dist/docx/layout/adapt-table.d.ts.map +1 -1
- package/dist/docx/layout/adapter.d.ts.map +1 -1
- package/dist/docx/layout/flow-paragraph.d.ts +5 -0
- package/dist/docx/layout/flow-paragraph.d.ts.map +1 -1
- package/dist/docx/layout/flow-table.d.ts +2 -1
- package/dist/docx/layout/flow-table.d.ts.map +1 -1
- package/dist/docx/layout/footnote-columns.d.ts +22 -0
- package/dist/docx/layout/footnote-columns.d.ts.map +1 -0
- package/dist/docx/layout/footnote-flow.d.ts +27 -0
- package/dist/docx/layout/footnote-flow.d.ts.map +1 -0
- package/dist/docx/layout/footnote-split.d.ts +7 -0
- package/dist/docx/layout/footnote-split.d.ts.map +1 -0
- package/dist/docx/layout/index.cjs +1099 -92
- package/dist/docx/layout/index.mjs +1099 -92
- package/dist/docx/layout/input.d.ts +17 -1
- package/dist/docx/layout/input.d.ts.map +1 -1
- package/dist/docx/layout/legacy-footnote-flow.d.ts +18 -0
- package/dist/docx/layout/legacy-footnote-flow.d.ts.map +1 -0
- package/dist/docx/layout/line-metrics.d.ts.map +1 -1
- package/dist/docx/layout/page-cursor.d.ts +13 -8
- package/dist/docx/layout/page-cursor.d.ts.map +1 -1
- package/dist/docx/layout/page-flow.d.ts.map +1 -1
- package/dist/docx/layout/paragraph-layout.d.ts.map +1 -1
- package/dist/docx/layout/paragraph-tokens.d.ts +2 -0
- package/dist/docx/layout/paragraph-tokens.d.ts.map +1 -1
- package/dist/docx/layout/reference-footnotes.d.ts +7 -0
- package/dist/docx/layout/reference-footnotes.d.ts.map +1 -0
- package/dist/docx/layout/result.d.ts +31 -0
- package/dist/docx/layout/result.d.ts.map +1 -1
- package/dist/docx/layout/section-flow.d.ts +2 -0
- package/dist/docx/layout/section-flow.d.ts.map +1 -1
- package/dist/docx/layout/table-cell-layout.d.ts +11 -0
- package/dist/docx/layout/table-cell-layout.d.ts.map +1 -0
- package/dist/docx/layout/table-footnotes.d.ts +27 -0
- package/dist/docx/layout/table-footnotes.d.ts.map +1 -0
- package/dist/docx/layout/table-layout.d.ts +10 -4
- package/dist/docx/layout/table-layout.d.ts.map +1 -1
- package/dist/docx/load/index.cjs +194 -25
- package/dist/docx/load/index.mjs +194 -25
- package/dist/docx/model-run.d.ts +2 -0
- package/dist/docx/model-run.d.ts.map +1 -1
- package/dist/docx/model.d.ts +7 -0
- package/dist/docx/model.d.ts.map +1 -1
- package/dist/docx/notes.d.ts +5 -0
- package/dist/docx/notes.d.ts.map +1 -1
- package/dist/docx/parse-table.d.ts.map +1 -1
- package/dist/docx/parse.d.ts.map +1 -1
- package/dist/docx/save.d.ts.map +1 -1
- package/dist/docx/section-model.d.ts +2 -0
- package/dist/docx/section-model.d.ts.map +1 -1
- package/dist/docx/sections.d.ts.map +1 -1
- package/dist/docx/settings.d.ts +2 -0
- package/dist/docx/settings.d.ts.map +1 -1
- package/dist/docx/table-model.d.ts +3 -1
- package/dist/docx/table-model.d.ts.map +1 -1
- package/dist/docx/ui/index.cjs +55 -0
- package/dist/docx/ui/index.d.ts +1 -0
- package/dist/docx/ui/index.d.ts.map +1 -1
- package/dist/docx/ui/index.mjs +55 -1
- package/dist/docx/ui/table-structure-guard.d.ts +4 -0
- package/dist/docx/ui/table-structure-guard.d.ts.map +1 -0
- package/dist/docx/write-footnote-columns.d.ts +3 -0
- package/dist/docx/write-footnote-columns.d.ts.map +1 -0
- package/dist/docx/write-notes.d.ts.map +1 -1
- package/dist/docx/write-run.d.ts.map +1 -1
- package/dist/docx/write-sections.d.ts.map +1 -1
- package/dist/index.cjs +8 -5
- package/dist/index.mjs +8 -5
- package/dist/opc/clone-part-graph.d.ts +4 -0
- package/dist/opc/clone-part-graph.d.ts.map +1 -1
- package/dist/opc/index.cjs +8 -5
- package/dist/opc/index.mjs +8 -5
- package/dist/pptx/automation/index.cjs +621 -207
- package/dist/pptx/automation/index.d.ts +3 -3
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/chunks/{index-Cn-GzYGp.d.ts → index-B4cnSPNz.d.ts} +33 -4
- package/dist/pptx/chunks/index-B4cnSPNz.d.ts.map +1 -0
- package/dist/pptx/chunks/{index-CKIUurnd.d.ts → index-BZh-IMkN.d.ts} +14 -9
- package/dist/pptx/chunks/{index-CKIUurnd.d.ts.map → index-BZh-IMkN.d.ts.map} +1 -1
- package/dist/pptx/chunks/{text-operations-BHfAm5K9.d.ts → text-operations-BLodkuXE.d.ts} +29 -12
- package/dist/pptx/chunks/text-operations-BLodkuXE.d.ts.map +1 -0
- package/dist/pptx/cli/index.cjs +622 -213
- package/dist/pptx/cli/index.d.ts +1 -1
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.cjs +53 -36
- package/dist/pptx/converter/index.d.ts +1 -1
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/editor/render/find-replace.cjs +416 -45
- package/dist/pptx/editor/render/find-replace.d.ts +35 -4
- package/dist/pptx/editor/render/find-replace.d.ts.map +1 -1
- package/dist/pptx/editor/render/find-replace.mjs +416 -46
- package/dist/pptx/editor/render/slide-operations.cjs +87 -0
- package/dist/pptx/editor/render/slide-operations.d.ts +17 -1
- package/dist/pptx/editor/render/slide-operations.d.ts.map +1 -1
- package/dist/pptx/editor/render/slide-operations.mjs +83 -1
- package/dist/pptx/editor/render/slide-search.cjs +6 -10
- package/dist/pptx/editor/render/slide-search.d.ts +1 -1
- package/dist/pptx/editor/render/slide-search.mjs +6 -10
- package/dist/pptx/editor/render/template-editing.d.ts +1 -1
- package/dist/pptx/editor/render/template-editing.d.ts.map +1 -1
- package/dist/pptx/index.cjs +889 -237
- package/dist/pptx/index.d.ts +4 -4
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +593 -34
- package/dist/teams/index.mjs +593 -34
- package/dist/visio/accessibility.d.ts +10 -0
- package/dist/visio/accessibility.d.ts.map +1 -0
- package/dist/visio/cell-formula.d.ts +2 -0
- package/dist/visio/cell-formula.d.ts.map +1 -1
- package/dist/visio/connector-curve-aligned.d.ts +5 -0
- package/dist/visio/connector-curve-aligned.d.ts.map +1 -0
- package/dist/visio/connector-curve-spans.d.ts +14 -0
- package/dist/visio/connector-curve-spans.d.ts.map +1 -0
- package/dist/visio/connector-jumps.d.ts +5 -0
- package/dist/visio/connector-jumps.d.ts.map +1 -0
- package/dist/visio/connector-route-walk.d.ts +2 -1
- package/dist/visio/connector-route-walk.d.ts.map +1 -1
- package/dist/visio/edit-alt-text-scope.d.ts +5 -0
- package/dist/visio/edit-alt-text-scope.d.ts.map +1 -0
- package/dist/visio/edit-alt-text.d.ts +3 -0
- package/dist/visio/edit-alt-text.d.ts.map +1 -0
- package/dist/visio/edit-commands.d.ts +7 -2
- package/dist/visio/edit-commands.d.ts.map +1 -1
- package/dist/visio/edit-formatting-commands.d.ts +5 -0
- package/dist/visio/edit-formatting-commands.d.ts.map +1 -1
- package/dist/visio/edit-formatting-paint.d.ts.map +1 -1
- package/dist/visio/edit-formatting-scope.d.ts.map +1 -1
- package/dist/visio/edit-line-jump-cache.d.ts +4 -0
- package/dist/visio/edit-line-jump-cache.d.ts.map +1 -0
- package/dist/visio/edit-master-index.d.ts.map +1 -1
- package/dist/visio/edit-metadata-commands.d.ts +10 -2
- package/dist/visio/edit-metadata-commands.d.ts.map +1 -1
- package/dist/visio/edit-metadata.d.ts +3 -1
- package/dist/visio/edit-metadata.d.ts.map +1 -1
- package/dist/visio/edit-page-alt-text.d.ts +4 -0
- package/dist/visio/edit-page-alt-text.d.ts.map +1 -0
- package/dist/visio/edit-page-layout.d.ts.map +1 -1
- package/dist/visio/edit-page-rename.d.ts.map +1 -1
- package/dist/visio/edit-page-setup-commands.d.ts +7 -1
- package/dist/visio/edit-page-setup-commands.d.ts.map +1 -1
- package/dist/visio/edit-page-size.d.ts.map +1 -1
- package/dist/visio/edit-pages.d.ts.map +1 -1
- package/dist/visio/edit-recalculate-index.d.ts.map +1 -1
- package/dist/visio/edit-scope.d.ts.map +1 -1
- package/dist/visio/edit-shape-create.d.ts.map +1 -1
- package/dist/visio/edit-stencil-connector-write.d.ts.map +1 -1
- package/dist/visio/edit-style-admission.d.ts.map +1 -1
- package/dist/visio/edit-text.d.ts.map +1 -1
- package/dist/visio/edit.d.ts +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/index.cjs +1091 -233
- package/dist/visio/index.d.ts +2 -1
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +1091 -234
- package/dist/visio/line-jumps.d.ts +1 -5
- package/dist/visio/line-jumps.d.ts.map +1 -1
- package/dist/visio/model.d.ts +13 -0
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/visio/page-layout.d.ts +11 -2
- package/dist/visio/page-layout.d.ts.map +1 -1
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/shape-metadata.d.ts +6 -0
- package/dist/visio/shape-metadata.d.ts.map +1 -1
- package/dist/visio/shapes.d.ts.map +1 -1
- package/dist/visio/text-field-case.d.ts +2 -0
- package/dist/visio/text-field-case.d.ts.map +1 -0
- package/dist/visio/text-field-display.d.ts.map +1 -1
- package/dist/visio/text-field-numeric.d.ts +4 -0
- package/dist/visio/text-field-numeric.d.ts.map +1 -0
- package/dist/visio/ui/connector-preview.d.ts +1 -1
- package/dist/visio/ui/connector-preview.d.ts.map +1 -1
- package/dist/visio/ui/data-graphic-rules.d.ts +2 -0
- package/dist/visio/ui/data-graphic-rules.d.ts.map +1 -1
- package/dist/visio/ui/data-graphics.d.ts +3 -2
- package/dist/visio/ui/data-graphics.d.ts.map +1 -1
- package/dist/visio/ui/edit-commands.d.ts.map +1 -1
- package/dist/visio/ui/index.cjs +16898 -15855
- package/dist/visio/ui/index.mjs +16898 -15856
- package/dist/visio/ui/scene-details.d.ts.map +1 -1
- package/dist/visio/ui/scene-validation.d.ts.map +1 -1
- package/dist/visio/ui/snapshot-scene.d.ts +2 -1
- package/dist/visio/ui/snapshot-scene.d.ts.map +1 -1
- package/dist/visio/xml-attribute-whitespace.d.ts +5 -0
- package/dist/visio/xml-attribute-whitespace.d.ts.map +1 -0
- package/dist/xlsx/edit/index.d.ts +1 -0
- package/dist/xlsx/edit/index.d.ts.map +1 -1
- package/dist/xlsx/edit/insert-guard.d.ts.map +1 -1
- package/dist/xlsx/edit/merge.d.ts.map +1 -1
- package/dist/xlsx/edit/page-breaks.d.ts +5 -0
- package/dist/xlsx/edit/page-breaks.d.ts.map +1 -0
- package/dist/xlsx/edit/pivots.d.ts +8 -0
- package/dist/xlsx/edit/pivots.d.ts.map +1 -0
- package/dist/xlsx/edit/print-titles.d.ts +7 -0
- package/dist/xlsx/edit/print-titles.d.ts.map +1 -0
- package/dist/xlsx/edit/session.d.ts.map +1 -1
- package/dist/xlsx/edit/sheets.d.ts.map +1 -1
- package/dist/xlsx/edit/shift-formulas.d.ts.map +1 -1
- package/dist/xlsx/edit/shift-sheet.d.ts.map +1 -1
- package/dist/xlsx/edit/sparkline-ranges.d.ts +11 -0
- package/dist/xlsx/edit/sparkline-ranges.d.ts.map +1 -0
- package/dist/xlsx/edit/sparkline-xml.d.ts +13 -0
- package/dist/xlsx/edit/sparkline-xml.d.ts.map +1 -0
- package/dist/xlsx/edit/sparklines.d.ts +16 -0
- package/dist/xlsx/edit/sparklines.d.ts.map +1 -0
- package/dist/xlsx/edit/table-edits.d.ts.map +1 -1
- package/dist/xlsx/edit/tables.d.ts.map +1 -1
- package/dist/xlsx/edit/types.d.ts +22 -1
- package/dist/xlsx/edit/types.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/text-regex.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +3159 -1164
- package/dist/xlsx/index.d.ts +1 -0
- package/dist/xlsx/index.d.ts.map +1 -1
- package/dist/xlsx/index.mjs +3140 -1165
- package/dist/xlsx/layout/cell-view.d.ts +2 -0
- package/dist/xlsx/layout/cell-view.d.ts.map +1 -1
- package/dist/xlsx/layout/header-footer.d.ts +58 -0
- package/dist/xlsx/layout/header-footer.d.ts.map +1 -0
- package/dist/xlsx/layout/index.d.ts +5 -0
- package/dist/xlsx/layout/index.d.ts.map +1 -1
- package/dist/xlsx/layout/print-breaks.d.ts +11 -0
- package/dist/xlsx/layout/print-breaks.d.ts.map +1 -0
- package/dist/xlsx/layout/print-layout.d.ts +34 -0
- package/dist/xlsx/layout/print-layout.d.ts.map +1 -0
- package/dist/xlsx/layout/print-merges.d.ts +18 -0
- package/dist/xlsx/layout/print-merges.d.ts.map +1 -0
- package/dist/xlsx/layout/print-repeat.d.ts +12 -0
- package/dist/xlsx/layout/print-repeat.d.ts.map +1 -0
- package/dist/xlsx/layout/print-titles.d.ts +20 -0
- package/dist/xlsx/layout/print-titles.d.ts.map +1 -0
- package/dist/xlsx/layout/sparkline-data.d.ts.map +1 -1
- package/dist/xlsx/layout/sparkline-view.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +7784 -6976
- package/dist/xlsx/load/index.mjs +7784 -6976
- package/dist/xlsx/model-pivots.d.ts +46 -0
- package/dist/xlsx/model-pivots.d.ts.map +1 -0
- package/dist/xlsx/model.d.ts +5 -0
- package/dist/xlsx/model.d.ts.map +1 -1
- package/dist/xlsx/pivot/admission.d.ts +5 -0
- package/dist/xlsx/pivot/admission.d.ts.map +1 -0
- package/dist/xlsx/pivot/aggregate.d.ts +19 -0
- package/dist/xlsx/pivot/aggregate.d.ts.map +1 -0
- package/dist/xlsx/pivot/cache-xml.d.ts +9 -0
- package/dist/xlsx/pivot/cache-xml.d.ts.map +1 -0
- package/dist/xlsx/pivot/data.d.ts +12 -0
- package/dist/xlsx/pivot/data.d.ts.map +1 -0
- package/dist/xlsx/pivot/hierarchy.d.ts +7 -0
- package/dist/xlsx/pivot/hierarchy.d.ts.map +1 -0
- package/dist/xlsx/pivot/index.d.ts +3 -0
- package/dist/xlsx/pivot/index.d.ts.map +1 -0
- package/dist/xlsx/pivot/read.d.ts +5 -0
- package/dist/xlsx/pivot/read.d.ts.map +1 -0
- package/dist/xlsx/pivot/table-xml.d.ts +5 -0
- package/dist/xlsx/pivot/table-xml.d.ts.map +1 -0
- package/dist/xlsx/pivot/write.d.ts +11 -0
- package/dist/xlsx/pivot/write.d.ts.map +1 -0
- package/dist/xlsx/read/load.d.ts.map +1 -1
- package/dist/xlsx/read/sheet-props.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/index.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/navigation.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/pivots.d.ts +3 -0
- package/dist/xlsx/ui/commands/i18n/pivots.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/i18n/print-layout.d.ts +3 -0
- package/dist/xlsx/ui/commands/i18n/print-layout.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/i18n/sparklines.d.ts +3 -0
- package/dist/xlsx/ui/commands/i18n/sparklines.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/i18n/tools.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/page-breaks.d.ts +3 -0
- package/dist/xlsx/ui/commands/page-breaks.d.ts.map +1 -0
- package/dist/xlsx/ui/index.cjs +2001 -288
- package/dist/xlsx/ui/index.d.ts +1 -0
- package/dist/xlsx/ui/index.d.ts.map +1 -1
- package/dist/xlsx/ui/index.mjs +2001 -289
- package/dist/xlsx/write/page-setup.d.ts.map +1 -1
- package/dist/xlsx/write/save.d.ts.map +1 -1
- package/dist/xlsx/write/sheet-parts.d.ts +1 -0
- package/dist/xlsx/write/sheet-parts.d.ts.map +1 -1
- package/dist/xlsx/write/workbook-part.d.ts +1 -1
- package/dist/xlsx/write/workbook-part.d.ts.map +1 -1
- package/dist/xlsx/write/worksheet.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/pptx/chunks/index-Cn-GzYGp.d.ts.map +0 -1
- package/dist/pptx/chunks/text-operations-BHfAm5K9.d.ts.map +0 -1
|
@@ -39,8 +39,8 @@ function named(element, local, ns, lenient = true) {
|
|
|
39
39
|
}
|
|
40
40
|
var children = (parent, local, ns, lenient = true) => elements(parent).filter((element) => named(element, local, ns, lenient));
|
|
41
41
|
var first = (parent, local, ns, lenient = true) => parent ? children(parent, local, ns, lenient)[0] : void 0;
|
|
42
|
-
function attr(element, local, ns,
|
|
43
|
-
return element?.getAttributeNS(ns, local) ?? element?.getAttribute(`${
|
|
42
|
+
function attr(element, local, ns, prefix2) {
|
|
43
|
+
return element?.getAttributeNS(ns, local) ?? element?.getAttribute(`${prefix2}:${local}`) ?? void 0;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// docx/xml.ts
|
|
@@ -2651,11 +2651,11 @@ function cssFontFamily(name) {
|
|
|
2651
2651
|
// chart/render/chart-svg-appearance.ts
|
|
2652
2652
|
var nextPaintId = 0;
|
|
2653
2653
|
function chartGradientPaint(model, width = 1024, height = 768) {
|
|
2654
|
-
const
|
|
2654
|
+
const prefix2 = `xlsx-chart-${++nextPaintId}`;
|
|
2655
2655
|
const appearance = { ...model.appearance };
|
|
2656
2656
|
const defs = [];
|
|
2657
2657
|
const shadowPaint = (shadow, suffix) => {
|
|
2658
|
-
const id = `${
|
|
2658
|
+
const id = `${prefix2}-${suffix}`;
|
|
2659
2659
|
const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
|
|
2660
2660
|
defs.push(
|
|
2661
2661
|
`<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
|
|
@@ -2670,7 +2670,7 @@ function chartGradientPaint(model, width = 1024, height = 768) {
|
|
|
2670
2670
|
};
|
|
2671
2671
|
}
|
|
2672
2672
|
const paint = (gradient, suffix, bounds) => {
|
|
2673
|
-
const def = buildChartGradientDef(`${
|
|
2673
|
+
const def = buildChartGradientDef(`${prefix2}-${suffix}`, gradient, bounds);
|
|
2674
2674
|
defs.push(chartGradientMarkup(def));
|
|
2675
2675
|
return `url(#${def.id})`;
|
|
2676
2676
|
};
|
|
@@ -3710,6 +3710,14 @@ function mapDocumentParagraphs(model, map) {
|
|
|
3710
3710
|
...section.footers ? { footers: slots(section.footers) } : {}
|
|
3711
3711
|
}))
|
|
3712
3712
|
} : {},
|
|
3713
|
+
...model.footnoteSeparators ? {
|
|
3714
|
+
footnoteSeparators: Object.fromEntries(
|
|
3715
|
+
Object.entries(model.footnoteSeparators).map(([kind, note]) => [
|
|
3716
|
+
kind,
|
|
3717
|
+
{ ...note, blocks: mapBlockParagraphs(note.blocks, map) }
|
|
3718
|
+
])
|
|
3719
|
+
)
|
|
3720
|
+
} : {},
|
|
3713
3721
|
...model.footnotes ? {
|
|
3714
3722
|
footnotes: model.footnotes.map((note) => ({
|
|
3715
3723
|
...note,
|
|
@@ -3730,6 +3738,32 @@ function fieldName(instr) {
|
|
|
3730
3738
|
return instr.trim().split(/\s+/)[0]?.toUpperCase() ?? "";
|
|
3731
3739
|
}
|
|
3732
3740
|
|
|
3741
|
+
// docx/cell-blocks.ts
|
|
3742
|
+
function cellSourceBlocks(cell) {
|
|
3743
|
+
if (!cell.sourceBlocks) return cell.paragraphs;
|
|
3744
|
+
const originalIds = new Set(
|
|
3745
|
+
cell.sourceBlocks.filter((block) => block.type === "paragraph").map((block) => block.id)
|
|
3746
|
+
);
|
|
3747
|
+
const positions = new Map(cell.paragraphs.map((paragraph, index) => [paragraph.id, index]));
|
|
3748
|
+
const blocks = [];
|
|
3749
|
+
let cursor = 0;
|
|
3750
|
+
for (const source of cell.sourceBlocks) {
|
|
3751
|
+
if (source.type === "table") {
|
|
3752
|
+
blocks.push(source);
|
|
3753
|
+
continue;
|
|
3754
|
+
}
|
|
3755
|
+
const position = positions.get(source.id);
|
|
3756
|
+
if (position !== void 0 && position >= cursor) {
|
|
3757
|
+
blocks.push(...cell.paragraphs.slice(cursor, position + 1));
|
|
3758
|
+
cursor = position + 1;
|
|
3759
|
+
}
|
|
3760
|
+
while (cursor < cell.paragraphs.length && !originalIds.has(cell.paragraphs[cursor].id))
|
|
3761
|
+
blocks.push(cell.paragraphs[cursor++]);
|
|
3762
|
+
}
|
|
3763
|
+
blocks.push(...cell.paragraphs.slice(cursor));
|
|
3764
|
+
return blocks;
|
|
3765
|
+
}
|
|
3766
|
+
|
|
3733
3767
|
// docx/notes.ts
|
|
3734
3768
|
var romanNumerals = [
|
|
3735
3769
|
[1e3, "M"],
|
|
@@ -3794,7 +3828,7 @@ function walkBlocks(blocks, kind, order) {
|
|
|
3794
3828
|
if (block.type === "paragraph") walkParagraph(block, kind, order);
|
|
3795
3829
|
else
|
|
3796
3830
|
for (const row of block.rows)
|
|
3797
|
-
for (const cell of row) walkBlocks(cell
|
|
3831
|
+
for (const cell of row) walkBlocks(cellSourceBlocks(cell), kind, order);
|
|
3798
3832
|
}
|
|
3799
3833
|
}
|
|
3800
3834
|
function numberNotesInOrder(blocks, kind) {
|
|
@@ -4505,6 +4539,9 @@ function resolveIndents(paragraph) {
|
|
|
4505
4539
|
firstLineExtraPx
|
|
4506
4540
|
};
|
|
4507
4541
|
}
|
|
4542
|
+
function sourceLengthOf(run) {
|
|
4543
|
+
return run.sourceLength ?? (run.object ? 1 : run.text.length || (run.breakAfter ? 1 : 0));
|
|
4544
|
+
}
|
|
4508
4545
|
function tokenizeParagraph(paragraph) {
|
|
4509
4546
|
const tokens = [];
|
|
4510
4547
|
const runOffsets = [];
|
|
@@ -4512,7 +4549,7 @@ function tokenizeParagraph(paragraph) {
|
|
|
4512
4549
|
paragraph.runs.forEach((run, runIndex) => {
|
|
4513
4550
|
runOffsets.push(cursor);
|
|
4514
4551
|
if (run.hidden) {
|
|
4515
|
-
if (!run.synthetic) cursor += run
|
|
4552
|
+
if (!run.synthetic) cursor += sourceLengthOf(run);
|
|
4516
4553
|
return;
|
|
4517
4554
|
}
|
|
4518
4555
|
if (run.object) tokens.push({ kind: "object", runIndex, sourceStart: 0 });
|
|
@@ -4528,7 +4565,7 @@ function tokenizeParagraph(paragraph) {
|
|
|
4528
4565
|
if (run.breakAfter) appendBreakMarker(tokens, runIndex, run.text.length, run.breakAfter);
|
|
4529
4566
|
if (run.synthetic) {
|
|
4530
4567
|
for (const token of tokens) if (token.runIndex === runIndex) token.sourceStart = 0;
|
|
4531
|
-
} else cursor += run
|
|
4568
|
+
} else cursor += sourceLengthOf(run);
|
|
4532
4569
|
});
|
|
4533
4570
|
return { tokens, runOffsets };
|
|
4534
4571
|
}
|
|
@@ -4550,7 +4587,9 @@ function lineMetrics(placed, fonts, paragraph, measurer) {
|
|
|
4550
4587
|
let above = 0;
|
|
4551
4588
|
let below = 0;
|
|
4552
4589
|
for (const token of tokens) {
|
|
4553
|
-
const
|
|
4590
|
+
const run = paragraph.runs[token.runIndex];
|
|
4591
|
+
const metrics = run?.object?.noteSeparator ? fontMetrics(measurer, fonts[token.runIndex] ?? fontOf(run)) : void 0;
|
|
4592
|
+
const extent = metrics ? { above: metrics.ascent, below: metrics.descent } : tokenExtent(token, paragraph, fonts, measurer);
|
|
4554
4593
|
above = Math.max(above, extent.above);
|
|
4555
4594
|
below = Math.max(below, extent.below);
|
|
4556
4595
|
}
|
|
@@ -4625,7 +4664,18 @@ function layoutParagraph(paragraph, contentWidthPx, measurer, note, lineBox, sta
|
|
|
4625
4664
|
const bodyWidth = Math.max(1, contentWidthPx - leftPx - rightPx);
|
|
4626
4665
|
const fonts = paragraph.runs.map(fontOf);
|
|
4627
4666
|
const { tokens, runOffsets } = tokenizeParagraph(paragraph);
|
|
4628
|
-
const globalOffset = (token
|
|
4667
|
+
const globalOffset = (token, advance = 0) => {
|
|
4668
|
+
const run = expectDefined(paragraph.runs[token.runIndex], "source run");
|
|
4669
|
+
const length = sourceLengthOf(run);
|
|
4670
|
+
const offset = run.synthetic ? 0 : Math.max(
|
|
4671
|
+
0,
|
|
4672
|
+
Math.min(
|
|
4673
|
+
length,
|
|
4674
|
+
Math.round((token.sourceStart + advance) * length / Math.max(1, run.text.length))
|
|
4675
|
+
)
|
|
4676
|
+
);
|
|
4677
|
+
return expectDefined(runOffsets[token.runIndex], "run offset index") + offset;
|
|
4678
|
+
};
|
|
4629
4679
|
const effectiveAlign = paragraph.align ?? (paragraph.direction === "rtl" ? "right" : "left");
|
|
4630
4680
|
const lines = [];
|
|
4631
4681
|
const pageBreakAfterLine = /* @__PURE__ */ new Set();
|
|
@@ -4676,9 +4726,9 @@ function layoutParagraph(paragraph, contentWidthPx, measurer, note, lineBox, sta
|
|
|
4676
4726
|
const token = expectDefined(tokens[next], "token index");
|
|
4677
4727
|
if (ends.has(token.kind)) break;
|
|
4678
4728
|
if (beforeDecimalPx === void 0 && token.kind === "word" && /[.,]/.test(token.text)) {
|
|
4679
|
-
const
|
|
4729
|
+
const prefix2 = token.text.slice(0, token.text.search(/[.,]/));
|
|
4680
4730
|
beforeDecimalPx = followingPx + runTextWidth(
|
|
4681
|
-
|
|
4731
|
+
prefix2,
|
|
4682
4732
|
expectDefined(paragraph.runs[token.runIndex], "decimal run"),
|
|
4683
4733
|
measurer
|
|
4684
4734
|
);
|
|
@@ -4697,14 +4747,17 @@ function layoutParagraph(paragraph, contentWidthPx, measurer, note, lineBox, sta
|
|
|
4697
4747
|
const [firstPlaced] = placed;
|
|
4698
4748
|
const start = firstPlaced ? globalOffset(firstPlaced.token) : 0;
|
|
4699
4749
|
const last = placed.at(-1)?.token;
|
|
4700
|
-
const end = last ? globalOffset(last
|
|
4750
|
+
const end = last ? globalOffset(last, last.kind === "word" || last.kind === "space" ? last.text.length : 1) : start;
|
|
4701
4751
|
const gapBeforePx = boxFor(lineIndex).gapBeforePx;
|
|
4702
4752
|
const { heightPx, baselinePx } = lineMetrics(placed, fonts, paragraph, measurer);
|
|
4703
4753
|
rendered.forEach(({ token }, index) => {
|
|
4704
4754
|
const extent2 = tokenExtent(token, paragraph, fonts, measurer);
|
|
4705
4755
|
const fragment = expectDefined(fragments[index], "fragment for rendered token");
|
|
4706
4756
|
fragment.sourceStart = globalOffset(token);
|
|
4707
|
-
fragment.sourceEnd =
|
|
4757
|
+
fragment.sourceEnd = globalOffset(
|
|
4758
|
+
token,
|
|
4759
|
+
token.kind === "word" || token.kind === "space" ? token.text.length : 1
|
|
4760
|
+
);
|
|
4708
4761
|
fragment.topPx = baselinePx - extent2.above;
|
|
4709
4762
|
if (token.kind !== "object") fragment.boxHeightPx = extent2.ascent + extent2.descent;
|
|
4710
4763
|
});
|
|
@@ -4838,6 +4891,57 @@ function widowControlEnabled(value) {
|
|
|
4838
4891
|
return value !== false;
|
|
4839
4892
|
}
|
|
4840
4893
|
|
|
4894
|
+
// docx/layout/table-cell-layout.ts
|
|
4895
|
+
function cellParagraphs(cell) {
|
|
4896
|
+
const walk = (blocks) => blocks.flatMap(
|
|
4897
|
+
(block) => block.kind === "paragraph" ? [block] : block.rows.flatMap((row) => row.cells.flatMap(cellParagraphs))
|
|
4898
|
+
);
|
|
4899
|
+
return cell.blocks ? walk(cell.blocks) : cell.paragraphs;
|
|
4900
|
+
}
|
|
4901
|
+
function stackCellBlocks(cell, width, measurer, note, top, starts) {
|
|
4902
|
+
if (!cell.blocks)
|
|
4903
|
+
return stackParagraphs(
|
|
4904
|
+
starts ? cell.paragraphs.filter((p) => starts.has(p.id)) : cell.paragraphs,
|
|
4905
|
+
width,
|
|
4906
|
+
measurer,
|
|
4907
|
+
note,
|
|
4908
|
+
top,
|
|
4909
|
+
starts
|
|
4910
|
+
);
|
|
4911
|
+
let y = top;
|
|
4912
|
+
const boxes = [];
|
|
4913
|
+
for (const block of cell.blocks) {
|
|
4914
|
+
if (block.kind === "paragraph") {
|
|
4915
|
+
if (starts && !starts.has(block.id)) continue;
|
|
4916
|
+
const result = stackParagraphs([block], width, measurer, note, y, starts);
|
|
4917
|
+
boxes.push(...result.boxes);
|
|
4918
|
+
y = result.heightPx;
|
|
4919
|
+
continue;
|
|
4920
|
+
}
|
|
4921
|
+
const tableWidth = block.widthPx ?? width;
|
|
4922
|
+
const x = block.alignment === "center" ? Math.max(0, (width - tableWidth) / 2) : block.alignment === "right" ? Math.max(0, width - tableWidth) : block.indentPx ?? 0;
|
|
4923
|
+
for (const row of block.rows) {
|
|
4924
|
+
if (starts && !row.cells.some((nested) => cellParagraphs(nested).some((p) => starts.has(p.id))))
|
|
4925
|
+
continue;
|
|
4926
|
+
const layout = layoutRow(row, tableWidth, measurer, note, void 0, starts);
|
|
4927
|
+
layout.cells.forEach((paragraphs, index) => {
|
|
4928
|
+
const geometry = layout.geometry[index];
|
|
4929
|
+
for (const paragraph of paragraphs)
|
|
4930
|
+
boxes.push({
|
|
4931
|
+
...paragraph,
|
|
4932
|
+
yPx: y + paragraph.yPx,
|
|
4933
|
+
xPx: x + geometry.xPx + geometry.paddingLeftPx + (paragraph.xPx ?? 0),
|
|
4934
|
+
widthPx: paragraph.widthPx ?? Math.max(1, geometry.widthPx - geometry.paddingLeftPx - geometry.paddingRightPx),
|
|
4935
|
+
readOnly: true
|
|
4936
|
+
});
|
|
4937
|
+
});
|
|
4938
|
+
y += layout.heightPx;
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
boxes.sort((a, b) => a.yPx - b.yPx);
|
|
4942
|
+
return { heightPx: y, boxes };
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4841
4945
|
// docx/layout/table-layout.ts
|
|
4842
4946
|
function stackParagraphs(paragraphs, widthPx, measurer, note, topPx = 0, startTokens) {
|
|
4843
4947
|
let y = topPx;
|
|
@@ -4853,29 +4957,30 @@ function stackParagraphs(paragraphs, widthPx, measurer, note, topPx = 0, startTo
|
|
|
4853
4957
|
);
|
|
4854
4958
|
y += layout.spacingBeforePx;
|
|
4855
4959
|
const top = y;
|
|
4856
|
-
const lines = layout.lines.map((line2) => ({ ...line2
|
|
4960
|
+
const lines = layout.lines.map((line2) => ({ ...line2 }));
|
|
4857
4961
|
boxes.push({
|
|
4858
4962
|
kind: "paragraph",
|
|
4859
4963
|
blockId: paragraph.id,
|
|
4860
4964
|
yPx: top,
|
|
4861
4965
|
heightPx: layout.contentHeightPx,
|
|
4862
|
-
lines
|
|
4966
|
+
lines,
|
|
4967
|
+
...layout.frame ? { frame: layout.frame } : {}
|
|
4863
4968
|
});
|
|
4864
4969
|
y += layout.contentHeightPx + layout.spacingAfterPx;
|
|
4865
4970
|
}
|
|
4866
4971
|
return { heightPx: y, boxes };
|
|
4867
4972
|
}
|
|
4868
|
-
function layoutRow(row, tableWidthPx, measurer, note, remaining) {
|
|
4973
|
+
function layoutRow(row, tableWidthPx, measurer, note, remaining, startTokens) {
|
|
4869
4974
|
const count = row.cells.length || 1;
|
|
4870
4975
|
let x = 0;
|
|
4871
4976
|
const geometry = [];
|
|
4872
4977
|
const laidOut = row.cells.map((cell) => {
|
|
4873
4978
|
const continuation = remaining?.[geometry.length];
|
|
4874
|
-
const starts = continuation ? new Map(continuation.map((box) => [box.blockId, box.lines[0]?.firstToken ?? 0])) :
|
|
4979
|
+
const starts = continuation ? new Map(continuation.map((box) => [box.blockId, box.lines[0]?.firstToken ?? 0])) : startTokens;
|
|
4875
4980
|
const widthPx = cell.widthPx ?? tableWidthPx / count;
|
|
4876
4981
|
const padding = cell.padding ?? { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4877
|
-
const content2 =
|
|
4878
|
-
|
|
4982
|
+
const content2 = stackCellBlocks(
|
|
4983
|
+
cell,
|
|
4879
4984
|
Math.max(1, widthPx - padding.left - padding.right),
|
|
4880
4985
|
measurer,
|
|
4881
4986
|
note,
|
|
@@ -4898,26 +5003,24 @@ function layoutRow(row, tableWidthPx, measurer, note, remaining) {
|
|
|
4898
5003
|
});
|
|
4899
5004
|
const content = Math.max(0, ...laidOut.map((cell) => cell.heightPx));
|
|
4900
5005
|
const heightPx = row.heightPx === void 0 ? content : row.heightRule === "exact" ? row.heightPx : Math.max(content, row.heightPx);
|
|
4901
|
-
return {
|
|
5006
|
+
return {
|
|
5007
|
+
heightPx,
|
|
5008
|
+
cells: laidOut.map((cell) => cell.boxes),
|
|
5009
|
+
geometry,
|
|
5010
|
+
cellPadding: row.cells.map((cell) => ({
|
|
5011
|
+
top: cell.padding?.top ?? 0,
|
|
5012
|
+
bottom: cell.padding?.bottom ?? 0
|
|
5013
|
+
}))
|
|
5014
|
+
};
|
|
4902
5015
|
}
|
|
4903
5016
|
function splitCellAtHeight(boxes, cutHeightPx) {
|
|
4904
5017
|
const before = [];
|
|
4905
5018
|
const after = [];
|
|
4906
|
-
let afterOrigin = null;
|
|
4907
5019
|
let beforeHeightPx = 0;
|
|
4908
5020
|
for (const box of boxes) {
|
|
4909
|
-
if (afterOrigin !== null) {
|
|
4910
|
-
after.push({ ...box, yPx: box.yPx - afterOrigin });
|
|
4911
|
-
continue;
|
|
4912
|
-
}
|
|
4913
5021
|
if (box.yPx + box.heightPx <= cutHeightPx) {
|
|
4914
5022
|
before.push(box);
|
|
4915
|
-
beforeHeightPx = box.yPx + box.heightPx;
|
|
4916
|
-
continue;
|
|
4917
|
-
}
|
|
4918
|
-
if (box.yPx >= cutHeightPx) {
|
|
4919
|
-
afterOrigin = box.yPx;
|
|
4920
|
-
after.push({ ...box, yPx: 0 });
|
|
5023
|
+
beforeHeightPx = Math.max(beforeHeightPx, box.yPx + box.heightPx);
|
|
4921
5024
|
continue;
|
|
4922
5025
|
}
|
|
4923
5026
|
const beforeLines = box.lines.filter(
|
|
@@ -4927,50 +5030,407 @@ function splitCellAtHeight(boxes, cutHeightPx) {
|
|
|
4927
5030
|
if (beforeLines.length) {
|
|
4928
5031
|
const bottom = beforeLines.at(-1).yPx + beforeLines.at(-1).heightPx;
|
|
4929
5032
|
before.push({ ...box, heightPx: bottom, lines: beforeLines });
|
|
4930
|
-
beforeHeightPx = box.yPx + bottom;
|
|
5033
|
+
beforeHeightPx = Math.max(beforeHeightPx, box.yPx + bottom);
|
|
4931
5034
|
}
|
|
4932
5035
|
if (afterLines.length) {
|
|
4933
5036
|
const shift = expectDefined(afterLines[0], "first line after split").yPx;
|
|
4934
|
-
afterOrigin = box.yPx + shift;
|
|
4935
5037
|
after.push({
|
|
4936
5038
|
...box,
|
|
4937
|
-
yPx:
|
|
5039
|
+
yPx: box.yPx + shift,
|
|
4938
5040
|
heightPx: afterLines.at(-1).yPx + afterLines.at(-1).heightPx - shift,
|
|
4939
5041
|
lines: afterLines.map((line2) => ({ ...line2, yPx: line2.yPx - shift }))
|
|
4940
5042
|
});
|
|
4941
|
-
} else {
|
|
4942
|
-
afterOrigin = box.yPx + box.heightPx;
|
|
4943
5043
|
}
|
|
4944
5044
|
}
|
|
5045
|
+
const afterOrigin = Math.min(...after.map((box) => box.yPx));
|
|
5046
|
+
for (const box of after) box.yPx -= afterOrigin;
|
|
4945
5047
|
return { before, after, beforeHeightPx };
|
|
4946
5048
|
}
|
|
4947
|
-
function splitRowAtHeight(row, cutHeightPx) {
|
|
4948
|
-
const splits = row.cells.map((cell) =>
|
|
5049
|
+
function splitRowAtHeight(row, cutHeightPx, cellCuts) {
|
|
5050
|
+
const splits = row.cells.map((cell, index) => {
|
|
5051
|
+
const padding = row.cellPadding?.[index] ?? { top: 0, bottom: 0 };
|
|
5052
|
+
const split = splitCellAtHeight(cell, (cellCuts?.[index] ?? cutHeightPx) - padding.bottom);
|
|
5053
|
+
if (split.before.length) split.beforeHeightPx += padding.bottom;
|
|
5054
|
+
if (split.after.length)
|
|
5055
|
+
split.after = split.after.map((box) => ({ ...box, yPx: box.yPx + padding.top }));
|
|
5056
|
+
return split;
|
|
5057
|
+
});
|
|
4949
5058
|
const anyAfter = splits.some((split) => split.after.length > 0);
|
|
4950
5059
|
const before = {
|
|
4951
5060
|
heightPx: Math.max(0, ...splits.map((split) => split.beforeHeightPx)),
|
|
4952
5061
|
cells: splits.map((split) => split.before),
|
|
4953
|
-
geometry: row.geometry
|
|
5062
|
+
geometry: row.geometry.map((geometry, index) => ({
|
|
5063
|
+
...geometry,
|
|
5064
|
+
contentHeightPx: splits[index].beforeHeightPx
|
|
5065
|
+
})),
|
|
5066
|
+
...row.cellPadding ? { cellPadding: row.cellPadding } : {}
|
|
4954
5067
|
};
|
|
4955
5068
|
if (!anyAfter) return { before, after: null };
|
|
4956
5069
|
const after = {
|
|
4957
5070
|
heightPx: Math.max(
|
|
4958
5071
|
0,
|
|
4959
5072
|
...splits.map(
|
|
4960
|
-
(split) => split.after.
|
|
5073
|
+
(split, index) => split.after.length ? split.after.at(-1).yPx + split.after.at(-1).heightPx + (row.cellPadding?.[index]?.bottom ?? 0) : 0
|
|
4961
5074
|
)
|
|
4962
5075
|
),
|
|
4963
5076
|
cells: splits.map((split) => split.after),
|
|
4964
|
-
geometry: row.geometry
|
|
5077
|
+
geometry: row.geometry.map((geometry, index) => ({
|
|
5078
|
+
...geometry,
|
|
5079
|
+
contentHeightPx: splits[index].after.length ? splits[index].after.at(-1).yPx + splits[index].after.at(-1).heightPx + (row.cellPadding?.[index]?.bottom ?? 0) : 0
|
|
5080
|
+
})),
|
|
5081
|
+
...row.cellPadding ? { cellPadding: row.cellPadding } : {}
|
|
4965
5082
|
};
|
|
4966
5083
|
return { before, after };
|
|
4967
5084
|
}
|
|
4968
5085
|
|
|
4969
|
-
// docx/layout/
|
|
5086
|
+
// docx/layout/footnote-split.ts
|
|
5087
|
+
function splitNote(note, budget) {
|
|
5088
|
+
if (note.heightPx <= budget + 1e-6) return { before: note };
|
|
5089
|
+
const before = [];
|
|
5090
|
+
const after = [];
|
|
5091
|
+
let origin;
|
|
5092
|
+
const sourceTokenStarts = { ...note.sourceTokenStarts };
|
|
5093
|
+
for (const paragraph of note.paragraphs) {
|
|
5094
|
+
if (origin !== void 0) {
|
|
5095
|
+
after.push({ ...paragraph, yPx: paragraph.yPx - origin });
|
|
5096
|
+
continue;
|
|
5097
|
+
}
|
|
5098
|
+
if (paragraph.yPx + paragraph.heightPx <= budget + 1e-6) {
|
|
5099
|
+
before.push(paragraph);
|
|
5100
|
+
continue;
|
|
5101
|
+
}
|
|
5102
|
+
const count = paragraph.lines.filter(
|
|
5103
|
+
(line2) => paragraph.yPx + line2.yPx + line2.heightPx <= budget + 1e-6
|
|
5104
|
+
).length;
|
|
5105
|
+
const head = paragraph.lines.slice(0, count);
|
|
5106
|
+
const tail = paragraph.lines.slice(count);
|
|
5107
|
+
if (head.length) {
|
|
5108
|
+
const bottom = head.at(-1).yPx + head.at(-1).heightPx;
|
|
5109
|
+
before.push({ ...paragraph, heightPx: bottom, lines: head });
|
|
5110
|
+
}
|
|
5111
|
+
const first3 = tail[0];
|
|
5112
|
+
if (head.length)
|
|
5113
|
+
sourceTokenStarts[paragraph.blockId] = head.at(-1).nextToken ?? sourceTokenStarts[paragraph.blockId] ?? 0;
|
|
5114
|
+
origin = paragraph.yPx + (first3?.yPx ?? 0);
|
|
5115
|
+
after.push({
|
|
5116
|
+
...paragraph,
|
|
5117
|
+
yPx: 0,
|
|
5118
|
+
heightPx: Math.max(0, paragraph.heightPx - (first3?.yPx ?? 0)),
|
|
5119
|
+
lines: tail.map((line2) => ({ ...line2, yPx: line2.yPx - (first3?.yPx ?? 0) }))
|
|
5120
|
+
});
|
|
5121
|
+
}
|
|
5122
|
+
if (!before.length) return { after: note };
|
|
5123
|
+
const last = before.at(-1);
|
|
5124
|
+
return {
|
|
5125
|
+
before: { ...note, heightPx: last.yPx + last.heightPx, paragraphs: before },
|
|
5126
|
+
...after.length ? {
|
|
5127
|
+
after: {
|
|
5128
|
+
...note,
|
|
5129
|
+
yPx: 0,
|
|
5130
|
+
heightPx: Math.max(0, note.heightPx - (origin ?? 0)),
|
|
5131
|
+
paragraphs: after,
|
|
5132
|
+
continued: true,
|
|
5133
|
+
sourceTokenStarts
|
|
5134
|
+
}
|
|
5135
|
+
} : {}
|
|
5136
|
+
};
|
|
5137
|
+
}
|
|
5138
|
+
|
|
5139
|
+
// docx/layout/footnote-columns.ts
|
|
5140
|
+
function footnoteColumns(page, columns) {
|
|
5141
|
+
const width = page.widthPx - page.marginLeftPx - page.marginRightPx;
|
|
5142
|
+
const equal = (width - columns.gapPx * (columns.count - 1)) / columns.count;
|
|
5143
|
+
let x = 0;
|
|
5144
|
+
return Array.from({ length: columns.count }, (_, index) => {
|
|
5145
|
+
const own = columns.widths?.[index];
|
|
5146
|
+
const column = { xPx: x, widthPx: Math.max(1, own?.widthPx ?? equal) };
|
|
5147
|
+
x += column.widthPx + (own?.gapPx ?? columns.gapPx);
|
|
5148
|
+
return column;
|
|
5149
|
+
});
|
|
5150
|
+
}
|
|
5151
|
+
function packFootnotes(notes, columns, height, reflow) {
|
|
5152
|
+
const remaining = [...notes], placed = [];
|
|
5153
|
+
let used = 0;
|
|
5154
|
+
for (const [columnIndex, column] of columns.entries()) {
|
|
5155
|
+
let y = 0;
|
|
5156
|
+
while (remaining.length) {
|
|
5157
|
+
const current = reflow(remaining[0], column.widthPx);
|
|
5158
|
+
const split = splitNote(current, Math.max(0, height - y));
|
|
5159
|
+
if (!split.before) break;
|
|
5160
|
+
placed.push({
|
|
5161
|
+
...split.before,
|
|
5162
|
+
yPx: y,
|
|
5163
|
+
xPx: column.xPx,
|
|
5164
|
+
widthPx: column.widthPx,
|
|
5165
|
+
columnIndex
|
|
5166
|
+
});
|
|
5167
|
+
y += split.before.heightPx;
|
|
5168
|
+
used = Math.max(used, y);
|
|
5169
|
+
if (split.after) {
|
|
5170
|
+
remaining[0] = { ...split.after, continued: !!current.continued };
|
|
5171
|
+
break;
|
|
5172
|
+
}
|
|
5173
|
+
remaining.shift();
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
return { placed, remaining, heightPx: used };
|
|
5177
|
+
}
|
|
5178
|
+
function balancedFootnotes(notes, columns, limit, reflow) {
|
|
5179
|
+
if (!notes.length) return { placed: [], remaining: [], heightPx: 0 };
|
|
5180
|
+
const full = packFootnotes(notes, columns, limit, reflow);
|
|
5181
|
+
if (full.remaining.length) return full;
|
|
5182
|
+
let lower = 0, upper = limit;
|
|
5183
|
+
for (let step = 0; step < 24 && upper - lower > 5e-3; step++) {
|
|
5184
|
+
const middle = (lower + upper) / 2;
|
|
5185
|
+
if (packFootnotes(notes, columns, middle, reflow).remaining.length) lower = middle;
|
|
5186
|
+
else upper = middle;
|
|
5187
|
+
}
|
|
5188
|
+
return packFootnotes(notes, columns, Math.ceil(upper * 100) / 100, reflow);
|
|
5189
|
+
}
|
|
5190
|
+
function minimumFootnoteHeight(notes, columns, reflow) {
|
|
5191
|
+
const width = columns[0].widthPx;
|
|
5192
|
+
const maximum = notes.reduce((sum, note) => sum + reflow(note, width).heightPx, 0);
|
|
5193
|
+
return balancedFootnotes(notes, columns, maximum, reflow).heightPx;
|
|
5194
|
+
}
|
|
5195
|
+
|
|
5196
|
+
// docx/layout/footnote-flow.ts
|
|
5197
|
+
function firstLineBottom(note) {
|
|
5198
|
+
const first3 = note?.paragraphs[0];
|
|
5199
|
+
return first3 ? first3.yPx + (first3.lines[0]?.yPx ?? 0) + (first3.lines[0]?.heightPx ?? first3.heightPx) : note?.heightPx ?? 0;
|
|
5200
|
+
}
|
|
4970
5201
|
var FOOTNOTE_SEPARATOR_PX = 12;
|
|
5202
|
+
var FootnoteFlow = class {
|
|
5203
|
+
constructor(report, separator, columns, reflow = (note) => note) {
|
|
5204
|
+
this.report = report;
|
|
5205
|
+
this.separator = separator;
|
|
5206
|
+
this.columns = columns;
|
|
5207
|
+
this.reflow = reflow;
|
|
5208
|
+
}
|
|
5209
|
+
report;
|
|
5210
|
+
separator;
|
|
5211
|
+
columns;
|
|
5212
|
+
reflow;
|
|
5213
|
+
pending;
|
|
5214
|
+
remaining = [];
|
|
5215
|
+
sources = /* @__PURE__ */ new WeakMap();
|
|
5216
|
+
separatorHeight(page, notes = this.pending?.notes ?? []) {
|
|
5217
|
+
return (page.footnoteSeparator ?? this.separator?.(page, !!notes[0]?.continued))?.heightPx ?? FOOTNOTE_SEPARATOR_PX;
|
|
5218
|
+
}
|
|
5219
|
+
get hasContinuation() {
|
|
5220
|
+
return this.remaining.length > 0;
|
|
5221
|
+
}
|
|
5222
|
+
hold(blockId, notes, bodyMinimum, freshBodyMinimum = bodyMinimum) {
|
|
5223
|
+
this.pending = notes.length ? { blockId, notes, bodyMinimum, freshBodyMinimum } : void 0;
|
|
5224
|
+
}
|
|
5225
|
+
reserved(page, _columnIndex = 0) {
|
|
5226
|
+
return page.footnotes?.length ? this.separatorHeight(page) + (page.footnoteHeightPx ?? page.footnotes.reduce((sum, note) => sum + note.heightPx, 0)) : 0;
|
|
5227
|
+
}
|
|
5228
|
+
pendingHeight(page, capacity, bodyUsed, _columnIndex = 0) {
|
|
5229
|
+
if (!this.pending) return 0;
|
|
5230
|
+
if (this.columns) {
|
|
5231
|
+
const existing = this.sources.get(page) ?? [];
|
|
5232
|
+
const height = minimumFootnoteHeight(
|
|
5233
|
+
[...existing, ...this.pending.notes],
|
|
5234
|
+
footnoteColumns(page, this.columns),
|
|
5235
|
+
this.reflow
|
|
5236
|
+
) + this.separatorHeight(page);
|
|
5237
|
+
if (height + this.pending.freshBodyMinimum <= capacity)
|
|
5238
|
+
return Math.max(0, height - this.reserved(page));
|
|
5239
|
+
return Math.max(
|
|
5240
|
+
firstLineBottom(this.pending.notes[0]) + (page.footnotes?.length ? 0 : this.separatorHeight(page)),
|
|
5241
|
+
capacity - bodyUsed - this.reserved(page) - this.pending.bodyMinimum
|
|
5242
|
+
);
|
|
5243
|
+
}
|
|
5244
|
+
const total = this.pending.notes.reduce((sum, note) => sum + note.heightPx, 0);
|
|
5245
|
+
const separator = page.footnotes?.length ? 0 : this.separatorHeight(page);
|
|
5246
|
+
if (total + this.separatorHeight(page) + this.pending.freshBodyMinimum <= capacity)
|
|
5247
|
+
return total + separator;
|
|
5248
|
+
return Math.max(
|
|
5249
|
+
firstLineBottom(this.pending.notes[0]) + separator,
|
|
5250
|
+
capacity - bodyUsed - this.reserved(page) - this.pending.bodyMinimum
|
|
5251
|
+
);
|
|
5252
|
+
}
|
|
5253
|
+
/** A later column cannot grow the page-wide note area into body content already placed. */
|
|
5254
|
+
blockedByEarlierColumn(page, capacity, bodyBottom) {
|
|
5255
|
+
if (!this.pending) return false;
|
|
5256
|
+
if (this.columns)
|
|
5257
|
+
return bodyBottom + this.reserved(page) + this.pendingHeight(page, capacity, bodyBottom) > capacity;
|
|
5258
|
+
const total = this.pending.notes.reduce((sum, note) => sum + note.heightPx, 0);
|
|
5259
|
+
const minimum = firstLineBottom(this.pending.notes[0]);
|
|
5260
|
+
const needed = total + this.separatorHeight(page) + this.pending.freshBodyMinimum <= capacity ? total : minimum;
|
|
5261
|
+
return bodyBottom + this.reserved(page) + needed + (page.footnotes?.length ? 0 : this.separatorHeight(page)) > capacity;
|
|
5262
|
+
}
|
|
5263
|
+
commit(blockId, page, available, _columnIndex = 0) {
|
|
5264
|
+
if (this.pending?.blockId !== blockId) return false;
|
|
5265
|
+
const notes = this.pending.notes;
|
|
5266
|
+
this.pending = void 0;
|
|
5267
|
+
this.append(page, notes, available);
|
|
5268
|
+
return true;
|
|
5269
|
+
}
|
|
5270
|
+
resume(page, capacity, _columnIndex, width) {
|
|
5271
|
+
const notes = width === void 0 ? this.remaining : this.remaining.map((note) => this.reflow(note, width));
|
|
5272
|
+
this.remaining = [];
|
|
5273
|
+
this.append(page, notes, capacity);
|
|
5274
|
+
}
|
|
5275
|
+
append(page, notes, available) {
|
|
5276
|
+
if (!page.footnotes?.length && notes.length) {
|
|
5277
|
+
const separator = this.separator?.(page, !!notes[0]?.continued);
|
|
5278
|
+
if (separator) page.footnoteSeparator = separator;
|
|
5279
|
+
}
|
|
5280
|
+
if (this.columns) {
|
|
5281
|
+
const sources = [...this.sources.get(page) ?? [], ...notes];
|
|
5282
|
+
this.sources.set(page, sources);
|
|
5283
|
+
const geometry = footnoteColumns(page, this.columns);
|
|
5284
|
+
const previousHeight = page.footnoteHeightPx ?? 0;
|
|
5285
|
+
const capacity = Math.max(
|
|
5286
|
+
0,
|
|
5287
|
+
available + previousHeight - (page.footnotes?.length ? 0 : this.separatorHeight(page))
|
|
5288
|
+
);
|
|
5289
|
+
let packed = balancedFootnotes(sources, geometry, capacity, this.reflow);
|
|
5290
|
+
if (!packed.placed.length && sources.length) {
|
|
5291
|
+
this.report(
|
|
5292
|
+
"A footnote line was taller than its available page area and was placed without splitting."
|
|
5293
|
+
);
|
|
5294
|
+
packed = balancedFootnotes(
|
|
5295
|
+
sources,
|
|
5296
|
+
geometry,
|
|
5297
|
+
firstLineBottom(this.reflow(sources[0], geometry[0].widthPx)),
|
|
5298
|
+
this.reflow
|
|
5299
|
+
);
|
|
5300
|
+
}
|
|
5301
|
+
page.footnotes = packed.placed;
|
|
5302
|
+
page.footnoteHeightPx = packed.heightPx;
|
|
5303
|
+
this.remaining = packed.remaining.map((note) => ({
|
|
5304
|
+
...note,
|
|
5305
|
+
continued: !!note.continued || packed.placed.some((fragment) => fragment.id === note.id)
|
|
5306
|
+
}));
|
|
5307
|
+
return;
|
|
5308
|
+
}
|
|
5309
|
+
let top = page.footnotes?.reduce((sum, note) => sum + note.heightPx, 0) ?? 0;
|
|
5310
|
+
let budget = Math.max(0, available - (page.footnotes?.length ? 0 : this.separatorHeight(page)));
|
|
5311
|
+
for (let index = 0; index < notes.length; index++) {
|
|
5312
|
+
const note = notes[index];
|
|
5313
|
+
let split = splitNote(note, budget);
|
|
5314
|
+
if (!split.before && !page.footnotes?.length) {
|
|
5315
|
+
split = splitNote(note, firstLineBottom(note));
|
|
5316
|
+
this.report(
|
|
5317
|
+
"A footnote line was taller than its available page area and was placed without splitting."
|
|
5318
|
+
);
|
|
5319
|
+
}
|
|
5320
|
+
if (split.before) {
|
|
5321
|
+
(page.footnotes ??= []).push({ ...split.before, yPx: top });
|
|
5322
|
+
top += split.before.heightPx;
|
|
5323
|
+
budget -= split.before.heightPx;
|
|
5324
|
+
}
|
|
5325
|
+
if (split.after) {
|
|
5326
|
+
this.remaining.push(split.after, ...notes.slice(index + 1));
|
|
5327
|
+
break;
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
};
|
|
5332
|
+
|
|
5333
|
+
// docx/layout/legacy-footnote-flow.ts
|
|
5334
|
+
var LegacyFootnoteFlow = class {
|
|
5335
|
+
flow;
|
|
5336
|
+
views = /* @__PURE__ */ new WeakMap();
|
|
5337
|
+
constructor(report, separator, reflow = (note) => note) {
|
|
5338
|
+
this.flow = new FootnoteFlow(report, separator, void 0, reflow);
|
|
5339
|
+
}
|
|
5340
|
+
view(page, index) {
|
|
5341
|
+
let views = this.views.get(page);
|
|
5342
|
+
if (!views) {
|
|
5343
|
+
views = /* @__PURE__ */ new Map();
|
|
5344
|
+
this.views.set(page, views);
|
|
5345
|
+
}
|
|
5346
|
+
let view = views.get(index);
|
|
5347
|
+
if (!view) {
|
|
5348
|
+
const {
|
|
5349
|
+
footnotes: _notes,
|
|
5350
|
+
footnoteSeparator: _separator,
|
|
5351
|
+
footnoteHeightPx: _height,
|
|
5352
|
+
footnoteColumnAreas: _areas,
|
|
5353
|
+
...geometry
|
|
5354
|
+
} = page;
|
|
5355
|
+
view = {
|
|
5356
|
+
...geometry,
|
|
5357
|
+
widthPx: page.columns[index].widthPx,
|
|
5358
|
+
marginLeftPx: 0,
|
|
5359
|
+
marginRightPx: 0,
|
|
5360
|
+
columns: []
|
|
5361
|
+
};
|
|
5362
|
+
views.set(index, view);
|
|
5363
|
+
}
|
|
5364
|
+
return view;
|
|
5365
|
+
}
|
|
5366
|
+
sync(page) {
|
|
5367
|
+
const views = this.views.get(page);
|
|
5368
|
+
if (!views) return;
|
|
5369
|
+
const areas = [...views].filter(([, view]) => view.footnotes?.length).map(([columnIndex, view]) => {
|
|
5370
|
+
const column = page.columns[columnIndex];
|
|
5371
|
+
return {
|
|
5372
|
+
columnIndex,
|
|
5373
|
+
xPx: column.xPx,
|
|
5374
|
+
widthPx: column.widthPx,
|
|
5375
|
+
heightPx: view.footnotes.reduce((sum, note) => sum + note.heightPx, 0),
|
|
5376
|
+
continued: !!view.footnotes[0]?.continued,
|
|
5377
|
+
...view.footnoteSeparator ? { separator: view.footnoteSeparator } : {},
|
|
5378
|
+
yPx: 0
|
|
5379
|
+
};
|
|
5380
|
+
});
|
|
5381
|
+
const height = Math.max(0, ...areas.map((area) => area.heightPx));
|
|
5382
|
+
for (const area of areas) area.yPx = height - area.heightPx;
|
|
5383
|
+
page.footnoteColumnAreas = areas;
|
|
5384
|
+
page.footnoteHeightPx = height;
|
|
5385
|
+
page.footnotes = areas.flatMap(
|
|
5386
|
+
(area) => this.view(page, area.columnIndex).footnotes.map((note) => ({
|
|
5387
|
+
...note,
|
|
5388
|
+
xPx: area.xPx,
|
|
5389
|
+
widthPx: area.widthPx,
|
|
5390
|
+
columnIndex: area.columnIndex,
|
|
5391
|
+
yPx: area.yPx + note.yPx
|
|
5392
|
+
}))
|
|
5393
|
+
);
|
|
5394
|
+
}
|
|
5395
|
+
get hasContinuation() {
|
|
5396
|
+
return this.flow.hasContinuation;
|
|
5397
|
+
}
|
|
5398
|
+
hold(blockId, notes, bodyMinimum, freshBodyMinimum = bodyMinimum) {
|
|
5399
|
+
this.flow.hold(blockId, notes, bodyMinimum, freshBodyMinimum);
|
|
5400
|
+
}
|
|
5401
|
+
reserved(page, columnIndex = 0) {
|
|
5402
|
+
return this.flow.reserved(this.view(page, columnIndex));
|
|
5403
|
+
}
|
|
5404
|
+
pendingHeight(page, capacity, bodyUsed, columnIndex = 0) {
|
|
5405
|
+
return this.flow.pendingHeight(this.view(page, columnIndex), capacity, bodyUsed);
|
|
5406
|
+
}
|
|
5407
|
+
blockedByEarlierColumn(_page, _capacity, _bodyBottom) {
|
|
5408
|
+
return false;
|
|
5409
|
+
}
|
|
5410
|
+
commit(blockId, page, available, columnIndex = 0) {
|
|
5411
|
+
if (this.flow.commit(blockId, this.view(page, columnIndex), available)) this.sync(page);
|
|
5412
|
+
}
|
|
5413
|
+
resume(page, capacity, columnIndex) {
|
|
5414
|
+
if (!this.flow.hasContinuation) return;
|
|
5415
|
+
const indexes = columnIndex === void 0 ? page.columns.map((_, index) => index) : [columnIndex];
|
|
5416
|
+
for (const index of indexes) {
|
|
5417
|
+
if (!this.flow.hasContinuation) break;
|
|
5418
|
+
const view = this.view(page, index);
|
|
5419
|
+
if (view.footnotes?.length) continue;
|
|
5420
|
+
this.flow.resume(view, capacity, void 0, view.widthPx);
|
|
5421
|
+
}
|
|
5422
|
+
this.sync(page);
|
|
5423
|
+
}
|
|
5424
|
+
};
|
|
5425
|
+
|
|
5426
|
+
// docx/layout/page-cursor.ts
|
|
4971
5427
|
var PageCursor = class {
|
|
4972
|
-
constructor(pages, geometry, columns, sectionIndex = 0, continueAt, balance) {
|
|
5428
|
+
constructor(pages, geometry, columns, sectionIndex = 0, continueAt, balance, report = () => {
|
|
5429
|
+
}, separator, noteColumns, reflow, legacyFootnoteColumns = false) {
|
|
4973
5430
|
this.balance = balance;
|
|
5431
|
+
this.noteColumns = noteColumns;
|
|
5432
|
+
this.legacyFootnoteColumns = legacyFootnoteColumns;
|
|
5433
|
+
this.footnotes = legacyFootnoteColumns ? new LegacyFootnoteFlow(report, separator, reflow) : new FootnoteFlow(report, separator, noteColumns, reflow);
|
|
4974
5434
|
this.sectionIndex = sectionIndex;
|
|
4975
5435
|
this.pages = pages;
|
|
4976
5436
|
this.geometry = geometry;
|
|
@@ -4994,6 +5454,8 @@ var PageCursor = class {
|
|
|
4994
5454
|
}
|
|
4995
5455
|
}
|
|
4996
5456
|
balance;
|
|
5457
|
+
noteColumns;
|
|
5458
|
+
legacyFootnoteColumns;
|
|
4997
5459
|
pages;
|
|
4998
5460
|
equalColumnWidthPx;
|
|
4999
5461
|
activeColumns = [];
|
|
@@ -5004,10 +5466,7 @@ var PageCursor = class {
|
|
|
5004
5466
|
yPx = 0;
|
|
5005
5467
|
sectionIndex;
|
|
5006
5468
|
pageInSection = 0;
|
|
5007
|
-
|
|
5008
|
-
reservedPx = 0;
|
|
5009
|
-
/** Footnotes of the paragraph about to be placed; they join the page its first box lands on. */
|
|
5010
|
-
pending;
|
|
5469
|
+
footnotes;
|
|
5011
5470
|
columnBoxes(offsetPx = 0) {
|
|
5012
5471
|
const columnBoxes = [];
|
|
5013
5472
|
let xPx = offsetPx;
|
|
@@ -5042,7 +5501,7 @@ var PageCursor = class {
|
|
|
5042
5501
|
this.columnIndex = 0;
|
|
5043
5502
|
this.columnTopPx = 0;
|
|
5044
5503
|
this.yPx = 0;
|
|
5045
|
-
this.
|
|
5504
|
+
this.footnotes.resume(this.page, this.physicalColumnHeightPx);
|
|
5046
5505
|
}
|
|
5047
5506
|
get page() {
|
|
5048
5507
|
return this.pages.at(-1);
|
|
@@ -5050,6 +5509,9 @@ var PageCursor = class {
|
|
|
5050
5509
|
get column() {
|
|
5051
5510
|
return expectDefined(this.activeColumns[this.columnIndex], "current page column");
|
|
5052
5511
|
}
|
|
5512
|
+
get noteColumnIndex() {
|
|
5513
|
+
return this.legacyFootnoteColumns ? this.page.columns.indexOf(this.column) : this.columnIndex;
|
|
5514
|
+
}
|
|
5053
5515
|
get columnWidthPx() {
|
|
5054
5516
|
return this.column.widthPx;
|
|
5055
5517
|
}
|
|
@@ -5064,6 +5526,9 @@ var PageCursor = class {
|
|
|
5064
5526
|
endBalance() {
|
|
5065
5527
|
this.balance = void 0;
|
|
5066
5528
|
}
|
|
5529
|
+
get footnoteWidthPx() {
|
|
5530
|
+
return this.noteColumns ? footnoteColumns(this.page, this.noteColumns)[0].widthPx : this.columnWidthPx;
|
|
5531
|
+
}
|
|
5067
5532
|
get y() {
|
|
5068
5533
|
return this.yPx;
|
|
5069
5534
|
}
|
|
@@ -5087,7 +5552,7 @@ var PageCursor = class {
|
|
|
5087
5552
|
);
|
|
5088
5553
|
}
|
|
5089
5554
|
remainingHeightPx() {
|
|
5090
|
-
return this.columnHeightPx - (this.yPx - this.columnTopPx) - this.
|
|
5555
|
+
return this.columnHeightPx - (this.yPx - this.columnTopPx) - this.footnotes.reserved(this.page, this.noteColumnIndex) - this.pendingHeightPx();
|
|
5091
5556
|
}
|
|
5092
5557
|
/** Close this section's column band before another section shares its page. */
|
|
5093
5558
|
finishBand() {
|
|
@@ -5106,16 +5571,41 @@ var PageCursor = class {
|
|
|
5106
5571
|
return bottom;
|
|
5107
5572
|
}
|
|
5108
5573
|
pendingHeightPx() {
|
|
5109
|
-
|
|
5110
|
-
|
|
5574
|
+
return this.footnotes.pendingHeight(
|
|
5575
|
+
this.page,
|
|
5576
|
+
this.columnHeightPx,
|
|
5577
|
+
this.usedColumnHeightPx,
|
|
5578
|
+
this.noteColumnIndex
|
|
5579
|
+
);
|
|
5111
5580
|
}
|
|
5112
5581
|
/**
|
|
5113
5582
|
* Reserves room for a paragraph's footnotes on whichever page its first box is placed, so the
|
|
5114
5583
|
* notes print on the same page as their reference, as Word does.
|
|
5115
5584
|
*/
|
|
5116
|
-
holdFootnotes(blockId, notes) {
|
|
5117
|
-
|
|
5118
|
-
|
|
5585
|
+
holdFootnotes(blockId, notes, bodyMinimum = 0, freshBodyMinimum = bodyMinimum) {
|
|
5586
|
+
this.footnotes.hold(blockId, notes, bodyMinimum, freshBodyMinimum);
|
|
5587
|
+
}
|
|
5588
|
+
/** Finish long notes even when the section has no more body paragraphs. */
|
|
5589
|
+
finishFootnotes() {
|
|
5590
|
+
while (this.footnotes.hasContinuation) {
|
|
5591
|
+
if (this.legacyFootnoteColumns) this.newColumn();
|
|
5592
|
+
else this.newPage();
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5595
|
+
/** Continued notes can occupy an otherwise empty page, before body/table content starts. */
|
|
5596
|
+
advancePastFootnotes(minimumBodyHeight) {
|
|
5597
|
+
while (this.page.footnotes?.length && this.atColumnTop && this.remainingHeightPx() < minimumBodyHeight - 1e-6 || this.columnIndex > 0 && this.footnotes.blockedByEarlierColumn(
|
|
5598
|
+
this.page,
|
|
5599
|
+
this.columnHeightPx,
|
|
5600
|
+
Math.max(
|
|
5601
|
+
0,
|
|
5602
|
+
...this.activeColumns.slice(0, this.columnIndex).flatMap(
|
|
5603
|
+
(column) => column.blocks.map((block) => block.yPx + block.heightPx - this.columnTopPx)
|
|
5604
|
+
)
|
|
5605
|
+
)
|
|
5606
|
+
))
|
|
5607
|
+
if (this.legacyFootnoteColumns) this.newColumn();
|
|
5608
|
+
else this.newPage();
|
|
5119
5609
|
}
|
|
5120
5610
|
newPage() {
|
|
5121
5611
|
this.pushPage();
|
|
@@ -5125,6 +5615,8 @@ var PageCursor = class {
|
|
|
5125
5615
|
if (this.columnIndex + 1 < this.columns.count) {
|
|
5126
5616
|
this.columnIndex++;
|
|
5127
5617
|
this.yPx = this.columnTopPx;
|
|
5618
|
+
if (this.legacyFootnoteColumns)
|
|
5619
|
+
this.footnotes.resume(this.page, this.physicalColumnHeightPx, this.noteColumnIndex);
|
|
5128
5620
|
} else {
|
|
5129
5621
|
this.pushPage();
|
|
5130
5622
|
}
|
|
@@ -5138,25 +5630,54 @@ var PageCursor = class {
|
|
|
5138
5630
|
box.yPx = this.yPx;
|
|
5139
5631
|
this.column.blocks.push(box);
|
|
5140
5632
|
this.yPx += advancePx;
|
|
5141
|
-
|
|
5142
|
-
this.
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
this.
|
|
5150
|
-
|
|
5633
|
+
const bodyBottom = this.legacyFootnoteColumns ? this.yPx : Math.max(
|
|
5634
|
+
this.yPx,
|
|
5635
|
+
...this.activeColumns.flatMap(
|
|
5636
|
+
(column) => column.blocks.map((block) => block.yPx + block.heightPx)
|
|
5637
|
+
)
|
|
5638
|
+
);
|
|
5639
|
+
this.footnotes.commit(
|
|
5640
|
+
box.blockId,
|
|
5641
|
+
this.page,
|
|
5642
|
+
this.columnHeightPx - (bodyBottom - this.columnTopPx) - this.footnotes.reserved(this.page, this.noteColumnIndex),
|
|
5643
|
+
this.noteColumnIndex
|
|
5644
|
+
);
|
|
5151
5645
|
}
|
|
5152
5646
|
};
|
|
5153
5647
|
|
|
5154
5648
|
// docx/layout/flow-paragraph.ts
|
|
5155
5649
|
function placeParagraph(cursor, placement, note) {
|
|
5156
5650
|
const { paragraph, spacingBeforePx, requiredTogetherPx, reflow } = placement;
|
|
5157
|
-
|
|
5651
|
+
const trailingBreakLine = (result) => {
|
|
5652
|
+
const last = result.lines.at(-1);
|
|
5653
|
+
if (!placement.trimLeadingColumnBreak || !last || !result.columnBreakAfterLine.has(result.lines.length - 1))
|
|
5654
|
+
return result;
|
|
5655
|
+
return {
|
|
5656
|
+
...result,
|
|
5657
|
+
contentHeightPx: result.contentHeightPx + last.heightPx,
|
|
5658
|
+
lines: [
|
|
5659
|
+
...result.lines,
|
|
5660
|
+
{
|
|
5661
|
+
...last,
|
|
5662
|
+
yPx: last.yPx + last.heightPx,
|
|
5663
|
+
fragments: [],
|
|
5664
|
+
sourceStart: last.sourceEnd,
|
|
5665
|
+
sourceEnd: last.sourceEnd
|
|
5666
|
+
}
|
|
5667
|
+
]
|
|
5668
|
+
};
|
|
5669
|
+
};
|
|
5670
|
+
let layout = trailingBreakLine(placement.layout);
|
|
5158
5671
|
let width = cursor.columnWidthPx;
|
|
5159
5672
|
if (paragraph.pageBreakBefore && cursor.hasPageContent) cursor.newPage();
|
|
5673
|
+
if (requiredTogetherPx > 0 && placement.footnotes) {
|
|
5674
|
+
cursor.holdFootnotes(
|
|
5675
|
+
paragraph.id,
|
|
5676
|
+
placement.footnotes(layout.lines, true),
|
|
5677
|
+
requiredTogetherPx,
|
|
5678
|
+
layout.lines[0]?.heightPx ?? 0
|
|
5679
|
+
);
|
|
5680
|
+
}
|
|
5160
5681
|
if (requiredTogetherPx > 0 && requiredTogetherPx <= cursor.columnHeightPx && requiredTogetherPx > cursor.remainingHeightPx() && !cursor.atColumnTop) {
|
|
5161
5682
|
cursor.newColumn();
|
|
5162
5683
|
}
|
|
@@ -5164,9 +5685,23 @@ function placeParagraph(cursor, placement, note) {
|
|
|
5164
5685
|
let lineCursor = 0;
|
|
5165
5686
|
let nextToken = 0;
|
|
5166
5687
|
let firstSegment = true;
|
|
5688
|
+
const lineHeight = (line2, index) => placement.trimLeadingColumnBreak && layout.columnBreakAfterLine.has(index) && line2.fragments.every((fragment) => !fragment.text && !fragment.object) ? 0 : line2.heightPx;
|
|
5689
|
+
const placedNotes = /* @__PURE__ */ new Set();
|
|
5690
|
+
const notesFor = (lines) => (placement.footnotes?.(lines, firstSegment) ?? []).filter((item) => !placedNotes.has(item.id));
|
|
5691
|
+
const hold = (lines, bodyMinimum) => {
|
|
5692
|
+
const notes = notesFor(lines);
|
|
5693
|
+
if (placement.footnotes)
|
|
5694
|
+
cursor.holdFootnotes(
|
|
5695
|
+
paragraph.id,
|
|
5696
|
+
notes,
|
|
5697
|
+
bodyMinimum,
|
|
5698
|
+
Math.max(0, ...lines.map((line2) => line2.heightPx))
|
|
5699
|
+
);
|
|
5700
|
+
return notes;
|
|
5701
|
+
};
|
|
5167
5702
|
const reflowIfNeeded = () => {
|
|
5168
5703
|
if (!reflow || cursor.columnWidthPx === width) return;
|
|
5169
|
-
layout = reflow(nextToken);
|
|
5704
|
+
layout = trailingBreakLine(reflow(nextToken));
|
|
5170
5705
|
lineCursor = 0;
|
|
5171
5706
|
width = cursor.columnWidthPx;
|
|
5172
5707
|
};
|
|
@@ -5180,15 +5715,27 @@ function placeParagraph(cursor, placement, note) {
|
|
|
5180
5715
|
}
|
|
5181
5716
|
while (lineCursor < layout.lines.length) {
|
|
5182
5717
|
reflowIfNeeded();
|
|
5183
|
-
|
|
5718
|
+
hold(
|
|
5719
|
+
layout.lines.slice(lineCursor, lineCursor + 1),
|
|
5720
|
+
layout.lines[lineCursor] ? lineHeight(layout.lines[lineCursor], lineCursor) : 0
|
|
5721
|
+
);
|
|
5722
|
+
cursor.advancePastFootnotes(
|
|
5723
|
+
layout.lines[lineCursor] ? lineHeight(layout.lines[lineCursor], lineCursor) : 0
|
|
5724
|
+
);
|
|
5725
|
+
reflowIfNeeded();
|
|
5184
5726
|
let cumulative = 0;
|
|
5185
5727
|
let end = lineCursor;
|
|
5186
5728
|
let forced;
|
|
5187
5729
|
for (let i = lineCursor; i < layout.lines.length; i++) {
|
|
5188
5730
|
const line2 = expectDefined(layout.lines[i], "paragraph line index");
|
|
5189
5731
|
const gap = i === lineCursor && !firstSegment ? 0 : line2.gapBeforePx ?? 0;
|
|
5190
|
-
const height = line2
|
|
5191
|
-
|
|
5732
|
+
const height = lineHeight(line2, i) + gap;
|
|
5733
|
+
hold(
|
|
5734
|
+
layout.lines.slice(lineCursor, i + 1),
|
|
5735
|
+
cumulative + height + (firstSegment ? spacingBeforePx : 0)
|
|
5736
|
+
);
|
|
5737
|
+
const budget = cursor.remainingHeightPx() - (firstSegment ? spacingBeforePx : 0);
|
|
5738
|
+
if (cumulative + height > budget + 1e-6 && (end > lineCursor || !cursor.atColumnTop)) break;
|
|
5192
5739
|
cumulative += height;
|
|
5193
5740
|
end = i + 1;
|
|
5194
5741
|
if (layout.pageBreakAfterLine.has(i)) {
|
|
@@ -5213,9 +5760,17 @@ function placeParagraph(cursor, placement, note) {
|
|
|
5213
5760
|
);
|
|
5214
5761
|
placedCount = Math.max(1, end - lineCursor);
|
|
5215
5762
|
}
|
|
5763
|
+
const committedNotes = hold(
|
|
5764
|
+
layout.lines.slice(lineCursor, lineCursor + placedCount),
|
|
5765
|
+
cumulative + (firstSegment ? spacingBeforePx : 0)
|
|
5766
|
+
);
|
|
5216
5767
|
const first3 = expectDefined(layout.lines[lineCursor], "first line of paragraph segment");
|
|
5217
5768
|
const origin = first3.yPx - (firstSegment ? (first3.gapBeforePx ?? 0) + layout.insetTopPx : 0);
|
|
5218
|
-
const segmentLines = layout.lines.slice(lineCursor, lineCursor + placedCount).map((line2) => ({
|
|
5769
|
+
const segmentLines = layout.lines.slice(lineCursor, lineCursor + placedCount).map((line2, index) => ({
|
|
5770
|
+
...line2,
|
|
5771
|
+
yPx: line2.yPx - origin,
|
|
5772
|
+
heightPx: lineHeight(line2, lineCursor + index)
|
|
5773
|
+
}));
|
|
5219
5774
|
const isFinal = lineCursor + placedCount >= layout.lines.length;
|
|
5220
5775
|
const lastLine = segmentLines.at(-1);
|
|
5221
5776
|
const isLastSegment = lineCursor + placedCount >= layout.lines.length;
|
|
@@ -5230,6 +5785,7 @@ function placeParagraph(cursor, placement, note) {
|
|
|
5230
5785
|
};
|
|
5231
5786
|
const advance = (firstSegment ? spacingBeforePx : 0) + segmentHeight + (isFinal ? layout.spacingAfterPx : 0);
|
|
5232
5787
|
cursor.place(box, advance);
|
|
5788
|
+
for (const item of committedNotes) placedNotes.add(item.id);
|
|
5233
5789
|
nextToken = layout.lines[lineCursor + placedCount - 1]?.nextToken ?? nextToken;
|
|
5234
5790
|
lineCursor += placedCount;
|
|
5235
5791
|
firstSegment = false;
|
|
@@ -5239,8 +5795,170 @@ function placeParagraph(cursor, placement, note) {
|
|
|
5239
5795
|
}
|
|
5240
5796
|
}
|
|
5241
5797
|
|
|
5798
|
+
// docx/layout/table-footnotes.ts
|
|
5799
|
+
function prefix(row, cut, cellCuts) {
|
|
5800
|
+
const cells = row.cells.map((cell, index) => {
|
|
5801
|
+
const contentCut = (cellCuts?.[index] ?? cut) - (row.cellPadding?.[index]?.bottom ?? 0);
|
|
5802
|
+
const boxes = [];
|
|
5803
|
+
for (const box of cell) {
|
|
5804
|
+
if (box.yPx >= contentCut + 1e-6) break;
|
|
5805
|
+
if (box.yPx + box.heightPx <= contentCut + 1e-6) {
|
|
5806
|
+
boxes.push(box);
|
|
5807
|
+
continue;
|
|
5808
|
+
}
|
|
5809
|
+
const lines = [];
|
|
5810
|
+
for (const line2 of box.lines) {
|
|
5811
|
+
if (box.yPx + line2.yPx + line2.heightPx > contentCut + 1e-6) break;
|
|
5812
|
+
lines.push(line2);
|
|
5813
|
+
}
|
|
5814
|
+
if (lines.length)
|
|
5815
|
+
boxes.push({ ...box, lines, heightPx: lines.at(-1).yPx + lines.at(-1).heightPx });
|
|
5816
|
+
continue;
|
|
5817
|
+
}
|
|
5818
|
+
return boxes;
|
|
5819
|
+
});
|
|
5820
|
+
if (cells.every(
|
|
5821
|
+
(cell, index) => cell.length === row.cells[index].length && cell.every(
|
|
5822
|
+
(box, boxIndex) => box.lines.length === row.cells[index][boxIndex].lines.length
|
|
5823
|
+
)
|
|
5824
|
+
))
|
|
5825
|
+
return row;
|
|
5826
|
+
return {
|
|
5827
|
+
...row,
|
|
5828
|
+
cells,
|
|
5829
|
+
heightPx: Math.max(
|
|
5830
|
+
0,
|
|
5831
|
+
...cells.flatMap(
|
|
5832
|
+
(cell, index) => cell.map((box) => box.yPx + box.heightPx + (row.cellPadding?.[index]?.bottom ?? 0))
|
|
5833
|
+
)
|
|
5834
|
+
)
|
|
5835
|
+
};
|
|
5836
|
+
}
|
|
5837
|
+
var TableFootnotes = class {
|
|
5838
|
+
constructor(cursor, table, height, resolve) {
|
|
5839
|
+
this.cursor = cursor;
|
|
5840
|
+
this.table = table;
|
|
5841
|
+
this.height = height;
|
|
5842
|
+
this.resolve = resolve;
|
|
5843
|
+
for (const row of table.rows)
|
|
5844
|
+
for (const cell of row.cells)
|
|
5845
|
+
for (const paragraph of cellParagraphs(cell))
|
|
5846
|
+
if (paragraph.footnotes?.length) this.paragraphs.set(paragraph.id, paragraph);
|
|
5847
|
+
}
|
|
5848
|
+
cursor;
|
|
5849
|
+
table;
|
|
5850
|
+
height;
|
|
5851
|
+
resolve;
|
|
5852
|
+
paragraphs = /* @__PURE__ */ new Map();
|
|
5853
|
+
placed = /* @__PURE__ */ new Set();
|
|
5854
|
+
fragment = /* @__PURE__ */ new Map();
|
|
5855
|
+
references(row) {
|
|
5856
|
+
const refs = /* @__PURE__ */ new Map();
|
|
5857
|
+
for (const cell of row.cells)
|
|
5858
|
+
for (const box of cell) {
|
|
5859
|
+
const source = this.paragraphs.get(box.blockId);
|
|
5860
|
+
if (!source) continue;
|
|
5861
|
+
for (const note of this.resolve(
|
|
5862
|
+
source,
|
|
5863
|
+
box.lines,
|
|
5864
|
+
(box.lines[0]?.sourceStart ?? 0) === 0
|
|
5865
|
+
)) {
|
|
5866
|
+
if (this.placed.has(note.id)) continue;
|
|
5867
|
+
const line2 = box.lines.find(
|
|
5868
|
+
(line3) => line3.fragments.some(
|
|
5869
|
+
(fragment) => source.runs[fragment.runIndex]?.footnoteReferenceId === note.id
|
|
5870
|
+
)
|
|
5871
|
+
) ?? box.lines[0];
|
|
5872
|
+
const bottom = Math.min(
|
|
5873
|
+
row.heightPx,
|
|
5874
|
+
box.yPx + (line2?.yPx ?? 0) + (line2?.heightPx ?? box.heightPx)
|
|
5875
|
+
);
|
|
5876
|
+
const prior = refs.get(note.id);
|
|
5877
|
+
if (!prior || bottom < prior.bottom) refs.set(note.id, { note, bottom });
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
return [...refs.values()];
|
|
5881
|
+
}
|
|
5882
|
+
hold(refs, minimumBody = 0) {
|
|
5883
|
+
const referenceBottom = Math.max(0, ...[...refs.values()].map((ref) => ref.bottom));
|
|
5884
|
+
const bodyHeight = Math.max(referenceBottom, minimumBody);
|
|
5885
|
+
this.cursor.holdFootnotes(
|
|
5886
|
+
this.table.id,
|
|
5887
|
+
[...refs.values()].map((ref) => ref.note),
|
|
5888
|
+
bodyHeight,
|
|
5889
|
+
this.cursor.usedColumnHeightPx + referenceBottom
|
|
5890
|
+
);
|
|
5891
|
+
}
|
|
5892
|
+
holdCandidate(row) {
|
|
5893
|
+
const refs = new Map(this.fragment);
|
|
5894
|
+
for (const ref of this.references(row))
|
|
5895
|
+
if (!refs.has(ref.note.id))
|
|
5896
|
+
refs.set(ref.note.id, { ...ref, bottom: this.height() + ref.bottom });
|
|
5897
|
+
const referenceBottom = Math.max(0, ...[...refs.values()].map((ref) => ref.bottom));
|
|
5898
|
+
const contentBottom = this.height() + Math.max(0, ...row.cells.flatMap((cell) => cell.map((box) => box.yPx + box.heightPx)));
|
|
5899
|
+
const paddingBottom = Math.max(0, ...(row.cellPadding ?? []).map((padding) => padding.bottom));
|
|
5900
|
+
this.hold(
|
|
5901
|
+
refs,
|
|
5902
|
+
contentBottom <= referenceBottom + 1e-6 ? this.height() + row.heightPx : referenceBottom + paddingBottom
|
|
5903
|
+
);
|
|
5904
|
+
}
|
|
5905
|
+
/** Largest complete prefix that keeps each new marker with available note content. */
|
|
5906
|
+
choose(row, atomic) {
|
|
5907
|
+
this.cursor.holdFootnotes(this.table.id, [], 0);
|
|
5908
|
+
const available = this.cursor.remainingHeightPx() - this.height();
|
|
5909
|
+
if (row.heightPx <= available + 1e-6) {
|
|
5910
|
+
this.holdCandidate(row);
|
|
5911
|
+
if (row.heightPx <= this.cursor.remainingHeightPx() - this.height() + 1e-6)
|
|
5912
|
+
return { layout: row, cut: row.heightPx };
|
|
5913
|
+
}
|
|
5914
|
+
if (!atomic) {
|
|
5915
|
+
const cuts = /* @__PURE__ */ new Set();
|
|
5916
|
+
for (const [index, cell] of row.cells.entries())
|
|
5917
|
+
for (const box of cell) {
|
|
5918
|
+
if (box.yPx > available + 1e-6) break;
|
|
5919
|
+
for (const line2 of box.lines) {
|
|
5920
|
+
const bottom = box.yPx + line2.yPx + line2.heightPx + (row.cellPadding?.[index]?.bottom ?? 0);
|
|
5921
|
+
if (bottom > available + 1e-6) break;
|
|
5922
|
+
if (bottom > 0) cuts.add(bottom);
|
|
5923
|
+
}
|
|
5924
|
+
}
|
|
5925
|
+
for (const cut of [...cuts].sort((a, b) => b - a)) {
|
|
5926
|
+
const candidate = prefix(row, cut);
|
|
5927
|
+
this.holdCandidate(candidate);
|
|
5928
|
+
if (candidate.heightPx <= this.cursor.remainingHeightPx() - this.height() + 1e-6) {
|
|
5929
|
+
const space = this.cursor.remainingHeightPx() - this.height();
|
|
5930
|
+
const cellCuts = row.cells.map(
|
|
5931
|
+
(cell) => cell.some((box) => this.paragraphs.has(box.blockId)) ? cut : space
|
|
5932
|
+
);
|
|
5933
|
+
const expanded = prefix(row, cut, cellCuts);
|
|
5934
|
+
this.holdCandidate(expanded);
|
|
5935
|
+
if (expanded.heightPx <= this.cursor.remainingHeightPx() - this.height() + 1e-6)
|
|
5936
|
+
return { layout: expanded, cut, cellCuts };
|
|
5937
|
+
this.holdCandidate(candidate);
|
|
5938
|
+
return { layout: candidate, cut };
|
|
5939
|
+
}
|
|
5940
|
+
}
|
|
5941
|
+
}
|
|
5942
|
+
this.holdFragment();
|
|
5943
|
+
return void 0;
|
|
5944
|
+
}
|
|
5945
|
+
add(row, repeated) {
|
|
5946
|
+
if (repeated) return;
|
|
5947
|
+
for (const ref of this.references(row))
|
|
5948
|
+
if (!this.fragment.has(ref.note.id))
|
|
5949
|
+
this.fragment.set(ref.note.id, { ...ref, bottom: this.height() + ref.bottom });
|
|
5950
|
+
}
|
|
5951
|
+
holdFragment() {
|
|
5952
|
+
this.hold(this.fragment);
|
|
5953
|
+
}
|
|
5954
|
+
flushed() {
|
|
5955
|
+
for (const id of this.fragment.keys()) this.placed.add(id);
|
|
5956
|
+
this.fragment.clear();
|
|
5957
|
+
}
|
|
5958
|
+
};
|
|
5959
|
+
|
|
5242
5960
|
// docx/layout/flow-table.ts
|
|
5243
|
-
function placeTable(cursor, table, measurer, note) {
|
|
5961
|
+
function placeTable(cursor, table, measurer, note, resolveFootnotes) {
|
|
5244
5962
|
const firstBodyRow = table.rows.findIndex((row) => !row.isHeader);
|
|
5245
5963
|
const headerRows = table.rows.slice(0, firstBodyRow < 0 ? table.rows.length : firstBodyRow);
|
|
5246
5964
|
const xPosition = () => {
|
|
@@ -5249,7 +5967,9 @@ function placeTable(cursor, table, measurer, note) {
|
|
|
5249
5967
|
};
|
|
5250
5968
|
let fragmentRows = [];
|
|
5251
5969
|
let fragmentHeight = 0;
|
|
5970
|
+
const footnotes = resolveFootnotes ? new TableFootnotes(cursor, table, () => fragmentHeight, resolveFootnotes) : void 0;
|
|
5252
5971
|
const toRowBox = (layout, repeated) => {
|
|
5972
|
+
footnotes?.add(layout, repeated);
|
|
5253
5973
|
const box = {
|
|
5254
5974
|
yPx: fragmentHeight,
|
|
5255
5975
|
heightPx: layout.heightPx,
|
|
@@ -5261,7 +5981,10 @@ function placeTable(cursor, table, measurer, note) {
|
|
|
5261
5981
|
return box;
|
|
5262
5982
|
};
|
|
5263
5983
|
function flushFragment() {
|
|
5264
|
-
if (!fragmentRows.length)
|
|
5984
|
+
if (!fragmentRows.length) {
|
|
5985
|
+
footnotes?.holdFragment();
|
|
5986
|
+
return;
|
|
5987
|
+
}
|
|
5265
5988
|
const box = {
|
|
5266
5989
|
kind: "table",
|
|
5267
5990
|
blockId: table.id,
|
|
@@ -5270,19 +5993,89 @@ function placeTable(cursor, table, measurer, note) {
|
|
|
5270
5993
|
heightPx: fragmentHeight,
|
|
5271
5994
|
rows: fragmentRows
|
|
5272
5995
|
};
|
|
5996
|
+
footnotes?.holdFragment();
|
|
5273
5997
|
cursor.place(box, fragmentHeight);
|
|
5998
|
+
footnotes?.flushed();
|
|
5274
5999
|
fragmentRows = [];
|
|
5275
6000
|
fragmentHeight = 0;
|
|
5276
6001
|
}
|
|
5277
6002
|
function startNewFragment() {
|
|
5278
6003
|
flushFragment();
|
|
5279
6004
|
cursor.newColumn();
|
|
6005
|
+
addHeaders();
|
|
6006
|
+
}
|
|
6007
|
+
function addHeaders() {
|
|
5280
6008
|
for (const header of headerRows)
|
|
5281
6009
|
fragmentRows.push(toRowBox(layoutRow(header, cursor.columnWidthPx, measurer, note), true));
|
|
5282
6010
|
}
|
|
5283
6011
|
function placeRow(row, initial, cantSplit) {
|
|
5284
6012
|
let remainingRow = initial;
|
|
5285
6013
|
while (remainingRow) {
|
|
6014
|
+
const minimum = cantSplit ? Math.min(remainingRow.heightPx, cursor.columnHeightPx) : Math.min(
|
|
6015
|
+
...remainingRow.cells.flatMap(
|
|
6016
|
+
(cell) => cell.map(
|
|
6017
|
+
(paragraph) => paragraph.yPx + (paragraph.lines[0]?.yPx ?? 0) + (paragraph.lines[0]?.heightPx ?? 0)
|
|
6018
|
+
)
|
|
6019
|
+
)
|
|
6020
|
+
);
|
|
6021
|
+
if (fragmentRows.every((item) => item.repeated)) {
|
|
6022
|
+
const width = cursor.columnWidthPx;
|
|
6023
|
+
cursor.advancePastFootnotes(fragmentHeight + (Number.isFinite(minimum) ? minimum : 0));
|
|
6024
|
+
if (width !== cursor.columnWidthPx) {
|
|
6025
|
+
remainingRow = layoutRow(
|
|
6026
|
+
remainingRow === initial ? row : { ...row, heightPx: 0, heightRule: "atLeast" },
|
|
6027
|
+
cursor.columnWidthPx,
|
|
6028
|
+
measurer,
|
|
6029
|
+
note,
|
|
6030
|
+
remainingRow.cells
|
|
6031
|
+
);
|
|
6032
|
+
if (fragmentRows.length) {
|
|
6033
|
+
fragmentRows = [];
|
|
6034
|
+
fragmentHeight = 0;
|
|
6035
|
+
addHeaders();
|
|
6036
|
+
}
|
|
6037
|
+
continue;
|
|
6038
|
+
}
|
|
6039
|
+
}
|
|
6040
|
+
if (footnotes) {
|
|
6041
|
+
const selected = footnotes.choose(remainingRow, cantSplit);
|
|
6042
|
+
if (selected) {
|
|
6043
|
+
if (selected.layout === remainingRow) {
|
|
6044
|
+
fragmentRows.push(toRowBox(remainingRow, false));
|
|
6045
|
+
remainingRow = null;
|
|
6046
|
+
continue;
|
|
6047
|
+
}
|
|
6048
|
+
const { before: before2, after: after2 } = splitRowAtHeight(
|
|
6049
|
+
remainingRow,
|
|
6050
|
+
selected.cut + 1e-6,
|
|
6051
|
+
selected.cellCuts?.map((cut) => cut + 1e-6)
|
|
6052
|
+
);
|
|
6053
|
+
fragmentRows.push(toRowBox(before2, false));
|
|
6054
|
+
const previousWidth2 = cursor.columnWidthPx;
|
|
6055
|
+
startNewFragment();
|
|
6056
|
+
remainingRow = after2 && previousWidth2 !== cursor.columnWidthPx ? layoutRow(
|
|
6057
|
+
{ ...row, heightPx: 0, heightRule: "atLeast" },
|
|
6058
|
+
cursor.columnWidthPx,
|
|
6059
|
+
measurer,
|
|
6060
|
+
note,
|
|
6061
|
+
after2.cells
|
|
6062
|
+
) : after2;
|
|
6063
|
+
continue;
|
|
6064
|
+
}
|
|
6065
|
+
if (fragmentRows.length || !cursor.atColumnTop) {
|
|
6066
|
+
const previousWidth2 = cursor.columnWidthPx;
|
|
6067
|
+
startNewFragment();
|
|
6068
|
+
if (previousWidth2 !== cursor.columnWidthPx)
|
|
6069
|
+
remainingRow = layoutRow(
|
|
6070
|
+
remainingRow === initial ? row : { ...row, heightPx: 0, heightRule: "atLeast" },
|
|
6071
|
+
cursor.columnWidthPx,
|
|
6072
|
+
measurer,
|
|
6073
|
+
note,
|
|
6074
|
+
remainingRow === initial ? void 0 : remainingRow.cells
|
|
6075
|
+
);
|
|
6076
|
+
continue;
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
5286
6079
|
const remaining = cursor.remainingHeightPx() - fragmentHeight;
|
|
5287
6080
|
if (remainingRow.heightPx <= remaining) {
|
|
5288
6081
|
fragmentRows.push(toRowBox(remainingRow, false));
|
|
@@ -5294,6 +6087,18 @@ function placeTable(cursor, table, measurer, note) {
|
|
|
5294
6087
|
startNewFragment();
|
|
5295
6088
|
remainingRow = layoutRow(row, cursor.columnWidthPx, measurer, note);
|
|
5296
6089
|
}
|
|
6090
|
+
const noteWidth = cursor.columnWidthPx;
|
|
6091
|
+
cursor.advancePastFootnotes(
|
|
6092
|
+
fragmentHeight + Math.min(remainingRow.heightPx, cursor.columnHeightPx)
|
|
6093
|
+
);
|
|
6094
|
+
if (noteWidth !== cursor.columnWidthPx) {
|
|
6095
|
+
remainingRow = layoutRow(row, cursor.columnWidthPx, measurer, note);
|
|
6096
|
+
if (fragmentRows.length) {
|
|
6097
|
+
fragmentRows = [];
|
|
6098
|
+
fragmentHeight = 0;
|
|
6099
|
+
addHeaders();
|
|
6100
|
+
}
|
|
6101
|
+
}
|
|
5297
6102
|
const freshRemaining = cursor.remainingHeightPx() - fragmentHeight;
|
|
5298
6103
|
if (remainingRow.heightPx > freshRemaining)
|
|
5299
6104
|
note('A table row marked "keep row together" is taller than an empty page/column.');
|
|
@@ -5324,11 +6129,37 @@ function placeTable(cursor, table, measurer, note) {
|
|
|
5324
6129
|
}
|
|
5325
6130
|
for (const row of table.rows) {
|
|
5326
6131
|
const layout = layoutRow(row, cursor.columnWidthPx, measurer, note);
|
|
5327
|
-
placeRow(
|
|
6132
|
+
placeRow(
|
|
6133
|
+
row,
|
|
6134
|
+
layout,
|
|
6135
|
+
Boolean(row.cantSplit) || headerRows.includes(row) || !!footnotes && row.heightRule === "exact"
|
|
6136
|
+
);
|
|
5328
6137
|
}
|
|
5329
6138
|
flushFragment();
|
|
5330
6139
|
}
|
|
5331
6140
|
|
|
6141
|
+
// docx/layout/reference-footnotes.ts
|
|
6142
|
+
function createReferenceFootnotes(width, measurer, report) {
|
|
6143
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6144
|
+
return (paragraph, lines, includeUnanchored) => {
|
|
6145
|
+
const selected = new Set(
|
|
6146
|
+
lines.flatMap(
|
|
6147
|
+
(line2) => line2.fragments.map((fragment) => paragraph.runs[fragment.runIndex]?.footnoteReferenceId)
|
|
6148
|
+
)
|
|
6149
|
+
);
|
|
6150
|
+
const anchored = new Set(paragraph.runs.map((run) => run.footnoteReferenceId));
|
|
6151
|
+
return (paragraph.footnotes ?? []).filter((note) => selected.has(note.id) || includeUnanchored && !anchored.has(note.id)).map((note) => {
|
|
6152
|
+
const key = `${note.id}:${width()}`;
|
|
6153
|
+
const prior = cache.get(key);
|
|
6154
|
+
if (prior) return prior;
|
|
6155
|
+
const stacked = stackParagraphs(note.paragraphs, width(), measurer, report);
|
|
6156
|
+
const box = { id: note.id, yPx: 0, heightPx: stacked.heightPx, paragraphs: stacked.boxes };
|
|
6157
|
+
cache.set(key, box);
|
|
6158
|
+
return box;
|
|
6159
|
+
});
|
|
6160
|
+
};
|
|
6161
|
+
}
|
|
6162
|
+
|
|
5332
6163
|
// docx/layout/wrap.ts
|
|
5333
6164
|
var SIDE_DISTANCE_PX = 12;
|
|
5334
6165
|
var MIN_SIDE_WIDTH_PX = 48;
|
|
@@ -5382,20 +6213,117 @@ function lineBoxesFor(exclusions, topPx, columnLeftPx, columnWidthPx) {
|
|
|
5382
6213
|
// docx/layout/section-flow.ts
|
|
5383
6214
|
var SectionFlow = class {
|
|
5384
6215
|
constructor(section, pages, measurer, note, sectionIndex = 0, exclusions, continueAt, balance) {
|
|
6216
|
+
this.section = section;
|
|
5385
6217
|
this.exclusions = exclusions;
|
|
5386
6218
|
this.balance = balance;
|
|
6219
|
+
const noteColumns = section.footnoteColumns ?? (section.modernFootnoteSeparator ? section.columns ?? { count: 1, gapPx: 0 } : void 0);
|
|
6220
|
+
if (!noteColumns && !section.legacyFootnoteColumns && (section.columns?.count ?? 1) > 1 && section.blocks.some(
|
|
6221
|
+
(block) => block.kind === "paragraph" ? !!block.footnotes?.length : block.rows.some(
|
|
6222
|
+
(row) => row.cells.some(
|
|
6223
|
+
(cell) => cellParagraphs(cell).some((paragraph) => !!paragraph.footnotes?.length)
|
|
6224
|
+
)
|
|
6225
|
+
)
|
|
6226
|
+
))
|
|
6227
|
+
note(
|
|
6228
|
+
"Multi-column footnotes use a page-wide area; native per-column footnote balancing is not yet modeled."
|
|
6229
|
+
);
|
|
6230
|
+
const sources = /* @__PURE__ */ new Map();
|
|
6231
|
+
for (const block of section.blocks) {
|
|
6232
|
+
const paragraphs = block.kind === "paragraph" ? [block] : block.rows.flatMap((row) => row.cells.flatMap(cellParagraphs));
|
|
6233
|
+
for (const paragraph of paragraphs)
|
|
6234
|
+
for (const source of paragraph.footnotes ?? []) sources.set(source.id, source);
|
|
6235
|
+
}
|
|
6236
|
+
const reflowCache = /* @__PURE__ */ new Map();
|
|
6237
|
+
const reflow = (box, width) => {
|
|
6238
|
+
const source = sources.get(box.id);
|
|
6239
|
+
if (!source) return box;
|
|
6240
|
+
const ids = new Set(box.paragraphs.map((paragraph) => paragraph.blockId));
|
|
6241
|
+
const key = JSON.stringify([box.id, width, [...ids], box.sourceTokenStarts]);
|
|
6242
|
+
const cached = reflowCache.get(key);
|
|
6243
|
+
if (cached) return { ...cached, continued: !!box.continued };
|
|
6244
|
+
const paragraphs = source.paragraphs.filter((paragraph) => ids.has(paragraph.id)).map(
|
|
6245
|
+
(paragraph) => box.sourceTokenStarts?.[paragraph.id] ? { ...paragraph, spacingBeforeTwips: NO_TWIPS } : paragraph
|
|
6246
|
+
);
|
|
6247
|
+
const stacked = stackParagraphs(
|
|
6248
|
+
paragraphs,
|
|
6249
|
+
width,
|
|
6250
|
+
measurer,
|
|
6251
|
+
note,
|
|
6252
|
+
0,
|
|
6253
|
+
new Map(Object.entries(box.sourceTokenStarts ?? {}))
|
|
6254
|
+
);
|
|
6255
|
+
const result = { ...box, yPx: 0, heightPx: stacked.heightPx, paragraphs: stacked.boxes };
|
|
6256
|
+
reflowCache.set(key, result);
|
|
6257
|
+
return result;
|
|
6258
|
+
};
|
|
5387
6259
|
this.blocks = section.blocks;
|
|
5388
6260
|
this.measurer = measurer;
|
|
5389
6261
|
this.note = note;
|
|
6262
|
+
const separatorCache = /* @__PURE__ */ new Map();
|
|
5390
6263
|
this.cursor = new PageCursor(
|
|
5391
6264
|
pages,
|
|
5392
6265
|
section.page,
|
|
5393
6266
|
section.columns ?? { count: 1, gapPx: 0 },
|
|
5394
6267
|
sectionIndex,
|
|
5395
6268
|
continueAt,
|
|
5396
|
-
balance
|
|
6269
|
+
balance,
|
|
6270
|
+
note,
|
|
6271
|
+
(page, continued) => {
|
|
6272
|
+
const paragraphs = section.footnoteSeparators?.[continued && !section.modernFootnoteSeparator ? "continuationSeparator" : "separator"];
|
|
6273
|
+
if (!paragraphs) return void 0;
|
|
6274
|
+
const width = page.widthPx - page.marginLeftPx - page.marginRightPx;
|
|
6275
|
+
const key = `${width}:${continued}`;
|
|
6276
|
+
const cached = separatorCache.get(key);
|
|
6277
|
+
if (cached) return cached;
|
|
6278
|
+
const adapted = paragraphs.map((paragraph) => {
|
|
6279
|
+
const probe = section.legacyFootnoteColumns ? layoutParagraph(
|
|
6280
|
+
{
|
|
6281
|
+
...paragraph,
|
|
6282
|
+
runs: paragraph.runs.map(
|
|
6283
|
+
(run) => run.object?.noteSeparator ? { ...run, object: { ...run.object, widthPx: 0 } } : run
|
|
6284
|
+
)
|
|
6285
|
+
},
|
|
6286
|
+
width,
|
|
6287
|
+
measurer,
|
|
6288
|
+
note
|
|
6289
|
+
) : void 0;
|
|
6290
|
+
return {
|
|
6291
|
+
...paragraph,
|
|
6292
|
+
runs: paragraph.runs.map(
|
|
6293
|
+
(run, index) => run.object?.noteSeparator ? {
|
|
6294
|
+
...run,
|
|
6295
|
+
object: {
|
|
6296
|
+
...run.object,
|
|
6297
|
+
widthPx: section.legacyFootnoteColumns ? Math.min(
|
|
6298
|
+
run.object.noteSeparator === "continuationSeparator" ? width : 192,
|
|
6299
|
+
Math.max(
|
|
6300
|
+
0,
|
|
6301
|
+
width - (probe?.lines.flatMap((line2) => line2.fragments).find(
|
|
6302
|
+
(fragment) => fragment.runIndex === index && fragment.object?.noteSeparator
|
|
6303
|
+
)?.xPx ?? 0)
|
|
6304
|
+
)
|
|
6305
|
+
) : run.object.noteSeparator === "continuationSeparator" ? width : Math.min(192, width)
|
|
6306
|
+
}
|
|
6307
|
+
} : run
|
|
6308
|
+
)
|
|
6309
|
+
};
|
|
6310
|
+
});
|
|
6311
|
+
const stacked = stackParagraphs(adapted, width, measurer, note);
|
|
6312
|
+
const result = { heightPx: stacked.heightPx, paragraphs: stacked.boxes };
|
|
6313
|
+
separatorCache.set(key, result);
|
|
6314
|
+
return result;
|
|
6315
|
+
},
|
|
6316
|
+
noteColumns,
|
|
6317
|
+
reflow,
|
|
6318
|
+
section.legacyFootnoteColumns
|
|
6319
|
+
);
|
|
6320
|
+
this.referenceFootnotes = createReferenceFootnotes(
|
|
6321
|
+
() => this.cursor.footnoteWidthPx,
|
|
6322
|
+
measurer,
|
|
6323
|
+
note
|
|
5397
6324
|
);
|
|
5398
6325
|
}
|
|
6326
|
+
section;
|
|
5399
6327
|
exclusions;
|
|
5400
6328
|
balance;
|
|
5401
6329
|
cursor;
|
|
@@ -5405,6 +6333,7 @@ var SectionFlow = class {
|
|
|
5405
6333
|
measurer;
|
|
5406
6334
|
note;
|
|
5407
6335
|
paragraphCache = /* @__PURE__ */ new Map();
|
|
6336
|
+
referenceFootnotes;
|
|
5408
6337
|
firstRowHeightCache = /* @__PURE__ */ new Map();
|
|
5409
6338
|
paragraphLayout(index) {
|
|
5410
6339
|
const key = `${index}:${this.cursor.columnWidthPx}`;
|
|
@@ -5479,7 +6408,17 @@ var SectionFlow = class {
|
|
|
5479
6408
|
for (let index = 0; index < this.blocks.length; index++) {
|
|
5480
6409
|
const block = expectDefined(this.blocks[index], "flow block index");
|
|
5481
6410
|
if (block.kind === "table") {
|
|
5482
|
-
placeTable(
|
|
6411
|
+
placeTable(
|
|
6412
|
+
this.cursor,
|
|
6413
|
+
block,
|
|
6414
|
+
this.measurer,
|
|
6415
|
+
this.note,
|
|
6416
|
+
block.rows.some(
|
|
6417
|
+
(row) => row.cells.some(
|
|
6418
|
+
(cell) => cellParagraphs(cell).some((paragraph) => paragraph.footnotes?.length)
|
|
6419
|
+
)
|
|
6420
|
+
) ? this.referenceFootnotes : void 0
|
|
6421
|
+
);
|
|
5483
6422
|
if (this.balance?.pageIndex === this.cursor.page.index && !this.cursor.columnContentFits)
|
|
5484
6423
|
this.balanceValid = false;
|
|
5485
6424
|
continue;
|
|
@@ -5487,19 +6426,7 @@ var SectionFlow = class {
|
|
|
5487
6426
|
if (block.afterTableSectionBreak) this.cursor.endBalance();
|
|
5488
6427
|
const spacingBeforePx = this.spacingBeforeFor(index);
|
|
5489
6428
|
const layout = this.wrappedLayout(index, spacingBeforePx) ?? this.paragraphLayout(index);
|
|
5490
|
-
|
|
5491
|
-
this.cursor.holdFootnotes(
|
|
5492
|
-
block.id,
|
|
5493
|
-
block.footnotes.map((note) => {
|
|
5494
|
-
const stacked = stackParagraphs(
|
|
5495
|
-
note.paragraphs,
|
|
5496
|
-
this.cursor.columnWidthPx,
|
|
5497
|
-
this.measurer,
|
|
5498
|
-
this.note
|
|
5499
|
-
);
|
|
5500
|
-
return { id: note.id, yPx: 0, heightPx: stacked.heightPx, paragraphs: stacked.boxes };
|
|
5501
|
-
})
|
|
5502
|
-
);
|
|
6429
|
+
const footnotes = (lines, includeUnanchored) => this.referenceFootnotes(block, lines, includeUnanchored);
|
|
5503
6430
|
const requiredTogetherPx = block.keepNext ? this.requiredKeepHeight(index) : block.keepLines ? spacingBeforePx + layout.contentHeightPx + layout.spacingAfterPx : 0;
|
|
5504
6431
|
if (requiredTogetherPx > this.cursor.columnHeightPx && requiredTogetherPx <= this.cursor.physicalColumnHeightPx)
|
|
5505
6432
|
this.balanceValid = false;
|
|
@@ -5508,7 +6435,9 @@ var SectionFlow = class {
|
|
|
5508
6435
|
{
|
|
5509
6436
|
paragraph: block,
|
|
5510
6437
|
layout,
|
|
6438
|
+
footnotes,
|
|
5511
6439
|
spacingBeforePx,
|
|
6440
|
+
...this.section.modernFootnoteSeparator || this.section.legacyFootnoteColumns ? { trimLeadingColumnBreak: true } : {},
|
|
5512
6441
|
requiredTogetherPx,
|
|
5513
6442
|
reflow: (token) => layoutParagraph(
|
|
5514
6443
|
block,
|
|
@@ -5524,6 +6453,7 @@ var SectionFlow = class {
|
|
|
5524
6453
|
if (this.balance?.pageIndex === this.cursor.page.index && this.cursor.usedColumnHeightPx > this.cursor.columnHeightPx)
|
|
5525
6454
|
this.balanceValid = false;
|
|
5526
6455
|
}
|
|
6456
|
+
this.cursor.finishFootnotes();
|
|
5527
6457
|
}
|
|
5528
6458
|
};
|
|
5529
6459
|
|
|
@@ -5566,8 +6496,16 @@ function insertParityBlank(pages, section) {
|
|
|
5566
6496
|
const nextNumber = pages.length + 1;
|
|
5567
6497
|
const wanted = section.break === "evenPage" ? 0 : 1;
|
|
5568
6498
|
if (nextNumber % 2 === wanted) return;
|
|
6499
|
+
const {
|
|
6500
|
+
footnotes: _footnotes,
|
|
6501
|
+
footnoteSeparator: _separator,
|
|
6502
|
+
footnoteHeightPx: _noteHeight,
|
|
6503
|
+
footnoteColumnAreas: _noteColumnAreas,
|
|
6504
|
+
floats: _floats,
|
|
6505
|
+
...geometry
|
|
6506
|
+
} = previous;
|
|
5569
6507
|
pages.push({
|
|
5570
|
-
...
|
|
6508
|
+
...geometry,
|
|
5571
6509
|
index: pages.length,
|
|
5572
6510
|
pageInSection: previous.pageInSection + 1,
|
|
5573
6511
|
columns: previous.columns.map((column) => ({ ...column, blocks: [] }))
|
|
@@ -5581,7 +6519,12 @@ function alignVertically(pages, section, note) {
|
|
|
5581
6519
|
return;
|
|
5582
6520
|
}
|
|
5583
6521
|
for (const page of pages) {
|
|
5584
|
-
const
|
|
6522
|
+
const footnoteHeight = page.footnoteColumnAreas?.length ? Math.max(
|
|
6523
|
+
...page.footnoteColumnAreas.map(
|
|
6524
|
+
(area) => area.heightPx + (area.separator?.heightPx ?? FOOTNOTE_SEPARATOR_PX)
|
|
6525
|
+
)
|
|
6526
|
+
) : page.footnotes?.length ? (page.footnoteSeparator?.heightPx ?? FOOTNOTE_SEPARATOR_PX) + (page.footnoteHeightPx ?? page.footnotes.reduce((sum, footnote) => sum + footnote.heightPx, 0)) : 0;
|
|
6527
|
+
const available = page.heightPx - page.marginTopPx - page.marginBottomPx - footnoteHeight;
|
|
5585
6528
|
const used = Math.max(
|
|
5586
6529
|
0,
|
|
5587
6530
|
...page.columns.flatMap((column) => column.blocks.map((block) => block.yPx + block.heightPx))
|
|
@@ -5774,6 +6717,11 @@ function adaptTable(table, model, adaptParagraph) {
|
|
|
5774
6717
|
const fill = cssHex(visuals.shadingFill);
|
|
5775
6718
|
return {
|
|
5776
6719
|
paragraphs: cell.paragraphs.map(adaptParagraph),
|
|
6720
|
+
...cell.sourceBlocks ? {
|
|
6721
|
+
blocks: cellSourceBlocks(cell).map(
|
|
6722
|
+
(block) => block.type === "paragraph" ? adaptParagraph(block) : adaptTable(block, model, adaptParagraph)
|
|
6723
|
+
)
|
|
6724
|
+
} : {},
|
|
5777
6725
|
...width !== void 0 ? { widthPx: width } : {},
|
|
5778
6726
|
...grid && xPx !== void 0 ? { xPx } : {},
|
|
5779
6727
|
padding,
|
|
@@ -5953,7 +6901,13 @@ function adaptDocumentModel(model, note = () => {
|
|
|
5953
6901
|
const script = formatting.verticalAlign === "superscript" || noteText !== void 0 && formatting.verticalAlign === void 0 ? "super" : formatting.verticalAlign === "subscript" ? "sub" : void 0;
|
|
5954
6902
|
const image = run.image;
|
|
5955
6903
|
if (image?.unsupported === "Text box") reportOnce(TEXT_BOX_NOTE);
|
|
5956
|
-
const object =
|
|
6904
|
+
const object = run.noteSeparator ? {
|
|
6905
|
+
partName: "",
|
|
6906
|
+
contentType: "",
|
|
6907
|
+
widthPx: 192,
|
|
6908
|
+
heightPx: 1,
|
|
6909
|
+
noteSeparator: run.noteSeparator
|
|
6910
|
+
} : image && !image.anchored ? {
|
|
5957
6911
|
partName: image.partName,
|
|
5958
6912
|
contentType: image.contentType,
|
|
5959
6913
|
widthPx: image.widthPx,
|
|
@@ -5961,8 +6915,10 @@ function adaptDocumentModel(model, note = () => {
|
|
|
5961
6915
|
...image.chart ? { chart: docxChartPaint(image.chart, image.widthPx, image.heightPx, theme) } : {}
|
|
5962
6916
|
} : void 0;
|
|
5963
6917
|
return {
|
|
6918
|
+
sourceLength: reviewSourceLength(run),
|
|
5964
6919
|
// Hidden text (`w:vanish`) takes no space when printed, as in Word by default.
|
|
5965
6920
|
text: image || formatting.vanish ? "" : formatting.caps ? text2.toUpperCase() : text2,
|
|
6921
|
+
...run.noteReference?.kind === "footnote" ? { footnoteReferenceId: run.noteReference.id } : {},
|
|
5966
6922
|
...object ? { object } : {},
|
|
5967
6923
|
...definedProps({
|
|
5968
6924
|
bold: formatting.bold,
|
|
@@ -6061,6 +7017,10 @@ function adaptDocumentModel(model, note = () => {
|
|
|
6061
7017
|
if (block.type === "paragraph") return adaptParagraph(block);
|
|
6062
7018
|
reportOnce(TABLE_ROW_NOTE);
|
|
6063
7019
|
reportOnce(VERTICAL_MERGE_NOTE);
|
|
7020
|
+
if (block.rows.some((row) => row.some((cell) => cell.nestedTables?.length)))
|
|
7021
|
+
reportOnce(
|
|
7022
|
+
"Nested tables are projected as read-only cell paragraphs in Print Layout; their borders, shading, vertical merge and repeated header geometry are not rendered."
|
|
7023
|
+
);
|
|
6064
7024
|
return adaptTable(block, model, adaptParagraph);
|
|
6065
7025
|
}
|
|
6066
7026
|
const blocks = [
|
|
@@ -6070,7 +7030,25 @@ function adaptDocumentModel(model, note = () => {
|
|
|
6070
7030
|
groupParagraphBorders(blocks, betweenBorders);
|
|
6071
7031
|
const folded = foldDropCaps(model.blocks, blocks);
|
|
6072
7032
|
if (folded.size) reportOnce(DROP_CAP_NOTE);
|
|
7033
|
+
if (Object.values(model.footnoteSeparators ?? {}).some(
|
|
7034
|
+
(note2) => note2.blocks.some((block) => block.type === "table")
|
|
7035
|
+
))
|
|
7036
|
+
reportOnce(
|
|
7037
|
+
"Tables in custom footnote separators are preserved but are not rendered in Print Layout."
|
|
7038
|
+
);
|
|
7039
|
+
const footnoteSeparators = model.footnoteSeparators ? Object.fromEntries(
|
|
7040
|
+
Object.entries(model.footnoteSeparators).map(([kind, note2]) => [
|
|
7041
|
+
kind,
|
|
7042
|
+
note2.blocks.filter((block) => block.type === "paragraph").map((paragraph) => adaptParagraph(paragraph))
|
|
7043
|
+
])
|
|
7044
|
+
) : void 0;
|
|
6073
7045
|
const sections = model.sections;
|
|
7046
|
+
const modernFootnoteSeparator = model.compatibilityMode === 15;
|
|
7047
|
+
const legacyFootnoteColumns = model.compatibilityMode === 12 || model.compatibilityMode === 14;
|
|
7048
|
+
if (!modernFootnoteSeparator && !legacyFootnoteColumns && model.sections?.some((section) => section.footnoteColumns !== void 0))
|
|
7049
|
+
reportOnce(
|
|
7050
|
+
"Footnote column settings are preserved, but this compatibility mode has not been verified against native Word; Print Layout uses the existing page-wide fallback."
|
|
7051
|
+
);
|
|
6074
7052
|
if (!sections || !sections.length) {
|
|
6075
7053
|
return {
|
|
6076
7054
|
sections: [
|
|
@@ -6083,6 +7061,9 @@ function adaptDocumentModel(model, note = () => {
|
|
|
6083
7061
|
marginBottomPx: model.page.marginBottom,
|
|
6084
7062
|
marginLeftPx: model.page.marginLeft
|
|
6085
7063
|
},
|
|
7064
|
+
...footnoteSeparators ? { footnoteSeparators } : {},
|
|
7065
|
+
...modernFootnoteSeparator ? { modernFootnoteSeparator: true } : {},
|
|
7066
|
+
...legacyFootnoteColumns ? { legacyFootnoteColumns: true } : {},
|
|
6086
7067
|
blocks: blocks.filter((block) => !folded.has(block))
|
|
6087
7068
|
}
|
|
6088
7069
|
]
|
|
@@ -6096,8 +7077,34 @@ function adaptDocumentModel(model, note = () => {
|
|
|
6096
7077
|
const end = Math.max(start, endIndex);
|
|
6097
7078
|
const slice = blocks.slice(start, end);
|
|
6098
7079
|
start = end;
|
|
7080
|
+
if (legacyFootnoteColumns && section.footnoteColumns)
|
|
7081
|
+
reportOnce(
|
|
7082
|
+
"Independent footnote column counts are preserved but ignored in measured compatibility modes 12 and 14; Print Layout attaches notes to body columns."
|
|
7083
|
+
);
|
|
7084
|
+
const footnoteWidth = twipsToPx3(section.pageWidthTwips) - twipsToPx3(section.marginLeftTwips) - twipsToPx3(section.marginRightTwips);
|
|
7085
|
+
if (modernFootnoteSeparator && section.footnoteColumns && (section.footnoteColumns > 45 || footnoteWidth <= 48 * (section.footnoteColumns - 1)))
|
|
7086
|
+
reportOnce(
|
|
7087
|
+
"Footnote columns exceeding the available page width or 45 rendered columns use one column in Print Layout; the saved count is preserved."
|
|
7088
|
+
);
|
|
6099
7089
|
const sectionStart = index === 0 ? void 0 : sectionBreak(section.type, reportOnce);
|
|
6100
7090
|
return {
|
|
7091
|
+
...footnoteSeparators ? { footnoteSeparators } : {},
|
|
7092
|
+
...modernFootnoteSeparator ? { modernFootnoteSeparator: true } : {},
|
|
7093
|
+
...legacyFootnoteColumns ? { legacyFootnoteColumns: true } : {},
|
|
7094
|
+
...section.footnoteColumns !== void 0 && modernFootnoteSeparator ? {
|
|
7095
|
+
footnoteColumns: {
|
|
7096
|
+
count: section.footnoteColumns && (section.footnoteColumns > 45 || footnoteWidth <= 48 * (section.footnoteColumns - 1)) ? 1 : Math.max(1, section.footnoteColumns || section.columns.count),
|
|
7097
|
+
gapPx: section.footnoteColumns ? 48 : twipsToPx3(section.columns.spacingTwips ?? twips(720)),
|
|
7098
|
+
...!section.footnoteColumns && !section.columns.equalWidth && section.columns.widths?.length ? {
|
|
7099
|
+
widths: section.columns.widths.map((column) => ({
|
|
7100
|
+
widthPx: twipsToPx3(column.widthTwips),
|
|
7101
|
+
gapPx: twipsToPx3(
|
|
7102
|
+
column.spacingTwips ?? section.columns.spacingTwips ?? twips(720)
|
|
7103
|
+
)
|
|
7104
|
+
}))
|
|
7105
|
+
} : {}
|
|
7106
|
+
}
|
|
7107
|
+
} : {},
|
|
6101
7108
|
page: {
|
|
6102
7109
|
widthPx: twipsToPx3(section.pageWidthTwips),
|
|
6103
7110
|
heightPx: twipsToPx3(section.pageHeightTwips),
|