documents.js 1.63.0 → 1.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +113 -20
  2. package/dist/convert/convert.cjs +3 -3
  3. package/dist/convert/convert.d.cts +5 -2
  4. package/dist/convert/convert.d.ts +4 -1
  5. package/dist/convert/convert.js +3 -3
  6. package/dist/edit/docx/content.d.cts +1 -1
  7. package/dist/edit/docx/content.d.ts +1 -1
  8. package/dist/edit/docx/paragraph.d.cts +3 -3
  9. package/dist/edit/docx/paragraph.d.ts +3 -3
  10. package/dist/edit/ods/address.cjs +42 -24
  11. package/dist/edit/ods/address.d.cts +12 -2
  12. package/dist/edit/ods/address.d.ts +12 -2
  13. package/dist/edit/ods/address.js +39 -25
  14. package/dist/edit/ods/column-row.cjs +68 -6
  15. package/dist/edit/ods/column-row.d.cts +5 -1
  16. package/dist/edit/ods/column-row.d.ts +5 -1
  17. package/dist/edit/ods/column-row.js +68 -10
  18. package/dist/edit/ods/content.cjs +10 -2
  19. package/dist/edit/ods/content.js +10 -2
  20. package/dist/edit/ods/floating.cjs +90 -0
  21. package/dist/edit/ods/floating.d.cts +7 -0
  22. package/dist/edit/ods/floating.d.ts +7 -0
  23. package/dist/edit/ods/floating.js +88 -0
  24. package/dist/edit/ods/print-settings.cjs +158 -2
  25. package/dist/edit/ods/print-settings.js +159 -3
  26. package/dist/edit/ods/sheet.cjs +13 -0
  27. package/dist/edit/ods/sheet.d.cts +5 -1
  28. package/dist/edit/ods/sheet.d.ts +5 -1
  29. package/dist/edit/ods/sheet.js +14 -1
  30. package/dist/edit/odt/content.cjs +8 -4
  31. package/dist/edit/odt/content.js +8 -4
  32. package/dist/edit/odt/editor.cjs +7 -0
  33. package/dist/edit/odt/editor.d.cts +3 -0
  34. package/dist/edit/odt/editor.d.ts +3 -0
  35. package/dist/edit/odt/editor.js +7 -0
  36. package/dist/edit/odt/formula.cjs +19 -0
  37. package/dist/edit/odt/formula.d.cts +8 -0
  38. package/dist/edit/odt/formula.d.ts +8 -0
  39. package/dist/edit/odt/formula.js +17 -0
  40. package/dist/evaluate-BU5N1Jk1.d.ts +11 -0
  41. package/dist/evaluate-BhMXY6DM.d.cts +11 -0
  42. package/dist/firebird/backup.d.cts +1 -1
  43. package/dist/firebird/backup.d.ts +1 -1
  44. package/dist/firebird/data.cjs +30 -16
  45. package/dist/firebird/data.d.cts +3 -2
  46. package/dist/firebird/data.d.ts +3 -2
  47. package/dist/firebird/data.js +30 -17
  48. package/dist/fonts/ooxml.d.cts +1 -1
  49. package/dist/fonts/registry.d.cts +1 -1
  50. package/dist/formula-CgydMiTt.d.ts +10 -0
  51. package/dist/formula-CiwPw8nY.d.cts +10 -0
  52. package/dist/hsqldb/binary-script.d.cts +1 -1
  53. package/dist/hsqldb/binary-script.d.ts +1 -1
  54. package/dist/hsqldb/cache.d.cts +1 -1
  55. package/dist/hsqldb/cache.d.ts +1 -1
  56. package/dist/hsqldb/rowformat.cjs +22 -13
  57. package/dist/hsqldb/rowformat.js +22 -13
  58. package/dist/hsqldb/script.d.cts +1 -18
  59. package/dist/hsqldb/script.d.ts +1 -18
  60. package/dist/index.cjs +56 -0
  61. package/dist/index.d.cts +22 -8
  62. package/dist/index.d.ts +21 -7
  63. package/dist/index.js +15 -2
  64. package/dist/layout/sheets.cjs +30 -24
  65. package/dist/layout/sheets.js +31 -25
  66. package/dist/layout/slides.cjs +6 -4
  67. package/dist/layout/slides.js +7 -5
  68. package/dist/lexer-DGPWx_f2.d.cts +42 -0
  69. package/dist/lexer-DGPWx_f2.d.ts +42 -0
  70. package/dist/mathml/layout.d.cts +1 -1
  71. package/dist/mathml/layout.d.ts +1 -1
  72. package/dist/mathml/variant.d.cts +1 -6
  73. package/dist/mathml/variant.d.ts +1 -6
  74. package/dist/odb/csv.d.cts +1 -1
  75. package/dist/odb/csv.d.ts +1 -1
  76. package/dist/odb/formula/definition.cjs +49 -0
  77. package/dist/odb/formula/definition.d.cts +8 -0
  78. package/dist/odb/formula/definition.d.ts +8 -0
  79. package/dist/odb/formula/definition.js +46 -0
  80. package/dist/odb/formula/errors.cjs +47 -0
  81. package/dist/odb/formula/errors.d.cts +21 -0
  82. package/dist/odb/formula/errors.d.ts +21 -0
  83. package/dist/odb/formula/errors.js +43 -0
  84. package/dist/odb/formula/evaluate.cjs +283 -0
  85. package/dist/odb/formula/evaluate.d.cts +43 -0
  86. package/dist/odb/formula/evaluate.d.ts +43 -0
  87. package/dist/odb/formula/evaluate.js +281 -0
  88. package/dist/odb/formula/parser.cjs +198 -0
  89. package/dist/odb/formula/parser.d.cts +29 -0
  90. package/dist/odb/formula/parser.d.ts +29 -0
  91. package/dist/odb/formula/parser.js +197 -0
  92. package/dist/odb/read.d.cts +1 -1
  93. package/dist/odb/read.d.ts +1 -1
  94. package/dist/odb/report/content.cjs +27 -0
  95. package/dist/odb/report/content.d.cts +14 -0
  96. package/dist/odb/report/content.d.ts +14 -0
  97. package/dist/odb/report/content.js +25 -0
  98. package/dist/odb/report/render.cjs +106 -0
  99. package/dist/odb/report/render.d.cts +7 -0
  100. package/dist/odb/report/render.d.ts +7 -0
  101. package/dist/odb/report/render.js +106 -0
  102. package/dist/odb/report/source.cjs +45 -0
  103. package/dist/odb/report/source.d.cts +14 -0
  104. package/dist/odb/report/source.d.ts +14 -0
  105. package/dist/odb/report/source.js +42 -0
  106. package/dist/odb/spreadsheet.d.cts +1 -1
  107. package/dist/odb/spreadsheet.d.ts +1 -1
  108. package/dist/odb/sql/errors.cjs +38 -0
  109. package/dist/odb/sql/errors.d.cts +17 -0
  110. package/dist/odb/sql/errors.d.ts +17 -0
  111. package/dist/odb/sql/errors.js +35 -0
  112. package/dist/odb/sql/evaluate.cjs +312 -0
  113. package/dist/odb/sql/evaluate.d.cts +2 -0
  114. package/dist/odb/sql/evaluate.d.ts +2 -0
  115. package/dist/odb/sql/evaluate.js +311 -0
  116. package/dist/odb/sql/lexer.cjs +282 -0
  117. package/dist/odb/sql/lexer.d.cts +2 -0
  118. package/dist/odb/sql/lexer.d.ts +2 -0
  119. package/dist/odb/sql/lexer.js +281 -0
  120. package/dist/odb/sql/parser.cjs +479 -0
  121. package/dist/odb/sql/parser.d.cts +2 -0
  122. package/dist/odb/sql/parser.d.ts +2 -0
  123. package/dist/odb/sql/parser.js +478 -0
  124. package/dist/odb/values.cjs +75 -0
  125. package/dist/odb/values.d.cts +2 -0
  126. package/dist/odb/values.d.ts +2 -0
  127. package/dist/odb/values.js +69 -0
  128. package/dist/odf/odt/read.cjs +43 -21
  129. package/dist/odf/odt/read.js +43 -21
  130. package/dist/odf-package/formula.cjs +59 -0
  131. package/dist/odf-package/formula.d.cts +11 -0
  132. package/dist/odf-package/formula.d.ts +11 -0
  133. package/dist/odf-package/formula.js +58 -0
  134. package/dist/odf-package/manifest.cjs +29 -0
  135. package/dist/odf-package/manifest.d.cts +5 -2
  136. package/dist/odf-package/manifest.d.ts +5 -2
  137. package/dist/odf-package/manifest.js +30 -2
  138. package/dist/odf-package/media.cjs +2 -1
  139. package/dist/odf-package/media.js +2 -2
  140. package/dist/omml/read.cjs +265 -0
  141. package/dist/omml/read.d.cts +12 -0
  142. package/dist/omml/read.d.ts +12 -0
  143. package/dist/omml/read.js +263 -0
  144. package/dist/omml/shared.cjs +67 -0
  145. package/dist/omml/shared.d.cts +2 -0
  146. package/dist/omml/shared.d.ts +2 -0
  147. package/dist/omml/shared.js +64 -0
  148. package/dist/omml/write.cjs +3 -51
  149. package/dist/omml/write.d.cts +2 -2
  150. package/dist/omml/write.d.ts +2 -2
  151. package/dist/omml/write.js +1 -49
  152. package/dist/ooxml/docx/extras.cjs +15 -0
  153. package/dist/ooxml/docx/extras.d.cts +12 -0
  154. package/dist/ooxml/docx/extras.d.ts +12 -0
  155. package/dist/ooxml/docx/extras.js +14 -0
  156. package/dist/ooxml/docx/formula.cjs +109 -0
  157. package/dist/ooxml/docx/formula.d.cts +2 -0
  158. package/dist/ooxml/docx/formula.d.ts +2 -0
  159. package/dist/ooxml/docx/formula.js +108 -0
  160. package/dist/ooxml/docx/read.cjs +10 -2
  161. package/dist/ooxml/docx/read.d.cts +6 -2
  162. package/dist/ooxml/docx/read.d.ts +6 -2
  163. package/dist/ooxml/docx/read.js +11 -3
  164. package/dist/parser-B9vC1T6T.d.cts +101 -0
  165. package/dist/parser-DQSgYJzQ.d.ts +101 -0
  166. package/dist/{registry-CtPhMD0f.d.cts → registry-lqJej0Jr.d.cts} +1 -1
  167. package/dist/script-DsGGIzGU.d.cts +19 -0
  168. package/dist/script-DsGGIzGU.d.ts +19 -0
  169. package/dist/shared-DLZ3IQUl.d.cts +15 -0
  170. package/dist/shared-DUOzjwcL.d.ts +15 -0
  171. package/dist/values-BetetbaH.d.cts +23 -0
  172. package/dist/values-BetetbaH.d.ts +23 -0
  173. package/dist/variant-BMrebjMw.d.cts +7 -0
  174. package/dist/variant-BMrebjMw.d.ts +7 -0
  175. package/dist/{write-DuyfnbL_.d.cts → write-BQ6SK8r8.d.cts} +2 -6
  176. package/dist/{write-Zqwx6pka.d.ts → write-THs7ipBq.d.ts} +2 -6
  177. package/package.json +1 -1
@@ -0,0 +1,281 @@
1
+ import { CELL_NULL, aggregateCellValues, cellComparisonKey, cellValuesEqual } from "../values.js";
2
+ import { RptFormulaEvaluationError } from "./errors.js";
3
+ import { parseRptFormula } from "./parser.js";
4
+ //#region src/odb/formula/evaluate.ts
5
+ function fail(message, formula) {
6
+ throw new RptFormulaEvaluationError(message, formula);
7
+ }
8
+ function matchNamed(candidates, nameOf, name) {
9
+ const exact = candidates.filter((candidate) => nameOf(candidate) === name);
10
+ return exact.length > 0 ? exact : candidates.filter((candidate) => nameOf(candidate).toUpperCase() === name.toUpperCase());
11
+ }
12
+ function identity(name) {
13
+ return name;
14
+ }
15
+ function prepareBandFormulas(band) {
16
+ return band.formulas.map((formula) => formula === void 0 ? void 0 : parseRptFormula(formula));
17
+ }
18
+ function prepareBand(band) {
19
+ return band === void 0 ? void 0 : prepareBandFormulas(band);
20
+ }
21
+ var PreparedReport = class {
22
+ resultSet;
23
+ namedFunctions;
24
+ groupExpressions;
25
+ bands;
26
+ columnNames;
27
+ resolutions = /* @__PURE__ */ new Map();
28
+ constructor(definition, resultSet) {
29
+ this.resultSet = resultSet;
30
+ this.columnNames = resultSet.columns;
31
+ const named = /* @__PURE__ */ new Map();
32
+ const declare = (functions, scope) => {
33
+ for (const declaration of functions) {
34
+ if (named.has(declaration.name)) fail(`rpt:function "${declaration.name}" is declared more than once in this report`, declaration.formula);
35
+ named.set(declaration.name, {
36
+ name: declaration.name,
37
+ formula: parseRptFormula(declaration.formula),
38
+ scope
39
+ });
40
+ }
41
+ };
42
+ declare(definition.functions, { kind: "report" });
43
+ for (const [level, group] of definition.groups.entries()) declare(group.functions, {
44
+ kind: "group",
45
+ level
46
+ });
47
+ this.namedFunctions = named;
48
+ this.groupExpressions = definition.groups.map((group) => parseRptFormula(group.groupExpression));
49
+ this.bands = {
50
+ reportHeader: prepareBand(definition.reportHeader),
51
+ detail: prepareBand(definition.detail),
52
+ reportFooter: prepareBand(definition.reportFooter),
53
+ groups: definition.groups.map((group) => ({
54
+ header: prepareBand(group.header),
55
+ footer: prepareBand(group.footer)
56
+ }))
57
+ };
58
+ for (const expression of this.groupExpressions) this.rejectAggregateDependency(expression, expression, /* @__PURE__ */ new Set());
59
+ }
60
+ rejectAggregateDependency(formula, expression, visiting) {
61
+ if (formula.kind === "aggregate") fail(`a group expression cannot depend on the aggregate rpt:${formula.aggregate}(${formula.reference.name}) -- an aggregate's own rows are defined by the very group boundaries this expression decides`, expression.text);
62
+ const resolved = matchNamed([...this.namedFunctions.values()], (candidate) => candidate.name, formula.reference.name)[0];
63
+ if (resolved === void 0) return;
64
+ if (visiting.has(resolved.name)) fail(`rpt:function "${resolved.name}" refers to itself, directly or through another function`, expression.text);
65
+ this.rejectAggregateDependency(resolved.formula, expression, /* @__PURE__ */ new Set([...visiting, resolved.name]));
66
+ }
67
+ resolveReference(reference, formula) {
68
+ const cached = this.resolutions.get(reference);
69
+ if (cached !== void 0) return cached;
70
+ const functionMatches = matchNamed([...this.namedFunctions.values()], (candidate) => candidate.name, reference.name);
71
+ const columnMatches = matchNamed(this.columnNames, identity, reference.name);
72
+ if (functionMatches.length + columnMatches.length > 1) fail(`reference "${reference.name}" is ambiguous -- it matches ${[...functionMatches.map((match) => `rpt:function ${match.name}`), ...columnMatches.map((match) => `column ${match}`)].join(", ")}`, formula);
73
+ const resolved = this.resolveSingleMatch(reference, functionMatches[0], columnMatches[0], formula);
74
+ this.resolutions.set(reference, resolved);
75
+ return resolved;
76
+ }
77
+ resolveSingleMatch(reference, named, columnName, formula) {
78
+ if (named !== void 0) return {
79
+ kind: "function",
80
+ resolved: named
81
+ };
82
+ if (columnName === void 0) fail(`reference "${reference.name}" names neither a declared rpt:function nor a column of the report's own data -- functions: ${this.namedFunctions.size === 0 ? "(none)" : [...this.namedFunctions.keys()].join(", ")}; columns: ${this.columnNames.length === 0 ? "(none)" : this.columnNames.join(", ")}`, formula);
83
+ return {
84
+ kind: "column",
85
+ index: this.columnNames.indexOf(columnName)
86
+ };
87
+ }
88
+ valueAt(columnIndex, rowIndex, formula) {
89
+ const value = this.resultSet.rows[rowIndex]?.[columnIndex];
90
+ if (value === void 0) fail(`the report's own data has no value at row ${String(rowIndex)}, column ${String(columnIndex)}`, formula);
91
+ return value;
92
+ }
93
+ };
94
+ var RunState = class {
95
+ rowCount;
96
+ openInstances;
97
+ constructor(levels, rowCount) {
98
+ this.rowCount = rowCount;
99
+ this.openInstances = Array.from({ length: levels }, () => void 0);
100
+ }
101
+ open(level, range) {
102
+ this.openInstances[level] = range;
103
+ }
104
+ openAt(level) {
105
+ return this.openInstances[level];
106
+ }
107
+ close(level) {
108
+ this.openInstances[level] = void 0;
109
+ }
110
+ rangeFor(scope, formula) {
111
+ if (scope.kind === "report") return {
112
+ startRow: 0,
113
+ endRowExclusive: this.rowCount
114
+ };
115
+ const open = this.openInstances[scope.level];
116
+ if (open === void 0) fail(`an aggregate scoped to group level ${String(scope.level)} was evaluated while no instance of that group was open`, formula);
117
+ return open;
118
+ }
119
+ };
120
+ function textOf(value, formula, what) {
121
+ if (value.kind === "empty") return;
122
+ const key = cellComparisonKey(value);
123
+ if (key?.valueClass !== "text") fail(`${what} requires a text value, but found a ${value.kind} value -- this engine does not format a number or a boolean into text, since a report's own number format lives in its band styles rather than in the formula`, formula);
124
+ return key.text;
125
+ }
126
+ var FormulaEvaluator = class {
127
+ prepared;
128
+ state;
129
+ constructor(prepared, state) {
130
+ this.prepared = prepared;
131
+ this.state = state;
132
+ }
133
+ evaluate(formula, rowIndex, scope, visiting = /* @__PURE__ */ new Set()) {
134
+ switch (formula.kind) {
135
+ case "field": return this.referenceValue(formula.reference, this.requireRow(rowIndex, formula.text, "a field: reference"), formula.text, visiting);
136
+ case "hasChanged": {
137
+ const rowOfChange = this.requireRow(rowIndex, formula.text, "rpt:HASCHANGED");
138
+ const current = this.referenceValue(formula.reference, rowOfChange, formula.text, visiting);
139
+ if (rowOfChange === 0) return {
140
+ kind: "boolean",
141
+ value: true
142
+ };
143
+ const previous = this.referenceValue(formula.reference, rowOfChange - 1, formula.text, visiting);
144
+ return {
145
+ kind: "boolean",
146
+ value: !cellValuesEqual(current, previous)
147
+ };
148
+ }
149
+ case "left": {
150
+ const text = textOf(this.referenceValue(formula.reference, this.requireRow(rowIndex, formula.text, "rpt:LEFT"), formula.text, visiting), formula.text, "rpt:LEFT");
151
+ return text === void 0 ? CELL_NULL : {
152
+ kind: "string",
153
+ value: [...text].slice(0, formula.length).join("")
154
+ };
155
+ }
156
+ case "aggregate": {
157
+ const range = this.state.rangeFor(scope, formula.text);
158
+ const values = [];
159
+ for (let row = range.startRow; row < range.endRowExclusive; row += 1) values.push(this.referenceValue(formula.reference, row, formula.text, visiting));
160
+ return aggregateCellValues(formula.aggregate, values, (message) => new RptFormulaEvaluationError(message, formula.text));
161
+ }
162
+ }
163
+ }
164
+ requireRow(rowIndex, formula, what) {
165
+ if (rowIndex === void 0) fail(`${what} needs a data row, but the band it appears in belongs to no row (the report header and footer print outside the data)`, formula);
166
+ return rowIndex;
167
+ }
168
+ referenceValue(reference, rowIndex, formula, visiting) {
169
+ const resolved = this.prepared.resolveReference(reference, formula);
170
+ if (resolved.kind === "column") return this.prepared.valueAt(resolved.index, rowIndex, formula);
171
+ if (visiting.has(resolved.resolved.name)) fail(`rpt:function "${resolved.resolved.name}" refers to itself, directly or through another function`, formula);
172
+ return this.evaluate(resolved.resolved.formula, rowIndex, resolved.resolved.scope, /* @__PURE__ */ new Set([...visiting, resolved.resolved.name]));
173
+ }
174
+ };
175
+ function resolveOwnBreak(value, formula) {
176
+ if (value.kind !== "boolean") fail(`a group expression must evaluate to a boolean break test (rpt:HASCHANGED(...)), but this one produced a ${value.kind} value`, formula);
177
+ return value.value;
178
+ }
179
+ var GroupBreaks = class {
180
+ rowCount;
181
+ rows;
182
+ constructor(prepared, evaluator, rowCount) {
183
+ this.rowCount = rowCount;
184
+ const rows = [];
185
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
186
+ const flags = [];
187
+ let enclosingBroke = false;
188
+ for (const [level, expression] of prepared.groupExpressions.entries()) {
189
+ const ownBreak = resolveOwnBreak(evaluator.evaluate(expression, rowIndex, {
190
+ kind: "group",
191
+ level
192
+ }), expression.text);
193
+ const broke = enclosingBroke || rowIndex === 0 || ownBreak;
194
+ flags.push(broke);
195
+ enclosingBroke = broke;
196
+ }
197
+ rows.push(flags);
198
+ }
199
+ this.rows = rows;
200
+ }
201
+ flagsAt(rowIndex) {
202
+ const flags = this.rows[rowIndex];
203
+ if (flags === void 0) throw new Error(`rpt report run: row ${String(rowIndex)} is outside the ${String(this.rowCount)} rows its group breaks were computed for`);
204
+ return flags;
205
+ }
206
+ outermostBreakAt(rowIndex) {
207
+ return this.flagsAt(rowIndex).indexOf(true);
208
+ }
209
+ breaksAt(rowIndex, level) {
210
+ return this.flagsAt(rowIndex)[level] === true;
211
+ }
212
+ instanceContaining(level, rowIndex) {
213
+ let startRow = rowIndex;
214
+ while (startRow > 0 && !this.breaksAt(startRow, level)) startRow -= 1;
215
+ let endRowExclusive = rowIndex + 1;
216
+ while (endRowExclusive < this.rowCount && !this.breaksAt(endRowExclusive, level)) endRowExclusive += 1;
217
+ return {
218
+ startRow,
219
+ endRowExclusive
220
+ };
221
+ }
222
+ };
223
+ function detailScope(groupCount) {
224
+ return groupCount === 0 ? { kind: "report" } : {
225
+ kind: "group",
226
+ level: groupCount - 1
227
+ };
228
+ }
229
+ function runRptReport(definition, resultSet) {
230
+ const rowCount = resultSet.rows.length;
231
+ const levels = definition.groups.length;
232
+ const prepared = new PreparedReport(definition, resultSet);
233
+ const state = new RunState(levels, rowCount);
234
+ const evaluator = new FormulaEvaluator(prepared, state);
235
+ const bands = [];
236
+ const emit = (band, kind, groupLevel, rowIndex, scope) => {
237
+ if (band === void 0) return;
238
+ bands.push({
239
+ kind,
240
+ groupLevel,
241
+ rowIndex,
242
+ values: band.map((formula) => formula === void 0 ? void 0 : evaluator.evaluate(formula, rowIndex, scope))
243
+ });
244
+ };
245
+ emit(prepared.bands.reportHeader, "report-header", void 0, void 0, { kind: "report" });
246
+ const breaks = new GroupBreaks(prepared, evaluator, rowCount);
247
+ const closeFrom = (level) => {
248
+ for (let openLevel = levels - 1; openLevel >= level; openLevel -= 1) {
249
+ const open = state.openAt(openLevel);
250
+ if (open === void 0) continue;
251
+ emit(prepared.bands.groups[openLevel]?.footer, "group-footer", openLevel, open.endRowExclusive - 1, {
252
+ kind: "group",
253
+ level: openLevel
254
+ });
255
+ state.close(openLevel);
256
+ }
257
+ };
258
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
259
+ const outermostBroken = breaks.outermostBreakAt(rowIndex);
260
+ if (outermostBroken >= 0) {
261
+ closeFrom(outermostBroken);
262
+ for (let level = outermostBroken; level < levels; level += 1) {
263
+ state.open(level, breaks.instanceContaining(level, rowIndex));
264
+ emit(prepared.bands.groups[level]?.header, "group-header", level, rowIndex, {
265
+ kind: "group",
266
+ level
267
+ });
268
+ }
269
+ }
270
+ emit(prepared.bands.detail, "detail", void 0, rowIndex, detailScope(levels));
271
+ }
272
+ closeFrom(0);
273
+ emit(prepared.bands.reportFooter, "report-footer", void 0, void 0, { kind: "report" });
274
+ return { bands };
275
+ }
276
+ function evaluateRptBandOutsideData(definition, band, resultSet) {
277
+ const evaluator = new FormulaEvaluator(new PreparedReport(definition, resultSet), new RunState(definition.groups.length, resultSet.rows.length));
278
+ return prepareBandFormulas(band).map((formula) => formula === void 0 ? void 0 : evaluator.evaluate(formula, void 0, { kind: "report" }));
279
+ }
280
+ //#endregion
281
+ export { evaluateRptBandOutsideData, runRptReport };
@@ -0,0 +1,198 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_odb_formula_errors = require("./errors.cjs");
3
+ //#region src/odb/formula/parser.ts
4
+ const AGGREGATE_FUNCTIONS = /* @__PURE__ */ new Set([
5
+ "COUNT",
6
+ "SUM",
7
+ "AVG",
8
+ "MIN",
9
+ "MAX"
10
+ ]);
11
+ function isAggregateFunction(name) {
12
+ return AGGREGATE_FUNCTIONS.has(name);
13
+ }
14
+ const FIELD_PREFIX = "field:";
15
+ const RPT_PREFIX = "rpt:";
16
+ function isNameCharacter(character) {
17
+ return character >= "A" && character <= "Z" || character >= "a" && character <= "z" || character >= "0" && character <= "9" || character === "_";
18
+ }
19
+ var FormulaScanner = class {
20
+ formula;
21
+ offset = 0;
22
+ constructor(formula) {
23
+ this.formula = formula;
24
+ }
25
+ get position() {
26
+ return this.offset;
27
+ }
28
+ fail(message) {
29
+ throw new require_odb_formula_errors.RptFormulaParseError(message, this.formula, this.offset);
30
+ }
31
+ skipWhitespace() {
32
+ while (this.offset < this.formula.length && /\s/.test(this.formula.charAt(this.offset))) this.offset += 1;
33
+ }
34
+ atEnd() {
35
+ this.skipWhitespace();
36
+ return this.offset >= this.formula.length;
37
+ }
38
+ peek() {
39
+ this.skipWhitespace();
40
+ return this.formula.charAt(this.offset);
41
+ }
42
+ tryConsume(text) {
43
+ this.skipWhitespace();
44
+ if (!this.formula.startsWith(text, this.offset)) return false;
45
+ this.offset += text.length;
46
+ return true;
47
+ }
48
+ expect(character, what) {
49
+ this.skipWhitespace();
50
+ if (this.formula.charAt(this.offset) !== character) this.fail(`expected ${what} ("${character}") but found ${this.offset >= this.formula.length ? "the end of the formula" : `"${this.formula.charAt(this.offset)}"`}`);
51
+ this.offset += 1;
52
+ }
53
+ readName(what) {
54
+ this.skipWhitespace();
55
+ const start = this.offset;
56
+ while (this.offset < this.formula.length && isNameCharacter(this.formula.charAt(this.offset))) this.offset += 1;
57
+ if (this.offset === start) this.fail(`expected ${what}`);
58
+ return this.formula.slice(start, this.offset);
59
+ }
60
+ readBracketReference() {
61
+ this.expect("[", "the opening bracket of a column reference");
62
+ const start = this.offset;
63
+ const close = this.formula.indexOf("]", this.offset);
64
+ if (close < 0) {
65
+ this.offset = this.formula.length;
66
+ this.fail("unterminated column reference -- no closing \"]\"");
67
+ }
68
+ this.offset = close + 1;
69
+ return {
70
+ name: this.formula.slice(start, close),
71
+ spelling: "bracket"
72
+ };
73
+ }
74
+ readQuotedReference() {
75
+ this.expect("\"", "the opening quote of a name reference");
76
+ let name = "";
77
+ for (;;) {
78
+ if (this.offset >= this.formula.length) this.fail("unterminated name reference -- no closing double quote");
79
+ const character = this.formula.charAt(this.offset);
80
+ this.offset += 1;
81
+ if (character !== "\"") {
82
+ name += character;
83
+ continue;
84
+ }
85
+ if (this.formula.charAt(this.offset) === "\"") {
86
+ name += "\"";
87
+ this.offset += 1;
88
+ continue;
89
+ }
90
+ return {
91
+ name,
92
+ spelling: "quote"
93
+ };
94
+ }
95
+ }
96
+ readNumber() {
97
+ this.skipWhitespace();
98
+ const start = this.offset;
99
+ if (this.formula.charAt(this.offset) === "-") this.offset += 1;
100
+ while (this.offset < this.formula.length && this.formula.charAt(this.offset) >= "0" && this.formula.charAt(this.offset) <= "9") this.offset += 1;
101
+ if (this.formula.charAt(this.offset) === ".") {
102
+ this.offset += 1;
103
+ while (this.offset < this.formula.length && this.formula.charAt(this.offset) >= "0" && this.formula.charAt(this.offset) <= "9") this.offset += 1;
104
+ }
105
+ const text = this.formula.slice(start, this.offset);
106
+ const value = Number(text);
107
+ if (text === "" || text === "-" || !Number.isFinite(value)) {
108
+ this.offset = start;
109
+ this.fail("expected a number");
110
+ }
111
+ return value;
112
+ }
113
+ readArgument() {
114
+ const next = this.peek();
115
+ if (next === "") this.fail("expected an argument but found the end of the formula");
116
+ if (next === "[") return {
117
+ kind: "reference",
118
+ reference: this.readBracketReference()
119
+ };
120
+ if (next === "\"") return {
121
+ kind: "reference",
122
+ reference: this.readQuotedReference()
123
+ };
124
+ return {
125
+ kind: "number",
126
+ value: this.readNumber()
127
+ };
128
+ }
129
+ };
130
+ function referenceArgument(argument, functionName, ordinal, scanner) {
131
+ if (argument?.kind !== "reference") scanner.fail(`rpt:${functionName}'s ${ordinal} argument must be a column or function reference ([NAME] or "NAME")`);
132
+ return argument.reference;
133
+ }
134
+ function expectArgumentCount(argumentValues, expected, functionName, scanner) {
135
+ if (argumentValues.length !== expected) scanner.fail(`rpt:${functionName} takes exactly ${String(expected)} argument${expected === 1 ? "" : "s"}, but ${String(argumentValues.length)} ${argumentValues.length === 1 ? "was" : "were"} given`);
136
+ }
137
+ function buildCall(functionName, argumentValues, formula, scanner) {
138
+ const canonical = functionName.toUpperCase();
139
+ if (canonical === "HASCHANGED") {
140
+ expectArgumentCount(argumentValues, 1, functionName, scanner);
141
+ return {
142
+ kind: "hasChanged",
143
+ reference: referenceArgument(argumentValues[0], functionName, "first", scanner),
144
+ text: formula
145
+ };
146
+ }
147
+ if (canonical === "LEFT") {
148
+ expectArgumentCount(argumentValues, 2, functionName, scanner);
149
+ const reference = referenceArgument(argumentValues[0], functionName, "first", scanner);
150
+ const lengthArgument = argumentValues[1];
151
+ if (lengthArgument?.kind !== "number") scanner.fail(`rpt:${functionName}'s second argument must be a number of characters`);
152
+ if (!Number.isInteger(lengthArgument.value) || lengthArgument.value < 0) scanner.fail(`rpt:${functionName}'s second argument must be a non-negative whole number of characters, but was ${String(lengthArgument.value)}`);
153
+ return {
154
+ kind: "left",
155
+ reference,
156
+ length: lengthArgument.value,
157
+ text: formula
158
+ };
159
+ }
160
+ if (isAggregateFunction(canonical)) {
161
+ expectArgumentCount(argumentValues, 1, functionName, scanner);
162
+ return {
163
+ kind: "aggregate",
164
+ aggregate: canonical,
165
+ reference: referenceArgument(argumentValues[0], functionName, "first", scanner),
166
+ text: formula
167
+ };
168
+ }
169
+ throw new require_odb_formula_errors.RptFormulaUnsupportedError(functionName, formula);
170
+ }
171
+ function parseRptFormula(formula) {
172
+ const scanner = new FormulaScanner(formula);
173
+ if (scanner.tryConsume(FIELD_PREFIX)) {
174
+ const reference = scanner.readBracketReference();
175
+ if (!scanner.atEnd()) scanner.fail("unexpected trailing text after a field: reference");
176
+ return {
177
+ kind: "field",
178
+ reference,
179
+ text: formula
180
+ };
181
+ }
182
+ if (!scanner.tryConsume(RPT_PREFIX)) scanner.fail(`expected a formula beginning "${FIELD_PREFIX}" or "${RPT_PREFIX}"`);
183
+ const functionName = scanner.readName("an rpt: function name");
184
+ scanner.expect("(", "the opening parenthesis of a function's argument list");
185
+ const argumentValues = [];
186
+ if (scanner.peek() !== ")") {
187
+ argumentValues.push(scanner.readArgument());
188
+ while (scanner.peek() === ";") {
189
+ scanner.expect(";", "an argument separator");
190
+ argumentValues.push(scanner.readArgument());
191
+ }
192
+ }
193
+ scanner.expect(")", "the closing parenthesis of a function's argument list");
194
+ if (!scanner.atEnd()) scanner.fail("unexpected trailing text after a function call");
195
+ return buildCall(functionName, argumentValues, formula, scanner);
196
+ }
197
+ //#endregion
198
+ exports.parseRptFormula = parseRptFormula;
@@ -0,0 +1,29 @@
1
+ import { n as CellAggregateFunction } from "../../values-BetetbaH.cjs";
2
+ //#region src/odb/formula/parser.d.ts
3
+ type RptAggregateFunction = CellAggregateFunction;
4
+ interface RptReference {
5
+ readonly name: string;
6
+ readonly spelling: 'bracket' | 'quote';
7
+ }
8
+ type RptFormula = {
9
+ readonly kind: 'field';
10
+ readonly reference: RptReference;
11
+ readonly text: string;
12
+ } | {
13
+ readonly kind: 'hasChanged';
14
+ readonly reference: RptReference;
15
+ readonly text: string;
16
+ } | {
17
+ readonly kind: 'left';
18
+ readonly reference: RptReference;
19
+ readonly length: number;
20
+ readonly text: string;
21
+ } | {
22
+ readonly kind: 'aggregate';
23
+ readonly aggregate: RptAggregateFunction;
24
+ readonly reference: RptReference;
25
+ readonly text: string;
26
+ };
27
+ declare function parseRptFormula(formula: string): RptFormula;
28
+ //#endregion
29
+ export { RptAggregateFunction, RptFormula, RptReference, parseRptFormula };
@@ -0,0 +1,29 @@
1
+ import { n as CellAggregateFunction } from "../../values-BetetbaH.js";
2
+ //#region src/odb/formula/parser.d.ts
3
+ type RptAggregateFunction = CellAggregateFunction;
4
+ interface RptReference {
5
+ readonly name: string;
6
+ readonly spelling: 'bracket' | 'quote';
7
+ }
8
+ type RptFormula = {
9
+ readonly kind: 'field';
10
+ readonly reference: RptReference;
11
+ readonly text: string;
12
+ } | {
13
+ readonly kind: 'hasChanged';
14
+ readonly reference: RptReference;
15
+ readonly text: string;
16
+ } | {
17
+ readonly kind: 'left';
18
+ readonly reference: RptReference;
19
+ readonly length: number;
20
+ readonly text: string;
21
+ } | {
22
+ readonly kind: 'aggregate';
23
+ readonly aggregate: RptAggregateFunction;
24
+ readonly reference: RptReference;
25
+ readonly text: string;
26
+ };
27
+ declare function parseRptFormula(formula: string): RptFormula;
28
+ //#endregion
29
+ export { RptAggregateFunction, RptFormula, RptReference, parseRptFormula };