@sme.up/doc-alchemist 1.8.1 → 1.8.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.
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getCellValueData = exports.evaluateStandardFormula = exports.handleSubtotalFormula = void 0;
7
- const commons_1 = require("../../excel/commons");
8
- const dates_utility_1 = require("../../../utils/dates-utility");
9
- const formatter_utility_1 = require("../../../utils/formatter-utility");
6
+ exports.getSanitizedCellValue = exports.getCellValueData = exports.evaluateStandardFormula = exports.handleSubtotalFormula = void 0;
7
+ const commons_1 = require("../converters/excel/commons");
8
+ const dates_utility_1 = require("./dates-utility");
9
+ const formatter_utility_1 = require("./formatter-utility");
10
10
  const exceljs_1 = __importDefault(require("exceljs"));
11
- const math_utility_1 = require("../../../utils/math-utility");
11
+ const math_utility_1 = require("./math-utility");
12
12
  /**
13
13
  * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.
14
14
  *
@@ -147,29 +147,36 @@ exports.handleSubtotalFormula = handleSubtotalFormula;
147
147
  * @param webupManagerData - Additional data used for number formatting.
148
148
  * @returns An object containing the evaluated value and its type.
149
149
  */
150
- const evaluateStandardFormula = (cell, worksheet, webupManagerData) => {
151
- const formula = cell.formula;
150
+ /**
151
+ * Core formula resolver: evaluates a single formula string against the worksheet.
152
+ * Delegates to handleSubtotalFormula for SUBTOTAL expressions, otherwise replaces
153
+ * cell references with their resolved values and evaluates the resulting arithmetic.
154
+ *
155
+ * @param formula - The raw formula string to evaluate (without leading "=").
156
+ * @param cell - The originating cell, used for formatting context (numFmt, address…).
157
+ * @param worksheet - The worksheet for resolving cell references.
158
+ * @param webupManagerData - Data used for number/date formatting.
159
+ * @returns The evaluated value and its type ("number" | "string").
160
+ */
161
+ const resolveFormula = (formula, cell, worksheet, webupManagerData) => {
162
+ const subtotalMatch = formula.match(/^SUBTOTAL\((\d+)\s*,\s*([A-Z]+\d+):([A-Z]+\d+)\)/i);
163
+ if (subtotalMatch) {
164
+ return (0, exports.handleSubtotalFormula)(cell, worksheet, webupManagerData, subtotalMatch);
165
+ }
152
166
  const formulaWithSolvedVariables = formula.replace(/([A-Z]+\d+)/g, ref => {
153
167
  try {
154
168
  const refCell = worksheet.getCell(ref);
155
169
  if (refCell) {
156
- if (refCell.type === exceljs_1.default.ValueType.Number) {
170
+ if (refCell.type === exceljs_1.default.ValueType.Number)
157
171
  return refCell.value?.toString() ?? "0";
158
- }
159
- else if (refCell.type === exceljs_1.default.ValueType.String) {
160
- // If the cell contains text, return as is (no quotes) for JS compatibility
172
+ if (refCell.type === exceljs_1.default.ValueType.String)
161
173
  return refCell.value?.toString() ?? "";
162
- }
163
- else if (refCell.type === exceljs_1.default.ValueType.Formula) {
174
+ if (refCell.type === exceljs_1.default.ValueType.Formula)
164
175
  return (0, exports.getCellValueData)(refCell, worksheet, webupManagerData).value.toString();
165
- }
166
- else if (refCell.type === exceljs_1.default.ValueType.Date &&
167
- refCell.value instanceof Date) {
176
+ if (refCell.type === exceljs_1.default.ValueType.Date &&
177
+ refCell.value instanceof Date)
168
178
  return refCell.value.getTime().toString();
169
- }
170
- else {
171
- return refCell.value?.toString() ?? "0";
172
- }
179
+ return refCell.value?.toString() ?? "0";
173
180
  }
174
181
  }
175
182
  catch {
@@ -178,7 +185,6 @@ const evaluateStandardFormula = (cell, worksheet, webupManagerData) => {
178
185
  return "0";
179
186
  });
180
187
  const result = (0, math_utility_1.calculateExpression)(formulaWithSolvedVariables);
181
- // If the result is a number and a format is specified, apply it
182
188
  if (typeof result === "number" && cell.numFmt) {
183
189
  return {
184
190
  value: result,
@@ -188,24 +194,51 @@ const evaluateStandardFormula = (cell, worksheet, webupManagerData) => {
188
194
  }
189
195
  return {
190
196
  value: result,
191
- text: result != null ? result.toString() : cell.formula,
197
+ text: result != null ? result.toString() : formula,
192
198
  type: typeof result === "number" ? "number" : "string",
193
199
  };
194
200
  };
201
+ const evaluateStandardFormula = (cell, worksheet, webupManagerData) => resolveFormula(cell.formula, cell, worksheet, webupManagerData);
195
202
  exports.evaluateStandardFormula = evaluateStandardFormula;
203
+ /**
204
+ * Evaluates a formula made of `&`-separated parts and returns their concatenation
205
+ * as a string. Quoted literals ("...") are used as-is; all other parts are resolved
206
+ * via resolveFormula.
207
+ *
208
+ * @param cell - The originating cell.
209
+ * @param parts - The formula split on `&`, each part already trimmed.
210
+ * @param worksheet - The worksheet for resolving any cell references.
211
+ * @param webupManagerData - Data used for number/date formatting.
212
+ * @returns A CellValueProps with type "string" and the concatenated text.
213
+ */
214
+ const evaluateConcatFormula = (cell, parts, worksheet, webupManagerData) => {
215
+ const concatenated = parts
216
+ .map(part => part.startsWith('"') && part.endsWith('"')
217
+ ? part.slice(1, -1)
218
+ : resolveFormula(part, cell, worksheet, webupManagerData).text)
219
+ .join("");
220
+ return { value: concatenated, text: concatenated, type: "string" };
221
+ };
196
222
  /**
197
223
  * Extracts and formats the value of a given ExcelJS cell based on its type.
224
+ * For Formula cells, supports:
225
+ * - `&`-concatenation expressions (e.g. `"Label: " & SUBTOTAL(9,A5:A10)`)
226
+ * - Standalone SUBTOTAL formulas
227
+ * - Standard arithmetic formulas with cell references
228
+ *
229
+ * @param cell - The ExcelJS cell to evaluate.
230
+ * @param worksheet - The worksheet containing the cell.
231
+ * @param webupManagerData - Data used for number/date formatting.
232
+ * @returns An object with value, display text, and type ("number" | "string" | "date").
198
233
  */
199
234
  const getCellValueData = (cell, worksheet, webupManagerData) => {
200
235
  if (cell.type === exceljs_1.default.ValueType.Formula &&
201
236
  typeof cell.formula === "string") {
202
- const subtotalMatch = cell.formula.match(/^SUBTOTAL\((\d+)\s*,\s*([A-Z]+\d+):([A-Z]+\d+)\)/i);
203
- if (subtotalMatch) {
204
- return (0, exports.handleSubtotalFormula)(cell, worksheet, webupManagerData, subtotalMatch);
205
- }
206
- else {
207
- return (0, exports.evaluateStandardFormula)(cell, worksheet, webupManagerData);
237
+ const parts = cell.formula.split("&").map(p => p.trim());
238
+ if (parts.length > 1) {
239
+ return evaluateConcatFormula(cell, parts, worksheet, webupManagerData);
208
240
  }
241
+ return resolveFormula(cell.formula, cell, worksheet, webupManagerData);
209
242
  }
210
243
  else if (cell.type === exceljs_1.default.ValueType.Date &&
211
244
  cell.value instanceof Date) {
@@ -233,4 +266,25 @@ const getCellValueData = (cell, worksheet, webupManagerData) => {
233
266
  }
234
267
  };
235
268
  exports.getCellValueData = getCellValueData;
236
- //# sourceMappingURL=formulas-helper.js.map
269
+ /**
270
+ * Returns a sanitized value for a given ExcelJS cell, resolving formulas and formatting as needed.
271
+ *
272
+ * - Uses getCellValueData to extract and format the cell value, handling numbers, strings, dates, and formulas.
273
+ * - If the resulting value is NaN (e.g., for an invalid formula), returns an empty string and logs a warning
274
+ * to avoid Excel errors.
275
+ *
276
+ * @param cell - The ExcelJS cell to extract the value from.
277
+ * @param worksheet - The worksheet containing the cell.
278
+ * @param webupManagerData - Additional data for formatting.
279
+ * @returns The sanitized cell value: string, number, or date.
280
+ */
281
+ const getSanitizedCellValue = (cell, worksheet, webupManagerData) => {
282
+ const cellValueData = (0, exports.getCellValueData)(cell, worksheet, webupManagerData);
283
+ if (typeof cellValueData.value === "number" && isNaN(cellValueData.value)) {
284
+ console.warn(`Warning: Formula in cell ${cell.address} resulted in NaN. Setting value to empty string to avoid Excel errors.`);
285
+ return "";
286
+ }
287
+ return cellValueData.value;
288
+ };
289
+ exports.getSanitizedCellValue = getSanitizedCellValue;
290
+ //# sourceMappingURL=excel-formulas-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"excel-formulas-helper.js","sourceRoot":"","sources":["../../src/utils/excel-formulas-helper.ts"],"names":[],"mappings":";;;;;;AAAA,yDAAgE;AAEhE,mDAAoD;AACpD,2DAA+D;AAE/D,sDAA8B;AAC9B,iDAAqD;AAErD;;;;;;;;;;;;;;;GAeG;AACI,MAAM,qBAAqB,GAAG,CACnC,IAAkB,EAClB,SAA4B,EAC5B,gBAAkC,EAClC,aAA+B,EACf,EAAE;IAClB,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,IAAA,2BAAiB,EAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CACjE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,OAAO,CAChD,CAAC;IACF,IAAI,MAA4B,CAAC;IACjC,MAAM,WAAW,GAAG,IAAA,iCAAiB,EAAC,KAAK,CAAC,CAAC;IAC7C,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,CAAC,EAAE,SAAS;YACf,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YACtB,MAAM;QACR,KAAK,CAAC,EAAE,MAAM;YACZ,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;gBAClC,MAAM,CAAC,GACL,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;oBAC5B,CAAC,CAAC,IAAI,CAAC,KAAK;oBACZ,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;wBAC9B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;wBACxB,CAAC,CAAC,GAAG,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;oBACd,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ;wBACtB,CAAC,CAAC,GAAG;wBACL,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ;4BACvB,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;4BACjB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;oBACd,CAAC,CAAC,GAAG,CAAC;YACV,CAAC,EAAE,CAAC,CAAC,CAAC;YACN,MAAM;QACR,KAAK,CAAC,EAAE,MAAM;YACZ,MAAM,GAAG,KAAK,CAAC,MAAM;gBACnB,CAAC,CAAC,IAAI,CAAC,GAAG,CACN,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;oBAClB,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;wBACzC,OAAO,IAAI,CAAC,KAAK,YAAY,IAAI;4BAC/B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;4BACtB,CAAC,CAAC,CAAC,QAAQ,CAAC;oBAChB,CAAC;oBACD,OAAO,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;wBACnC,CAAC,CAAC,IAAI,CAAC,KAAK;wBACZ,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;4BAC7B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;4BACxB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAClC,CAAC,CAAC,CACH;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,MAAM;QACR,KAAK,CAAC,EAAE,MAAM;YACZ,MAAM,GAAG,KAAK,CAAC,MAAM;gBACnB,CAAC,CAAC,IAAI,CAAC,GAAG,CACN,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;oBAClB,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;wBACzC,OAAO,IAAI,CAAC,KAAK,YAAY,IAAI;4BAC/B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;4BACtB,CAAC,CAAC,QAAQ,CAAC;oBACf,CAAC;oBACD,OAAO,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;wBACnC,CAAC,CAAC,IAAI,CAAC,KAAK;wBACZ,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;4BAC7B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;4BACxB,CAAC,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;gBAChC,CAAC,CAAC,CACH;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,MAAM;QACR,KAAK,CAAC,CAAC,CAAC,CAAC;YACP,UAAU;YACV,MAAM,IAAI,GAAG,KAAK;iBACf,GAAG,CAAC,IAAI,CAAC,EAAE,CACV,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;gBAC5B,CAAC,CAAC,IAAI,CAAC,KAAK;gBACZ,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;oBAC9B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;oBACxB,CAAC,CAAC,GAAG,CACV;iBACA,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,MAAM;QACR,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC3D,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,MAAM;oBACJ,IAAI,CAAC,IAAI;wBACT,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;4BAC/D,CAAC,CAAC,IAAI,CAAC,KAAK;4BACZ,CAAC,CAAC,EAAE,CAAC;wBACP,EAAE,CAAC;YACP,CAAC;YACD,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,IAAA,8BAAU,EAAC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;YACpD,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACrD,OAAO;YACL,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,IAAA,gCAAY,EAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC;YACzD,IAAI,EAAE,QAAQ;SACf,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;QACvB,IAAI,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;KACvD,CAAC;AACJ,CAAC,CAAC;AAtHW,QAAA,qBAAqB,yBAsHhC;AAEF;;;;;;;;;;;;;;GAcG;AACH;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,CACrB,OAAe,EACf,IAAkB,EAClB,SAA4B,EAC5B,gBAAkC,EAClB,EAAE;IAClB,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CACjC,mDAAmD,CACpD,CAAC;IACF,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAA,6BAAqB,EAC1B,IAAI,EACJ,SAAS,EACT,gBAAgB,EAChB,aAAa,CACd,CAAC;IACJ,CAAC;IACD,MAAM,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,EAAE;QACvE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,MAAM;oBAC3C,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC;gBAC1C,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,MAAM;oBAC3C,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACzC,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,OAAO;oBAC5C,OAAO,IAAA,wBAAgB,EACrB,OAAO,EACP,SAAS,EACT,gBAAgB,CACjB,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACrB,IACE,OAAO,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,IAAI;oBACvC,OAAO,CAAC,KAAK,YAAY,IAAI;oBAE7B,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;gBAC5C,OAAO,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC;YAC1C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,CAAC;QACb,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAA,kCAAmB,EAAC,0BAA0B,CAAC,CAAC;IAC/D,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9C,OAAO;YACL,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,IAAA,gCAAY,EAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC;YACzD,IAAI,EAAE,QAAQ;SACf,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO;QAClD,IAAI,EAAE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;KACvD,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,uBAAuB,GAAG,CACrC,IAAkB,EAClB,SAA4B,EAC5B,gBAAkC,EAClB,EAAE,CAClB,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AALrD,QAAA,uBAAuB,2BAK8B;AAElE;;;;;;;;;;GAUG;AACH,MAAM,qBAAqB,GAAG,CAC5B,IAAkB,EAClB,KAAe,EACf,SAA4B,EAC5B,gBAAkC,EAClB,EAAE;IAClB,MAAM,YAAY,GAAG,KAAK;SACvB,GAAG,CAAC,IAAI,CAAC,EAAE,CACV,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC,IAAI,CACjE;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACrE,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACI,MAAM,gBAAgB,GAAG,CAC9B,IAAkB,EAClB,SAA4B,EAC5B,gBAAkC,EAClB,EAAE;IAClB,IACE,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,OAAO;QACvC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAChC,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACzE,CAAC;SAAM,IACL,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,IAAI;QACpC,IAAI,CAAC,KAAK,YAAY,IAAI,EAC1B,CAAC;QACD,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAA,8BAAU,EAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC;YAC9C,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAClD,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAe;YAC3B,IAAI,EAAE,IAAA,gCAAY,EAChB,IAAI,CAAC,KAAe,EACpB,IAAI,CAAC,MAAM,IAAI,CAAC,EAChB,gBAAgB,CACjB;YACD,IAAI,EAAE,QAAQ;SACf,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,iEAAiE;QACjE,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC1D,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,QAAQ;SACf,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AA1CW,QAAA,gBAAgB,oBA0C3B;AAEF;;;;;;;;;;;GAWG;AACI,MAAM,qBAAqB,GAAG,CACnC,IAAkB,EAClB,SAA4B,EAC5B,gBAAkC,EACV,EAAE;IAC1B,MAAM,aAAa,GAAG,IAAA,wBAAgB,EAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC1E,IAAI,OAAO,aAAa,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1E,OAAO,CAAC,IAAI,CACV,4BAA4B,IAAI,CAAC,OAAO,wEAAwE,CACjH,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,aAAa,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC;AAbW,QAAA,qBAAqB,yBAahC","sourcesContent":["import { getCellsFromRange } from \"../converters/excel/commons\";\nimport { WebupManagerData } from \"../types/index\";\nimport { areAllValuesDates } from \"./dates-utility\";\nimport { formatDate, formatNumber } from \"./formatter-utility\";\nimport { CellValueProps } from \"../converters/pdf/jspdf/pdf-converter.types\";\nimport ExcelJS from \"exceljs\";\nimport { calculateExpression } from \"./math-utility\";\n\n/**\n * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.\n *\n * Supports various SUBTOTAL types such as SUM, AVERAGE, COUNTA, MAX, and MIN.\n * The function extracts the relevant range from the worksheet, computes the result\n * based on the subtotal type, and formats the output as needed (including date and number formatting).\n *\n * @param cell - The ExcelJS cell object where the formula is applied.\n * @param worksheet - The ExcelJS worksheet containing the data range.\n * @param webupManagerData - Additional data/context used for formatting numbers and dates.\n * @param subtotalMatch - The RegExp match array containing the parsed SUBTOTAL formula components:\n * - [1]: The subtotal type (e.g., 1 for AVERAGE, 3 for COUNTA, 4 for MAX, 5 for MIN, 9 for SUM).\n * - [2]: The start cell reference of the range.\n * - [3]: The end cell reference of the range.\n * @returns An object containing the computed value and its type (\"number\" or \"string\").\n */\nexport const handleSubtotalFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n subtotalMatch: RegExpMatchArray,\n): CellValueProps => {\n const subtotalType = parseInt(subtotalMatch[1], 10);\n const startRef = subtotalMatch[2];\n const endRef = subtotalMatch[3];\n const cells = getCellsFromRange(worksheet, startRef, endRef).filter(\n cell => cell.type !== ExcelJS.ValueType.Formula,\n );\n let result: number | string | \"\";\n const areAllDates = areAllValuesDates(cells);\n switch (subtotalType) {\n case 3: // COUNTA\n result = cells.length;\n break;\n case 9: // SUM\n result = cells.reduce((sum, cell) => {\n const n =\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN;\n return !isNaN(n)\n ? (typeof sum === \"number\"\n ? sum\n : typeof sum === \"string\"\n ? parseFloat(sum)\n : 0) + n\n : sum;\n }, 0);\n break;\n case 4: // MAX\n result = cells.length\n ? Math.max(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : -Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : -Infinity) || -Infinity;\n }),\n )\n : \"\";\n break;\n case 5: // MIN\n result = cells.length\n ? Math.min(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : Infinity) || Infinity;\n }),\n )\n : \"\";\n break;\n case 1: {\n // AVERAGE\n const nums = cells\n .map(cell =>\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN,\n )\n .filter(v => !isNaN(v));\n result = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : \"\";\n break;\n }\n default: {\n if (cell.result != null && typeof cell.result !== \"object\") {\n result = cell.result;\n } else {\n result =\n cell.text ||\n (typeof cell.value === \"string\" || typeof cell.value === \"number\"\n ? cell.value\n : \"\") ||\n \"\";\n }\n break;\n }\n }\n\n if (areAllDates) {\n return {\n value: result,\n text: formatDate(new Date(result), webupManagerData),\n type: \"date\",\n };\n } else if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result.toString(),\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\n/**\n * Evaluates a standard Excel formula from a given cell by replacing cell references\n * with their actual values from the worksheet and then computing the result.\n *\n * - Replaces cell references (e.g., \"A1\") in the formula with their corresponding values.\n * - Handles different cell value types: number, string, formula result, and date.\n * - Evaluates the resulting formula string using a safe function context.\n * - Applies number formatting if the result is numeric and a format is specified.\n * - Returns the computed value and its type (\"number\" or \"string\").\n *\n * @param cell - The ExcelJS cell containing the formula to evaluate.\n * @param worksheet - The ExcelJS worksheet object for resolving cell references.\n * @param webupManagerData - Additional data used for number formatting.\n * @returns An object containing the evaluated value and its type.\n */\n/**\n * Core formula resolver: evaluates a single formula string against the worksheet.\n * Delegates to handleSubtotalFormula for SUBTOTAL expressions, otherwise replaces\n * cell references with their resolved values and evaluates the resulting arithmetic.\n *\n * @param formula - The raw formula string to evaluate (without leading \"=\").\n * @param cell - The originating cell, used for formatting context (numFmt, address…).\n * @param worksheet - The worksheet for resolving cell references.\n * @param webupManagerData - Data used for number/date formatting.\n * @returns The evaluated value and its type (\"number\" | \"string\").\n */\nconst resolveFormula = (\n formula: string,\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n const subtotalMatch = formula.match(\n /^SUBTOTAL\\((\\d+)\\s*,\\s*([A-Z]+\\d+):([A-Z]+\\d+)\\)/i,\n );\n if (subtotalMatch) {\n return handleSubtotalFormula(\n cell,\n worksheet,\n webupManagerData,\n subtotalMatch,\n );\n }\n const formulaWithSolvedVariables = formula.replace(/([A-Z]+\\d+)/g, ref => {\n try {\n const refCell = worksheet.getCell(ref);\n if (refCell) {\n if (refCell.type === ExcelJS.ValueType.Number)\n return refCell.value?.toString() ?? \"0\";\n if (refCell.type === ExcelJS.ValueType.String)\n return refCell.value?.toString() ?? \"\";\n if (refCell.type === ExcelJS.ValueType.Formula)\n return getCellValueData(\n refCell,\n worksheet,\n webupManagerData,\n ).value.toString();\n if (\n refCell.type === ExcelJS.ValueType.Date &&\n refCell.value instanceof Date\n )\n return refCell.value.getTime().toString();\n return refCell.value?.toString() ?? \"0\";\n }\n } catch {\n return \"0\";\n }\n return \"0\";\n });\n const result = calculateExpression(formulaWithSolvedVariables);\n if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result != null ? result.toString() : formula,\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\nexport const evaluateStandardFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps =>\n resolveFormula(cell.formula, cell, worksheet, webupManagerData);\n\n/**\n * Evaluates a formula made of `&`-separated parts and returns their concatenation\n * as a string. Quoted literals (\"...\") are used as-is; all other parts are resolved\n * via resolveFormula.\n *\n * @param cell - The originating cell.\n * @param parts - The formula split on `&`, each part already trimmed.\n * @param worksheet - The worksheet for resolving any cell references.\n * @param webupManagerData - Data used for number/date formatting.\n * @returns A CellValueProps with type \"string\" and the concatenated text.\n */\nconst evaluateConcatFormula = (\n cell: ExcelJS.Cell,\n parts: string[],\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n const concatenated = parts\n .map(part =>\n part.startsWith('\"') && part.endsWith('\"')\n ? part.slice(1, -1)\n : resolveFormula(part, cell, worksheet, webupManagerData).text,\n )\n .join(\"\");\n return { value: concatenated, text: concatenated, type: \"string\" };\n};\n\n/**\n * Extracts and formats the value of a given ExcelJS cell based on its type.\n * For Formula cells, supports:\n * - `&`-concatenation expressions (e.g. `\"Label: \" & SUBTOTAL(9,A5:A10)`)\n * - Standalone SUBTOTAL formulas\n * - Standard arithmetic formulas with cell references\n *\n * @param cell - The ExcelJS cell to evaluate.\n * @param worksheet - The worksheet containing the cell.\n * @param webupManagerData - Data used for number/date formatting.\n * @returns An object with value, display text, and type (\"number\" | \"string\" | \"date\").\n */\nexport const getCellValueData = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n if (\n cell.type === ExcelJS.ValueType.Formula &&\n typeof cell.formula === \"string\"\n ) {\n const parts = cell.formula.split(\"&\").map(p => p.trim());\n if (parts.length > 1) {\n return evaluateConcatFormula(cell, parts, worksheet, webupManagerData);\n }\n return resolveFormula(cell.formula, cell, worksheet, webupManagerData);\n } else if (\n cell.type === ExcelJS.ValueType.Date &&\n cell.value instanceof Date\n ) {\n return {\n value: cell.value,\n text: formatDate(cell.value, webupManagerData),\n type: \"date\",\n };\n } else if (cell.type === ExcelJS.ValueType.Number) {\n return {\n value: cell.value as number,\n text: formatNumber(\n cell.value as number,\n cell.numFmt ?? 0,\n webupManagerData,\n ),\n type: \"number\",\n };\n } else {\n // Fallback to text or value if available, otherwise empty string\n const value = cell?.text || cell?.value?.toString() || \"\";\n return {\n value: value,\n text: value,\n type: \"string\",\n };\n }\n};\n\n/**\n * Returns a sanitized value for a given ExcelJS cell, resolving formulas and formatting as needed.\n *\n * - Uses getCellValueData to extract and format the cell value, handling numbers, strings, dates, and formulas.\n * - If the resulting value is NaN (e.g., for an invalid formula), returns an empty string and logs a warning\n * to avoid Excel errors.\n *\n * @param cell - The ExcelJS cell to extract the value from.\n * @param worksheet - The worksheet containing the cell.\n * @param webupManagerData - Additional data for formatting.\n * @returns The sanitized cell value: string, number, or date.\n */\nexport const getSanitizedCellValue = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): string | number | Date => {\n const cellValueData = getCellValueData(cell, worksheet, webupManagerData);\n if (typeof cellValueData.value === \"number\" && isNaN(cellValueData.value)) {\n console.warn(\n `Warning: Formula in cell ${cell.address} resulted in NaN. Setting value to empty string to avoid Excel errors.`,\n );\n return \"\";\n }\n return cellValueData.value;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sme.up/doc-alchemist",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "description": "Library for generating documents in various formats, including Excel and PDF.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Smeup LAB <info@smeup.com> (https://www.smeup.com/)",
@@ -1 +0,0 @@
1
- {"version":3,"file":"formulas-helper.js","sourceRoot":"","sources":["../../../../src/converters/pdf/jspdf/formulas-helper.ts"],"names":[],"mappings":"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","sourcesContent":["import { getCellsFromRange } from \"../../excel/commons\";\nimport { WebupManagerData } from \"../../../types/index\";\nimport { areAllValuesDates } from \"../../../utils/dates-utility\";\nimport { formatDate, formatNumber } from \"../../../utils/formatter-utility\";\nimport { CellValueProps } from \"./pdf-converter.types\";\nimport ExcelJS from \"exceljs\";\nimport { calculateExpression } from \"../../../utils/math-utility\";\n\n/**\n * Handles the calculation of Excel-like SUBTOTAL formulas for a given cell and range.\n *\n * Supports various SUBTOTAL types such as SUM, AVERAGE, COUNTA, MAX, and MIN.\n * The function extracts the relevant range from the worksheet, computes the result\n * based on the subtotal type, and formats the output as needed (including date and number formatting).\n *\n * @param cell - The ExcelJS cell object where the formula is applied.\n * @param worksheet - The ExcelJS worksheet containing the data range.\n * @param webupManagerData - Additional data/context used for formatting numbers and dates.\n * @param subtotalMatch - The RegExp match array containing the parsed SUBTOTAL formula components:\n * - [1]: The subtotal type (e.g., 1 for AVERAGE, 3 for COUNTA, 4 for MAX, 5 for MIN, 9 for SUM).\n * - [2]: The start cell reference of the range.\n * - [3]: The end cell reference of the range.\n * @returns An object containing the computed value and its type (\"number\" or \"string\").\n */\nexport const handleSubtotalFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n subtotalMatch: RegExpMatchArray,\n): CellValueProps => {\n const subtotalType = parseInt(subtotalMatch[1], 10);\n const startRef = subtotalMatch[2];\n const endRef = subtotalMatch[3];\n const cells = getCellsFromRange(worksheet, startRef, endRef).filter(\n cell => cell.type !== ExcelJS.ValueType.Formula,\n );\n let result: number | string | \"\";\n const areAllDates = areAllValuesDates(cells);\n switch (subtotalType) {\n case 3: // COUNTA\n result = cells.length;\n break;\n case 9: // SUM\n result = cells.reduce((sum, cell) => {\n const n =\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN;\n return !isNaN(n)\n ? (typeof sum === \"number\"\n ? sum\n : typeof sum === \"string\"\n ? parseFloat(sum)\n : 0) + n\n : sum;\n }, 0);\n break;\n case 4: // MAX\n result = cells.length\n ? Math.max(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : -Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : -Infinity) || -Infinity;\n }),\n )\n : \"\";\n break;\n case 5: // MIN\n result = cells.length\n ? Math.min(\n ...cells.map(cell => {\n if (cell.type === ExcelJS.ValueType.Date) {\n return cell.value instanceof Date\n ? cell.value.getTime()\n : Infinity;\n }\n return typeof cell.value === \"number\"\n ? cell.value\n : (typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : Infinity) || Infinity;\n }),\n )\n : \"\";\n break;\n case 1: {\n // AVERAGE\n const nums = cells\n .map(cell =>\n typeof cell.value === \"number\"\n ? cell.value\n : typeof cell.value === \"string\"\n ? parseFloat(cell.value)\n : NaN,\n )\n .filter(v => !isNaN(v));\n result = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : \"\";\n break;\n }\n default: {\n if (cell.result != null && typeof cell.result !== \"object\") {\n result = cell.result;\n } else {\n result =\n cell.text ||\n (typeof cell.value === \"string\" || typeof cell.value === \"number\"\n ? cell.value\n : \"\") ||\n \"\";\n }\n break;\n }\n }\n\n if (areAllDates) {\n return {\n value: result,\n text: formatDate(new Date(result), webupManagerData),\n type: \"date\",\n };\n } else if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result.toString(),\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\n/**\n * Evaluates a standard Excel formula from a given cell by replacing cell references\n * with their actual values from the worksheet and then computing the result.\n *\n * - Replaces cell references (e.g., \"A1\") in the formula with their corresponding values.\n * - Handles different cell value types: number, string, formula result, and date.\n * - Evaluates the resulting formula string using a safe function context.\n * - Applies number formatting if the result is numeric and a format is specified.\n * - Returns the computed value and its type (\"number\" or \"string\").\n *\n * @param cell - The ExcelJS cell containing the formula to evaluate.\n * @param worksheet - The ExcelJS worksheet object for resolving cell references.\n * @param webupManagerData - Additional data used for number formatting.\n * @returns An object containing the evaluated value and its type.\n */\nexport const evaluateStandardFormula = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n const formula = cell.formula;\n const formulaWithSolvedVariables = formula.replace(/([A-Z]+\\d+)/g, ref => {\n try {\n const refCell = worksheet.getCell(ref);\n if (refCell) {\n if (refCell.type === ExcelJS.ValueType.Number) {\n return refCell.value?.toString() ?? \"0\";\n } else if (refCell.type === ExcelJS.ValueType.String) {\n // If the cell contains text, return as is (no quotes) for JS compatibility\n return refCell.value?.toString() ?? \"\";\n } else if (refCell.type === ExcelJS.ValueType.Formula) {\n return getCellValueData(\n refCell,\n worksheet,\n webupManagerData,\n ).value.toString();\n } else if (\n refCell.type === ExcelJS.ValueType.Date &&\n refCell.value instanceof Date\n ) {\n return refCell.value.getTime().toString();\n } else {\n return refCell.value?.toString() ?? \"0\";\n }\n }\n } catch {\n return \"0\";\n }\n return \"0\";\n });\n const result = calculateExpression(formulaWithSolvedVariables);\n // If the result is a number and a format is specified, apply it\n if (typeof result === \"number\" && cell.numFmt) {\n return {\n value: result,\n text: formatNumber(result, cell.numFmt, webupManagerData),\n type: \"number\",\n };\n }\n return {\n value: result,\n text: result != null ? result.toString() : cell.formula,\n type: typeof result === \"number\" ? \"number\" : \"string\",\n };\n};\n\n/**\n * Extracts and formats the value of a given ExcelJS cell based on its type.\n */\nexport const getCellValueData = (\n cell: ExcelJS.Cell,\n worksheet: ExcelJS.Worksheet,\n webupManagerData: WebupManagerData,\n): CellValueProps => {\n if (\n cell.type === ExcelJS.ValueType.Formula &&\n typeof cell.formula === \"string\"\n ) {\n const subtotalMatch = cell.formula.match(\n /^SUBTOTAL\\((\\d+)\\s*,\\s*([A-Z]+\\d+):([A-Z]+\\d+)\\)/i,\n );\n if (subtotalMatch) {\n return handleSubtotalFormula(\n cell,\n worksheet,\n webupManagerData,\n subtotalMatch,\n );\n } else {\n return evaluateStandardFormula(cell, worksheet, webupManagerData);\n }\n } else if (\n cell.type === ExcelJS.ValueType.Date &&\n cell.value instanceof Date\n ) {\n return {\n value: cell.value,\n text: formatDate(cell.value, webupManagerData),\n type: \"date\",\n };\n } else if (cell.type === ExcelJS.ValueType.Number) {\n return {\n value: cell.value as number,\n text: formatNumber(\n cell.value as number,\n cell.numFmt ?? 0,\n webupManagerData,\n ),\n type: \"number\",\n };\n } else {\n // Fallback to text or value if available, otherwise empty string\n const value = cell?.text || cell?.value?.toString() || \"\";\n return {\n value: value,\n text: value,\n type: \"string\",\n };\n }\n};\n"]}