@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.cjs
CHANGED
|
@@ -85,6 +85,7 @@ var REF_BEAM = "range_beam";
|
|
|
85
85
|
var REF_TERNARY = "range_ternary";
|
|
86
86
|
var REF_NAMED = "range_named";
|
|
87
87
|
var REF_STRUCT = "structured";
|
|
88
|
+
var REF_CELL = "cell";
|
|
88
89
|
var FX_PREFIX = "fx_prefix";
|
|
89
90
|
var UNKNOWN = "unknown";
|
|
90
91
|
var UNARY = "UnaryExpression";
|
|
@@ -104,24 +105,26 @@ var MAX_ROWS = 2 ** 20 - 1;
|
|
|
104
105
|
// lib/mergeRefTokens.ts
|
|
105
106
|
var END = "$";
|
|
106
107
|
var validRunsMerge = [
|
|
107
|
-
[
|
|
108
|
-
[
|
|
109
|
-
[
|
|
110
|
-
[
|
|
108
|
+
[REF_CELL, ":", REF_CELL],
|
|
109
|
+
[REF_CELL, ".:", REF_CELL],
|
|
110
|
+
[REF_CELL, ":.", REF_CELL],
|
|
111
|
+
[REF_CELL, ".:.", REF_CELL],
|
|
111
112
|
[REF_RANGE],
|
|
112
113
|
[REF_BEAM],
|
|
113
114
|
[REF_TERNARY],
|
|
114
|
-
[CONTEXT, "!",
|
|
115
|
-
[CONTEXT, "!",
|
|
116
|
-
[CONTEXT, "!",
|
|
117
|
-
[CONTEXT, "!",
|
|
115
|
+
[CONTEXT, "!", REF_CELL, ":", REF_CELL],
|
|
116
|
+
[CONTEXT, "!", REF_CELL, ".:", REF_CELL],
|
|
117
|
+
[CONTEXT, "!", REF_CELL, ":.", REF_CELL],
|
|
118
|
+
[CONTEXT, "!", REF_CELL, ".:.", REF_CELL],
|
|
119
|
+
[CONTEXT, "!", REF_CELL],
|
|
118
120
|
[CONTEXT, "!", REF_RANGE],
|
|
119
121
|
[CONTEXT, "!", REF_BEAM],
|
|
120
122
|
[CONTEXT, "!", REF_TERNARY],
|
|
121
|
-
[CONTEXT_QUOTE, "!",
|
|
122
|
-
[CONTEXT_QUOTE, "!",
|
|
123
|
-
[CONTEXT_QUOTE, "!",
|
|
124
|
-
[CONTEXT_QUOTE, "!",
|
|
123
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ":", REF_CELL],
|
|
124
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ".:", REF_CELL],
|
|
125
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ":.", REF_CELL],
|
|
126
|
+
[CONTEXT_QUOTE, "!", REF_CELL, ".:.", REF_CELL],
|
|
127
|
+
[CONTEXT_QUOTE, "!", REF_CELL],
|
|
125
128
|
[CONTEXT_QUOTE, "!", REF_RANGE],
|
|
126
129
|
[CONTEXT_QUOTE, "!", REF_BEAM],
|
|
127
130
|
[CONTEXT_QUOTE, "!", REF_TERNARY],
|
|
@@ -153,7 +156,11 @@ var matcher = (tokens2, currNode, anchorIndex, index = 0) => {
|
|
|
153
156
|
while (i <= max) {
|
|
154
157
|
const token = tokens2[anchorIndex - i];
|
|
155
158
|
if (token) {
|
|
156
|
-
const
|
|
159
|
+
const value = token.value;
|
|
160
|
+
let key = token.type === OPERATOR ? value : token.type;
|
|
161
|
+
if (key === REF_RANGE && !value.includes(":")) {
|
|
162
|
+
key = REF_CELL;
|
|
163
|
+
}
|
|
157
164
|
if (key in node) {
|
|
158
165
|
node = node[key];
|
|
159
166
|
i += 1;
|
|
@@ -543,7 +550,7 @@ function lexRangeA1(str, pos, options) {
|
|
|
543
550
|
}
|
|
544
551
|
}
|
|
545
552
|
}
|
|
546
|
-
if (top && canEndRange(str, preOp)) {
|
|
553
|
+
if (top && canEndRange(str, preOp) && str.charCodeAt(preOp) !== 33) {
|
|
547
554
|
return { type: REF_RANGE, value: str.slice(pos, preOp) };
|
|
548
555
|
}
|
|
549
556
|
} else {
|
|
@@ -583,6 +590,7 @@ var UC_C = 67;
|
|
|
583
590
|
var LC_C = 99;
|
|
584
591
|
var PLUS = 43;
|
|
585
592
|
var MINUS = 45;
|
|
593
|
+
var EXCL2 = 33;
|
|
586
594
|
function lexR1C1Part(str, pos, isRow = false) {
|
|
587
595
|
const start = pos;
|
|
588
596
|
const c0 = str.charCodeAt(pos);
|
|
@@ -637,7 +645,7 @@ function lexRangeR1C1(str, pos, options) {
|
|
|
637
645
|
p += r1;
|
|
638
646
|
const c1 = lexR1C1Part(str, p);
|
|
639
647
|
p += c1;
|
|
640
|
-
if (c1 || r1) {
|
|
648
|
+
if ((c1 || r1) && str.charCodeAt(p) !== EXCL2) {
|
|
641
649
|
const op = advRangeOp(str, p);
|
|
642
650
|
const preOp = p;
|
|
643
651
|
if (op) {
|
|
@@ -854,7 +862,7 @@ function parseSRange(str, pos = 0) {
|
|
|
854
862
|
}
|
|
855
863
|
|
|
856
864
|
// lib/lexers/lexStructured.ts
|
|
857
|
-
var
|
|
865
|
+
var EXCL3 = 33;
|
|
858
866
|
function lexStructured(str, pos) {
|
|
859
867
|
const structData = parseSRange(str, pos);
|
|
860
868
|
if (structData && structData.length) {
|
|
@@ -862,7 +870,7 @@ function lexStructured(str, pos) {
|
|
|
862
870
|
while (isWS(str.charCodeAt(pos + i))) {
|
|
863
871
|
i++;
|
|
864
872
|
}
|
|
865
|
-
if (str.charCodeAt(pos + i) !==
|
|
873
|
+
if (str.charCodeAt(pos + i) !== EXCL3) {
|
|
866
874
|
return {
|
|
867
875
|
type: REF_STRUCT,
|
|
868
876
|
value: structData.token
|
|
@@ -957,9 +965,9 @@ function lexNamed(str, pos) {
|
|
|
957
965
|
}
|
|
958
966
|
|
|
959
967
|
// lib/lexers/lexRefOp.ts
|
|
960
|
-
var
|
|
968
|
+
var EXCL4 = 33;
|
|
961
969
|
function lexRefOp(str, pos, opts) {
|
|
962
|
-
if (str.charCodeAt(pos) ===
|
|
970
|
+
if (str.charCodeAt(pos) === EXCL4) {
|
|
963
971
|
return { type: OPERATOR, value: str[pos] };
|
|
964
972
|
}
|
|
965
973
|
if (!opts.r1c1) {
|
|
@@ -973,7 +981,7 @@ function lexRefOp(str, pos, opts) {
|
|
|
973
981
|
// lib/lexers/lexNameFuncCntx.ts
|
|
974
982
|
var BR_OPEN4 = 91;
|
|
975
983
|
var PAREN_OPEN = 40;
|
|
976
|
-
var
|
|
984
|
+
var EXCL5 = 33;
|
|
977
985
|
var OFFS = 32;
|
|
978
986
|
var ALLOWED = new Uint8Array(180 - OFFS);
|
|
979
987
|
var OK_NAME_0 = 1;
|
|
@@ -1038,7 +1046,7 @@ function lexNameFuncCntx(str, pos, opts) {
|
|
|
1038
1046
|
} else {
|
|
1039
1047
|
if (c === PAREN_OPEN && func) {
|
|
1040
1048
|
return { type: FUNCTION, value: str.slice(start, pos) };
|
|
1041
|
-
} else if (c ===
|
|
1049
|
+
} else if (c === EXCL5 && cntx) {
|
|
1042
1050
|
return { type: CONTEXT, value: str.slice(start, pos) };
|
|
1043
1051
|
}
|
|
1044
1052
|
return nameOrUnknown(str, s, start, pos, name);
|
|
@@ -1074,6 +1082,11 @@ var lexersRefs = [
|
|
|
1074
1082
|
lexNamed
|
|
1075
1083
|
];
|
|
1076
1084
|
|
|
1085
|
+
// lib/isRCTokenValue.ts
|
|
1086
|
+
function isRCTokenValue(value) {
|
|
1087
|
+
return value === "r" || value === "R" || value === "c" || value === "C";
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1077
1090
|
// lib/tokenize.ts
|
|
1078
1091
|
var reLetLambda = /^l(?:ambda|et)$/i;
|
|
1079
1092
|
var isType = (t, type) => t && t.type === type;
|
|
@@ -1081,12 +1094,13 @@ var isTextTokenType = (tokenType) => tokenType === REF_NAMED || tokenType === FU
|
|
|
1081
1094
|
var causesBinaryMinus = (token) => {
|
|
1082
1095
|
return !isType(token, OPERATOR) || (token.value === "%" || token.value === "}" || token.value === ")" || token.value === "#");
|
|
1083
1096
|
};
|
|
1084
|
-
function fixRCNames(tokens2) {
|
|
1097
|
+
function fixRCNames(tokens2, r1c1Mode) {
|
|
1085
1098
|
let withinCall = 0;
|
|
1086
1099
|
let parenDepth = 0;
|
|
1087
1100
|
let lastToken;
|
|
1088
1101
|
for (const token of tokens2) {
|
|
1089
|
-
|
|
1102
|
+
const tokenType = token.type;
|
|
1103
|
+
if (tokenType === OPERATOR) {
|
|
1090
1104
|
if (token.value === "(") {
|
|
1091
1105
|
parenDepth++;
|
|
1092
1106
|
if (lastToken.type === FUNCTION) {
|
|
@@ -1100,7 +1114,9 @@ function fixRCNames(tokens2) {
|
|
|
1100
1114
|
withinCall = 0;
|
|
1101
1115
|
}
|
|
1102
1116
|
}
|
|
1103
|
-
} else if (withinCall &&
|
|
1117
|
+
} else if (withinCall && tokenType === UNKNOWN && isRCTokenValue(token.value)) {
|
|
1118
|
+
token.type = REF_NAMED;
|
|
1119
|
+
} else if (withinCall && r1c1Mode && tokenType === REF_BEAM && isRCTokenValue(token.value)) {
|
|
1104
1120
|
token.type = REF_NAMED;
|
|
1105
1121
|
}
|
|
1106
1122
|
lastToken = token;
|
|
@@ -1187,9 +1203,8 @@ function getTokens(fx, tokenHandlers, options = {}) {
|
|
|
1187
1203
|
letOrLambda++;
|
|
1188
1204
|
}
|
|
1189
1205
|
}
|
|
1190
|
-
if (token.type === UNKNOWN && token.
|
|
1191
|
-
|
|
1192
|
-
unknownRC += valLC === "r" || valLC === "c" ? 1 : 0;
|
|
1206
|
+
if (token.value.length === 1 && (token.type === UNKNOWN || opts.r1c1 && token.type === REF_BEAM)) {
|
|
1207
|
+
unknownRC += isRCTokenValue(token.value) ? 1 : 0;
|
|
1193
1208
|
}
|
|
1194
1209
|
if (negativeNumbers && token.type === NUMBER) {
|
|
1195
1210
|
const last1 = lastToken;
|
|
@@ -1208,7 +1223,7 @@ function getTokens(fx, tokenHandlers, options = {}) {
|
|
|
1208
1223
|
pushToken(token);
|
|
1209
1224
|
}
|
|
1210
1225
|
if (unknownRC && letOrLambda) {
|
|
1211
|
-
fixRCNames(tokens2);
|
|
1226
|
+
fixRCNames(tokens2, opts.r1c1);
|
|
1212
1227
|
}
|
|
1213
1228
|
for (const index of trimOps) {
|
|
1214
1229
|
const before = tokens2[index - 1];
|
|
@@ -1811,20 +1826,38 @@ function parse(tokenlist, options = {}) {
|
|
|
1811
1826
|
|
|
1812
1827
|
// lib/stringifyPrefix.ts
|
|
1813
1828
|
var reBannedChars = /[^0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]/;
|
|
1829
|
+
var reIsRangelike = /^(R|C|RC|[A-Z]{1,3}\d{1,7})$/i;
|
|
1830
|
+
function needQuotes(scope, yesItDoes = 0) {
|
|
1831
|
+
if (yesItDoes) {
|
|
1832
|
+
return 1;
|
|
1833
|
+
}
|
|
1834
|
+
if (scope) {
|
|
1835
|
+
if (reBannedChars.test(scope)) {
|
|
1836
|
+
return 1;
|
|
1837
|
+
}
|
|
1838
|
+
if (reIsRangelike.test(scope)) {
|
|
1839
|
+
return 1;
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
return 0;
|
|
1843
|
+
}
|
|
1844
|
+
function quotePrefix(prefix2) {
|
|
1845
|
+
return "'" + prefix2.replace(/'/g, "''") + "'";
|
|
1846
|
+
}
|
|
1814
1847
|
function stringifyPrefixXlsx(ref) {
|
|
1815
1848
|
let pre = "";
|
|
1816
1849
|
let quote = 0;
|
|
1817
1850
|
const { workbookName, sheetName } = ref;
|
|
1818
1851
|
if (workbookName) {
|
|
1819
1852
|
pre += "[" + workbookName + "]";
|
|
1820
|
-
quote +=
|
|
1853
|
+
quote += needQuotes(workbookName);
|
|
1821
1854
|
}
|
|
1822
1855
|
if (sheetName) {
|
|
1823
1856
|
pre += sheetName;
|
|
1824
|
-
quote +=
|
|
1857
|
+
quote += needQuotes(sheetName);
|
|
1825
1858
|
}
|
|
1826
1859
|
if (quote) {
|
|
1827
|
-
pre =
|
|
1860
|
+
pre = quotePrefix(pre);
|
|
1828
1861
|
}
|
|
1829
1862
|
return pre ? pre + "!" : pre;
|
|
1830
1863
|
}
|
|
@@ -2242,6 +2275,7 @@ function parseRefXlsx(ref, opts = {}) {
|
|
|
2242
2275
|
}
|
|
2243
2276
|
|
|
2244
2277
|
// lib/translateToR1C1.ts
|
|
2278
|
+
var reLetLambda2 = /^l(?:ambda|et)$/i;
|
|
2245
2279
|
var calc = (abs, vX, aX) => {
|
|
2246
2280
|
if (vX == null) {
|
|
2247
2281
|
return null;
|
|
@@ -2270,29 +2304,53 @@ function translateTokensToR1C1(tokens2, anchorCell) {
|
|
|
2270
2304
|
throw new Error("translateTokensToR1C1 got an invalid anchorCell: " + anchorCell);
|
|
2271
2305
|
}
|
|
2272
2306
|
const { top, left } = anchorRange;
|
|
2307
|
+
let withinCall = 0;
|
|
2308
|
+
let parenDepth = 0;
|
|
2273
2309
|
let offsetSkew = 0;
|
|
2274
2310
|
const outTokens = [];
|
|
2275
2311
|
for (let token of tokens2) {
|
|
2276
2312
|
const tokenType = token?.type;
|
|
2313
|
+
if (tokenType === OPERATOR) {
|
|
2314
|
+
if (token.value === "(") {
|
|
2315
|
+
parenDepth++;
|
|
2316
|
+
const lastToken = outTokens[outTokens.length - 1];
|
|
2317
|
+
if (lastToken && lastToken.type === FUNCTION) {
|
|
2318
|
+
if (reLetLambda2.test(lastToken.value)) {
|
|
2319
|
+
withinCall = parenDepth;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
} else if (token.value === ")") {
|
|
2323
|
+
parenDepth--;
|
|
2324
|
+
if (parenDepth < withinCall) {
|
|
2325
|
+
withinCall = 0;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2277
2329
|
if (tokenType === REF_RANGE || tokenType === REF_BEAM || tokenType === REF_TERNARY) {
|
|
2278
2330
|
token = cloneToken(token);
|
|
2279
2331
|
const tokenValue = token.value;
|
|
2280
2332
|
const ref = quickParseA1(tokenValue);
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2333
|
+
if (ref) {
|
|
2334
|
+
const d = ref.range;
|
|
2335
|
+
const range = {};
|
|
2336
|
+
range.r0 = calc(d.$top, d.top, top);
|
|
2337
|
+
range.r1 = calc(d.$bottom, d.bottom, top);
|
|
2338
|
+
range.c0 = calc(d.$left, d.left, left);
|
|
2339
|
+
range.c1 = calc(d.$right, d.right, left);
|
|
2340
|
+
range.$r0 = d.$top;
|
|
2341
|
+
range.$r1 = d.$bottom;
|
|
2342
|
+
range.$c0 = d.$left;
|
|
2343
|
+
range.$c1 = d.$right;
|
|
2344
|
+
if (d.trim) {
|
|
2345
|
+
range.trim = d.trim;
|
|
2346
|
+
}
|
|
2347
|
+
ref.range = range;
|
|
2348
|
+
let val = stringifyR1C1RefXlsx(ref);
|
|
2349
|
+
if (isRCTokenValue(val) && withinCall) {
|
|
2350
|
+
val += "[0]";
|
|
2351
|
+
}
|
|
2352
|
+
token.value = val;
|
|
2353
|
+
}
|
|
2296
2354
|
if (token.loc) {
|
|
2297
2355
|
token.loc[0] += offsetSkew;
|
|
2298
2356
|
offsetSkew += token.value.length - tokenValue.length;
|
|
@@ -2585,44 +2643,46 @@ function translateTokensToA1(tokens2, anchorCell, options = {}) {
|
|
|
2585
2643
|
token = cloneToken(token);
|
|
2586
2644
|
const tokenValue = token.value;
|
|
2587
2645
|
const ref = parseR1C1RefXlsx(tokenValue, REF_OPTS);
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2646
|
+
if (ref) {
|
|
2647
|
+
const d = ref.range;
|
|
2648
|
+
const range = { top: 0, left: 0 };
|
|
2649
|
+
const r0 = toFixed(d.r0, d.$r0, top, MAX_ROWS, wrapEdges);
|
|
2650
|
+
const r1 = toFixed(d.r1, d.$r1, top, MAX_ROWS, wrapEdges);
|
|
2651
|
+
if (r0 > r1) {
|
|
2652
|
+
range.top = r1;
|
|
2653
|
+
range.$top = d.$r1;
|
|
2654
|
+
range.bottom = r0;
|
|
2655
|
+
range.$bottom = d.$r0;
|
|
2656
|
+
} else {
|
|
2657
|
+
range.top = r0;
|
|
2658
|
+
range.$top = d.$r0;
|
|
2659
|
+
range.bottom = r1;
|
|
2660
|
+
range.$bottom = d.$r1;
|
|
2661
|
+
}
|
|
2662
|
+
const c0 = toFixed(d.c0, d.$c0, left, MAX_COLS, wrapEdges);
|
|
2663
|
+
const c1 = toFixed(d.c1, d.$c1, left, MAX_COLS, wrapEdges);
|
|
2664
|
+
if (c0 > c1) {
|
|
2665
|
+
range.left = c1;
|
|
2666
|
+
range.$left = d.$c1;
|
|
2667
|
+
range.right = c0;
|
|
2668
|
+
range.$right = d.$c0;
|
|
2669
|
+
} else {
|
|
2670
|
+
range.left = c0;
|
|
2671
|
+
range.$left = d.$c0;
|
|
2672
|
+
range.right = c1;
|
|
2673
|
+
range.$right = d.$c1;
|
|
2674
|
+
}
|
|
2675
|
+
if (d.trim) {
|
|
2676
|
+
range.trim = d.trim;
|
|
2677
|
+
}
|
|
2678
|
+
if (isNaN(r0) || isNaN(r1) || isNaN(c0) || isNaN(c1)) {
|
|
2679
|
+
token.type = ERROR;
|
|
2680
|
+
token.value = "#REF!";
|
|
2681
|
+
delete token.groupId;
|
|
2682
|
+
} else {
|
|
2683
|
+
ref.range = range;
|
|
2684
|
+
token.value = stringifyA1RefXlsx(ref);
|
|
2685
|
+
}
|
|
2626
2686
|
}
|
|
2627
2687
|
if (token.loc) {
|
|
2628
2688
|
token.loc[0] += offsetSkew;
|