reamkit 1.15.1 → 1.15.3
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/esm/core/arc-to-bezier.d.ts +23 -0
- package/dist/esm/core/arc-to-bezier.js +23 -0
- package/dist/esm/core/bidi/algorithm.d.ts +26 -0
- package/dist/esm/core/bidi/algorithm.js +21 -0
- package/dist/esm/core/bidi/char-types.d.ts +17 -0
- package/dist/esm/core/bidi/char-types.js +10 -0
- package/dist/esm/core/bidi/index.d.ts +42 -0
- package/dist/esm/core/bidi/index.js +27 -0
- package/dist/esm/core/bidi/segments.d.ts +22 -0
- package/dist/esm/core/bidi/segments.js +14 -0
- package/dist/esm/core/bytes.d.ts +20 -0
- package/dist/esm/core/bytes.js +24 -1
- package/dist/esm/core/converter/facade.d.ts +38 -1
- package/dist/esm/core/converter/facade.js +25 -0
- package/dist/esm/core/converter/project.d.ts +12 -0
- package/dist/esm/core/converter/project.js +11 -0
- package/dist/esm/core/converter/ream.d.ts +107 -0
- package/dist/esm/core/converter/ream.js +76 -0
- package/dist/esm/core/crypto/asn1.d.ts +77 -0
- package/dist/esm/core/crypto/asn1.js +65 -0
- package/dist/esm/core/crypto/cms.d.ts +25 -0
- package/dist/esm/core/crypto/cms.js +8 -0
- package/dist/esm/core/document-model/index.d.ts +7 -0
- package/dist/esm/core/document-model/types.d.ts +328 -0
- package/dist/esm/core/drawingml/chart-geometry.d.ts +125 -0
- package/dist/esm/core/drawingml/chart-geometry.js +96 -0
- package/dist/esm/core/drawingml/chart-parser.d.ts +34 -0
- package/dist/esm/core/drawingml/chart-parser.js +34 -0
- package/dist/esm/core/drawingml/chart-serializer.d.ts +12 -0
- package/dist/esm/core/drawingml/chart-serializer.js +12 -0
- package/dist/esm/core/drawingml/colors.d.ts +53 -0
- package/dist/esm/core/drawingml/colors.js +41 -0
- package/dist/esm/core/drawingml/preset-geometry.d.ts +30 -0
- package/dist/esm/core/drawingml/preset-geometry.js +30 -0
- package/dist/esm/core/drawingml/shape-render.d.ts +54 -0
- package/dist/esm/core/drawingml/shape-render.js +54 -0
- package/dist/esm/core/drawingml/sparkline-geometry.d.ts +15 -0
- package/dist/esm/core/drawingml/sparkline-geometry.js +13 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +11 -0
- package/dist/esm/core/drawingml/theme-parser.js +11 -0
- package/dist/esm/core/font/arabic-joining.d.ts +21 -0
- package/dist/esm/core/font/arabic-joining.js +16 -0
- package/dist/esm/core/font/binary-reader.d.ts +17 -0
- package/dist/esm/core/font/binary-reader.js +17 -0
- package/dist/esm/core/font/font-registry.d.ts +37 -0
- package/dist/esm/core/font/font-registry.js +31 -0
- package/dist/esm/core/font/measure.d.ts +20 -0
- package/dist/esm/core/font/measure.js +11 -0
- package/dist/esm/core/font/opentype-layout.d.ts +49 -0
- package/dist/esm/core/font/opentype-layout.js +37 -0
- package/dist/esm/core/font/ttf-parser.d.ts +32 -0
- package/dist/esm/core/font/ttf-parser.js +7 -0
- package/dist/esm/core/font/ttf-subset.d.ts +21 -0
- package/dist/esm/core/font/ttf-subset.js +21 -0
- package/dist/esm/core/fonts/provider.d.ts +8 -1
- package/dist/esm/core/fonts/provider.js +1 -0
- package/dist/esm/core/fonts/remote-fonts.d.ts +22 -0
- package/dist/esm/core/fonts/remote-fonts.js +16 -0
- package/dist/esm/core/hyphenation/index.d.ts +25 -0
- package/dist/esm/core/hyphenation/index.js +17 -0
- package/dist/esm/core/hyphenation/liang.d.ts +27 -0
- package/dist/esm/core/hyphenation/liang.js +14 -0
- package/dist/esm/core/images.d.ts +32 -0
- package/dist/esm/core/images.js +12 -0
- package/dist/esm/core/ir/adapters.d.ts +23 -0
- package/dist/esm/core/ir/features.d.ts +8 -0
- package/dist/esm/core/ir/features.js +1 -0
- package/dist/esm/core/ir/flow.d.ts +20 -0
- package/dist/esm/core/ir/index.d.ts +7 -0
- package/dist/esm/core/ir/loss.d.ts +12 -0
- package/dist/esm/core/ir/loss.js +8 -0
- package/dist/esm/core/ir/resources.d.ts +12 -0
- package/dist/esm/core/ir/resources.js +11 -0
- package/dist/esm/core/ir/sheet.d.ts +81 -0
- package/dist/esm/core/ir/units.d.ts +9 -0
- package/dist/esm/core/ir/units.js +2 -0
- package/dist/esm/core/line-breaker/cjk.d.ts +26 -0
- package/dist/esm/core/line-breaker/cjk.js +60 -0
- package/dist/esm/core/line-breaker/greedy.d.ts +14 -0
- package/dist/esm/core/line-breaker/greedy.js +14 -0
- package/dist/esm/core/line-breaker/index.d.ts +1 -0
- package/dist/esm/core/line-breaker/index.js +3 -0
- package/dist/esm/core/line-breaker/knuth-plass.d.ts +29 -5
- package/dist/esm/core/line-breaker/knuth-plass.js +10 -5
- package/dist/esm/core/numbering/apply.d.ts +19 -0
- package/dist/esm/core/numbering/apply.js +19 -0
- package/dist/esm/core/numbering/state.d.ts +15 -0
- package/dist/esm/core/numbering/state.js +15 -0
- package/dist/esm/core/ole/cfb.d.ts +19 -0
- package/dist/esm/core/ole/cfb.js +16 -0
- package/dist/esm/core/opc/core-properties.d.ts +12 -0
- package/dist/esm/core/opc/core-properties.js +5 -0
- package/dist/esm/core/opc/opc-writer.d.ts +24 -4
- package/dist/esm/core/opc/opc-writer.js +12 -0
- package/dist/esm/core/opc/package.d.ts +55 -0
- package/dist/esm/core/opc/package.js +49 -1
- package/dist/esm/core/opc/relationship-types.d.ts +8 -0
- package/dist/esm/core/opc/relationship-types.js +5 -0
- package/dist/esm/core/opc/relationships.d.ts +12 -0
- package/dist/esm/core/opc/relationships.js +7 -0
- package/dist/esm/core/po-helpers.d.ts +38 -0
- package/dist/esm/core/po-helpers.js +33 -0
- package/dist/esm/core/spreadsheet-model/types.d.ts +302 -0
- package/dist/esm/core/style-cascade/resolver.d.ts +31 -0
- package/dist/esm/core/style-cascade/resolver.js +31 -0
- package/dist/esm/core/style-cascade/table.d.ts +7 -0
- package/dist/esm/core/style-cascade/table.js +7 -0
- package/dist/esm/core/style-cascade/types.d.ts +27 -0
- package/dist/esm/core/style-cascade/types.js +2 -0
- package/dist/esm/core/vector.d.ts +67 -0
- package/dist/esm/core/vector.js +23 -0
- package/dist/esm/excel/activex-parser.d.ts +31 -0
- package/dist/esm/excel/activex-parser.js +24 -0
- package/dist/esm/excel/cell-reference.d.ts +14 -0
- package/dist/esm/excel/cell-reference.js +9 -0
- package/dist/esm/excel/column-bands.d.ts +29 -0
- package/dist/esm/excel/column-bands.js +27 -7
- package/dist/esm/excel/comments-parser.d.ts +19 -0
- package/dist/esm/excel/comments-parser.js +19 -0
- package/dist/esm/excel/conditional-format.d.ts +38 -0
- package/dist/esm/excel/conditional-format.js +25 -0
- package/dist/esm/excel/defined-name-ref.d.ts +21 -0
- package/dist/esm/excel/defined-name-ref.js +20 -0
- package/dist/esm/excel/form-control-parser.d.ts +13 -0
- package/dist/esm/excel/form-control-parser.js +5 -0
- package/dist/esm/excel/formula/context.d.ts +37 -0
- package/dist/esm/excel/formula/dates.d.ts +23 -0
- package/dist/esm/excel/formula/dates.js +20 -0
- package/dist/esm/excel/formula/eval.d.ts +21 -0
- package/dist/esm/excel/formula/eval.js +11 -0
- package/dist/esm/excel/formula/functions.d.ts +12 -0
- package/dist/esm/excel/formula/functions.js +12 -0
- package/dist/esm/excel/formula/index.d.ts +21 -0
- package/dist/esm/excel/formula/index.js +16 -0
- package/dist/esm/excel/formula/lexer.d.ts +12 -0
- package/dist/esm/excel/formula/lexer.js +10 -0
- package/dist/esm/excel/formula/parser.d.ts +20 -0
- package/dist/esm/excel/formula/parser.js +53 -0
- package/dist/esm/excel/formula/value.d.ts +53 -0
- package/dist/esm/excel/formula/value.js +30 -0
- package/dist/esm/excel/header-footer.d.ts +9 -0
- package/dist/esm/excel/header-footer.js +9 -0
- package/dist/esm/excel/number-format.d.ts +34 -0
- package/dist/esm/excel/number-format.js +34 -0
- package/dist/esm/excel/pivot-table-parser.d.ts +8 -0
- package/dist/esm/excel/pivot-table-parser.js +8 -0
- package/dist/esm/excel/print-model.d.ts +77 -1
- package/dist/esm/excel/print-model.js +230 -26
- package/dist/esm/excel/shared-strings-parser.d.ts +13 -0
- package/dist/esm/excel/shared-strings-parser.js +5 -0
- package/dist/esm/excel/sheet-drawing.d.ts +34 -0
- package/dist/esm/excel/sheet-drawing.js +21 -0
- package/dist/esm/excel/sheet-shape-parser.d.ts +12 -0
- package/dist/esm/excel/sheet-shape-parser.js +12 -0
- package/dist/esm/excel/sheet-to-flow.d.ts +29 -0
- package/dist/esm/excel/sheet-to-flow.js +24 -7
- package/dist/esm/excel/slicer-parser.d.ts +23 -0
- package/dist/esm/excel/slicer-parser.js +10 -0
- package/dist/esm/excel/styles-parser.d.ts +8 -0
- package/dist/esm/excel/styles-parser.js +8 -0
- package/dist/esm/excel/table-parser.d.ts +24 -0
- package/dist/esm/excel/table-parser.js +5 -0
- package/dist/esm/excel/workbook-parser.d.ts +17 -0
- package/dist/esm/excel/workbook-parser.js +5 -0
- package/dist/esm/excel/worksheet-parser.d.ts +9 -0
- package/dist/esm/excel/worksheet-parser.js +39 -6
- package/dist/esm/excel/xls/biff-chart.d.ts +10 -0
- package/dist/esm/excel/xls/biff-chart.js +10 -0
- package/dist/esm/excel/xls/biff-reader.d.ts +27 -0
- package/dist/esm/excel/xls/biff-reader.js +44 -0
- package/dist/esm/excel/xls/biff-styles.d.ts +20 -0
- package/dist/esm/excel/xls/biff-styles.js +20 -0
- package/dist/esm/excel/xls/escher.d.ts +27 -0
- package/dist/esm/excel/xls/escher.js +18 -0
- package/dist/esm/excel/xls/xls-reader.d.ts +6 -0
- package/dist/esm/excel/xls/xls-reader.js +6 -0
- package/dist/esm/excel/xlsx-reader.d.ts +30 -0
- package/dist/esm/excel/xlsx-reader.js +38 -4
- package/dist/esm/excel/xlsx-to-pdf.d.ts +27 -0
- package/dist/esm/excel/xlsx-writer.d.ts +14 -0
- package/dist/esm/excel/xlsx-writer.js +13 -0
- package/dist/esm/html/html-writer.d.ts +18 -0
- package/dist/esm/html/html-writer.js +18 -0
- package/dist/esm/index.d.ts +23 -0
- package/dist/esm/layout/math-layout.d.ts +39 -0
- package/dist/esm/layout/math-layout.js +18 -0
- package/dist/esm/layout/page-doc.d.ts +91 -0
- package/dist/esm/layout/styled-layout.d.ts +175 -0
- package/dist/esm/layout/styled-layout.js +136 -4
- package/dist/esm/pdf/builtin-fonts.d.ts +5 -0
- package/dist/esm/pdf/cid-font.d.ts +22 -0
- package/dist/esm/pdf/cid-font.js +10 -0
- package/dist/esm/pdf/embedded-file.d.ts +16 -0
- package/dist/esm/pdf/embedded-file.js +9 -0
- package/dist/esm/pdf/encryption.d.ts +59 -0
- package/dist/esm/pdf/encryption.js +37 -0
- package/dist/esm/pdf/icc-profile.d.ts +8 -0
- package/dist/esm/pdf/icc-profile.js +8 -0
- package/dist/esm/pdf/image-xobject.d.ts +19 -0
- package/dist/esm/pdf/image-xobject.js +9 -0
- package/dist/esm/pdf/objects.d.ts +40 -0
- package/dist/esm/pdf/objects.js +36 -0
- package/dist/esm/pdf/serialize.d.ts +18 -0
- package/dist/esm/pdf/serialize.js +18 -0
- package/dist/esm/pdf/shading.d.ts +16 -0
- package/dist/esm/pdf/shading.js +16 -0
- package/dist/esm/pdf/signature.d.ts +36 -0
- package/dist/esm/pdf/signature.js +22 -0
- package/dist/esm/pdf/struct-tree.d.ts +64 -0
- package/dist/esm/pdf/struct-tree.js +60 -0
- package/dist/esm/pdf/styled-page-emitter.d.ts +33 -0
- package/dist/esm/pdf/styled-page-emitter.js +21 -0
- package/dist/esm/pdf/styled-page-renderer.d.ts +18 -0
- package/dist/esm/pdf/styled-page-renderer.js +18 -0
- package/dist/esm/pdf/text-encoding.d.ts +16 -0
- package/dist/esm/pdf/text-page-renderer.d.ts +11 -0
- package/dist/esm/pdf/vector-graphics.d.ts +12 -0
- package/dist/esm/pdf/vector-graphics.js +12 -0
- package/dist/esm/pdf/writer.d.ts +39 -0
- package/dist/esm/pdf/writer.js +27 -0
- package/dist/esm/pdf/xmp.d.ts +16 -0
- package/dist/esm/pdf/xmp.js +9 -0
- package/dist/esm/pdf-reader/ccitt.d.ts +25 -0
- package/dist/esm/pdf-reader/ccitt.js +15 -0
- package/dist/esm/pdf-reader/cmap.d.ts +12 -0
- package/dist/esm/pdf-reader/cmap.js +9 -0
- package/dist/esm/pdf-reader/content.d.ts +69 -0
- package/dist/esm/pdf-reader/content.js +16 -0
- package/dist/esm/pdf-reader/crypto.d.ts +5 -0
- package/dist/esm/pdf-reader/crypto.js +5 -0
- package/dist/esm/pdf-reader/decrypt.d.ts +17 -0
- package/dist/esm/pdf-reader/decrypt.js +12 -0
- package/dist/esm/pdf-reader/document.d.ts +53 -0
- package/dist/esm/pdf-reader/document.js +50 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +47 -0
- package/dist/esm/pdf-reader/flow-build.js +42 -0
- package/dist/esm/pdf-reader/font.d.ts +12 -0
- package/dist/esm/pdf-reader/font.js +12 -0
- package/dist/esm/pdf-reader/image-decode.d.ts +21 -0
- package/dist/esm/pdf-reader/image-decode.js +14 -0
- package/dist/esm/pdf-reader/images.d.ts +19 -0
- package/dist/esm/pdf-reader/images.js +9 -0
- package/dist/esm/pdf-reader/layout.d.ts +15 -0
- package/dist/esm/pdf-reader/layout.js +15 -0
- package/dist/esm/pdf-reader/lexer.d.ts +43 -0
- package/dist/esm/pdf-reader/lexer.js +38 -0
- package/dist/esm/pdf-reader/parser.d.ts +15 -0
- package/dist/esm/pdf-reader/parser.js +8 -0
- package/dist/esm/pdf-reader/png-encode.d.ts +9 -0
- package/dist/esm/pdf-reader/png-encode.js +8 -0
- package/dist/esm/pdf-reader/predictor.d.ts +9 -0
- package/dist/esm/pdf-reader/predictor.js +8 -0
- package/dist/esm/pdf-reader/reader.d.ts +16 -0
- package/dist/esm/pdf-reader/reader.js +16 -0
- package/dist/esm/pdf-reader/shading.d.ts +10 -0
- package/dist/esm/pdf-reader/shading.js +10 -0
- package/dist/esm/pdf-reader/struct-tree.d.ts +24 -0
- package/dist/esm/pdf-reader/struct-tree.js +12 -0
- package/dist/esm/pdf-reader/tagged.d.ts +13 -0
- package/dist/esm/pdf-reader/tagged.js +13 -0
- package/dist/esm/pdf-reader/text.d.ts +11 -0
- package/dist/esm/pdf-reader/text.js +11 -0
- package/dist/esm/pdf-reader/vector.d.ts +19 -0
- package/dist/esm/pdf-reader/vector.js +9 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +21 -0
- package/dist/esm/pptx/placeholder-cascade.js +10 -0
- package/dist/esm/pptx/ppt/ppt-reader.d.ts +16 -0
- package/dist/esm/pptx/ppt/ppt-reader.js +16 -0
- package/dist/esm/pptx/ppt/ppt-text.d.ts +55 -0
- package/dist/esm/pptx/ppt/ppt-text.js +14 -0
- package/dist/esm/pptx/pptx-reader.d.ts +21 -0
- package/dist/esm/pptx/pptx-reader.js +23 -2
- package/dist/esm/pptx/slide-parser.d.ts +102 -0
- package/dist/esm/pptx/slide-parser.js +78 -0
- package/dist/esm/pptx/sp-helpers.d.ts +28 -0
- package/dist/esm/pptx/sp-helpers.js +22 -0
- package/dist/esm/svg/svg-writer.d.ts +17 -0
- package/dist/esm/svg/svg-writer.js +16 -0
- package/dist/esm/word/doc/doc-reader.d.ts +16 -0
- package/dist/esm/word/doc/doc-reader.js +16 -0
- package/dist/esm/word/doc/doc-text.d.ts +77 -0
- package/dist/esm/word/doc/doc-text.js +13 -0
- package/dist/esm/word/document-parser.d.ts +134 -0
- package/dist/esm/word/document-parser.js +86 -0
- package/dist/esm/word/docx-reader.d.ts +16 -0
- package/dist/esm/word/docx-reader.js +18 -2
- package/dist/esm/word/docx-to-pdf.d.ts +52 -0
- package/dist/esm/word/docx-to-pdf.js +21 -0
- package/dist/esm/word/docx-writer.d.ts +17 -0
- package/dist/esm/word/docx-writer.js +17 -0
- package/dist/esm/word/drawing-parser.d.ts +88 -0
- package/dist/esm/word/drawing-parser.js +68 -0
- package/dist/esm/word/font-table.d.ts +24 -0
- package/dist/esm/word/font-table.js +24 -0
- package/dist/esm/word/numbering-parser.d.ts +11 -0
- package/dist/esm/word/numbering-parser.js +11 -0
- package/dist/esm/word/omml-parser.d.ts +15 -0
- package/dist/esm/word/omml-parser.js +15 -0
- package/dist/esm/word/omml-serializer.d.ts +9 -0
- package/dist/esm/word/omml-serializer.js +9 -0
- package/dist/esm/word/paragraph-properties.d.ts +10 -0
- package/dist/esm/word/paragraph-properties.js +10 -0
- package/dist/esm/word/po-to-flat.d.ts +11 -0
- package/dist/esm/word/po-to-flat.js +11 -0
- package/dist/esm/word/run-properties.d.ts +10 -0
- package/dist/esm/word/run-properties.js +10 -0
- package/dist/esm/word/settings-parser.d.ts +13 -0
- package/dist/esm/word/settings-parser.js +8 -0
- package/dist/esm/word/styles-parser.d.ts +10 -0
- package/dist/esm/word/styles-parser.js +10 -0
- package/dist/esm/word/table-parser.d.ts +11 -0
- package/dist/esm/word/table-parser.js +11 -0
- package/dist/esm/word/text-extractor.d.ts +9 -0
- package/dist/esm/word/xml-helpers.d.ts +44 -0
- package/dist/esm/word/xml-helpers.js +38 -0
- package/package.json +5 -2
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { eighthPtToPt, halfPtToPt, pt, twipsToPt } from "../core/ir/units.js";
|
|
2
|
+
import { FEATURES } from "../core/ir/features.js";
|
|
2
3
|
import { parseAreaRef, parseTitleRowRange } from "./defined-name-ref.js";
|
|
3
4
|
import { applyNumberFormat } from "./number-format.js";
|
|
4
5
|
import "./index.js";
|
|
5
6
|
import { bandedTables, computeColumnBands } from "./column-bands.js";
|
|
6
7
|
import { buildConditionalFormatter } from "./conditional-format.js";
|
|
8
|
+
/**
|
|
9
|
+
* Excel insets a cell's text by ~2 px each side (1.5 pt at 96 DPI). The layout
|
|
10
|
+
* engine's default is a word processor's 108 twips (5.4 pt), which is nearly
|
|
11
|
+
* four times as much.
|
|
12
|
+
*/
|
|
13
|
+
var EXCEL_CELL_INSET_PT = 1.5;
|
|
14
|
+
/**
|
|
15
|
+
* ECMA-376 §18.3.1.81 — the row height Excel uses when a sheet declares no
|
|
16
|
+
* `<sheetFormatPr defaultRowHeight>`: 15pt, the line height of its default
|
|
17
|
+
* theme font (Calibri 11). Independent of whatever font we end up rendering
|
|
18
|
+
* with — the height belongs to the document, not to the typesetter.
|
|
19
|
+
*/
|
|
20
|
+
var EXCEL_DEFAULT_ROW_HEIGHT_PT = 15;
|
|
7
21
|
var TWIPS_PER_POINT = 20;
|
|
8
22
|
var TWIPS_PER_INCH = 1440;
|
|
9
23
|
var PAPER_SIZES_TWIPS = new Map([
|
|
@@ -16,13 +30,22 @@ var PAPER_SIZES_TWIPS = new Map([
|
|
|
16
30
|
[70, [5953, 8392]]
|
|
17
31
|
]);
|
|
18
32
|
var DEFAULT_PAPER_TWIPS = [11906, 16838];
|
|
33
|
+
/**
|
|
34
|
+
* Build the page section (paper size + margins) from a worksheet's `<pageSetup>`
|
|
35
|
+
* / `<pageMargins>`.
|
|
36
|
+
*
|
|
37
|
+
* Margins are always set, to Excel's own defaults when the worksheet declares
|
|
38
|
+
* none (§18.3.1.62) — the renderer's fallback is a word processor's inch, which
|
|
39
|
+
* is not what a spreadsheet prints. The paper size is left unset when the
|
|
40
|
+
* worksheet names none, because there the file genuinely holds no answer: Excel
|
|
41
|
+
* picks by locale and printer, and the renderer's deterministic A4 is as good
|
|
42
|
+
* as anything we could invent.
|
|
43
|
+
*/
|
|
19
44
|
function sectionFromWorksheet(worksheet) {
|
|
20
45
|
const pageSize = pageSizeFromSetup(worksheet.pageSetup);
|
|
21
|
-
const margins = marginsFromXlsx(worksheet.pageMargins);
|
|
22
|
-
if (!pageSize && !margins) return void 0;
|
|
23
46
|
return {
|
|
24
47
|
...pageSize ? { pageSize } : {},
|
|
25
|
-
|
|
48
|
+
margins: marginsFromXlsx(worksheet.pageMargins),
|
|
26
49
|
headers: [],
|
|
27
50
|
footers: []
|
|
28
51
|
};
|
|
@@ -39,8 +62,23 @@ function pageSizeFromSetup(setup) {
|
|
|
39
62
|
orientation
|
|
40
63
|
};
|
|
41
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* ECMA-376 §18.3.1.62 — the page margins Excel writes when the user has not
|
|
67
|
+
* touched them, in inches. A worksheet may omit `<pageMargins>` entirely, and
|
|
68
|
+
* falling through to the renderer's default (a word processor's 1 inch) put the
|
|
69
|
+
* grid 0.3 inch — 21.6 pt — right of where Excel and LibreOffice print it, on
|
|
70
|
+
* every such sheet.
|
|
71
|
+
*/
|
|
72
|
+
var EXCEL_DEFAULT_MARGINS = {
|
|
73
|
+
left: twipsToPt(Math.round(.7 * TWIPS_PER_INCH)),
|
|
74
|
+
right: twipsToPt(Math.round(.7 * TWIPS_PER_INCH)),
|
|
75
|
+
top: twipsToPt(Math.round(.75 * TWIPS_PER_INCH)),
|
|
76
|
+
bottom: twipsToPt(Math.round(.75 * TWIPS_PER_INCH)),
|
|
77
|
+
header: twipsToPt(Math.round(.3 * TWIPS_PER_INCH)),
|
|
78
|
+
footer: twipsToPt(Math.round(.3 * TWIPS_PER_INCH))
|
|
79
|
+
};
|
|
42
80
|
function marginsFromXlsx(margins) {
|
|
43
|
-
if (!margins) return
|
|
81
|
+
if (!margins) return EXCEL_DEFAULT_MARGINS;
|
|
44
82
|
return {
|
|
45
83
|
top: twipsToPt(Math.round(margins.topInches * TWIPS_PER_INCH)),
|
|
46
84
|
right: twipsToPt(Math.round(margins.rightInches * TWIPS_PER_INCH)),
|
|
@@ -52,9 +90,14 @@ function marginsFromXlsx(margins) {
|
|
|
52
90
|
}
|
|
53
91
|
var PRINT_AREA_NAME = "_xlnm.Print_Area";
|
|
54
92
|
var PRINT_TITLES_NAME = "_xlnm.Print_Titles";
|
|
93
|
+
/**
|
|
94
|
+
* ECMA-376 §18.2.5 — resolve the sheet-scoped `_xlnm.Print_Area` defined name
|
|
95
|
+
* (`localSheetId` = the sheet's 0-based index) into a clipping range.
|
|
96
|
+
*/
|
|
55
97
|
function resolvePrintArea(definedNames, sheetIdx) {
|
|
56
98
|
for (const dn of definedNames) if (dn.name === PRINT_AREA_NAME && dn.localSheetId === sheetIdx) return parseAreaRef(dn.value);
|
|
57
99
|
}
|
|
100
|
+
/** ECMA-376 §18.2.5 — `_xlnm.Print_Titles` → the repeated row range (0-indexed). */
|
|
58
101
|
function resolvePrintTitleRows(definedNames, sheetIdx) {
|
|
59
102
|
for (const dn of definedNames) if (dn.name === PRINT_TITLES_NAME && dn.localSheetId === sheetIdx) return parseTitleRowRange(dn.value);
|
|
60
103
|
}
|
|
@@ -63,16 +106,16 @@ function sheetContentWidthTwips(worksheet) {
|
|
|
63
106
|
const pageSize = pageSizeFromSetup(worksheet.pageSetup);
|
|
64
107
|
const pageWidthTwips = pageSize ? Math.round(pageSize.width * 20) : DEFAULT_PAPER_TWIPS[0];
|
|
65
108
|
const margins = marginsFromXlsx(worksheet.pageMargins);
|
|
66
|
-
const left =
|
|
67
|
-
const right =
|
|
109
|
+
const left = Math.round(margins.left * 20);
|
|
110
|
+
const right = Math.round(margins.right * 20);
|
|
68
111
|
return Math.max(TWIPS_PER_INCH / 2, pageWidthTwips - left - right);
|
|
69
112
|
}
|
|
70
113
|
function sheetContentHeightTwips(worksheet) {
|
|
71
114
|
const pageSize = pageSizeFromSetup(worksheet.pageSetup);
|
|
72
115
|
const pageHeightTwips = pageSize ? Math.round(pageSize.height * 20) : DEFAULT_PAPER_TWIPS[1];
|
|
73
116
|
const margins = marginsFromXlsx(worksheet.pageMargins);
|
|
74
|
-
const top =
|
|
75
|
-
const bottom =
|
|
117
|
+
const top = Math.round(margins.top * 20);
|
|
118
|
+
const bottom = Math.round(margins.bottom * 20);
|
|
76
119
|
return Math.max(TWIPS_PER_INCH / 2, pageHeightTwips - top - bottom);
|
|
77
120
|
}
|
|
78
121
|
function computePrintScale(worksheet, totalGridTwips, contentWidthTwips, totalGridHeightTwips, contentHeightTwips) {
|
|
@@ -97,6 +140,22 @@ function scaleRunFont(props, scale) {
|
|
|
97
140
|
};
|
|
98
141
|
}
|
|
99
142
|
var MAX_SHEET_TEXT_CHARS = 1e6;
|
|
143
|
+
/**
|
|
144
|
+
* Project one worksheet's grid into Flow body elements — a single {@link Table}
|
|
145
|
+
* (or, when the sheet is wider than the page, several column-banded tables). The
|
|
146
|
+
* full print model lives here: the used-range/print-area window, merge handling,
|
|
147
|
+
* the style cascade (fonts/fills/borders/alignment), print scaling, conditional
|
|
148
|
+
* formatting, sparklines, table/pivot banding, overflow and rotation. Memory- and
|
|
149
|
+
* text-budget-bounded against untrusted input.
|
|
150
|
+
*
|
|
151
|
+
* @param worksheet The parsed grid + per-sheet geometry.
|
|
152
|
+
* @param sharedStrings The workbook shared-string table (`t="s"` cells index it).
|
|
153
|
+
* @param styles The workbook style table (cellXfs + fonts/fills/borders).
|
|
154
|
+
* @param date1904 The 1904 date system flag (serial-to-date epoch).
|
|
155
|
+
* @param print The print-model knobs (print area, gridlines, title rows, …).
|
|
156
|
+
* @returns The body elements (one table block, or banded tables); empty for a
|
|
157
|
+
* blank or empty-print-area sheet.
|
|
158
|
+
*/
|
|
100
159
|
function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
101
160
|
if (worksheet.maxRow < 0 || worksheet.maxColumn < 0) return [];
|
|
102
161
|
let usedRow = -1;
|
|
@@ -128,11 +187,34 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
128
187
|
}
|
|
129
188
|
if (rowEnd < rowStart || colEnd < colStart) return [];
|
|
130
189
|
const MAX_GRID_COLS = 1024;
|
|
131
|
-
const
|
|
132
|
-
const
|
|
190
|
+
const MAX_GRID_ROWS = 5e4;
|
|
191
|
+
const MAX_GRID_CELLS = 1e6;
|
|
192
|
+
const wantRows = rowEnd - rowStart + 1;
|
|
193
|
+
const wantCols = colEnd - colStart + 1;
|
|
194
|
+
let colCount = Math.min(wantCols, MAX_GRID_COLS);
|
|
195
|
+
let rowCount = Math.max(1, Math.min(wantRows, MAX_GRID_ROWS, Math.floor(MAX_GRID_CELLS / colCount)));
|
|
196
|
+
if (rowCount < wantRows) rowCount = Math.max(1, lastContentRow(worksheet, rowStart, rowCount, colStart, colCount) + 1);
|
|
197
|
+
if (colCount < wantCols) colCount = Math.max(1, lastContentColumn(worksheet, rowStart, rowCount, colStart, colCount) + 1);
|
|
198
|
+
if (rowCount < wantRows) print.losses?.push({
|
|
199
|
+
severity: "dropped",
|
|
200
|
+
feature: FEATURES.tables,
|
|
201
|
+
detail: `grid clipped to the first ${rowCount} rows of ${wantRows} in the used range (memory guard)`,
|
|
202
|
+
...print.sheetName ? { where: `sheet "${print.sheetName}"` } : {}
|
|
203
|
+
});
|
|
204
|
+
if (colCount < wantCols) print.losses?.push({
|
|
205
|
+
severity: "dropped",
|
|
206
|
+
feature: FEATURES.tables,
|
|
207
|
+
detail: `grid clipped to the first ${colCount} columns of ${wantCols} in the used range (memory guard)`,
|
|
208
|
+
...print.sheetName ? { where: `sheet "${print.sheetName}"` } : {}
|
|
209
|
+
});
|
|
133
210
|
const rowWindowEnd = rowStart + rowCount - 1;
|
|
134
211
|
const colWindowEnd = colStart + colCount - 1;
|
|
212
|
+
const defaultRowTwips = Math.round((worksheet.defaultRowHeightPt ?? EXCEL_DEFAULT_ROW_HEIGHT_PT) * TWIPS_PER_POINT);
|
|
135
213
|
const rowHeightMap = /* @__PURE__ */ new Map();
|
|
214
|
+
for (let r = 0; r < rowCount; r++) rowHeightMap.set(r, {
|
|
215
|
+
heightTwips: defaultRowTwips,
|
|
216
|
+
heightRule: "atLeast"
|
|
217
|
+
});
|
|
136
218
|
for (const h of worksheet.rowHeights) {
|
|
137
219
|
const local = h.row - rowStart;
|
|
138
220
|
if (local < 0 || local >= rowCount) continue;
|
|
@@ -158,9 +240,11 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
158
240
|
const cEnd = Math.min(m.endColumn, colWindowEnd);
|
|
159
241
|
for (let r = Math.max(m.startRow, rowStart); r <= rEnd; r++) for (let c = Math.max(m.startColumn, colStart); c <= cEnd; c++) if (!(r === m.startRow && c === m.startColumn)) insideMerge.add(key(r, c));
|
|
160
242
|
}
|
|
161
|
-
const
|
|
243
|
+
const defaultColChars = worksheet.defaultColWidthChars ?? worksheet.baseColWidthChars;
|
|
244
|
+
const defaultColTwips = defaultColChars !== void 0 ? Math.round(defaultColChars * 105 + 75) : 960;
|
|
245
|
+
const columnWidths = new Array(colCount).fill(defaultColTwips);
|
|
162
246
|
for (const col of worksheet.columns) {
|
|
163
|
-
const twips = Math.round(col.widthChars * 105);
|
|
247
|
+
const twips = Math.round(col.widthChars * 105 + 75);
|
|
164
248
|
for (let abs = col.min - 1; abs <= col.max - 1; abs++) {
|
|
165
249
|
const i = abs - colStart;
|
|
166
250
|
if (i >= 0 && i < colCount) columnWidths[i] = twips;
|
|
@@ -173,6 +257,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
173
257
|
const scaled = printScale < .999;
|
|
174
258
|
const breakRows = new Set(worksheet.rowBreaks ?? []);
|
|
175
259
|
let textBudget = MAX_SHEET_TEXT_CHARS;
|
|
260
|
+
let textBudgetReported = false;
|
|
176
261
|
const runPropsByXf = /* @__PURE__ */ new Map();
|
|
177
262
|
const cellRunProps = (xf) => {
|
|
178
263
|
let props = runPropsByXf.get(xf);
|
|
@@ -200,7 +285,9 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
200
285
|
for (let r = 0; r < rowCount; r++) {
|
|
201
286
|
const absR = r + rowStart;
|
|
202
287
|
const cells = [];
|
|
288
|
+
const overflowed = /* @__PURE__ */ new Set();
|
|
203
289
|
for (let c = 0; c < colCount; c++) {
|
|
290
|
+
if (overflowed.has(c)) continue;
|
|
204
291
|
const absC = c + colStart;
|
|
205
292
|
const merge = mergeOrigins.get(key(absR, absC));
|
|
206
293
|
if (insideMerge.has(key(absR, absC)) && !merge) {
|
|
@@ -211,11 +298,22 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
211
298
|
const ws = cellMatrix[r]?.[c];
|
|
212
299
|
let text = ws ? resolveCellText(ws, sharedStrings, styles, date1904) : "";
|
|
213
300
|
const cfText = text.length > 0 ? text : void 0;
|
|
214
|
-
if (text.length > textBudget)
|
|
301
|
+
if (text.length > textBudget) {
|
|
302
|
+
text = text.slice(0, Math.max(0, textBudget));
|
|
303
|
+
if (!textBudgetReported) {
|
|
304
|
+
textBudgetReported = true;
|
|
305
|
+
print.losses?.push({
|
|
306
|
+
severity: "dropped",
|
|
307
|
+
feature: FEATURES.text,
|
|
308
|
+
detail: `per-sheet text budget of ${MAX_SHEET_TEXT_CHARS} characters exhausted; the remaining cells render empty`,
|
|
309
|
+
...print.sheetName ? { where: `sheet "${print.sheetName}"` } : {}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
215
313
|
textBudget -= text.length;
|
|
216
314
|
const xf = ws && ws.styleIndex !== void 0 ? styles.cellXfs[ws.styleIndex] : void 0;
|
|
217
315
|
let runProps = cellRunProps(xf);
|
|
218
|
-
const alignment =
|
|
316
|
+
const alignment = alignmentFromXf(xf, ws?.type);
|
|
219
317
|
let shading = xf ? shadingFromXf(xf, styles) : void 0;
|
|
220
318
|
const tableFmt = tableFormatByCell.get(key(absR, absC));
|
|
221
319
|
if (!shading && tableFmt?.shading) shading = tableFmt.shading;
|
|
@@ -236,14 +334,16 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
236
334
|
runProps = applyCfOverride(runProps, over);
|
|
237
335
|
}
|
|
238
336
|
}
|
|
337
|
+
let overflowSpan = 1;
|
|
239
338
|
const wrapText = xf?.alignment?.wrapText === true;
|
|
240
339
|
const rotation = xf?.alignment?.textRotation;
|
|
241
340
|
const rotated = rotation !== void 0 && rotation !== 0 && text.length > 0;
|
|
242
341
|
const shrinkToFit = xf?.alignment?.shrinkToFit === true && !wrapText && !rotated;
|
|
243
|
-
if (text.length > 0 && !merge && !wrapText && !rotated && !shrinkToFit && ws && (ws.type === "s" || ws.type === "str" || ws.type === "inlineStr") &&
|
|
342
|
+
if (text.length > 0 && !merge && !wrapText && !rotated && !shrinkToFit && ws && (ws.type === "s" || ws.type === "str" || ws.type === "inlineStr") && alignment === "left") {
|
|
244
343
|
let availTwips = columnWidths[c];
|
|
245
344
|
let cc = c + 1;
|
|
246
|
-
|
|
345
|
+
const neighbourIsFree = (col) => !cellHasContent(cellMatrix[r]?.[col]) && !cellPaintsSomething(cellMatrix[r]?.[col], styles) && !sparklineByCell.has(key(absR, col + colStart)) && !(dropdownRanges.length > 0 && rangesCover(dropdownRanges, absR, col + colStart));
|
|
346
|
+
while (cc < colCount && neighbourIsFree(cc)) {
|
|
247
347
|
availTwips += columnWidths[cc];
|
|
248
348
|
cc++;
|
|
249
349
|
}
|
|
@@ -251,6 +351,10 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
251
351
|
const charsFit = Math.max(1, Math.round(availTwips / 105));
|
|
252
352
|
if (text.length > charsFit) text = text.slice(0, charsFit);
|
|
253
353
|
}
|
|
354
|
+
if (cc > c + 1) {
|
|
355
|
+
overflowSpan = cc - c;
|
|
356
|
+
for (let k = c + 1; k < cc; k++) overflowed.add(k);
|
|
357
|
+
}
|
|
254
358
|
}
|
|
255
359
|
if (shrinkToFit && ws && text.length > 0) {
|
|
256
360
|
const charsFit = Math.max(1, columnWidths[c] / 105);
|
|
@@ -267,7 +371,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
267
371
|
const href = print.hyperlinks && print.hyperlinks.length > 0 ? hyperlinkUrlAt(print.hyperlinks, absR, absC) : void 0;
|
|
268
372
|
const visibleEndCol = merge ? Math.min(merge.endColumn, colWindowEnd) : 0;
|
|
269
373
|
const properties = {
|
|
270
|
-
...merge && visibleEndCol > merge.startColumn ? { colSpan: visibleEndCol - merge.startColumn + 1 } : {},
|
|
374
|
+
...merge && visibleEndCol > merge.startColumn ? { colSpan: visibleEndCol - merge.startColumn + 1 } : overflowSpan > 1 ? { colSpan: overflowSpan } : {},
|
|
271
375
|
...merge && Math.min(merge.endRow, rowWindowEnd) > merge.startRow ? { merge: "start" } : {},
|
|
272
376
|
...shading ? { shading } : {},
|
|
273
377
|
...dataBar ? { dataBar } : {},
|
|
@@ -292,7 +396,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
292
396
|
properties: runProps,
|
|
293
397
|
...href ? { href } : {}
|
|
294
398
|
}] : [];
|
|
295
|
-
const content = rotated ? stackedVerticalContent(text, runProps, href) : [{
|
|
399
|
+
const content = rotated ? stackedVerticalContent(text, runProps, href) : cellRuns.length === 0 ? [] : [{
|
|
296
400
|
kind: "paragraph",
|
|
297
401
|
paragraph: {
|
|
298
402
|
properties: paragraphProps,
|
|
@@ -326,6 +430,13 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
326
430
|
};
|
|
327
431
|
const centered = worksheet.printOptions?.horizontalCentered === true;
|
|
328
432
|
const tableProperties = {
|
|
433
|
+
defaultCellMargins: {
|
|
434
|
+
left: pt(EXCEL_CELL_INSET_PT),
|
|
435
|
+
right: pt(EXCEL_CELL_INSET_PT),
|
|
436
|
+
top: pt(0),
|
|
437
|
+
bottom: pt(0)
|
|
438
|
+
},
|
|
439
|
+
layout: "fixed",
|
|
329
440
|
...print.gridLines ? { borders: {
|
|
330
441
|
top: thin,
|
|
331
442
|
bottom: thin,
|
|
@@ -360,7 +471,7 @@ function worksheetToBody(worksheet, sharedStrings, styles, date1904, print) {
|
|
|
360
471
|
...tableProperties,
|
|
361
472
|
frozen
|
|
362
473
|
} : tableProperties,
|
|
363
|
-
grid:
|
|
474
|
+
grid: bandWidths.map((w) => twipsToPt(w)),
|
|
364
475
|
rows
|
|
365
476
|
}
|
|
366
477
|
}];
|
|
@@ -384,6 +495,17 @@ function makeVerticalContinuation(merge, colWindowEnd, absR, rowWindowEnd) {
|
|
|
384
495
|
}]
|
|
385
496
|
};
|
|
386
497
|
}
|
|
498
|
+
/**
|
|
499
|
+
* Resolve a cell's displayed text from its RAW stored value: shared-string and
|
|
500
|
+
* inline-string lookup, boolean → `TRUE`/`FALSE`, and the number-format pass
|
|
501
|
+
* (§18.8) for numeric cells. Error/string/date cells pass through verbatim.
|
|
502
|
+
*
|
|
503
|
+
* @param cell The parsed cell.
|
|
504
|
+
* @param sharedStrings The shared-string table for `t="s"` cells.
|
|
505
|
+
* @param styles The style table (for the cell's number format).
|
|
506
|
+
* @param date1904 The 1904 date system flag.
|
|
507
|
+
* @returns The resolved display string.
|
|
508
|
+
*/
|
|
387
509
|
function resolveCellText(cell, sharedStrings, styles, date1904) {
|
|
388
510
|
if (cell.type === "inlineStr") return cell.inlineText ?? "";
|
|
389
511
|
if (cell.type === "s") {
|
|
@@ -440,10 +562,29 @@ function applyCfOverride(base, o) {
|
|
|
440
562
|
...o.italic !== void 0 ? { italic: o.italic } : {}
|
|
441
563
|
};
|
|
442
564
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
565
|
+
/**
|
|
566
|
+
* ECMA-376 §18.8.1 — a cell's horizontal alignment, falling back to `general`.
|
|
567
|
+
*
|
|
568
|
+
* "General" is not "left": it is decided by the VALUE. Numbers, dates and times
|
|
569
|
+
* go right, booleans and errors centre, text goes left. Treating an absent
|
|
570
|
+
* `<alignment>` as no alignment at all left every number hugging the left edge
|
|
571
|
+
* of its column, tens of points from where Excel and LibreOffice put it — on
|
|
572
|
+
* the sheets where it matters most, since a column of figures is the common
|
|
573
|
+
* case.
|
|
574
|
+
*/
|
|
575
|
+
function alignmentFromXf(xf, type) {
|
|
576
|
+
const explicit = xf?.alignment ? mapAlignment(xf.alignment.horizontal) : void 0;
|
|
577
|
+
if (explicit) return explicit;
|
|
578
|
+
return generalAlignment(type);
|
|
579
|
+
}
|
|
580
|
+
function generalAlignment(type) {
|
|
581
|
+
switch (type) {
|
|
582
|
+
case "n":
|
|
583
|
+
case "d": return "right";
|
|
584
|
+
case "b":
|
|
585
|
+
case "e": return "center";
|
|
586
|
+
default: return "left";
|
|
587
|
+
}
|
|
447
588
|
}
|
|
448
589
|
function mapAlignment(h) {
|
|
449
590
|
if (!h) return void 0;
|
|
@@ -603,7 +744,7 @@ function buildSparklineLookup(worksheet, print) {
|
|
|
603
744
|
const host = parseAreaRef(sp.sqref);
|
|
604
745
|
const area = parseAreaRef(sp.dataRange);
|
|
605
746
|
if (!host || !area) continue;
|
|
606
|
-
const values = collectSeriesValues(resolveSeriesGrid(sp.dataRange, worksheet, print.sheetGrids).cells, area);
|
|
747
|
+
const values = collectSeriesValues(resolveSeriesGrid(sp.dataRange, worksheet, print.sheetGrids).cells, area, print);
|
|
607
748
|
if (values.length === 0 || values.every((v) => v === null)) continue;
|
|
608
749
|
out.set(key(host.startRow, host.startColumn), {
|
|
609
750
|
kind: sp.kind,
|
|
@@ -623,7 +764,7 @@ function resolveSeriesGrid(dataRange, current, sheetGrids) {
|
|
|
623
764
|
return sheetGrids.get(name) ?? current;
|
|
624
765
|
}
|
|
625
766
|
var MAX_SPARKLINE_POINTS = 1e3;
|
|
626
|
-
function collectSeriesValues(cells, area) {
|
|
767
|
+
function collectSeriesValues(cells, area, print) {
|
|
627
768
|
const byKey = /* @__PURE__ */ new Map();
|
|
628
769
|
for (const c of cells) {
|
|
629
770
|
if (c.row < area.startRow || c.row > area.endRow) continue;
|
|
@@ -632,7 +773,14 @@ function collectSeriesValues(cells, area) {
|
|
|
632
773
|
const v = Number(c.rawValue);
|
|
633
774
|
if (Number.isFinite(v)) byKey.set(key(c.row, c.column), v);
|
|
634
775
|
}
|
|
635
|
-
|
|
776
|
+
const cellCount = (area.endRow - area.startRow + 1) * (area.endColumn - area.startColumn + 1);
|
|
777
|
+
if (cellCount > MAX_SPARKLINE_POINTS) {
|
|
778
|
+
print.losses?.push({
|
|
779
|
+
severity: "degraded",
|
|
780
|
+
feature: FEATURES.charts,
|
|
781
|
+
detail: `sparkline range spans ${cellCount} cells (over ${MAX_SPARKLINE_POINTS}); plotted as the compact populated series, so blank gaps no longer hold their x-positions`,
|
|
782
|
+
...print.sheetName ? { where: `sheet "${print.sheetName}"` } : {}
|
|
783
|
+
});
|
|
636
784
|
const pts = [...byKey.entries()].map(([k, v]) => {
|
|
637
785
|
const [r, col] = k.split(",").map(Number);
|
|
638
786
|
return {
|
|
@@ -695,9 +843,65 @@ function buildTableFormatLookup(worksheet) {
|
|
|
695
843
|
function cellHasContent(cell) {
|
|
696
844
|
return !!cell && (cell.rawValue !== "" || cell.inlineText !== void 0);
|
|
697
845
|
}
|
|
846
|
+
/**
|
|
847
|
+
* The window-local index of the last row inside `[rowStart, rowStart+rowCount)`
|
|
848
|
+
* that carries anything — a value, or a merge reaching into the window. `-1`
|
|
849
|
+
* when the window is entirely blank.
|
|
850
|
+
*/
|
|
851
|
+
function lastContentRow(worksheet, rowStart, rowCount, colStart, colCount) {
|
|
852
|
+
const rowEnd = rowStart + rowCount - 1;
|
|
853
|
+
const colEnd = colStart + colCount - 1;
|
|
854
|
+
let last = -1;
|
|
855
|
+
for (const c of worksheet.cells) {
|
|
856
|
+
if (!cellHasContent(c)) continue;
|
|
857
|
+
if (c.row < rowStart || c.row > rowEnd || c.column < colStart || c.column > colEnd) continue;
|
|
858
|
+
if (c.row - rowStart > last) last = c.row - rowStart;
|
|
859
|
+
}
|
|
860
|
+
for (const m of worksheet.merges) {
|
|
861
|
+
if (m.startColumn > colEnd || m.endColumn < colStart) continue;
|
|
862
|
+
const reach = Math.min(m.endRow, rowEnd) - rowStart;
|
|
863
|
+
if (reach > last) last = reach;
|
|
864
|
+
}
|
|
865
|
+
return last;
|
|
866
|
+
}
|
|
867
|
+
/** The column twin of {@link lastContentRow}. */
|
|
868
|
+
function lastContentColumn(worksheet, rowStart, rowCount, colStart, colCount) {
|
|
869
|
+
const rowEnd = rowStart + rowCount - 1;
|
|
870
|
+
const colEnd = colStart + colCount - 1;
|
|
871
|
+
let last = -1;
|
|
872
|
+
for (const c of worksheet.cells) {
|
|
873
|
+
if (!cellHasContent(c)) continue;
|
|
874
|
+
if (c.row < rowStart || c.row > rowEnd || c.column < colStart || c.column > colEnd) continue;
|
|
875
|
+
if (c.column - colStart > last) last = c.column - colStart;
|
|
876
|
+
}
|
|
877
|
+
for (const m of worksheet.merges) {
|
|
878
|
+
if (m.startRow > rowEnd || m.endRow < rowStart) continue;
|
|
879
|
+
const reach = Math.min(m.endColumn, colEnd) - colStart;
|
|
880
|
+
if (reach > last) last = reach;
|
|
881
|
+
}
|
|
882
|
+
return last;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Whether an EMPTY cell still draws something of its own — a fill or a border.
|
|
886
|
+
*
|
|
887
|
+
* Such a cell cannot be swallowed by a neighbour's overflowing text: the span
|
|
888
|
+
* that gives the text its width would take the paint with it.
|
|
889
|
+
*/
|
|
890
|
+
function cellPaintsSomething(cell, styles) {
|
|
891
|
+
if (!cell || cell.styleIndex === void 0) return false;
|
|
892
|
+
const xf = styles.cellXfs[cell.styleIndex];
|
|
893
|
+
if (!xf) return false;
|
|
894
|
+
return shadingFromXf(xf, styles) !== void 0 || bordersFromXf(xf, styles) !== void 0;
|
|
895
|
+
}
|
|
698
896
|
var SLICER_WIDTH_PT = 108;
|
|
699
897
|
var SLICER_ROW_PT = 16;
|
|
700
898
|
var SLICER_UNSELECTED_HEX = "F2F2F2";
|
|
899
|
+
/**
|
|
900
|
+
* Project a slicer panel (E-SHEET SV2) into a styled mini-{@link Table} emitted
|
|
901
|
+
* after the grid: a caption header spanning the button columns, then one button
|
|
902
|
+
* cell per item — the slicer accent fill + white text when selected, a light
|
|
903
|
+
* band when not; the last row padded so every row keeps the column count.
|
|
904
|
+
*/
|
|
701
905
|
function slicerTable(slicer) {
|
|
702
906
|
const cols = Math.max(1, slicer.columnCount);
|
|
703
907
|
const colWidthPt = SLICER_WIDTH_PT / cols;
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { SheetRichRun } from '../core/spreadsheet-model/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The flattened text of every shared string (a cell with `t="s"` indexes into it),
|
|
4
|
+
* plus — for the strings that carry per-run formatting — the parsed rich runs
|
|
5
|
+
* (E-SHEET W6). `runs[i]` is undefined unless si `i` has ≥ 2 runs OR a single run
|
|
6
|
+
* that actually sets formatting, so the common plain-text case stays cheap.
|
|
7
|
+
*/
|
|
2
8
|
export interface SharedStrings {
|
|
9
|
+
/** The flattened text of each shared string, parallel to the `<si>` order. */
|
|
3
10
|
readonly texts: ReadonlyArray<string>;
|
|
11
|
+
/** Per-index rich runs, parallel to {@link SharedStrings.texts}; `undefined` for plain strings. */
|
|
4
12
|
readonly runs: ReadonlyArray<ReadonlyArray<SheetRichRun> | undefined>;
|
|
5
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse `xl/sharedStrings.xml` (§18.4.8) into the deduplicated string table plus,
|
|
16
|
+
* for rich strings, their per-run formatting. Each string is capped to the Excel
|
|
17
|
+
* cell limit (32 767 chars).
|
|
18
|
+
*/
|
|
6
19
|
export declare function parseSharedStrings(data: Uint8Array): SharedStrings;
|
|
@@ -14,6 +14,11 @@ var MAX_CELL_CHARS = 32767;
|
|
|
14
14
|
function capLen(s) {
|
|
15
15
|
return s.length > MAX_CELL_CHARS ? s.slice(0, MAX_CELL_CHARS) : s;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse `xl/sharedStrings.xml` (§18.4.8) into the deduplicated string table plus,
|
|
19
|
+
* for rich strings, their per-run formatting. Each string is capped to the Excel
|
|
20
|
+
* cell limit (32 767 chars).
|
|
21
|
+
*/
|
|
17
22
|
function parseSharedStrings(data) {
|
|
18
23
|
const xml = decoder.decode(data);
|
|
19
24
|
const sst = parser.parse(xml)["sst"];
|
|
@@ -1,21 +1,55 @@
|
|
|
1
1
|
import { OpcPackage } from '../core/opc/index.js';
|
|
2
2
|
import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
|
|
3
|
+
/** §20.5 — a chart frame anchored over the grid, sized from its cell-range anchor. */
|
|
3
4
|
export interface SheetChartRef {
|
|
5
|
+
/**
|
|
6
|
+
* The resolved chart part path (`'xl/charts/chart1.xml'`) — globally unique, used
|
|
7
|
+
* as the FlowDoc charts key and the `ChartBlock.chartRelId`.
|
|
8
|
+
*/
|
|
4
9
|
readonly chartPartPath: string;
|
|
5
10
|
readonly widthPt: number;
|
|
6
11
|
readonly heightPt: number;
|
|
12
|
+
/** Anchor top row (0-based) — used only to order charts on the sheet. */
|
|
7
13
|
readonly anchorRow: number;
|
|
8
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* §20.5.2.1 `xdr:pic` — a picture anchored over the grid. The reader reads the
|
|
17
|
+
* resolved media part's bytes into the SheetDoc resource store.
|
|
18
|
+
*/
|
|
9
19
|
export interface SheetPicture {
|
|
20
|
+
/** The resolved media part path; the reader loads its bytes into the resource store. */
|
|
10
21
|
readonly imagePartPath: string;
|
|
11
22
|
readonly widthPt: number;
|
|
12
23
|
readonly heightPt: number;
|
|
24
|
+
/** Anchor top row (0-based) — used only to order pictures on the sheet. */
|
|
13
25
|
readonly anchorRow: number;
|
|
14
26
|
}
|
|
27
|
+
/** Both kinds of anchored frame the drawing yields, anchor-ordered. */
|
|
15
28
|
export interface SheetDrawing {
|
|
16
29
|
readonly charts: Array<SheetChartRef>;
|
|
17
30
|
readonly pictures: Array<SheetPicture>;
|
|
18
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Parse a `xl/drawings/drawingN.xml` part (§20.5.2.35/.33/.1 — `xdr:twoCellAnchor`
|
|
34
|
+
* / `oneCellAnchor` / `absoluteAnchor`) into the {@link SheetDrawing} it yields.
|
|
35
|
+
* Each anchor frames either a chart (`graphicFrame`) or a picture (`xdr:pic`); both
|
|
36
|
+
* are sized from the anchor and returned anchor-ordered.
|
|
37
|
+
*
|
|
38
|
+
* @param drawingXml The drawing part bytes.
|
|
39
|
+
* @param drawingPartPath The drawing part path, for resolving its relationships.
|
|
40
|
+
* @param pkg The OPC package, used to resolve relId → part path.
|
|
41
|
+
* @param worksheet The host worksheet, for the column/row track geometry.
|
|
42
|
+
*/
|
|
19
43
|
export declare function parseSheetDrawing(drawingXml: Uint8Array, drawingPartPath: string, pkg: OpcPackage, worksheet: ParsedWorksheet): SheetDrawing;
|
|
44
|
+
/**
|
|
45
|
+
* Build a `col → width-in-points` accessor: a `<col>` override (Excel "chars")
|
|
46
|
+
* where present, else the default — the same conversions the print model uses.
|
|
47
|
+
* Exported so the sheet-shape parser (E-SHEET W2) sizes shape anchors with the same
|
|
48
|
+
* track geometry.
|
|
49
|
+
*/
|
|
20
50
|
export declare function makeColWidthPt(ws: ParsedWorksheet): (col: number) => number;
|
|
51
|
+
/**
|
|
52
|
+
* Build a `row → height-in-points` accessor: the explicit row height where present,
|
|
53
|
+
* else the default. Pairs with {@link makeColWidthPt} for the anchor track geometry.
|
|
54
|
+
*/
|
|
21
55
|
export declare function makeRowHeightPt(ws: ParsedWorksheet): (row: number) => number;
|
|
@@ -10,6 +10,17 @@ var parser = new XMLParser({
|
|
|
10
10
|
parseTagValue: false
|
|
11
11
|
});
|
|
12
12
|
var TWIPS_PER_PT = 20;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a `xl/drawings/drawingN.xml` part (§20.5.2.35/.33/.1 — `xdr:twoCellAnchor`
|
|
15
|
+
* / `oneCellAnchor` / `absoluteAnchor`) into the {@link SheetDrawing} it yields.
|
|
16
|
+
* Each anchor frames either a chart (`graphicFrame`) or a picture (`xdr:pic`); both
|
|
17
|
+
* are sized from the anchor and returned anchor-ordered.
|
|
18
|
+
*
|
|
19
|
+
* @param drawingXml The drawing part bytes.
|
|
20
|
+
* @param drawingPartPath The drawing part path, for resolving its relationships.
|
|
21
|
+
* @param pkg The OPC package, used to resolve relId → part path.
|
|
22
|
+
* @param worksheet The host worksheet, for the column/row track geometry.
|
|
23
|
+
*/
|
|
13
24
|
function parseSheetDrawing(drawingXml, drawingPartPath, pkg, worksheet) {
|
|
14
25
|
const root = parser.parse(new TextDecoder().decode(drawingXml))["wsDr"];
|
|
15
26
|
if (!root || typeof root !== "object") return {
|
|
@@ -120,12 +131,22 @@ function spanPt(from, fromOffPt, to, toOffPt, trackPt) {
|
|
|
120
131
|
for (let i = from; i < to; i++) span += trackPt(i);
|
|
121
132
|
return span - fromOffPt + toOffPt;
|
|
122
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Build a `col → width-in-points` accessor: a `<col>` override (Excel "chars")
|
|
136
|
+
* where present, else the default — the same conversions the print model uses.
|
|
137
|
+
* Exported so the sheet-shape parser (E-SHEET W2) sizes shape anchors with the same
|
|
138
|
+
* track geometry.
|
|
139
|
+
*/
|
|
123
140
|
function makeColWidthPt(ws) {
|
|
124
141
|
return (col) => {
|
|
125
142
|
for (const c of ws.columns) if (col >= c.min - 1 && col <= c.max - 1) return c.widthChars * 105 / TWIPS_PER_PT;
|
|
126
143
|
return 960 / TWIPS_PER_PT;
|
|
127
144
|
};
|
|
128
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Build a `row → height-in-points` accessor: the explicit row height where present,
|
|
148
|
+
* else the default. Pairs with {@link makeColWidthPt} for the anchor track geometry.
|
|
149
|
+
*/
|
|
129
150
|
function makeRowHeightPt(ws) {
|
|
130
151
|
return (row) => {
|
|
131
152
|
for (const r of ws.rowHeights) if (r.row === row) return r.heightPt;
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { ShapeBlock } from '../core/document-model/index.js';
|
|
2
2
|
import { ColorResolver } from '../core/drawingml/colors.js';
|
|
3
3
|
import { ParsedWorksheet } from '../core/spreadsheet-model/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parse a drawing's `xdr:sp` shape anchors (§20.5.2.30) into anchor-ordered
|
|
6
|
+
* {@link ShapeBlock}s (E-SHEET W2), reusing the shared DrawingML geometry / fill /
|
|
7
|
+
* line / text readers. A shape's box comes from its sheet anchor (from/to tracks),
|
|
8
|
+
* not its `a:xfrm`. Returns `[]` when the drawing has no shapes (chart/picture-only),
|
|
9
|
+
* so the reader's gate keeps non-shape sheets off this second parse.
|
|
10
|
+
*
|
|
11
|
+
* @param drawingXml The drawing part bytes (re-parsed via `parseXml` for the
|
|
12
|
+
* preserveOrder tree the shape readers expect).
|
|
13
|
+
* @param worksheet The host worksheet, for the column/row track geometry.
|
|
14
|
+
* @param colors The theme colour resolver threaded into fill/line parsing.
|
|
15
|
+
*/
|
|
4
16
|
export declare function parseSheetShapes(drawingXml: Uint8Array, worksheet: ParsedWorksheet, colors: ColorResolver): Array<ShapeBlock>;
|
|
@@ -10,6 +10,18 @@ var ANCHOR_KINDS = [
|
|
|
10
10
|
"xdr:oneCellAnchor",
|
|
11
11
|
"xdr:absoluteAnchor"
|
|
12
12
|
];
|
|
13
|
+
/**
|
|
14
|
+
* Parse a drawing's `xdr:sp` shape anchors (§20.5.2.30) into anchor-ordered
|
|
15
|
+
* {@link ShapeBlock}s (E-SHEET W2), reusing the shared DrawingML geometry / fill /
|
|
16
|
+
* line / text readers. A shape's box comes from its sheet anchor (from/to tracks),
|
|
17
|
+
* not its `a:xfrm`. Returns `[]` when the drawing has no shapes (chart/picture-only),
|
|
18
|
+
* so the reader's gate keeps non-shape sheets off this second parse.
|
|
19
|
+
*
|
|
20
|
+
* @param drawingXml The drawing part bytes (re-parsed via `parseXml` for the
|
|
21
|
+
* preserveOrder tree the shape readers expect).
|
|
22
|
+
* @param worksheet The host worksheet, for the column/row track geometry.
|
|
23
|
+
* @param colors The theme colour resolver threaded into fill/line parsing.
|
|
24
|
+
*/
|
|
13
25
|
function parseSheetShapes(drawingXml, worksheet, colors) {
|
|
14
26
|
const wsDr = parseXml(drawingXml).find((n) => poIs(n, "xdr:wsDr"));
|
|
15
27
|
if (!wsDr) return [];
|
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import { FlowDoc } from '../core/ir/flow.js';
|
|
2
|
+
import { Loss } from '../core/ir/loss.js';
|
|
2
3
|
import { SheetDoc } from '../core/ir/sheet.js';
|
|
4
|
+
/**
|
|
5
|
+
* Projection knobs (E-SHEET W9).
|
|
6
|
+
*/
|
|
3
7
|
export interface ProjectSheetOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The injected reference date that drives conditional-format `timePeriod`
|
|
10
|
+
* windows and `TODAY()`/`NOW()` in `expression` rules. Omitted ⇒ those
|
|
11
|
+
* clock-relative constructs no-op, so the projection stays deterministic and
|
|
12
|
+
* byte-identical to before.
|
|
13
|
+
*/
|
|
4
14
|
readonly now?: Date;
|
|
15
|
+
/**
|
|
16
|
+
* Sink the projection writes its {@link Loss} entries into — the print
|
|
17
|
+
* model's defence-in-depth caps (grid size, per-sheet text budget, sparkline
|
|
18
|
+
* range) fire on pathological input, and a cap that fires without saying so
|
|
19
|
+
* is a silent wrongness. {@link readXlsx} always supplies one and returns it
|
|
20
|
+
* as the read result's loss report; omitted ⇒ the caps still apply but go
|
|
21
|
+
* unreported.
|
|
22
|
+
*/
|
|
23
|
+
readonly losses?: Array<Loss>;
|
|
5
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Project a {@link SheetDoc} into a {@link FlowDoc} (E-SHEET SA2): each grid sheet
|
|
27
|
+
* becomes flow blocks (a table + chart/picture/shape/slicer frames, then comment
|
|
28
|
+
* / control listings), with sheets after the first starting on a new page. The
|
|
29
|
+
* first sheet's page geometry + header/footer drive the document section.
|
|
30
|
+
*
|
|
31
|
+
* @param sheet The SpreadsheetML IR tree.
|
|
32
|
+
* @param options Projection knobs (the W9 reference date).
|
|
33
|
+
* @returns The format-neutral flow document the render path consumes.
|
|
34
|
+
*/
|
|
6
35
|
export declare function projectSheetDoc(sheet: SheetDoc, options?: ProjectSheetOptions): FlowDoc;
|