reamkit 1.15.1 → 1.15.2
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 +9 -0
- package/dist/esm/core/bytes.js +9 -0
- 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 +46 -0
- 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 +281 -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 +26 -0
- 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 +56 -0
- package/dist/esm/excel/print-model.js +43 -0
- 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 +19 -0
- package/dist/esm/excel/sheet-to-flow.js +10 -0
- 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 +9 -0
- 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 +26 -0
- package/dist/esm/excel/xlsx-reader.js +26 -0
- 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 +117 -2
- 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 +21 -0
- 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 +16 -0
- 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 +1 -1
|
@@ -30,6 +30,16 @@ function parseSingleArea(token) {
|
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract the repeated-row range from an `_xlnm.Print_Titles` value, e.g.
|
|
35
|
+
* `"Sheet1!$1:$2"` (rows 1-2) or `"Sheet1!$A:$B,Sheet1!$1:$1"` (cols A-B + row 1).
|
|
36
|
+
* Only the ROW range is recovered — column titles repeat across horizontal page
|
|
37
|
+
* breaks, which the layout does not paginate.
|
|
38
|
+
*
|
|
39
|
+
* @param value The defined-name value.
|
|
40
|
+
* @returns The 0-indexed inclusive row range, or `undefined` when no pure row
|
|
41
|
+
* range is present.
|
|
42
|
+
*/
|
|
33
43
|
function parseTitleRowRange(value) {
|
|
34
44
|
if (!value) return void 0;
|
|
35
45
|
for (const token of value.split(",")) {
|
|
@@ -45,6 +55,16 @@ function parseTitleRowRange(value) {
|
|
|
45
55
|
};
|
|
46
56
|
}
|
|
47
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a `<definedName>` area value (§18.2.5 / §18.17) to the bounding box of
|
|
60
|
+
* every parseable area. A value may be a single cell (`"Sheet1!$A$1"`), a range
|
|
61
|
+
* (`"Sheet1!$A$1:$D$20"`), or several comma-separated areas; the sheet qualifier
|
|
62
|
+
* and `$` absolute markers are stripped. Multiple disjoint areas collapse to one
|
|
63
|
+
* enclosing box (a faithful approximation — Excel prints them in sequence).
|
|
64
|
+
*
|
|
65
|
+
* @param value The defined-name value (e.g. a `_xlnm.Print_Area`).
|
|
66
|
+
* @returns The 0-indexed inclusive bounding box, or `undefined` when no area parses.
|
|
67
|
+
*/
|
|
48
68
|
function parseAreaRef(value) {
|
|
49
69
|
if (!value) return void 0;
|
|
50
70
|
let box;
|
|
@@ -1,6 +1,19 @@
|
|
|
1
|
+
/** A form control's resolved state from its `ctrlProp` part (E-SHEET W8). */
|
|
1
2
|
export interface FormControlProps {
|
|
3
|
+
/**
|
|
4
|
+
* §18.18.18-ish `ST_ObjectType` — `CheckBox`, `Radio`, `Spin`, `Scroll`, `Drop`,
|
|
5
|
+
* `List`, `Buttons`, `Label`, `GBox`, `Dialog`, `EditBox`, `Note` … (the
|
|
6
|
+
* producer's spelling kept).
|
|
7
|
+
*/
|
|
2
8
|
readonly objectType?: string;
|
|
9
|
+
/** Checked state for a check/option button. */
|
|
3
10
|
readonly checked?: boolean;
|
|
11
|
+
/** Current value for a spin / scroll / list control. */
|
|
4
12
|
readonly value?: number;
|
|
5
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse a `xl/ctrlProps/ctrlProp#.xml` part (a single `<formControlPr>`) into the
|
|
16
|
+
* control's {@link FormControlProps} — its `objectType` plus the bit of state the
|
|
17
|
+
* listing shows (`checked` for check/option buttons, `val` for spin/scroll/list).
|
|
18
|
+
*/
|
|
6
19
|
export declare function parseFormControlProps(data: Uint8Array): FormControlProps;
|
|
@@ -7,6 +7,11 @@ var parser = new XMLParser({
|
|
|
7
7
|
parseAttributeValue: false,
|
|
8
8
|
removeNSPrefix: true
|
|
9
9
|
});
|
|
10
|
+
/**
|
|
11
|
+
* Parse a `xl/ctrlProps/ctrlProp#.xml` part (a single `<formControlPr>`) into the
|
|
12
|
+
* control's {@link FormControlProps} — its `objectType` plus the bit of state the
|
|
13
|
+
* listing shows (`checked` for check/option buttons, `val` for spin/scroll/list).
|
|
14
|
+
*/
|
|
10
15
|
function parseFormControlProps(data) {
|
|
11
16
|
const pr = parser.parse(decoder.decode(data))["formControlPr"];
|
|
12
17
|
const obj = pr && typeof pr === "object" ? pr : void 0;
|
|
@@ -1,11 +1,48 @@
|
|
|
1
1
|
import { FValue, Rect, Scalar } from './value.js';
|
|
2
|
+
/**
|
|
3
|
+
* Everything a formula needs from the world outside its own syntax tree (E-SHEET
|
|
4
|
+
* W9): the grid's cached cell values, the injected reference date, and the workbook
|
|
5
|
+
* date epoch — optionally extended with cross-sheet / defined-name resolution. The
|
|
6
|
+
* context is the seam that keeps the evaluator pure and deterministic: it never
|
|
7
|
+
* reads the wall clock or recomputes a cell, only looking up values Excel already
|
|
8
|
+
* cached.
|
|
9
|
+
*/
|
|
2
10
|
export interface EvalContext {
|
|
11
|
+
/**
|
|
12
|
+
* The cached value of the cell at `(row, col)` — both absolute, 0-indexed. An
|
|
13
|
+
* absent or empty cell yields a blank scalar; the evaluator never recurses into a
|
|
14
|
+
* referenced cell's own formula (there is none stored — we have only the cached
|
|
15
|
+
* value), which is exactly why no recalculation engine is needed.
|
|
16
|
+
*/
|
|
3
17
|
readonly getCell: (row: number, col: number) => Scalar;
|
|
18
|
+
/**
|
|
19
|
+
* Visit every POPULATED cell within a rectangle (blanks are skipped — they
|
|
20
|
+
* contribute nothing to SUM/COUNT/COUNTIF). Iterating the sparse cell set keeps an
|
|
21
|
+
* aggregate over a whole-column range O(populated), not O(rows), mirroring the
|
|
22
|
+
* colorScale extent scan. The order is unspecified.
|
|
23
|
+
*/
|
|
4
24
|
readonly eachCell: (rect: Rect, visit: (row: number, col: number, value: Scalar) => void) => void;
|
|
25
|
+
/**
|
|
26
|
+
* The reference "today" as an Excel serial day (`options.now`, converted with the
|
|
27
|
+
* workbook epoch). `TODAY()`/`NOW()` and the `timePeriod` windows read it.
|
|
28
|
+
* undefined ⇒ those clock-relative constructs yield `#VALUE!` / no-op, preserving
|
|
29
|
+
* determinism when the caller supplies no date.
|
|
30
|
+
*/
|
|
5
31
|
readonly nowSerial: number | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* false = 1900 epoch (the default), true = 1904 epoch. Date functions
|
|
34
|
+
* (YEAR/MONTH/DAY/DATE/WEEKDAY/…) convert serials ↔ calendar with it.
|
|
35
|
+
*/
|
|
6
36
|
readonly date1904: boolean;
|
|
37
|
+
/** A sheet name (case-insensitive) → its 0-based workbook index, or undefined. */
|
|
7
38
|
readonly sheetIndex?: (name: string) => number | undefined;
|
|
39
|
+
/** {@link EvalContext.getCell}, but on a specific sheet by index (cross-sheet references). */
|
|
8
40
|
readonly getCellOn?: (sheet: number, row: number, col: number) => Scalar;
|
|
41
|
+
/** {@link EvalContext.eachCell}, but on a specific sheet by index (cross-sheet references). */
|
|
9
42
|
readonly eachCellOn?: (sheet: number, rect: Rect, visit: (row: number, col: number, value: Scalar) => void) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a defined name (case-insensitive) to its target — a reference value (a
|
|
45
|
+
* Rect, optionally on another sheet) or a literal scalar; undefined ⇒ `#NAME?`.
|
|
46
|
+
*/
|
|
10
47
|
readonly resolveName?: (name: string) => FValue | undefined;
|
|
11
48
|
}
|
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
import { TimePeriodKind } from '../../core/spreadsheet-model/index.js';
|
|
2
|
+
/** The UTC calendar fields an Excel serial decomposes into. */
|
|
2
3
|
export interface DateParts {
|
|
3
4
|
readonly year: number;
|
|
5
|
+
/** 1-indexed month (January = 1). */
|
|
4
6
|
readonly month: number;
|
|
5
7
|
readonly day: number;
|
|
8
|
+
/** Day of week, 0 = Sunday … 6 = Saturday (Excel WEEKDAY type 1 minus 1). */
|
|
6
9
|
readonly dow: number;
|
|
7
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Decompose an Excel serial into UTC calendar parts. A fractional serial is
|
|
13
|
+
* floored to its day first (the calendar date is time-of-day independent).
|
|
14
|
+
*/
|
|
8
15
|
export declare function serialToParts(serial: number, date1904: boolean): DateParts;
|
|
16
|
+
/**
|
|
17
|
+
* A UTC Date's calendar day → integer Excel serial. Reads the Date's UTC date
|
|
18
|
+
* parts (not its instant), so a caller passing `new Date('2026-06-17')`
|
|
19
|
+
* (UTC midnight) maps to that day regardless of the host time zone.
|
|
20
|
+
*/
|
|
9
21
|
export declare function serialFromDate(d: Date, date1904: boolean): number;
|
|
22
|
+
/**
|
|
23
|
+
* `(year, month1, day)` → integer serial. Excel's `DATE` rolls out-of-range
|
|
24
|
+
* months and days (`DATE(2024,13,1)` = 2025-01-01); `Date.UTC` already
|
|
25
|
+
* normalises, so this inherits the same behaviour.
|
|
26
|
+
*/
|
|
10
27
|
export declare function serialFromYmd(year: number, month1: number, day: number, date1904: boolean): number;
|
|
28
|
+
/**
|
|
29
|
+
* §18.3.1.10 `timePeriod` — does a cell's date fall in the window relative to
|
|
30
|
+
* `nowSerial` (the injected reference day)? Windows match Excel's built-in
|
|
31
|
+
* rules: the week runs Sunday..Saturday; "last 7 days" is today and the previous
|
|
32
|
+
* six. Both serials are floored to whole days before comparison.
|
|
33
|
+
*/
|
|
11
34
|
export declare function timePeriodMatches(period: TimePeriodKind, cellSerial: number, nowSerial: number, date1904: boolean): boolean;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { excelSerialFromUtcParts, excelSerialToDate } from "../number-format.js";
|
|
2
2
|
//#region src/excel/formula/dates.ts
|
|
3
|
+
/**
|
|
4
|
+
* Decompose an Excel serial into UTC calendar parts. A fractional serial is
|
|
5
|
+
* floored to its day first (the calendar date is time-of-day independent).
|
|
6
|
+
*/
|
|
3
7
|
function serialToParts(serial, date1904) {
|
|
4
8
|
const d = excelSerialToDate(Math.floor(serial), date1904);
|
|
5
9
|
return {
|
|
@@ -9,12 +13,28 @@ function serialToParts(serial, date1904) {
|
|
|
9
13
|
dow: d.getUTCDay()
|
|
10
14
|
};
|
|
11
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* A UTC Date's calendar day → integer Excel serial. Reads the Date's UTC date
|
|
18
|
+
* parts (not its instant), so a caller passing `new Date('2026-06-17')`
|
|
19
|
+
* (UTC midnight) maps to that day regardless of the host time zone.
|
|
20
|
+
*/
|
|
12
21
|
function serialFromDate(d, date1904) {
|
|
13
22
|
return excelSerialFromUtcParts(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), date1904);
|
|
14
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* `(year, month1, day)` → integer serial. Excel's `DATE` rolls out-of-range
|
|
26
|
+
* months and days (`DATE(2024,13,1)` = 2025-01-01); `Date.UTC` already
|
|
27
|
+
* normalises, so this inherits the same behaviour.
|
|
28
|
+
*/
|
|
15
29
|
function serialFromYmd(year, month1, day, date1904) {
|
|
16
30
|
return excelSerialFromUtcParts(year, month1 - 1, day, date1904);
|
|
17
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* §18.3.1.10 `timePeriod` — does a cell's date fall in the window relative to
|
|
34
|
+
* `nowSerial` (the injected reference day)? Windows match Excel's built-in
|
|
35
|
+
* rules: the week runs Sunday..Saturday; "last 7 days" is today and the previous
|
|
36
|
+
* six. Both serials are floored to whole days before comparison.
|
|
37
|
+
*/
|
|
18
38
|
function timePeriodMatches(period, cellSerial, nowSerial, date1904) {
|
|
19
39
|
const cell = Math.floor(cellSerial);
|
|
20
40
|
const today = Math.floor(nowSerial);
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import { Ast } from './parser.js';
|
|
2
2
|
import { EvalContext } from './context.js';
|
|
3
3
|
import { FValue } from './value.js';
|
|
4
|
+
/**
|
|
5
|
+
* The cell's offset from the rule origin, added to UNANCHORED reference axes.
|
|
6
|
+
* `curRow`/`curCol` carry the ABSOLUTE current cell (origin + delta) so `ROW()`/
|
|
7
|
+
* `COLUMN()` with no argument can report it; absent ({@link NO_SHIFT}) ⇒ those
|
|
8
|
+
* no-arg forms have no cell to name and yield `#VALUE!`.
|
|
9
|
+
*/
|
|
4
10
|
export interface Shift {
|
|
11
|
+
/** Row delta from the rule origin, added to an unanchored row axis. */
|
|
5
12
|
readonly dRow: number;
|
|
13
|
+
/** Column delta from the rule origin, added to an unanchored column axis. */
|
|
6
14
|
readonly dCol: number;
|
|
15
|
+
/** The absolute current row, for no-arg `ROW()`; absent ⇒ `#VALUE!`. */
|
|
7
16
|
readonly curRow?: number;
|
|
17
|
+
/** The absolute current column, for no-arg `COLUMN()`; absent ⇒ `#VALUE!`. */
|
|
8
18
|
readonly curCol?: number;
|
|
9
19
|
}
|
|
20
|
+
/** The zero shift — no offset and no current cell (no-arg `ROW`/`COLUMN` → `#VALUE!`). */
|
|
10
21
|
export declare const NO_SHIFT: Shift;
|
|
22
|
+
/**
|
|
23
|
+
* Evaluate an {@link Ast} against an `EvalContext` and a per-cell {@link Shift},
|
|
24
|
+
* yielding an `FValue` (a scalar, a reference, or an array). Cells/ranges
|
|
25
|
+
* evaluate to reference values; scalar operators dereference them.
|
|
26
|
+
*
|
|
27
|
+
* @param ast The syntax tree to evaluate.
|
|
28
|
+
* @param ctx The evaluation context (grid access, defined names, date system).
|
|
29
|
+
* @param shift The current cell's offset from the rule origin.
|
|
30
|
+
* @returns The computed value.
|
|
31
|
+
*/
|
|
11
32
|
export declare function evaluate(ast: Ast, ctx: EvalContext, shift: Shift): FValue;
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { bool, deref, err, num, str, toNumber, toText } from "./value.js";
|
|
2
2
|
import { callFn } from "./functions.js";
|
|
3
3
|
//#region src/excel/formula/eval.ts
|
|
4
|
+
/** The zero shift — no offset and no current cell (no-arg `ROW`/`COLUMN` → `#VALUE!`). */
|
|
4
5
|
var NO_SHIFT = {
|
|
5
6
|
dRow: 0,
|
|
6
7
|
dCol: 0
|
|
7
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Evaluate an {@link Ast} against an `EvalContext` and a per-cell {@link Shift},
|
|
11
|
+
* yielding an `FValue` (a scalar, a reference, or an array). Cells/ranges
|
|
12
|
+
* evaluate to reference values; scalar operators dereference them.
|
|
13
|
+
*
|
|
14
|
+
* @param ast The syntax tree to evaluate.
|
|
15
|
+
* @param ctx The evaluation context (grid access, defined names, date system).
|
|
16
|
+
* @param shift The current cell's offset from the rule origin.
|
|
17
|
+
* @returns The computed value.
|
|
18
|
+
*/
|
|
8
19
|
function evaluate(ast, ctx, shift) {
|
|
9
20
|
switch (ast.k) {
|
|
10
21
|
case "num": return num(ast.v);
|
|
@@ -3,5 +3,17 @@ import { EvalContext } from './context.js';
|
|
|
3
3
|
import { Shift } from './eval.js';
|
|
4
4
|
import { FValue } from './value.js';
|
|
5
5
|
type Ev = (a: Ast) => FValue;
|
|
6
|
+
/**
|
|
7
|
+
* Dispatch a built-in formula function by name, evaluating its arguments through
|
|
8
|
+
* `ev`. An unknown or misused function returns `#NAME?`/`#VALUE!` so the calling
|
|
9
|
+
* conditional-format rule simply does not apply — Ream never guesses.
|
|
10
|
+
*
|
|
11
|
+
* @param name The upper-cased function name (e.g. `SUM`, `VLOOKUP`).
|
|
12
|
+
* @param args The unevaluated argument expressions.
|
|
13
|
+
* @param ev Evaluator for one argument (closes over the context + shift).
|
|
14
|
+
* @param ctx The evaluation context (grid access, defined names, date system).
|
|
15
|
+
* @param shift The per-cell shift (used by no-arg `ROW`/`COLUMN`).
|
|
16
|
+
* @returns The function's result value.
|
|
17
|
+
*/
|
|
6
18
|
export declare function callFn(name: string, args: ReadonlyArray<Ast>, ev: Ev, ctx: EvalContext, shift: Shift): FValue;
|
|
7
19
|
export {};
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { serialFromYmd, serialToParts } from "./dates.js";
|
|
2
2
|
import { arrEach, bool, deref, err, isErr, num, refEach, refGet, str, toBool, toNumber, toText } from "./value.js";
|
|
3
3
|
//#region src/excel/formula/functions.ts
|
|
4
|
+
/**
|
|
5
|
+
* Dispatch a built-in formula function by name, evaluating its arguments through
|
|
6
|
+
* `ev`. An unknown or misused function returns `#NAME?`/`#VALUE!` so the calling
|
|
7
|
+
* conditional-format rule simply does not apply — Ream never guesses.
|
|
8
|
+
*
|
|
9
|
+
* @param name The upper-cased function name (e.g. `SUM`, `VLOOKUP`).
|
|
10
|
+
* @param args The unevaluated argument expressions.
|
|
11
|
+
* @param ev Evaluator for one argument (closes over the context + shift).
|
|
12
|
+
* @param ctx The evaluation context (grid access, defined names, date system).
|
|
13
|
+
* @param shift The per-cell shift (used by no-arg `ROW`/`COLUMN`).
|
|
14
|
+
* @returns The function's result value.
|
|
15
|
+
*/
|
|
4
16
|
function callFn(name, args, ev, ctx, shift) {
|
|
5
17
|
switch (name) {
|
|
6
18
|
case "TRUE": return bool(true);
|
|
@@ -7,8 +7,29 @@ export type { Scalar, FValue, Rect, FErr } from './value.js';
|
|
|
7
7
|
export { num, str, bool, err, BLANK } from './value.js';
|
|
8
8
|
export { serialFromDate, serialToParts, timePeriodMatches } from './dates.js';
|
|
9
9
|
export { NO_SHIFT, evaluate } from './eval.js';
|
|
10
|
+
/**
|
|
11
|
+
* A parsed formula, ready to evaluate against many cells (the AST is compiled once
|
|
12
|
+
* per conditional-format rule, then evaluated per covered cell with a per-cell
|
|
13
|
+
* shift).
|
|
14
|
+
*/
|
|
10
15
|
export interface CompiledFormula {
|
|
11
16
|
readonly ast: Ast;
|
|
12
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a formula string into a {@link CompiledFormula}. Returns undefined (rather
|
|
20
|
+
* than throwing) when the formula cannot be parsed — the caller treats that as a
|
|
21
|
+
* rule that never applies, which is the correct graceful-loss behaviour for an
|
|
22
|
+
* unsupported construct.
|
|
23
|
+
*/
|
|
13
24
|
export declare function compileFormula(src: string): CompiledFormula | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Evaluate a compiled formula in a cell context and reduce it to the rule's truth
|
|
27
|
+
* test: the conditional format applies iff the result is the logical TRUE or a
|
|
28
|
+
* non-zero number (Excel §18.3.1.10). Any error / blank / text / zero — and a
|
|
29
|
+
* multi-cell result — yields false, so the rule simply does not paint.
|
|
30
|
+
*
|
|
31
|
+
* @param compiled The compiled formula from {@link compileFormula}.
|
|
32
|
+
* @param ctx The evaluation context (cached grid values + reference date).
|
|
33
|
+
* @param shift The per-cell relative-reference shift; defaults to {@link NO_SHIFT}.
|
|
34
|
+
*/
|
|
14
35
|
export declare function evaluateToBool(compiled: CompiledFormula, ctx: EvalContext, shift?: Shift): boolean;
|
|
@@ -3,6 +3,12 @@ import "./dates.js";
|
|
|
3
3
|
import { toBool } from "./value.js";
|
|
4
4
|
import { NO_SHIFT, evaluate } from "./eval.js";
|
|
5
5
|
//#region src/excel/formula/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* Parse a formula string into a {@link CompiledFormula}. Returns undefined (rather
|
|
8
|
+
* than throwing) when the formula cannot be parsed — the caller treats that as a
|
|
9
|
+
* rule that never applies, which is the correct graceful-loss behaviour for an
|
|
10
|
+
* unsupported construct.
|
|
11
|
+
*/
|
|
6
12
|
function compileFormula(src) {
|
|
7
13
|
try {
|
|
8
14
|
return { ast: parse(src) };
|
|
@@ -10,6 +16,16 @@ function compileFormula(src) {
|
|
|
10
16
|
return;
|
|
11
17
|
}
|
|
12
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Evaluate a compiled formula in a cell context and reduce it to the rule's truth
|
|
21
|
+
* test: the conditional format applies iff the result is the logical TRUE or a
|
|
22
|
+
* non-zero number (Excel §18.3.1.10). Any error / blank / text / zero — and a
|
|
23
|
+
* multi-cell result — yields false, so the rule simply does not paint.
|
|
24
|
+
*
|
|
25
|
+
* @param compiled The compiled formula from {@link compileFormula}.
|
|
26
|
+
* @param ctx The evaluation context (cached grid values + reference date).
|
|
27
|
+
* @param shift The per-cell relative-reference shift; defaults to {@link NO_SHIFT}.
|
|
28
|
+
*/
|
|
13
29
|
function evaluateToBool(compiled, ctx, shift = NO_SHIFT) {
|
|
14
30
|
return toBool(evaluate(compiled.ast, ctx, shift), ctx) === true;
|
|
15
31
|
}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
/** The lexical categories the {@link tokenize} pass emits. */
|
|
1
2
|
export type TokenKind = 'num' | 'str' | 'err' | 'word' | 'sheetq' | 'op' | 'eof';
|
|
3
|
+
/** One token: its {@link TokenKind} and the matched source text. */
|
|
2
4
|
export interface Token {
|
|
3
5
|
readonly kind: TokenKind;
|
|
4
6
|
readonly text: string;
|
|
5
7
|
}
|
|
8
|
+
/** Thrown when the source cannot be tokenized (bad character, over-long input). */
|
|
6
9
|
export declare class LexError extends Error {
|
|
7
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Tokenize a formula string into a flat token stream terminated by an `eof`
|
|
13
|
+
* token. Whitespace separates tokens but is otherwise dropped.
|
|
14
|
+
*
|
|
15
|
+
* @param src The formula source.
|
|
16
|
+
* @returns The token list, ending with an `eof` token.
|
|
17
|
+
* @throws LexError when `src` exceeds the source cap or holds an unexpected
|
|
18
|
+
* character / bad error literal.
|
|
19
|
+
*/
|
|
8
20
|
export declare function tokenize(src: string): Array<Token>;
|
|
@@ -9,6 +9,7 @@ var KNOWN_ERRORS = new Set([
|
|
|
9
9
|
"#NUM!",
|
|
10
10
|
"#N/A"
|
|
11
11
|
]);
|
|
12
|
+
/** Thrown when the source cannot be tokenized (bad character, over-long input). */
|
|
12
13
|
var LexError = class extends Error {};
|
|
13
14
|
function isDigit(ch) {
|
|
14
15
|
return ch >= "0" && ch <= "9";
|
|
@@ -19,6 +20,15 @@ function isWordStart(ch) {
|
|
|
19
20
|
function isWordPart(ch) {
|
|
20
21
|
return isWordStart(ch) || isDigit(ch) || ch === ".";
|
|
21
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Tokenize a formula string into a flat token stream terminated by an `eof`
|
|
25
|
+
* token. Whitespace separates tokens but is otherwise dropped.
|
|
26
|
+
*
|
|
27
|
+
* @param src The formula source.
|
|
28
|
+
* @returns The token list, ending with an `eof` token.
|
|
29
|
+
* @throws LexError when `src` exceeds the source cap or holds an unexpected
|
|
30
|
+
* character / bad error literal.
|
|
31
|
+
*/
|
|
22
32
|
function tokenize(src) {
|
|
23
33
|
if (src.length > MAX_SOURCE) throw new LexError("formula too long");
|
|
24
34
|
const out = [];
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { FErr } from './value.js';
|
|
2
|
+
/**
|
|
3
|
+
* One coordinate of a cell reference. `abs` records whether the axis was `$`
|
|
4
|
+
* anchored — an unanchored axis shifts by the cell's offset from the rule's
|
|
5
|
+
* origin when a conditional-format expression is evaluated per cell.
|
|
6
|
+
*/
|
|
2
7
|
export interface Axis {
|
|
8
|
+
/** 0-indexed row or column. */
|
|
3
9
|
readonly index: number;
|
|
10
|
+
/** Whether the axis carried a `$` anchor (stays put under the per-cell shift). */
|
|
4
11
|
readonly abs: boolean;
|
|
5
12
|
}
|
|
13
|
+
/** A single-cell reference: its column and row {@link Axis}es. */
|
|
6
14
|
export interface CellRef {
|
|
7
15
|
readonly col: Axis;
|
|
8
16
|
readonly row: Axis;
|
|
9
17
|
}
|
|
18
|
+
/** The formula syntax tree — a discriminated union over the node kind `k`. */
|
|
10
19
|
export type Ast = {
|
|
11
20
|
readonly k: 'num';
|
|
12
21
|
readonly v: number;
|
|
@@ -51,7 +60,18 @@ export type Ast = {
|
|
|
51
60
|
readonly name: string;
|
|
52
61
|
readonly args: ReadonlyArray<Ast>;
|
|
53
62
|
};
|
|
63
|
+
/** The binary operators the parser recognises (see {@link Ast} `bin` nodes). */
|
|
54
64
|
export type BinOp = '+' | '-' | '*' | '/' | '^' | '&' | '=' | '<>' | '<' | '>' | '<=' | '>=';
|
|
65
|
+
/** Thrown when the token stream is not a well-formed formula. */
|
|
55
66
|
export declare class ParseError extends Error {
|
|
56
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Parse a formula string into an {@link Ast}. Callers (the CF compiler) catch
|
|
70
|
+
* the throw and treat a parse failure as "rule does not apply" — a formula using
|
|
71
|
+
* a construct we do not model never misrenders, it just no-ops.
|
|
72
|
+
*
|
|
73
|
+
* @param src The formula source.
|
|
74
|
+
* @returns The parsed syntax tree.
|
|
75
|
+
* @throws ParseError on a malformed formula (or {@link LexError} from tokenizing).
|
|
76
|
+
*/
|
|
57
77
|
export declare function parse(src: string): Ast;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { tokenize } from "./lexer.js";
|
|
2
2
|
//#region src/excel/formula/parser.ts
|
|
3
|
+
/** Thrown when the token stream is not a well-formed formula. */
|
|
3
4
|
var ParseError = class extends Error {};
|
|
4
5
|
var PREC = {
|
|
5
6
|
"=": 1,
|
|
@@ -21,27 +22,49 @@ var MAX_ARGS = 255;
|
|
|
21
22
|
var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)([0-9]{1,7})$/;
|
|
22
23
|
var MAX_COL = 16383;
|
|
23
24
|
var MAX_ROW = 1048575;
|
|
25
|
+
/**
|
|
26
|
+
* Parse a formula string into an {@link Ast}. Callers (the CF compiler) catch
|
|
27
|
+
* the throw and treat a parse failure as "rule does not apply" — a formula using
|
|
28
|
+
* a construct we do not model never misrenders, it just no-ops.
|
|
29
|
+
*
|
|
30
|
+
* @param src The formula source.
|
|
31
|
+
* @returns The parsed syntax tree.
|
|
32
|
+
* @throws ParseError on a malformed formula (or {@link LexError} from tokenizing).
|
|
33
|
+
*/
|
|
24
34
|
function parse(src) {
|
|
25
35
|
const parser = new Parser(tokenize(src));
|
|
26
36
|
const ast = parser.parseExpr(0);
|
|
27
37
|
parser.expectEof();
|
|
28
38
|
return ast;
|
|
29
39
|
}
|
|
40
|
+
/** A precedence-climbing (Pratt) parser over a {@link tokenize} token stream. */
|
|
30
41
|
var Parser = class {
|
|
31
42
|
pos = 0;
|
|
32
43
|
depth = 0;
|
|
44
|
+
/** @param toks The token stream to parse (must end with an `eof` token). */
|
|
33
45
|
constructor(toks) {
|
|
34
46
|
this.toks = toks;
|
|
35
47
|
}
|
|
48
|
+
/** The current token without consuming it. */
|
|
36
49
|
peek() {
|
|
37
50
|
return this.toks[this.pos];
|
|
38
51
|
}
|
|
52
|
+
/** Consume and return the current token. */
|
|
39
53
|
next() {
|
|
40
54
|
return this.toks[this.pos++];
|
|
41
55
|
}
|
|
56
|
+
/** Assert the stream is fully consumed; throws `ParseError` on trailing tokens. */
|
|
42
57
|
expectEof() {
|
|
43
58
|
if (this.peek().kind !== "eof") throw new ParseError(`trailing tokens at ${this.pos}`);
|
|
44
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Parse an expression whose operators bind at least as tightly as `minBp`
|
|
62
|
+
* (the precedence-climbing entry point).
|
|
63
|
+
*
|
|
64
|
+
* @param minBp The minimum binding power; operators below it stop the climb.
|
|
65
|
+
* @returns The parsed sub-tree.
|
|
66
|
+
* @throws ParseError when the expression nests past the depth cap or is malformed.
|
|
67
|
+
*/
|
|
45
68
|
parseExpr(minBp) {
|
|
46
69
|
if (++this.depth > MAX_DEPTH) throw new ParseError("expression too deep");
|
|
47
70
|
let left = this.parseUnary();
|
|
@@ -63,6 +86,11 @@ var Parser = class {
|
|
|
63
86
|
this.depth--;
|
|
64
87
|
return left;
|
|
65
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse a (possibly signed) operand. Unary `+`/`-` bind tighter than `^`
|
|
91
|
+
* (Excel: `-2^2` = 4), so they live above the binary loop; postfix `%` binds
|
|
92
|
+
* tighter still.
|
|
93
|
+
*/
|
|
66
94
|
parseUnary() {
|
|
67
95
|
const t = this.peek();
|
|
68
96
|
if (t.kind === "op" && (t.text === "-" || t.text === "+")) {
|
|
@@ -75,6 +103,7 @@ var Parser = class {
|
|
|
75
103
|
}
|
|
76
104
|
return this.parsePostfix();
|
|
77
105
|
}
|
|
106
|
+
/** Parse a primary then fold any trailing postfix `%` percent operators. */
|
|
78
107
|
parsePostfix() {
|
|
79
108
|
let x = this.parsePrimary();
|
|
80
109
|
while (this.peek().kind === "op" && this.peek().text === "%") {
|
|
@@ -86,6 +115,11 @@ var Parser = class {
|
|
|
86
115
|
}
|
|
87
116
|
return x;
|
|
88
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Parse a primary expression: a literal, a parenthesised sub-expression, an
|
|
120
|
+
* inline array constant, or a word (classified by `parseWord` /
|
|
121
|
+
* sheet-qualifier handling).
|
|
122
|
+
*/
|
|
89
123
|
parsePrimary() {
|
|
90
124
|
const t = this.next();
|
|
91
125
|
switch (t.kind) {
|
|
@@ -125,6 +159,12 @@ var Parser = class {
|
|
|
125
159
|
case "eof": throw new ParseError("unexpected end of formula");
|
|
126
160
|
}
|
|
127
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Classify a `word` token: a `(` directly after it makes it a function call,
|
|
164
|
+
* regardless of shape (so `LOG10( … )` is the function, bare `LOG10` is the
|
|
165
|
+
* cell reference); else an A1-shaped word is a cell ref (extended to a range on
|
|
166
|
+
* a trailing `:`), `TRUE`/`FALSE` a logical, anything else a defined name.
|
|
167
|
+
*/
|
|
128
168
|
parseWord(word) {
|
|
129
169
|
if (this.peek().kind === "op" && this.peek().text === "(") {
|
|
130
170
|
this.next();
|
|
@@ -174,6 +214,11 @@ var Parser = class {
|
|
|
174
214
|
name: upper
|
|
175
215
|
};
|
|
176
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Parse a sheet-qualified cell or range — the `!` is already consumed; `sheet`
|
|
219
|
+
* is the (unquoted) sheet name. `Sheet2!A1` or `Sheet2!A1:B3`. The evaluator
|
|
220
|
+
* resolves the name against the workbook; an unknown sheet becomes `#REF!`.
|
|
221
|
+
*/
|
|
177
222
|
parseSheetCell(sheet) {
|
|
178
223
|
const t = this.next();
|
|
179
224
|
if (t.kind !== "word") throw new ParseError("expected a cell after !");
|
|
@@ -198,6 +243,12 @@ var Parser = class {
|
|
|
198
243
|
sheet
|
|
199
244
|
};
|
|
200
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Parse an inline array constant `{1,2,3}` / `{1,2;3,4}`: rows separated by
|
|
248
|
+
* `;`, elements by `,`. The opening `{` is already consumed. Elements are
|
|
249
|
+
* parsed as expressions (so a signed literal like `-1` works) and reduced to
|
|
250
|
+
* scalars at eval; the element count is capped against a crafted huge array.
|
|
251
|
+
*/
|
|
201
252
|
parseArray() {
|
|
202
253
|
const rows = [];
|
|
203
254
|
let row = [];
|
|
@@ -225,6 +276,7 @@ var Parser = class {
|
|
|
225
276
|
rows
|
|
226
277
|
};
|
|
227
278
|
}
|
|
279
|
+
/** Parse a comma-separated function argument list (the `(` already consumed). */
|
|
228
280
|
parseArgs() {
|
|
229
281
|
const args = [];
|
|
230
282
|
if (this.peek().kind === "op" && this.peek().text === ")") return args;
|
|
@@ -240,6 +292,7 @@ var Parser = class {
|
|
|
240
292
|
}
|
|
241
293
|
return args;
|
|
242
294
|
}
|
|
295
|
+
/** Consume the next token, asserting it is the operator `op`. */
|
|
243
296
|
expect(op) {
|
|
244
297
|
const t = this.next();
|
|
245
298
|
if (t.kind !== "op" || t.text !== op) throw new ParseError(`expected ${op}`);
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { EvalContext } from './context.js';
|
|
2
|
+
/**
|
|
3
|
+
* §18.17.2 — the seven error values a formula can carry. Stored as their literal
|
|
4
|
+
* display text so they round-trip and read naturally in diagnostics.
|
|
5
|
+
*/
|
|
2
6
|
export type FErr = '#NULL!' | '#DIV/0!' | '#VALUE!' | '#REF!' | '#NAME?' | '#NUM!' | '#N/A';
|
|
7
|
+
/**
|
|
8
|
+
* A rectangle of cells (absolute, 0-indexed, inclusive) — the value an `A1:B3`
|
|
9
|
+
* reference evaluates to. A single cell is a 1×1 rect. Aggregate functions iterate
|
|
10
|
+
* it; scalar contexts dereference it (1×1 → its value, else `#VALUE!`).
|
|
11
|
+
*/
|
|
3
12
|
export interface Rect {
|
|
4
13
|
readonly r0: number;
|
|
5
14
|
readonly c0: number;
|
|
6
15
|
readonly r1: number;
|
|
7
16
|
readonly c1: number;
|
|
8
17
|
}
|
|
18
|
+
/** One of the five scalar value kinds a formula evaluates to. */
|
|
9
19
|
export type Scalar = {
|
|
10
20
|
readonly t: 'num';
|
|
11
21
|
readonly v: number;
|
|
@@ -21,6 +31,19 @@ export type Scalar = {
|
|
|
21
31
|
} | {
|
|
22
32
|
readonly t: 'blank';
|
|
23
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* Any value a formula evaluates to: a {@link Scalar}, a `ref` (a {@link Rect},
|
|
36
|
+
* optionally cross-sheet), or an `arr` (an inline array constant).
|
|
37
|
+
*
|
|
38
|
+
* `sheet` (a workbook sheet index) is set only for a cross-sheet qualifier
|
|
39
|
+
* (`Sheet2!A1`) or a defined name that targets another sheet; when undefined the
|
|
40
|
+
* reference is on the rule's own sheet (the common case).
|
|
41
|
+
*
|
|
42
|
+
* An `arr` value is an inline array constant (`{1,2;3,4}`) — rows of scalars. It
|
|
43
|
+
* flattens into aggregates, broadcasts element-wise against a scalar in the
|
|
44
|
+
* operators, and collapses to its top-left element in a scalar context (Excel's
|
|
45
|
+
* implicit intersection of a constant array).
|
|
46
|
+
*/
|
|
24
47
|
export type FValue = Scalar | {
|
|
25
48
|
readonly t: 'ref';
|
|
26
49
|
readonly rect: Rect;
|
|
@@ -29,24 +52,54 @@ export type FValue = Scalar | {
|
|
|
29
52
|
readonly t: 'arr';
|
|
30
53
|
readonly rows: ReadonlyArray<ReadonlyArray<Scalar>>;
|
|
31
54
|
};
|
|
55
|
+
/** The blank scalar (an empty / absent cell). */
|
|
32
56
|
export declare const BLANK: Scalar;
|
|
57
|
+
/** The logical TRUE scalar. */
|
|
33
58
|
export declare const TRUE: Scalar;
|
|
59
|
+
/** The logical FALSE scalar. */
|
|
34
60
|
export declare const FALSE: Scalar;
|
|
61
|
+
/** Wrap a number as a scalar; a non-finite result (overflow, 0/0) becomes `#NUM!`. */
|
|
35
62
|
export declare function num(v: number): Scalar;
|
|
63
|
+
/** Wrap a string as a text scalar. */
|
|
36
64
|
export declare function str(v: string): Scalar;
|
|
65
|
+
/** The {@link TRUE} / {@link FALSE} scalar for a boolean. */
|
|
37
66
|
export declare function bool(v: boolean): Scalar;
|
|
67
|
+
/** Wrap an error code as an error scalar. */
|
|
38
68
|
export declare function err(v: FErr): Scalar;
|
|
69
|
+
/** Type guard: is the value an error scalar? */
|
|
39
70
|
export declare function isErr(v: FValue): v is {
|
|
40
71
|
t: 'err';
|
|
41
72
|
v: FErr;
|
|
42
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* Collapse a reference to a scalar: a 1×1 rect yields the cell's value (a blank cell
|
|
76
|
+
* → blank); any larger rect in a scalar context is `#VALUE!` (we do not implement
|
|
77
|
+
* implicit intersection). An array constant collapses to its top-left element;
|
|
78
|
+
* non-refs pass through unchanged.
|
|
79
|
+
*/
|
|
43
80
|
export declare function deref(v: FValue, ctx: EvalContext): Scalar;
|
|
81
|
+
/** Visit every scalar element of an array constant, row by row. */
|
|
44
82
|
export declare function arrEach(rows: ReadonlyArray<ReadonlyArray<Scalar>>, visit: (value: Scalar) => void): void;
|
|
83
|
+
/**
|
|
84
|
+
* Iterate the populated cells of a reference, honouring a cross-sheet qualifier (an
|
|
85
|
+
* absent `eachCellOn` ⇒ no cross-sheet support ⇒ the foreign range is empty).
|
|
86
|
+
*/
|
|
45
87
|
export declare function refEach(v: {
|
|
46
88
|
readonly rect: Rect;
|
|
47
89
|
readonly sheet?: number;
|
|
48
90
|
}, ctx: EvalContext, visit: (row: number, col: number, value: Scalar) => void): void;
|
|
91
|
+
/** Read one absolute cell on a reference's sheet (the current sheet when `sheet` is unset). */
|
|
49
92
|
export declare function refGet(sheet: number | undefined, ctx: EvalContext, row: number, col: number): Scalar;
|
|
93
|
+
/**
|
|
94
|
+
* §18.17.3 — number coercion. blank → 0, logical → 1/0, a numeric string → its
|
|
95
|
+
* number (Excel parses `"5"` and `" 5 "` leniently); non-numeric text → `#VALUE!`.
|
|
96
|
+
* An error propagates (returned as the {@link FErr}); references are dereferenced first.
|
|
97
|
+
*/
|
|
50
98
|
export declare function toNumber(v: FValue, ctx: EvalContext): number | FErr;
|
|
99
|
+
/**
|
|
100
|
+
* §18.17.3 — text coercion. A number formats with the shortest round-trip
|
|
101
|
+
* representation, a logical as `TRUE`/`FALSE`, blank as the empty string. Errors
|
|
102
|
+
* propagate (returned as the {@link FErr}).
|
|
103
|
+
*/
|
|
51
104
|
export declare function toText(v: FValue, ctx: EvalContext): string | FErr;
|
|
52
105
|
export declare function toBool(v: FValue, ctx: EvalContext): boolean | FErr;
|