@rowsncolumns/fast-formula-parser 6.2.33 → 6.2.35
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/cjs/index.js +75 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +75 -6
- package/dist/esm/index.js.map +1 -1
- package/index.d.ts +4 -1
- package/package.json +2 -2
package/dist/cjs/index.js
CHANGED
|
@@ -3223,12 +3223,15 @@ const IndexedColors = Object.freeze([
|
|
|
3223
3223
|
|
|
3224
3224
|
const isSingleSectionElapsedTimePattern = (pattern) => !pattern.includes(";") &&
|
|
3225
3225
|
/\[(?:h+|m+|s+)\]/i.test(pattern.replace(/\[\$[^\]]+\]/g, ""));
|
|
3226
|
+
const localeForPattern = (pattern, locale) => {
|
|
3227
|
+
return locale;
|
|
3228
|
+
};
|
|
3226
3229
|
const ssfFormat = (pattern, value, locale) => {
|
|
3227
3230
|
try {
|
|
3228
3231
|
const isNegativeElapsedTime = typeof value === "number" &&
|
|
3229
3232
|
value < 0 &&
|
|
3230
3233
|
isSingleSectionElapsedTimePattern(pattern);
|
|
3231
|
-
const formatted = format(pattern, isNegativeElapsedTime ? Math.abs(value) : value, { locale });
|
|
3234
|
+
const formatted = format(pattern, isNegativeElapsedTime ? Math.abs(value) : value, { locale: localeForPattern(pattern, locale) });
|
|
3232
3235
|
return isNegativeElapsedTime ? `-${formatted}` : formatted;
|
|
3233
3236
|
}
|
|
3234
3237
|
catch (err) {
|
|
@@ -41824,7 +41827,19 @@ const allTokens = [
|
|
|
41824
41827
|
|
|
41825
41828
|
const SelectLexer = new Lexer(allTokens, { ensureOptimizations: true });
|
|
41826
41829
|
|
|
41827
|
-
|
|
41830
|
+
// Catch-all for characters no other token matches. Spelled out as a code-unit
|
|
41831
|
+
// range because Chevrotain's first-char optimisation mis-analyses `[\s\S]`
|
|
41832
|
+
// (it never matches) and refuses to optimise the complement set `[^]`.
|
|
41833
|
+
const UnknownChar = createToken({
|
|
41834
|
+
name: "UnknownChar",
|
|
41835
|
+
pattern: /[\u0000-\uFFFF]/,
|
|
41836
|
+
});
|
|
41837
|
+
|
|
41838
|
+
const tolerantTokens = [...allTokens, UnknownChar];
|
|
41839
|
+
|
|
41840
|
+
const TolerantLexer = new Lexer(tolerantTokens, { ensureOptimizations: true });
|
|
41841
|
+
|
|
41842
|
+
tolerantTokens.forEach((tokenType) => {
|
|
41828
41843
|
tokenVocabulary$1[tokenType.name] = tokenType;
|
|
41829
41844
|
});
|
|
41830
41845
|
|
|
@@ -41852,11 +41867,29 @@ function lex(inputText) {
|
|
|
41852
41867
|
/**
|
|
41853
41868
|
* Tolerant lexer that returns partial tokens even when errors occur.
|
|
41854
41869
|
* Useful for incomplete formulas (e.g., '=SUM(') without throwing.
|
|
41870
|
+
*
|
|
41871
|
+
* Every character the formula grammar has no token for (e.g. a bare `\`)
|
|
41872
|
+
* is lexed as an `UnknownChar` token instead of being dropped by Chevrotain's
|
|
41873
|
+
* error recovery, which never advances its column counter over the dropped
|
|
41874
|
+
* characters. Unknown characters stay in `tokens` as first-class tokens with
|
|
41875
|
+
* native positions and are additionally reported in `errors` (Chevrotain's
|
|
41876
|
+
* `ILexingError` shape) so callers can still detect them.
|
|
41855
41877
|
*/
|
|
41856
41878
|
function tolerantLex(inputText) {
|
|
41857
|
-
const lexingResult =
|
|
41858
|
-
|
|
41859
|
-
|
|
41879
|
+
const lexingResult = TolerantLexer.tokenize(inputText);
|
|
41880
|
+
const errors = [];
|
|
41881
|
+
for (const token of lexingResult.tokens) {
|
|
41882
|
+
if (token.tokenType === UnknownChar) {
|
|
41883
|
+
errors.push({
|
|
41884
|
+
offset: token.startOffset,
|
|
41885
|
+
line: token.startLine,
|
|
41886
|
+
column: token.startColumn,
|
|
41887
|
+
length: 1,
|
|
41888
|
+
message: `unexpected character: ->${token.image}<- at offset: ${token.startOffset}, skipped 1 characters.`,
|
|
41889
|
+
});
|
|
41890
|
+
}
|
|
41891
|
+
}
|
|
41892
|
+
return { tokens: lexingResult.tokens, groups: lexingResult.groups, errors };
|
|
41860
41893
|
}
|
|
41861
41894
|
|
|
41862
41895
|
const tokenVocabulary = tokenVocabulary$1;
|
|
@@ -45499,6 +45532,17 @@ class DepParser {
|
|
|
45499
45532
|
if (fnName === "OFFSET") {
|
|
45500
45533
|
return this.handleOffset(args);
|
|
45501
45534
|
}
|
|
45535
|
+
// ADDRESS is pure and is the idiomatic way to build INDIRECT's
|
|
45536
|
+
// target. Folding it here lets handleIndirect register the real
|
|
45537
|
+
// precedent edge (`INDIRECT(ADDRESS(1,3,1,1,"Source"))` →
|
|
45538
|
+
// Source!$C$1), so the calc engine orders the INDIRECT cell after
|
|
45539
|
+
// the chain it reads instead of evaluating it against stale values.
|
|
45540
|
+
if (fnName === "ADDRESS") {
|
|
45541
|
+
const folded = this.foldAddress(args);
|
|
45542
|
+
if (folded !== undefined) {
|
|
45543
|
+
return { value: folded };
|
|
45544
|
+
}
|
|
45545
|
+
}
|
|
45502
45546
|
// Phase 7 LAMBDA: __RNC_LAMBDA__("params", "body") is the
|
|
45503
45547
|
// preprocessor's runtime lambda constructor. The body is a string
|
|
45504
45548
|
// literal that may contain cell refs — recurse the dep parser on
|
|
@@ -45565,6 +45609,31 @@ class DepParser {
|
|
|
45565
45609
|
}
|
|
45566
45610
|
}
|
|
45567
45611
|
|
|
45612
|
+
/**
|
|
45613
|
+
* Evaluate ADDRESS(...) when every argument is a literal scalar.
|
|
45614
|
+
* Returns undefined when an argument is a reference or another
|
|
45615
|
+
* function's placeholder result (the dep parser does not evaluate
|
|
45616
|
+
* those), or when ADDRESS itself would error.
|
|
45617
|
+
*/
|
|
45618
|
+
foldAddress(args = []) {
|
|
45619
|
+
if (!args.length || args.length > 5) return undefined;
|
|
45620
|
+
const scalars = [];
|
|
45621
|
+
for (const arg of args) {
|
|
45622
|
+
if (arg == null) {
|
|
45623
|
+
scalars.push(undefined);
|
|
45624
|
+
continue;
|
|
45625
|
+
}
|
|
45626
|
+
if (typeof arg === "object") return undefined;
|
|
45627
|
+
scalars.push(arg);
|
|
45628
|
+
}
|
|
45629
|
+
try {
|
|
45630
|
+
const address = ReferenceFunctions.ADDRESS(...scalars);
|
|
45631
|
+
return typeof address === "string" ? address : undefined;
|
|
45632
|
+
} catch {
|
|
45633
|
+
return undefined;
|
|
45634
|
+
}
|
|
45635
|
+
}
|
|
45636
|
+
|
|
45568
45637
|
handleIndirect(args = []) {
|
|
45569
45638
|
const refText = this.extractScalar(args[0]);
|
|
45570
45639
|
if (typeof refText !== "string") {
|
|
@@ -45757,6 +45826,7 @@ exports.MAX_COLUMN = MAX_COLUMN;
|
|
|
45757
45826
|
exports.MAX_ROW = MAX_ROW;
|
|
45758
45827
|
exports.ReversedTypes = ReversedTypes;
|
|
45759
45828
|
exports.Types = Types;
|
|
45829
|
+
exports.UnknownChar = UnknownChar;
|
|
45760
45830
|
exports.WildCard = WildCard;
|
|
45761
45831
|
exports.allTokens = allTokens;
|
|
45762
45832
|
exports.default = FormulaParser;
|