reamkit 1.31.0 → 1.32.1
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/README.md +10 -0
- package/dist/esm/core/bidi/index.d.ts +10 -0
- package/dist/esm/core/bidi/index.js +18 -2
- package/dist/esm/core/converter/facade.js +10 -5
- package/dist/esm/core/converter/project.js +1 -0
- package/dist/esm/core/converter/ream.js +17 -6
- package/dist/esm/core/converter/sheet-images.d.ts +17 -0
- package/dist/esm/core/converter/sheet-images.js +33 -0
- package/dist/esm/core/crypto/offcrypto.js +56 -12
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +112 -0
- package/dist/esm/core/drawingml/chart-geometry.d.ts +36 -13
- package/dist/esm/core/drawingml/chart-geometry.js +372 -146
- package/dist/esm/core/drawingml/chart-parser.d.ts +19 -0
- package/dist/esm/core/drawingml/chart-parser.js +126 -18
- package/dist/esm/core/drawingml/colors.d.ts +6 -0
- package/dist/esm/core/drawingml/colors.js +23 -3
- package/dist/esm/core/drawingml/shape-render.d.ts +3 -1
- package/dist/esm/core/drawingml/shape-render.js +4 -2
- package/dist/esm/core/font/measure.d.ts +9 -0
- package/dist/esm/core/font/measure.js +9 -1
- package/dist/esm/core/fonts/families.js +4 -2
- package/dist/esm/core/fonts/scripts.js +4 -2
- package/dist/esm/core/ir/flow.d.ts +6 -0
- package/dist/esm/core/ir/sheet.d.ts +43 -0
- package/dist/esm/core/number-format.d.ts +40 -15
- package/dist/esm/core/number-format.js +295 -83
- package/dist/esm/core/opc/tag-scan.d.ts +15 -0
- package/dist/esm/core/opc/tag-scan.js +41 -0
- package/dist/esm/core/opc/xml-entities.js +39 -2
- package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +96 -0
- package/dist/esm/core/style-cascade/resolver.js +4 -2
- package/dist/esm/excel/column-bands.d.ts +39 -6
- package/dist/esm/excel/column-bands.js +41 -17
- package/dist/esm/excel/comments-parser.js +19 -0
- package/dist/esm/excel/conditional-format.d.ts +7 -3
- package/dist/esm/excel/conditional-format.js +77 -39
- package/dist/esm/excel/formula/context.d.ts +18 -0
- package/dist/esm/excel/formula/eval.js +51 -0
- package/dist/esm/excel/formula/functions.js +37 -14
- package/dist/esm/excel/formula/index.d.ts +2 -2
- package/dist/esm/excel/formula/lexer.d.ts +1 -1
- package/dist/esm/excel/formula/lexer.js +41 -0
- package/dist/esm/excel/formula/parser.d.ts +25 -0
- package/dist/esm/excel/formula/parser.js +95 -0
- package/dist/esm/excel/print-model.d.ts +38 -1
- package/dist/esm/excel/print-model.js +536 -83
- package/dist/esm/excel/shared-strings-parser.d.ts +9 -0
- package/dist/esm/excel/shared-strings-parser.js +11 -1
- package/dist/esm/excel/sheet-drawing.d.ts +38 -2
- package/dist/esm/excel/sheet-drawing.js +47 -13
- package/dist/esm/excel/sheet-shape-parser.d.ts +6 -2
- package/dist/esm/excel/sheet-shape-parser.js +18 -6
- package/dist/esm/excel/sheet-to-flow.d.ts +17 -0
- package/dist/esm/excel/sheet-to-flow.js +434 -47
- package/dist/esm/excel/styles-parser.d.ts +9 -0
- package/dist/esm/excel/styles-parser.js +80 -26
- package/dist/esm/excel/table-parser.js +5 -0
- package/dist/esm/excel/table-style-presets.d.ts +26 -0
- package/dist/esm/excel/table-style-presets.js +1555 -0
- package/dist/esm/excel/table-style.d.ts +13 -0
- package/dist/esm/excel/table-style.js +75 -0
- package/dist/esm/excel/tint.d.ts +10 -0
- package/dist/esm/excel/tint.js +75 -0
- package/dist/esm/excel/vml-drawing.d.ts +41 -3
- package/dist/esm/excel/vml-drawing.js +144 -11
- package/dist/esm/excel/worksheet-parser.js +89 -15
- package/dist/esm/excel/xls/biff-reader.js +10 -2
- package/dist/esm/excel/xlsx-reader.js +234 -19
- package/dist/esm/excel/xlsx-writer.js +8 -7
- package/dist/esm/html/html-writer.js +202 -20
- package/dist/esm/layout/fit-pages.d.ts +11 -0
- package/dist/esm/layout/fit-pages.js +86 -0
- package/dist/esm/layout/line-paint.d.ts +58 -0
- package/dist/esm/layout/line-paint.js +107 -0
- package/dist/esm/layout/page-doc.d.ts +51 -0
- package/dist/esm/layout/page-doc.js +141 -1
- package/dist/esm/layout/styled-layout.d.ts +7 -0
- package/dist/esm/layout/styled-layout.js +275 -52
- package/dist/esm/layout/turned-section.js +14 -2
- package/dist/esm/markdown/markdown-writer.js +75 -13
- package/dist/esm/pdf/styled-page-emitter.js +49 -71
- package/dist/esm/pdf/styled-page-renderer.js +1 -1
- package/dist/esm/pdf-reader/annot-draw.js +2 -2
- package/dist/esm/pdf-reader/annots.js +3 -1
- package/dist/esm/pdf-reader/font.js +4 -4
- package/dist/esm/pdf-reader/layout.js +1 -1
- package/dist/esm/svg/svg-text.d.ts +58 -0
- package/dist/esm/svg/svg-text.js +322 -0
- package/dist/esm/svg/svg-writer.js +135 -71
- package/dist/esm/word/document-parser.js +1 -1
- package/dist/esm/word/docx-reader.js +13 -8
- package/dist/esm/word/docx-to-pdf.js +3 -3
- package/dist/esm/word/docx-writer.js +11 -2
- package/dist/esm/word/font-table.js +89 -10
- package/dist/esm/word/numbering-parser.js +1 -1
- package/package.json +7 -3
|
@@ -3,6 +3,7 @@ import { scriptForCodepoint } from "../core/fonts/scripts.js";
|
|
|
3
3
|
import { shapeText } from "../core/font/opentype-layout.js";
|
|
4
4
|
import { hasSubstitutable, substituteLetters } from "../core/font/ligatures.js";
|
|
5
5
|
import { createFontMeasure } from "../core/font/measure.js";
|
|
6
|
+
import { pageItemBounds } from "./page-doc.js";
|
|
6
7
|
import { halfPtToPt, pt } from "../core/ir/units.js";
|
|
7
8
|
import { ResourceStore } from "../core/ir/resources.js";
|
|
8
9
|
import { headingLevelOf } from "../core/outline.js";
|
|
@@ -1841,7 +1842,7 @@ function metafileDrawing(pic, widthPt, heightPt, options, fontResources, colorCh
|
|
|
1841
1842
|
function layoutChartBlock(block, options, fontResources, contentWidth, maxHeight, imageResources) {
|
|
1842
1843
|
let widthPt = block.width;
|
|
1843
1844
|
let heightPt = block.height;
|
|
1844
|
-
if (widthPt > contentWidth && widthPt > 0) {
|
|
1845
|
+
if (widthPt > contentWidth && widthPt > 0 && !isOutOfFlowFloat(block.float)) {
|
|
1845
1846
|
const scale = contentWidth / widthPt;
|
|
1846
1847
|
widthPt = contentWidth;
|
|
1847
1848
|
heightPt *= scale;
|
|
@@ -1911,8 +1912,13 @@ function rectAtPath(x, y, w, h) {
|
|
|
1911
1912
|
return new PathBuilder().moveTo(x, y).lineTo(x + w, y).lineTo(x + w, y + h).lineTo(x, y + h).close().build();
|
|
1912
1913
|
}
|
|
1913
1914
|
var CF_ICON_SIZE_PT = 9;
|
|
1915
|
+
/** How far inside its cell Excel keeps a data bar, on every side — 2px. */
|
|
1916
|
+
var DATA_BAR_INSET_PT = 1.5;
|
|
1914
1917
|
var CF_ICON_GUTTER_PT = 12;
|
|
1915
1918
|
var CF_ICON_EMPTY_HEX = "BFBFBF";
|
|
1919
|
+
var NOTE_FLAG_PT = 4.5;
|
|
1920
|
+
var NOTE_FLAG_HEX = "FF0000";
|
|
1921
|
+
var NOTE_THREAD_HEX = "7030A0";
|
|
1916
1922
|
var DROPDOWN_BUTTON_PT = 11;
|
|
1917
1923
|
var DROPDOWN_FILL_HEX = "F0F0F0";
|
|
1918
1924
|
var DROPDOWN_BORDER_HEX = "B0B0B0";
|
|
@@ -2138,8 +2144,10 @@ function collectImageResources(body, headersFooters, options) {
|
|
|
2138
2144
|
if (el.image.resource) seen.add(el.image.resource);
|
|
2139
2145
|
} else if (el.kind === "paragraph") {
|
|
2140
2146
|
for (const run of el.paragraph.runs) if (run.inlineImage?.resource) seen.add(run.inlineImage.resource);
|
|
2141
|
-
} else if (el.kind === "table")
|
|
2142
|
-
|
|
2147
|
+
} else if (el.kind === "table") {
|
|
2148
|
+
for (const row of el.table.rows) for (const cell of row.cells) visit(cell.content);
|
|
2149
|
+
visit(el.table.overlay?.drawings ?? []);
|
|
2150
|
+
} else if (el.kind === "shape") {
|
|
2143
2151
|
const shapeImages = (sh) => {
|
|
2144
2152
|
if (sh.fill.imageResource) seen.add(sh.fill.imageResource);
|
|
2145
2153
|
if (sh.text) visit(sh.text.content);
|
|
@@ -2467,28 +2475,47 @@ function emitCellFloat(cf, ctx, frame) {
|
|
|
2467
2475
|
if (!float) return;
|
|
2468
2476
|
const x = floatXIn(frame, float, cf.block.widthPt);
|
|
2469
2477
|
const topYUp = floatTopYUpIn(frame, float, cf.block.heightPt);
|
|
2470
|
-
|
|
2471
|
-
if (cf.block.kind === "shape") emitShapeItems(cf.block, x, topYUp - cf.block.heightPt, sink, ctx.pageHeight, void 0);
|
|
2472
|
-
else {
|
|
2473
|
-
const ins = cf.block.drawInset;
|
|
2474
|
-
sink.push({
|
|
2475
|
-
type: "image",
|
|
2476
|
-
x: pt(x + (ins?.dxPt ?? 0)),
|
|
2477
|
-
y: pt(ctx.pageHeight - (topYUp - (ins?.dyTopPt ?? 0))),
|
|
2478
|
-
width: pt(ins?.widthPt ?? cf.block.widthPt),
|
|
2479
|
-
height: pt(ins?.heightPt ?? cf.block.heightPt),
|
|
2480
|
-
imageResourceName: cf.block.resourceName,
|
|
2481
|
-
...cf.block.crop ? { crop: cf.block.crop } : {},
|
|
2482
|
-
...cf.block.wash ? { wash: cf.block.wash } : {},
|
|
2483
|
-
...cf.block.alpha !== void 0 ? { alpha: cf.block.alpha } : {},
|
|
2484
|
-
...cf.block.rotationDeg ? { rotationDeg: cf.block.rotationDeg } : {},
|
|
2485
|
-
...cf.block.flipH ? { flipH: true } : {},
|
|
2486
|
-
...cf.block.flipV ? { flipV: true } : {}
|
|
2487
|
-
});
|
|
2488
|
-
if (cf.block.outline) sink.push(...pictureOutlineItems(cf.block.outline, x + (ins?.dxPt ?? 0), ctx.pageHeight - (topYUp - (ins?.dyTopPt ?? 0)), ins?.widthPt ?? cf.block.widthPt, ins?.heightPt ?? cf.block.heightPt, void 0));
|
|
2489
|
-
}
|
|
2478
|
+
emitDrawing(cf.block, x, topYUp, ctx.sink(float.behind === true, float.zOrder), ctx.pageHeight, void 0);
|
|
2490
2479
|
if (float.wrap !== "none") ctx.exclude(float, x, topYUp, cf.block.widthPt, cf.block.heightPt);
|
|
2491
2480
|
}
|
|
2481
|
+
/**
|
|
2482
|
+
* A drawing out of the flow — a picture, a shape or a chart — in the items it
|
|
2483
|
+
* paints, its top-left corner at `(x, topYUp)` in the y-up cursor frame.
|
|
2484
|
+
*
|
|
2485
|
+
* @param block The drawing, laid out.
|
|
2486
|
+
* @param x Its left edge on the page.
|
|
2487
|
+
* @param topYUp Its top, y-up.
|
|
2488
|
+
* @param sink Where its items go.
|
|
2489
|
+
* @param pageHeight The page's height, for the flip into the page frame.
|
|
2490
|
+
* @param figId The tagged-PDF Figure its items belong to, if any.
|
|
2491
|
+
*/
|
|
2492
|
+
function emitDrawing(block, x, topYUp, sink, pageHeight, figId) {
|
|
2493
|
+
if (block.kind === "shape") {
|
|
2494
|
+
emitShapeItems(block, x, topYUp - block.heightPt, sink, pageHeight, figId);
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
if (block.kind === "chart") {
|
|
2498
|
+
sink.push(...chartPageItems(block, x, topYUp - block.heightPt, pageHeight, figId));
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
const ins = block.drawInset;
|
|
2502
|
+
sink.push({
|
|
2503
|
+
type: "image",
|
|
2504
|
+
x: pt(x + (ins?.dxPt ?? 0)),
|
|
2505
|
+
y: pt(pageHeight - (topYUp - (ins?.dyTopPt ?? 0))),
|
|
2506
|
+
width: pt(ins?.widthPt ?? block.widthPt),
|
|
2507
|
+
height: pt(ins?.heightPt ?? block.heightPt),
|
|
2508
|
+
imageResourceName: block.resourceName,
|
|
2509
|
+
...block.crop ? { crop: block.crop } : {},
|
|
2510
|
+
...block.wash ? { wash: block.wash } : {},
|
|
2511
|
+
...block.alpha !== void 0 ? { alpha: block.alpha } : {},
|
|
2512
|
+
...block.rotationDeg ? { rotationDeg: block.rotationDeg } : {},
|
|
2513
|
+
...block.flipH ? { flipH: true } : {},
|
|
2514
|
+
...block.flipV ? { flipV: true } : {},
|
|
2515
|
+
...figId !== void 0 ? { structId: figId } : {}
|
|
2516
|
+
});
|
|
2517
|
+
if (block.outline) sink.push(...pictureOutlineItems(block.outline, x + (ins?.dxPt ?? 0), pageHeight - (topYUp - (ins?.dyTopPt ?? 0)), ins?.widthPt ?? block.widthPt, ins?.heightPt ?? block.heightPt, figId));
|
|
2518
|
+
}
|
|
2492
2519
|
function emitShapeItems(sh, x, bottomYUp, sink, pageHeight, figId) {
|
|
2493
2520
|
const castsUnderPicture = sh.fillImageResourceName !== void 0 ? sh.shadow : void 0;
|
|
2494
2521
|
const shadowedFill = castsUnderPicture !== void 0;
|
|
@@ -3107,17 +3134,19 @@ function collectFontResources(body, headersFooters, options, imageResources) {
|
|
|
3107
3134
|
}
|
|
3108
3135
|
addRun(run, el.paragraph);
|
|
3109
3136
|
}
|
|
3110
|
-
} else if (el.kind === "table")
|
|
3111
|
-
|
|
3112
|
-
if (
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3137
|
+
} else if (el.kind === "table") {
|
|
3138
|
+
for (const row of el.table.rows) for (const cell of row.cells) {
|
|
3139
|
+
if (cell.properties.hashOnOverflow === true) for (const inner of cell.content) {
|
|
3140
|
+
if (inner.kind !== "paragraph") continue;
|
|
3141
|
+
for (const run of inner.paragraph.runs) addRun({
|
|
3142
|
+
text: "#",
|
|
3143
|
+
properties: run.properties
|
|
3144
|
+
}, inner.paragraph);
|
|
3145
|
+
}
|
|
3146
|
+
visit(cell.content);
|
|
3117
3147
|
}
|
|
3118
|
-
visit(
|
|
3119
|
-
}
|
|
3120
|
-
else if (el.kind === "shape") {
|
|
3148
|
+
visit(el.table.overlay?.drawings ?? []);
|
|
3149
|
+
} else if (el.kind === "shape") {
|
|
3121
3150
|
const shapeText = (sh) => {
|
|
3122
3151
|
if (sh.text) visit(sh.text.content);
|
|
3123
3152
|
for (const child of sh.children ?? []) shapeText(child.shape);
|
|
@@ -3145,7 +3174,7 @@ function collectFontResources(body, headersFooters, options, imageResources) {
|
|
|
3145
3174
|
if (chart.catAxisTitle) add(chart.catAxisTitle);
|
|
3146
3175
|
if (chart.valAxisTitle) add(chart.valAxisTitle);
|
|
3147
3176
|
for (const sr of chart.series) for (const label of sr.pointLabels ?? []) add(label.text);
|
|
3148
|
-
add("0123456789
|
|
3177
|
+
add("0123456789.,-+E%() ");
|
|
3149
3178
|
if (chart.numberFormat) add(chart.numberFormat);
|
|
3150
3179
|
}
|
|
3151
3180
|
}
|
|
@@ -4417,16 +4446,18 @@ function layoutTableBlock(table, options, fontResources, imageResources, content
|
|
|
4417
4446
|
}
|
|
4418
4447
|
aboveBordersByCol = nextAbove;
|
|
4419
4448
|
const rp = table.rows[r].properties;
|
|
4420
|
-
rows.push(rp.isHeader || rp.pageBreakBefore ? {
|
|
4449
|
+
rows.push(rp.isHeader || rp.pageBreakBefore || rp.sheetTopPt !== void 0 ? {
|
|
4421
4450
|
...rl,
|
|
4422
4451
|
...rp.isHeader ? { isHeader: true } : {},
|
|
4423
|
-
...rp.pageBreakBefore ? { breakBefore: true } : {}
|
|
4452
|
+
...rp.pageBreakBefore ? { breakBefore: true } : {},
|
|
4453
|
+
...rp.sheetTopPt !== void 0 ? { sheetTopPt: rp.sheetTopPt } : {}
|
|
4424
4454
|
} : rl);
|
|
4425
4455
|
}
|
|
4426
4456
|
growRowsForMerges(rows);
|
|
4427
4457
|
const heightPt = rows.reduce((s, r) => s + r.heightPt, 0);
|
|
4428
4458
|
const totalWidthPt = columnWidthsPt.reduce((s, w) => s + w, 0);
|
|
4429
4459
|
const xOffsetPt = (table.properties.indentPt ?? 0) + tableXOffset(table.properties.alignment, contentWidth, totalWidthPt) - legacyTableOutdent(table, rows, options);
|
|
4460
|
+
const overlay = table.overlay ? layoutOverlay(table.overlay, options, fontResources, imageResources, contentWidth) : void 0;
|
|
4430
4461
|
return {
|
|
4431
4462
|
kind: "table",
|
|
4432
4463
|
...table.properties.float ? { float: table.properties.float } : {},
|
|
@@ -4434,7 +4465,40 @@ function layoutTableBlock(table, options, fontResources, imageResources, content
|
|
|
4434
4465
|
heightPt,
|
|
4435
4466
|
totalWidthPt,
|
|
4436
4467
|
colCount,
|
|
4437
|
-
xOffsetPt
|
|
4468
|
+
xOffsetPt,
|
|
4469
|
+
...overlay ? { overlay } : {}
|
|
4470
|
+
};
|
|
4471
|
+
}
|
|
4472
|
+
/**
|
|
4473
|
+
* The drawings over a spreadsheet grid (TableOverlay), each laid out as the
|
|
4474
|
+
* float it is and placed by its corner in the sheet's own frame.
|
|
4475
|
+
*
|
|
4476
|
+
* @param overlay The drawings and the part of the sheet the table prints.
|
|
4477
|
+
* @param options The render options.
|
|
4478
|
+
* @param fontResources The fonts the drawings' text is set in.
|
|
4479
|
+
* @param imageResources The pictures they show.
|
|
4480
|
+
* @param contentWidth The width between the margins.
|
|
4481
|
+
* @returns The overlay laid out, or undefined when none of it draws.
|
|
4482
|
+
*/
|
|
4483
|
+
function layoutOverlay(overlay, options, fontResources, imageResources, contentWidth) {
|
|
4484
|
+
const drawings = [];
|
|
4485
|
+
for (const el of overlay.drawings) {
|
|
4486
|
+
if (el.kind !== "image" && el.kind !== "shape" && el.kind !== "chart") continue;
|
|
4487
|
+
const block = layoutBodyElement(el, options, fontResources, imageResources, contentWidth);
|
|
4488
|
+
if (block.kind !== "image" && block.kind !== "shape" && block.kind !== "chart") continue;
|
|
4489
|
+
drawings.push({
|
|
4490
|
+
block,
|
|
4491
|
+
xPt: block.float?.posH?.offsetPt ?? 0,
|
|
4492
|
+
yPt: block.float?.posV?.offsetPt ?? 0
|
|
4493
|
+
});
|
|
4494
|
+
}
|
|
4495
|
+
if (drawings.length === 0) return void 0;
|
|
4496
|
+
return {
|
|
4497
|
+
sheetLeftPt: overlay.sheetLeftPt,
|
|
4498
|
+
widthPt: overlay.widthPt,
|
|
4499
|
+
leftPt: overlay.leftPt,
|
|
4500
|
+
mirrored: overlay.mirrored === true,
|
|
4501
|
+
drawings
|
|
4438
4502
|
};
|
|
4439
4503
|
}
|
|
4440
4504
|
/**
|
|
@@ -4684,15 +4748,19 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
|
|
|
4684
4748
|
let widthPt = 0;
|
|
4685
4749
|
for (let k = 0; k < span && colIdx + k < columnWidthsPt.length; k++) widthPt += columnWidthsPt[colIdx + k];
|
|
4686
4750
|
const paintSpan = Math.min(span, Math.max(1, cell.properties.paintColumns ?? span));
|
|
4751
|
+
const paintFrom = cell.properties.paintAtEnd === true ? span - paintSpan : 0;
|
|
4687
4752
|
let paintWidthPt = 0;
|
|
4688
|
-
|
|
4753
|
+
let paintOffsetPt = 0;
|
|
4754
|
+
for (let k = 0; k < paintFrom + paintSpan && colIdx + k < columnWidthsPt.length; k++) if (k < paintFrom) paintOffsetPt += columnWidthsPt[colIdx + k];
|
|
4755
|
+
else paintWidthPt += columnWidthsPt[colIdx + k];
|
|
4689
4756
|
columnXOffsets.push(cursorX);
|
|
4690
4757
|
const mergeRole = rowMergeRoles[cellIdx] ?? "standalone";
|
|
4691
4758
|
const leftNeighbor = cellIdx > 0 ? row.cells[cellIdx - 1].properties.borders : void 0;
|
|
4692
4759
|
const cellLayout = layoutTableCell(cell, tableProps, widthPt, options, fontResources, imageResources, rowIdx, colIdx, span, rowCount, colCount, mergeRole, leftNeighbor, aboveOfSpan(aboveBordersByCol, colIdx, span));
|
|
4693
4760
|
cells.push(paintWidthPt < widthPt ? {
|
|
4694
4761
|
...cellLayout,
|
|
4695
|
-
paintWidthPt
|
|
4762
|
+
paintWidthPt,
|
|
4763
|
+
...paintOffsetPt > 0 ? { paintOffsetPt } : {}
|
|
4696
4764
|
} : cellLayout);
|
|
4697
4765
|
cursorX += widthPt;
|
|
4698
4766
|
colIdx += span;
|
|
@@ -4784,14 +4852,16 @@ function clipCellToHeight(cell, heightPt) {
|
|
|
4784
4852
|
let used = 0;
|
|
4785
4853
|
for (const line of cell.lines) {
|
|
4786
4854
|
const h = computeLineHeight(line, line.resolved);
|
|
4787
|
-
|
|
4855
|
+
const below = line.metricDescentPt ?? line.maxFontSizePt * .2;
|
|
4856
|
+
if (kept.length > 0 && used + h - below > room) break;
|
|
4788
4857
|
kept.push(line);
|
|
4789
4858
|
used += h;
|
|
4790
4859
|
}
|
|
4791
4860
|
return {
|
|
4792
4861
|
...cell,
|
|
4793
4862
|
lines: kept,
|
|
4794
|
-
contentHeightPt: used
|
|
4863
|
+
contentHeightPt: used,
|
|
4864
|
+
...used > room ? { clipped: true } : {}
|
|
4795
4865
|
};
|
|
4796
4866
|
}
|
|
4797
4867
|
/**
|
|
@@ -4900,6 +4970,13 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4900
4970
|
}
|
|
4901
4971
|
const colEnd = colStart + colSpan - 1;
|
|
4902
4972
|
const borders = resolveCellBorders(cell.properties.borders, tableProps.borders, rowIdx, colStart, colEnd, rowCount, colCount, mergeRole, leftNeighborBorders, aboveNeighborBorders);
|
|
4973
|
+
const grid = tableProps.gridlines;
|
|
4974
|
+
const ruled = grid && !cell.properties.shading?.colorHex ? {
|
|
4975
|
+
...borders.top || mergeRole === "middle" || mergeRole === "end" ? {} : { top: grid },
|
|
4976
|
+
...borders.left ? {} : { left: grid },
|
|
4977
|
+
...borders.bottom || rowIdx !== rowCount - 1 || mergeRole === "start" || mergeRole === "middle" ? {} : { bottom: grid },
|
|
4978
|
+
...borders.right || colEnd !== colCount - 1 ? {} : { right: grid }
|
|
4979
|
+
} : void 0;
|
|
4903
4980
|
const alongPt = turned ? lines.reduce((a, l) => Math.max(a, l.contentWidthPt), 0) : 0;
|
|
4904
4981
|
const heightPt = turned ? alongPt : contentHeightPt;
|
|
4905
4982
|
const totalHeightPt = mergeRole === "middle" || mergeRole === "end" ? 0 : padTopPt + heightPt + padBottomPt;
|
|
@@ -4909,11 +4986,15 @@ function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imag
|
|
|
4909
4986
|
padRightPt,
|
|
4910
4987
|
padBottomPt,
|
|
4911
4988
|
padLeftPt,
|
|
4912
|
-
borders
|
|
4989
|
+
borders: ruled ? {
|
|
4990
|
+
...ruled,
|
|
4991
|
+
...borders
|
|
4992
|
+
} : borders,
|
|
4913
4993
|
...cell.properties.shading?.colorHex ? { shadingColorHex: cell.properties.shading.colorHex } : {},
|
|
4914
4994
|
...cell.properties.dataBar ? { dataBar: cell.properties.dataBar } : {},
|
|
4915
4995
|
...cell.properties.icon ? { icon: cell.properties.icon } : {},
|
|
4916
4996
|
...cell.properties.sparkline ? { sparkline: cell.properties.sparkline } : {},
|
|
4997
|
+
...cell.properties.noteFlag ? { noteFlag: cell.properties.noteFlag } : {},
|
|
4917
4998
|
lines,
|
|
4918
4999
|
...lineGaps.size > 0 ? { lineGaps } : {},
|
|
4919
5000
|
...nestedTables.length > 0 ? { nestedTables } : {},
|
|
@@ -5298,6 +5379,17 @@ var PageAssembler = class PageAssembler {
|
|
|
5298
5379
|
floatsBehind = [];
|
|
5299
5380
|
floatsFront = [];
|
|
5300
5381
|
/**
|
|
5382
|
+
* The front floats as the page paints them: over its text, when the
|
|
5383
|
+
* document's floats cover what is under them (StyledRenderOptions
|
|
5384
|
+
* floatsOverText); in the ordinary passes, under it, otherwise.
|
|
5385
|
+
*/
|
|
5386
|
+
inFront(items) {
|
|
5387
|
+
return this.ctx.options?.floatsOverText === true ? items.map((item) => ({
|
|
5388
|
+
...item,
|
|
5389
|
+
over: true
|
|
5390
|
+
})) : items;
|
|
5391
|
+
}
|
|
5392
|
+
/**
|
|
5301
5393
|
* Side-wrapping floats (wrapSquare/tight/through): rectangles the body text
|
|
5302
5394
|
* must flow around. Page-scoped, like the float graphics.
|
|
5303
5395
|
*/
|
|
@@ -5575,7 +5667,7 @@ var PageAssembler = class PageAssembler {
|
|
|
5575
5667
|
behind: true
|
|
5576
5668
|
}))),
|
|
5577
5669
|
...onSheet(this.current),
|
|
5578
|
-
...onSheet(PageAssembler.byZ(this.floatsFront)),
|
|
5670
|
+
...onSheet(this.inFront(PageAssembler.byZ(this.floatsFront))),
|
|
5579
5671
|
...onSheet(this.renderNotesBand()),
|
|
5580
5672
|
...footer.commands
|
|
5581
5673
|
],
|
|
@@ -5791,6 +5883,105 @@ var PageAssembler = class PageAssembler {
|
|
|
5791
5883
|
};
|
|
5792
5884
|
};
|
|
5793
5885
|
/**
|
|
5886
|
+
* §20.5 — one spreadsheet table's drawings as its pages show them
|
|
5887
|
+
* (TableBlock.overlay). The table lays its rows down page by page, and each
|
|
5888
|
+
* stretch of sheet rows a page takes unbroken is a window onto the sheet:
|
|
5889
|
+
* every drawing over that stretch is drawn where it stands relative to those
|
|
5890
|
+
* rows and cut off at the window's edges. A chart across a page break so
|
|
5891
|
+
* prints in two pieces, one on each page, and a drawing in the title rows on
|
|
5892
|
+
* every page that repeats them — which is what Excel prints.
|
|
5893
|
+
*/
|
|
5894
|
+
var SheetView = class {
|
|
5895
|
+
runs = [];
|
|
5896
|
+
figures = /* @__PURE__ */ new Map();
|
|
5897
|
+
/**
|
|
5898
|
+
* @param overlay The table's drawings and the part of the sheet it prints.
|
|
5899
|
+
* @param tableX The table's left edge on the page.
|
|
5900
|
+
* @param builder The tagged-PDF structure, when the document is tagged.
|
|
5901
|
+
*/
|
|
5902
|
+
constructor(overlay, tableX, builder) {
|
|
5903
|
+
this.overlay = overlay;
|
|
5904
|
+
this.tableX = tableX;
|
|
5905
|
+
this.builder = builder;
|
|
5906
|
+
}
|
|
5907
|
+
/**
|
|
5908
|
+
* A row, or a piece of one, laid down on the page in hand.
|
|
5909
|
+
*
|
|
5910
|
+
* @param sheetTop Where its top stands on the sheet; undefined for a row the sheet does not have.
|
|
5911
|
+
* @param topYUp Where its top stands on the page, y-up.
|
|
5912
|
+
* @param heightPt How tall it was laid out.
|
|
5913
|
+
*/
|
|
5914
|
+
lay(sheetTop, topYUp, heightPt) {
|
|
5915
|
+
if (sheetTop === void 0) return;
|
|
5916
|
+
const last = this.runs[this.runs.length - 1];
|
|
5917
|
+
if (last && Math.abs(last.bottomYUp - topYUp) < .01 && Math.abs(last.sheetBottom - sheetTop) < .5) {
|
|
5918
|
+
last.sheetBottom = sheetTop + heightPt;
|
|
5919
|
+
last.bottomYUp = topYUp - heightPt;
|
|
5920
|
+
return;
|
|
5921
|
+
}
|
|
5922
|
+
this.runs.push({
|
|
5923
|
+
sheetTop,
|
|
5924
|
+
sheetBottom: sheetTop + heightPt,
|
|
5925
|
+
topYUp,
|
|
5926
|
+
bottomYUp: topYUp - heightPt
|
|
5927
|
+
});
|
|
5928
|
+
}
|
|
5929
|
+
/**
|
|
5930
|
+
* Draw what the page's rows show of the drawings, and start over for the
|
|
5931
|
+
* next page.
|
|
5932
|
+
*
|
|
5933
|
+
* @param asm The page assembler, still on the page the rows were laid on.
|
|
5934
|
+
*/
|
|
5935
|
+
show(asm) {
|
|
5936
|
+
const o = this.overlay;
|
|
5937
|
+
const pageHeight = asm.ctx.pageHeight;
|
|
5938
|
+
for (const run of this.runs) {
|
|
5939
|
+
const window = {
|
|
5940
|
+
x: pt(this.tableX + o.leftPt),
|
|
5941
|
+
y: pt(pageHeight - run.topYUp),
|
|
5942
|
+
width: pt(o.widthPt),
|
|
5943
|
+
height: pt(run.topYUp - run.bottomYUp)
|
|
5944
|
+
};
|
|
5945
|
+
o.drawings.forEach((d, i) => {
|
|
5946
|
+
const { block } = d;
|
|
5947
|
+
if (d.yPt > run.sheetBottom || d.yPt + block.heightPt < run.sheetTop) return;
|
|
5948
|
+
const left = d.xPt - o.sheetLeftPt;
|
|
5949
|
+
if (left > o.widthPt || left + block.widthPt < 0) return;
|
|
5950
|
+
const x = this.tableX + o.leftPt + (o.mirrored ? o.widthPt - left - block.widthPt : left);
|
|
5951
|
+
const items = [];
|
|
5952
|
+
emitDrawing(block, x, run.topYUp - (d.yPt - run.sheetTop), items, pageHeight, void 0);
|
|
5953
|
+
const shown = items.filter((item) => {
|
|
5954
|
+
const box = pageItemBounds(item);
|
|
5955
|
+
return box.x1 >= window.x && box.x0 <= window.x + window.width && box.y1 >= window.y && box.y0 <= window.y + window.height;
|
|
5956
|
+
});
|
|
5957
|
+
if (shown.length === 0) return;
|
|
5958
|
+
const figId = this.figure(i, block);
|
|
5959
|
+
seenThrough(PageAssembler.zSink(asm.floatsFront, block.float?.zOrder), window).push(...figId === void 0 ? shown : shown.map((item) => ({
|
|
5960
|
+
...item,
|
|
5961
|
+
structId: figId
|
|
5962
|
+
})));
|
|
5963
|
+
});
|
|
5964
|
+
}
|
|
5965
|
+
this.runs = [];
|
|
5966
|
+
}
|
|
5967
|
+
/** The tagged-PDF Figure a drawing is, made once however many pages show it. */
|
|
5968
|
+
figure(i, block) {
|
|
5969
|
+
if (!this.builder) return void 0;
|
|
5970
|
+
let id = this.figures.get(i);
|
|
5971
|
+
if (id === void 0) {
|
|
5972
|
+
const role = block.kind === "chart" ? block.figureRole ?? "Chart" : block.kind === "image" ? "Image" : "Shape";
|
|
5973
|
+
id = createFigure(this.builder, block.altText, role);
|
|
5974
|
+
this.figures.set(i, id);
|
|
5975
|
+
}
|
|
5976
|
+
return id;
|
|
5977
|
+
}
|
|
5978
|
+
};
|
|
5979
|
+
/** A sink that marks each item it takes as seen through `window` (PageItemBase.window). */
|
|
5980
|
+
var seenThrough = (target, window) => ({ push: (...items) => target.push(...items.map((item) => ({
|
|
5981
|
+
...item,
|
|
5982
|
+
window
|
|
5983
|
+
}))) });
|
|
5984
|
+
/**
|
|
5794
5985
|
* §17.3.1.14/15 — the height a paragraph needs in one column: all of its lines
|
|
5795
5986
|
* where it keeps them together, and where it keeps with the next, the whole of
|
|
5796
5987
|
* every paragraph in the chain it heads and as much of the block after as has
|
|
@@ -6143,6 +6334,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
|
|
|
6143
6334
|
const headerHeightPt = headerRows.reduce((s, r) => s + r.heightPt, 0);
|
|
6144
6335
|
const tableNode = builder ? builder.create("Table", builder.root) : void 0;
|
|
6145
6336
|
const tableX = asm.colLeft() + block.xOffsetPt;
|
|
6337
|
+
const sheetView = block.overlay ? new SheetView(block.overlay, tableX, builder) : void 0;
|
|
6146
6338
|
for (let ri = 0; ri < block.rows.length; ri++) {
|
|
6147
6339
|
const row = block.rows[ri];
|
|
6148
6340
|
const isLeadingHeader = ri < headerRows.length;
|
|
@@ -6163,20 +6355,25 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
|
|
|
6163
6355
|
const room = asm.cursorY - asm.bottomLimit();
|
|
6164
6356
|
const page = asm.ctx.pageContentHeight;
|
|
6165
6357
|
const chunks = !row.cantSplit && row.heightPt > room && asm.colHasContent() && room > 0 ? splitRowIntoChunks(row, room, page) : row.heightPt > page ? splitRowIntoChunks(row, page) : [row];
|
|
6358
|
+
let chunkOffsetPt = 0;
|
|
6166
6359
|
for (let ci = 0; ci < chunks.length; ci++) {
|
|
6167
6360
|
const chunk = chunks[ci];
|
|
6168
|
-
const forcedBreak = ci === 0 && row.breakBefore && !isLeadingHeader && asm.pageHasContent();
|
|
6361
|
+
const forcedBreak = ci === 0 && row.breakBefore && (ri === 0 || !isLeadingHeader) && asm.pageHasContent();
|
|
6169
6362
|
const overflow = asm.cursorY - chunk.heightPt < asm.bottomLimit() && asm.colHasContent();
|
|
6170
6363
|
if (forcedBreak || overflow) {
|
|
6364
|
+
sheetView?.show(asm);
|
|
6171
6365
|
if (forcedBreak) asm.flushPage();
|
|
6172
6366
|
else asm.advanceColumn();
|
|
6173
6367
|
if (!isLeadingHeader && headerRows.length > 0 && asm.cursorY - headerHeightPt - chunk.heightPt >= asm.bottomLimit()) for (const hr of headerRows) {
|
|
6174
6368
|
emitRowChunk(asm.current, hr, tableX, asm.cursorY, asm.ctx.pageHeight, colCount, void 0);
|
|
6369
|
+
sheetView?.lay(hr.sheetTopPt, asm.cursorY, hr.heightPt);
|
|
6175
6370
|
asm.cursorY -= hr.heightPt;
|
|
6176
6371
|
}
|
|
6177
6372
|
}
|
|
6178
6373
|
const mergedHeights = chunks.length === 1 && row.cells.some((c) => c.mergeRole === "start") ? row.cells.map((c) => c.mergeRole === "start" ? mergedBoxHeightPt(block.rows, ri, c.colStart, asm.cursorY - asm.bottomLimit()) : void 0) : void 0;
|
|
6179
6374
|
emitRowChunk(asm.current, chunk, tableX, asm.cursorY, asm.ctx.pageHeight, colCount, cellStructIds, mergedHeights, cellAnchorCtx(asm));
|
|
6375
|
+
sheetView?.lay(row.sheetTopPt !== void 0 ? row.sheetTopPt + chunkOffsetPt : void 0, asm.cursorY, chunk.heightPt);
|
|
6376
|
+
chunkOffsetPt += chunk.heightPt;
|
|
6180
6377
|
asm.cursorY -= chunk.heightPt;
|
|
6181
6378
|
if (ci === chunks.length - 1 && ri < block.rows.length - 1) {
|
|
6182
6379
|
const next = block.rows[ri + 1];
|
|
@@ -6187,6 +6384,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US", n
|
|
|
6187
6384
|
}
|
|
6188
6385
|
}
|
|
6189
6386
|
}
|
|
6387
|
+
sheetView?.show(asm);
|
|
6190
6388
|
}
|
|
6191
6389
|
}
|
|
6192
6390
|
asm.flushPage();
|
|
@@ -6267,7 +6465,7 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
6267
6465
|
}
|
|
6268
6466
|
out.push({
|
|
6269
6467
|
type: "fill",
|
|
6270
|
-
x: pt(marginLeft + (row.columnXOffsets[i] ?? 0)),
|
|
6468
|
+
x: pt(marginLeft + (row.columnXOffsets[i] ?? 0) + (cell.paintOffsetPt ?? 0)),
|
|
6271
6469
|
y: pt(pageHeight - rowBottom - row.heightPt - FILL_SEAM_PT),
|
|
6272
6470
|
width: pt(width),
|
|
6273
6471
|
height: pt(row.heightPt + FILL_SEAM_PT),
|
|
@@ -6282,16 +6480,19 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
6282
6480
|
const structId = cellStructIds?.[i];
|
|
6283
6481
|
if (cell.dataBar && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
6284
6482
|
const start = Math.max(0, Math.min(1, cell.dataBar.startFraction ?? 0));
|
|
6285
|
-
const
|
|
6483
|
+
const inner = Math.max(0, cell.widthPt - 2 * DATA_BAR_INSET_PT);
|
|
6484
|
+
const barWidth = inner * Math.max(0, Math.min(1, cell.dataBar.fraction));
|
|
6286
6485
|
if (barWidth > 0) {
|
|
6287
|
-
const barX = cellX +
|
|
6288
|
-
const
|
|
6486
|
+
const barX = cellX + DATA_BAR_INSET_PT + inner * start;
|
|
6487
|
+
const boxHeightPt = Math.max(row.heightPt, mergedHeights?.[i] ?? row.heightPt);
|
|
6488
|
+
const barHeightPt = Math.max(0, boxHeightPt - 2 * DATA_BAR_INSET_PT);
|
|
6489
|
+
const barBottomYUp = rowBottom + row.heightPt - boxHeightPt + DATA_BAR_INSET_PT;
|
|
6289
6490
|
out.push({
|
|
6290
6491
|
type: "shape",
|
|
6291
6492
|
shape: {
|
|
6292
|
-
paths: [rectAtPath(0, 0, barWidth,
|
|
6493
|
+
paths: [rectAtPath(0, 0, barWidth, barHeightPt)],
|
|
6293
6494
|
fillColorHex: cell.dataBar.colorHex,
|
|
6294
|
-
fillGradient: {
|
|
6495
|
+
...cell.dataBar.solid ? {} : { fillGradient: {
|
|
6295
6496
|
kind: "linear",
|
|
6296
6497
|
angle: cell.dataBar.negative ? 180 : 0,
|
|
6297
6498
|
stops: [{
|
|
@@ -6301,7 +6502,7 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
6301
6502
|
offset: 1,
|
|
6302
6503
|
colorHex: "FFFFFF"
|
|
6303
6504
|
}]
|
|
6304
|
-
},
|
|
6505
|
+
} },
|
|
6305
6506
|
transform: flipTransform([
|
|
6306
6507
|
1,
|
|
6307
6508
|
0,
|
|
@@ -6358,6 +6559,28 @@ function emitRowChunk(out, row, marginLeft, cursorY, pageHeight, colCount, cellS
|
|
|
6358
6559
|
});
|
|
6359
6560
|
}
|
|
6360
6561
|
}
|
|
6562
|
+
if (cell.noteFlag && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
6563
|
+
const left = cell.paintOffsetPt ?? 0;
|
|
6564
|
+
const right = left + (cell.paintWidthPt ?? cell.widthPt);
|
|
6565
|
+
const side = Math.min(NOTE_FLAG_PT, row.heightPt, right - left);
|
|
6566
|
+
const top = row.heightPt;
|
|
6567
|
+
const corner = cell.noteFlag.atLeft ? new PathBuilder().moveTo(left, top).lineTo(left + side, top).lineTo(left, top - side) : new PathBuilder().moveTo(right - side, top).lineTo(right, top).lineTo(right, top - side);
|
|
6568
|
+
out.push({
|
|
6569
|
+
type: "shape",
|
|
6570
|
+
shape: {
|
|
6571
|
+
paths: [corner.close().build()],
|
|
6572
|
+
fillColorHex: cell.noteFlag.kind === "thread" ? NOTE_THREAD_HEX : NOTE_FLAG_HEX,
|
|
6573
|
+
transform: flipTransform([
|
|
6574
|
+
1,
|
|
6575
|
+
0,
|
|
6576
|
+
0,
|
|
6577
|
+
1,
|
|
6578
|
+
cellX,
|
|
6579
|
+
rowBottom
|
|
6580
|
+
], pageHeight)
|
|
6581
|
+
}
|
|
6582
|
+
});
|
|
6583
|
+
}
|
|
6361
6584
|
if (cell.sparkline && cell.sparkline.values.length > 0 && cell.mergeRole !== "middle" && cell.mergeRole !== "end") {
|
|
6362
6585
|
const inset = 1.5;
|
|
6363
6586
|
const sw = cell.widthPt - 2 * inset;
|
|
@@ -6609,7 +6832,7 @@ function emitCellBorders(out, cell, cellX, cellY, rowHeight, pageHeight, rowIdx,
|
|
|
6609
6832
|
out.push({
|
|
6610
6833
|
type: "border",
|
|
6611
6834
|
side,
|
|
6612
|
-
x: pt(cellX),
|
|
6835
|
+
x: pt(side === "left" ? cellX : cellX + (cell.paintOffsetPt ?? 0)),
|
|
6613
6836
|
y: pt(pageHeight - cellY - rowHeight + lowered),
|
|
6614
6837
|
width: pt(cell.paintWidthPt ?? cell.widthPt),
|
|
6615
6838
|
height: pt(rowHeight - lowered - raised),
|
|
@@ -13,12 +13,24 @@ var QUARTER_60K = 90 * 6e4;
|
|
|
13
13
|
* @returns The same item on the sheet, turned a quarter clockwise.
|
|
14
14
|
*/
|
|
15
15
|
function turnOntoSheet(item, sheetWidth) {
|
|
16
|
-
const
|
|
16
|
+
const turned = turnItem(item, sheetWidth);
|
|
17
|
+
const w = item.window;
|
|
18
|
+
return w ? {
|
|
19
|
+
...turned,
|
|
20
|
+
window: turnBox(w.x, w.y, w.width, w.height, sheetWidth)
|
|
21
|
+
} : turned;
|
|
22
|
+
}
|
|
23
|
+
/** A top-left-frame box of the frame, as it stands on the sheet once turned a quarter clockwise. */
|
|
24
|
+
function turnBox(x, y, w, h, sheetWidth) {
|
|
25
|
+
return {
|
|
17
26
|
x: pt(sheetWidth - y - h),
|
|
18
27
|
y: pt(x),
|
|
19
28
|
width: pt(h),
|
|
20
29
|
height: pt(w)
|
|
21
|
-
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function turnItem(item, sheetWidth) {
|
|
33
|
+
const box = (x, y, w, h) => turnBox(x, y, w, h, sheetWidth);
|
|
22
34
|
switch (item.type) {
|
|
23
35
|
case "line": {
|
|
24
36
|
const quarter = withinTurn((item.rotationDeg ?? 0) - 90);
|