@borgar/fx 5.0.0 → 5.0.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/index.cjs +145 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +145 -85
- package/dist/index.js.map +1 -1
- package/dist/xlsx/index.cjs +144 -84
- package/dist/xlsx/index.cjs.map +1 -1
- package/dist/xlsx/index.js +144 -84
- package/dist/xlsx/index.js.map +1 -1
- package/lib/constants.ts +3 -0
- package/lib/fixRanges.spec.ts +14 -0
- package/lib/isRCTokenValue.ts +3 -0
- package/lib/lexers/lexRangeA1.ts +1 -1
- package/lib/lexers/lexRangeR1C1.ts +2 -1
- package/lib/mergeRefTokens.ts +23 -14
- package/lib/parseA1Ref.spec.ts +7 -0
- package/lib/stringifyA1Ref.spec.ts +18 -0
- package/lib/stringifyPrefix.ts +26 -5
- package/lib/tokenize.spec.ts +99 -0
- package/lib/tokenize.ts +17 -9
- package/lib/translateToA1.spec.ts +84 -0
- package/lib/translateToA1.ts +45 -43
- package/lib/translateToR1C1.spec.ts +68 -4
- package/lib/translateToR1C1.ts +46 -19
- package/package.json +7 -7
package/dist/xlsx/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var REF_BEAM = "range_beam";
|
|
|
15
15
|
var REF_TERNARY = "range_ternary";
|
|
16
16
|
var REF_NAMED = "range_named";
|
|
17
17
|
var REF_STRUCT = "structured";
|
|
18
|
+
var REF_CELL = "cell";
|
|
18
19
|
var FX_PREFIX = "fx_prefix";
|
|
19
20
|
var UNKNOWN = "unknown";
|
|
20
21
|
var UNARY = "UnaryExpression";
|
|
@@ -34,24 +35,26 @@ var MAX_ROWS = 2 ** 20 - 1;
|
|
|
34
35
|
// lib/mergeRefTokens.ts
|
|
35
36
|
var END = "$";
|
|
36
37
|
var validRunsMerge = [
|
|
37
|
-
[
|
|
38
|
-
[
|
|
39
|
-
[
|
|
40
|
-
[
|
|
38
|
+
[REF_CELL, ":", REF_CELL],
|
|
39
|
+
[REF_CELL, ".:", REF_CELL],
|
|
40
|
+
[REF_CELL, ":.", REF_CELL],
|
|
41
|
+
[REF_CELL, ".:.", REF_CELL],
|
|
41
42
|
[REF_RANGE],
|
|
42
43
|
[REF_BEAM],
|
|
43
44
|
[REF_TERNARY],
|
|
44
|
-
[CONTEXT, "!",
|
|
45
|
-
[CONTEXT, "!",
|
|
46
|
-
[CONTEXT, "!",
|
|
47
|
-
[CONTEXT, "!",
|
|
45
|
+
[CONTEXT, "!", REF_CELL, ":", REF_CELL],
|
|
46
|
+
[CONTEXT, "!", REF_CELL, ".:", REF_CELL],
|
|
47
|
+
[CONTEXT, "!", REF_CELL, ":.", REF_CELL],
|
|
48
|
+
[CONTEXT, "!", REF_CELL, ".:.", REF_CELL],
|
|
49
|
+
[CONTEXT, "!", REF_CELL],
|
|
48
50
|
[CONTEXT, "!", REF_RANGE],
|
|
49
51
|
[CONTEXT, "!", REF_BEAM],
|
|
50
52
|
[CONTEXT, "!", REF_TERNARY],
|
|
51
|
-
[CONTEXT_QUOTE, "!",
|
|
52
|
-
[CONTEXT_QUOTE, "!",
|
|
53
|
-
[CONTEXT_QUOTE, "!",
|
|
54
|
-
[CONTEXT_QUOTE, "!",
|
|
53
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ":", REF_CELL],
|
|
54
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ".:", REF_CELL],
|
|
55
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ":.", REF_CELL],
|
|
56
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ".:.", REF_CELL],
|
|
57
|
+
[CONTEXT_QUOTE, "!", REF_CELL],
|
|
55
58
|
[CONTEXT_QUOTE, "!", REF_RANGE],
|
|
56
59
|
[CONTEXT_QUOTE, "!", REF_BEAM],
|
|
57
60
|
[CONTEXT_QUOTE, "!", REF_TERNARY],
|
|
@@ -83,7 +86,11 @@ var matcher = (tokens2, currNode, anchorIndex, index = 0) => {
|
|
|
83
86
|
while (i <= max) {
|
|
84
87
|
const token = tokens2[anchorIndex - i];
|
|
85
88
|
if (token) {
|
|
86
|
-
const
|
|
89
|
+
const value = token.value;
|
|
90
|
+
let key = token.type === OPERATOR ? value : token.type;
|
|
91
|
+
if (key === REF_RANGE && !value.includes(":")) {
|
|
92
|
+
key = REF_CELL;
|
|
93
|
+
}
|
|
87
94
|
if (key in node) {
|
|
88
95
|
node = node[key];
|
|
89
96
|
i += 1;
|
|
@@ -473,7 +480,7 @@ function lexRangeA1(str, pos, options) {
|
|
|
473
480
|
}
|
|
474
481
|
}
|
|
475
482
|
}
|
|
476
|
-
if (top && canEndRange(str, preOp)) {
|
|
483
|
+
if (top && canEndRange(str, preOp) && str.charCodeAt(preOp) !== 33) {
|
|
477
484
|
return { type: REF_RANGE, value: str.slice(pos, preOp) };
|
|
478
485
|
}
|
|
479
486
|
} else {
|
|
@@ -513,6 +520,7 @@ var UC_C = 67;
|
|
|
513
520
|
var LC_C = 99;
|
|
514
521
|
var PLUS = 43;
|
|
515
522
|
var MINUS = 45;
|
|
523
|
+
var EXCL2 = 33;
|
|
516
524
|
function lexR1C1Part(str, pos, isRow = false) {
|
|
517
525
|
const start = pos;
|
|
518
526
|
const c0 = str.charCodeAt(pos);
|
|
@@ -567,7 +575,7 @@ function lexRangeR1C1(str, pos, options) {
|
|
|
567
575
|
p += r1;
|
|
568
576
|
const c1 = lexR1C1Part(str, p);
|
|
569
577
|
p += c1;
|
|
570
|
-
if (c1 || r1) {
|
|
578
|
+
if ((c1 || r1) && str.charCodeAt(p) !== EXCL2) {
|
|
571
579
|
const op = advRangeOp(str, p);
|
|
572
580
|
const preOp = p;
|
|
573
581
|
if (op) {
|
|
@@ -784,7 +792,7 @@ function parseSRange(str, pos = 0) {
|
|
|
784
792
|
}
|
|
785
793
|
|
|
786
794
|
// lib/lexers/lexStructured.ts
|
|
787
|
-
var
|
|
795
|
+
var EXCL3 = 33;
|
|
788
796
|
function lexStructured(str, pos) {
|
|
789
797
|
const structData = parseSRange(str, pos);
|
|
790
798
|
if (structData && structData.length) {
|
|
@@ -792,7 +800,7 @@ function lexStructured(str, pos) {
|
|
|
792
800
|
while (isWS(str.charCodeAt(pos + i))) {
|
|
793
801
|
i++;
|
|
794
802
|
}
|
|
795
|
-
if (str.charCodeAt(pos + i) !==
|
|
803
|
+
if (str.charCodeAt(pos + i) !== EXCL3) {
|
|
796
804
|
return {
|
|
797
805
|
type: REF_STRUCT,
|
|
798
806
|
value: structData.token
|
|
@@ -887,9 +895,9 @@ function lexNamed(str, pos) {
|
|
|
887
895
|
}
|
|
888
896
|
|
|
889
897
|
// lib/lexers/lexRefOp.ts
|
|
890
|
-
var
|
|
898
|
+
var EXCL4 = 33;
|
|
891
899
|
function lexRefOp(str, pos, opts) {
|
|
892
|
-
if (str.charCodeAt(pos) ===
|
|
900
|
+
if (str.charCodeAt(pos) === EXCL4) {
|
|
893
901
|
return { type: OPERATOR, value: str[pos] };
|
|
894
902
|
}
|
|
895
903
|
if (!opts.r1c1) {
|
|
@@ -903,7 +911,7 @@ function lexRefOp(str, pos, opts) {
|
|
|
903
911
|
// lib/lexers/lexNameFuncCntx.ts
|
|
904
912
|
var BR_OPEN4 = 91;
|
|
905
913
|
var PAREN_OPEN = 40;
|
|
906
|
-
var
|
|
914
|
+
var EXCL5 = 33;
|
|
907
915
|
var OFFS = 32;
|
|
908
916
|
var ALLOWED = new Uint8Array(180 - OFFS);
|
|
909
917
|
var OK_NAME_0 = 1;
|
|
@@ -968,7 +976,7 @@ function lexNameFuncCntx(str, pos, opts) {
|
|
|
968
976
|
} else {
|
|
969
977
|
if (c === PAREN_OPEN && func) {
|
|
970
978
|
return { type: FUNCTION, value: str.slice(start, pos) };
|
|
971
|
-
} else if (c ===
|
|
979
|
+
} else if (c === EXCL5 && cntx) {
|
|
972
980
|
return { type: CONTEXT, value: str.slice(start, pos) };
|
|
973
981
|
}
|
|
974
982
|
return nameOrUnknown(str, s, start, pos, name);
|
|
@@ -1004,6 +1012,11 @@ var lexersRefs = [
|
|
|
1004
1012
|
lexNamed
|
|
1005
1013
|
];
|
|
1006
1014
|
|
|
1015
|
+
// lib/isRCTokenValue.ts
|
|
1016
|
+
function isRCTokenValue(value) {
|
|
1017
|
+
return value === "r" || value === "R" || value === "c" || value === "C";
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1007
1020
|
// lib/tokenize.ts
|
|
1008
1021
|
var reLetLambda = /^l(?:ambda|et)$/i;
|
|
1009
1022
|
var isType = (t, type) => t && t.type === type;
|
|
@@ -1011,12 +1024,13 @@ var isTextTokenType = (tokenType) => tokenType === REF_NAMED || tokenType === FU
|
|
|
1011
1024
|
var causesBinaryMinus = (token) => {
|
|
1012
1025
|
return !isType(token, OPERATOR) || (token.value === "%" || token.value === "}" || token.value === ")" || token.value === "#");
|
|
1013
1026
|
};
|
|
1014
|
-
function fixRCNames(tokens2) {
|
|
1027
|
+
function fixRCNames(tokens2, r1c1Mode) {
|
|
1015
1028
|
let withinCall = 0;
|
|
1016
1029
|
let parenDepth = 0;
|
|
1017
1030
|
let lastToken;
|
|
1018
1031
|
for (const token of tokens2) {
|
|
1019
|
-
|
|
1032
|
+
const tokenType = token.type;
|
|
1033
|
+
if (tokenType === OPERATOR) {
|
|
1020
1034
|
if (token.value === "(") {
|
|
1021
1035
|
parenDepth++;
|
|
1022
1036
|
if (lastToken.type === FUNCTION) {
|
|
@@ -1030,7 +1044,9 @@ function fixRCNames(tokens2) {
|
|
|
1030
1044
|
withinCall = 0;
|
|
1031
1045
|
}
|
|
1032
1046
|
}
|
|
1033
|
-
} else if (withinCall &&
|
|
1047
|
+
} else if (withinCall && tokenType === UNKNOWN && isRCTokenValue(token.value)) {
|
|
1048
|
+
token.type = REF_NAMED;
|
|
1049
|
+
} else if (withinCall && r1c1Mode && tokenType === REF_BEAM && isRCTokenValue(token.value)) {
|
|
1034
1050
|
token.type = REF_NAMED;
|
|
1035
1051
|
}
|
|
1036
1052
|
lastToken = token;
|
|
@@ -1117,9 +1133,8 @@ function getTokens(fx, tokenHandlers, options = {}) {
|
|
|
1117
1133
|
letOrLambda++;
|
|
1118
1134
|
}
|
|
1119
1135
|
}
|
|
1120
|
-
if (token.type === UNKNOWN && token.
|
|
1121
|
-
|
|
1122
|
-
unknownRC += valLC === "r" || valLC === "c" ? 1 : 0;
|
|
1136
|
+
if (token.value.length === 1 && (token.type === UNKNOWN || opts.r1c1 && token.type === REF_BEAM)) {
|
|
1137
|
+
unknownRC += isRCTokenValue(token.value) ? 1 : 0;
|
|
1123
1138
|
}
|
|
1124
1139
|
if (negativeNumbers && token.type === NUMBER) {
|
|
1125
1140
|
const last1 = lastToken;
|
|
@@ -1138,7 +1153,7 @@ function getTokens(fx, tokenHandlers, options = {}) {
|
|
|
1138
1153
|
pushToken(token);
|
|
1139
1154
|
}
|
|
1140
1155
|
if (unknownRC && letOrLambda) {
|
|
1141
|
-
fixRCNames(tokens2);
|
|
1156
|
+
fixRCNames(tokens2, opts.r1c1);
|
|
1142
1157
|
}
|
|
1143
1158
|
for (const index of trimOps) {
|
|
1144
1159
|
const before = tokens2[index - 1];
|
|
@@ -1741,20 +1756,38 @@ function parse(tokenlist, options = {}) {
|
|
|
1741
1756
|
|
|
1742
1757
|
// lib/stringifyPrefix.ts
|
|
1743
1758
|
var reBannedChars = /[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;
|
|
1759
|
+
var reIsRangelike = /^(R|C|RC|[A-Z]{1,3}\d{1,7})$/i;
|
|
1760
|
+
function needQuotes(scope, yesItDoes = 0) {
|
|
1761
|
+
if (yesItDoes) {
|
|
1762
|
+
return 1;
|
|
1763
|
+
}
|
|
1764
|
+
if (scope) {
|
|
1765
|
+
if (reBannedChars.test(scope)) {
|
|
1766
|
+
return 1;
|
|
1767
|
+
}
|
|
1768
|
+
if (reIsRangelike.test(scope)) {
|
|
1769
|
+
return 1;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
return 0;
|
|
1773
|
+
}
|
|
1774
|
+
function quotePrefix(prefix2) {
|
|
1775
|
+
return "'" + prefix2.replace(/'/g, "''") + "'";
|
|
1776
|
+
}
|
|
1744
1777
|
function stringifyPrefixXlsx(ref) {
|
|
1745
1778
|
let pre = "";
|
|
1746
1779
|
let quote = 0;
|
|
1747
1780
|
const { workbookName, sheetName } = ref;
|
|
1748
1781
|
if (workbookName) {
|
|
1749
1782
|
pre += "[" + workbookName + "]";
|
|
1750
|
-
quote +=
|
|
1783
|
+
quote += needQuotes(workbookName);
|
|
1751
1784
|
}
|
|
1752
1785
|
if (sheetName) {
|
|
1753
1786
|
pre += sheetName;
|
|
1754
|
-
quote +=
|
|
1787
|
+
quote += needQuotes(sheetName);
|
|
1755
1788
|
}
|
|
1756
1789
|
if (quote) {
|
|
1757
|
-
pre =
|
|
1790
|
+
pre = quotePrefix(pre);
|
|
1758
1791
|
}
|
|
1759
1792
|
return pre ? pre + "!" : pre;
|
|
1760
1793
|
}
|
|
@@ -2172,6 +2205,7 @@ function parseRefXlsx(ref, opts = {}) {
|
|
|
2172
2205
|
}
|
|
2173
2206
|
|
|
2174
2207
|
// lib/translateToR1C1.ts
|
|
2208
|
+
var reLetLambda2 = /^l(?:ambda|et)$/i;
|
|
2175
2209
|
var calc = (abs, vX, aX) => {
|
|
2176
2210
|
if (vX == null) {
|
|
2177
2211
|
return null;
|
|
@@ -2200,29 +2234,53 @@ function translateTokensToR1C1(tokens2, anchorCell) {
|
|
|
2200
2234
|
throw new Error("translateTokensToR1C1 got an invalid anchorCell: " + anchorCell);
|
|
2201
2235
|
}
|
|
2202
2236
|
const { top, left } = anchorRange;
|
|
2237
|
+
let withinCall = 0;
|
|
2238
|
+
let parenDepth = 0;
|
|
2203
2239
|
let offsetSkew = 0;
|
|
2204
2240
|
const outTokens = [];
|
|
2205
2241
|
for (let token of tokens2) {
|
|
2206
2242
|
const tokenType = token?.type;
|
|
2243
|
+
if (tokenType === OPERATOR) {
|
|
2244
|
+
if (token.value === "(") {
|
|
2245
|
+
parenDepth++;
|
|
2246
|
+
const lastToken = outTokens[outTokens.length - 1];
|
|
2247
|
+
if (lastToken && lastToken.type === FUNCTION) {
|
|
2248
|
+
if (reLetLambda2.test(lastToken.value)) {
|
|
2249
|
+
withinCall = parenDepth;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
} else if (token.value === ")") {
|
|
2253
|
+
parenDepth--;
|
|
2254
|
+
if (parenDepth < withinCall) {
|
|
2255
|
+
withinCall = 0;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2207
2259
|
if (tokenType === REF_RANGE || tokenType === REF_BEAM || tokenType === REF_TERNARY) {
|
|
2208
2260
|
token = cloneToken(token);
|
|
2209
2261
|
const tokenValue = token.value;
|
|
2210
2262
|
const ref = quickParseA1(tokenValue);
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2263
|
+
if (ref) {
|
|
2264
|
+
const d = ref.range;
|
|
2265
|
+
const range = {};
|
|
2266
|
+
range.r0 = calc(d.$top, d.top, top);
|
|
2267
|
+
range.r1 = calc(d.$bottom, d.bottom, top);
|
|
2268
|
+
range.c0 = calc(d.$left, d.left, left);
|
|
2269
|
+
range.c1 = calc(d.$right, d.right, left);
|
|
2270
|
+
range.$r0 = d.$top;
|
|
2271
|
+
range.$r1 = d.$bottom;
|
|
2272
|
+
range.$c0 = d.$left;
|
|
2273
|
+
range.$c1 = d.$right;
|
|
2274
|
+
if (d.trim) {
|
|
2275
|
+
range.trim = d.trim;
|
|
2276
|
+
}
|
|
2277
|
+
ref.range = range;
|
|
2278
|
+
let val = stringifyR1C1RefXlsx(ref);
|
|
2279
|
+
if (isRCTokenValue(val) && withinCall) {
|
|
2280
|
+
val += "[0]";
|
|
2281
|
+
}
|
|
2282
|
+
token.value = val;
|
|
2283
|
+
}
|
|
2226
2284
|
if (token.loc) {
|
|
2227
2285
|
token.loc[0] += offsetSkew;
|
|
2228
2286
|
offsetSkew += token.value.length - tokenValue.length;
|
|
@@ -2515,44 +2573,46 @@ function translateTokensToA1(tokens2, anchorCell, options = {}) {
|
|
|
2515
2573
|
token = cloneToken(token);
|
|
2516
2574
|
const tokenValue = token.value;
|
|
2517
2575
|
const ref = parseR1C1RefXlsx(tokenValue, REF_OPTS);
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2576
|
+
if (ref) {
|
|
2577
|
+
const d = ref.range;
|
|
2578
|
+
const range = { top: 0, left: 0 };
|
|
2579
|
+
const r0 = toFixed(d.r0, d.$r0, top, MAX_ROWS, wrapEdges);
|
|
2580
|
+
const r1 = toFixed(d.r1, d.$r1, top, MAX_ROWS, wrapEdges);
|
|
2581
|
+
if (r0 > r1) {
|
|
2582
|
+
range.top = r1;
|
|
2583
|
+
range.$top = d.$r1;
|
|
2584
|
+
range.bottom = r0;
|
|
2585
|
+
range.$bottom = d.$r0;
|
|
2586
|
+
} else {
|
|
2587
|
+
range.top = r0;
|
|
2588
|
+
range.$top = d.$r0;
|
|
2589
|
+
range.bottom = r1;
|
|
2590
|
+
range.$bottom = d.$r1;
|
|
2591
|
+
}
|
|
2592
|
+
const c0 = toFixed(d.c0, d.$c0, left, MAX_COLS, wrapEdges);
|
|
2593
|
+
const c1 = toFixed(d.c1, d.$c1, left, MAX_COLS, wrapEdges);
|
|
2594
|
+
if (c0 > c1) {
|
|
2595
|
+
range.left = c1;
|
|
2596
|
+
range.$left = d.$c1;
|
|
2597
|
+
range.right = c0;
|
|
2598
|
+
range.$right = d.$c0;
|
|
2599
|
+
} else {
|
|
2600
|
+
range.left = c0;
|
|
2601
|
+
range.$left = d.$c0;
|
|
2602
|
+
range.right = c1;
|
|
2603
|
+
range.$right = d.$c1;
|
|
2604
|
+
}
|
|
2605
|
+
if (d.trim) {
|
|
2606
|
+
range.trim = d.trim;
|
|
2607
|
+
}
|
|
2608
|
+
if (isNaN(r0) || isNaN(r1) || isNaN(c0) || isNaN(c1)) {
|
|
2609
|
+
token.type = ERROR;
|
|
2610
|
+
token.value = "#REF!";
|
|
2611
|
+
delete token.groupId;
|
|
2612
|
+
} else {
|
|
2613
|
+
ref.range = range;
|
|
2614
|
+
token.value = stringifyA1RefXlsx(ref);
|
|
2615
|
+
}
|
|
2556
2616
|
}
|
|
2557
2617
|
if (token.loc) {
|
|
2558
2618
|
token.loc[0] += offsetSkew;
|