@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.
@@ -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
- [REF_RANGE, ":", REF_RANGE],
38
- [REF_RANGE, ".:", REF_RANGE],
39
- [REF_RANGE, ":.", REF_RANGE],
40
- [REF_RANGE, ".:.", REF_RANGE],
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, "!", REF_RANGE, ":", REF_RANGE],
45
- [CONTEXT, "!", REF_RANGE, ".:", REF_RANGE],
46
- [CONTEXT, "!", REF_RANGE, ":.", REF_RANGE],
47
- [CONTEXT, "!", REF_RANGE, ".:.", REF_RANGE],
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, "!", REF_RANGE, ":", REF_RANGE],
52
- [CONTEXT_QUOTE, "!", REF_RANGE, ".:", REF_RANGE],
53
- [CONTEXT_QUOTE, "!", REF_RANGE, ":.", REF_RANGE],
54
- [CONTEXT_QUOTE, "!", REF_RANGE, ".:.", REF_RANGE],
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 key = token.type === OPERATOR ? token.value : token.type;
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 EXCL2 = 33;
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) !== EXCL2) {
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 EXCL3 = 33;
898
+ var EXCL4 = 33;
891
899
  function lexRefOp(str, pos, opts) {
892
- if (str.charCodeAt(pos) === EXCL3) {
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 EXCL4 = 33;
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 === EXCL4 && cntx) {
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
- if (token.type === OPERATOR) {
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 && token.type === UNKNOWN && /^[rc]$/.test(token.value)) {
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.value.length === 1) {
1121
- const valLC = token.value.toLowerCase();
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 += +reBannedChars.test(workbookName);
1783
+ quote += needQuotes(workbookName);
1751
1784
  }
1752
1785
  if (sheetName) {
1753
1786
  pre += sheetName;
1754
- quote += +reBannedChars.test(sheetName);
1787
+ quote += needQuotes(sheetName);
1755
1788
  }
1756
1789
  if (quote) {
1757
- pre = "'" + pre.replace(/'/g, "''") + "'";
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
- const d = ref.range;
2212
- const range = {};
2213
- range.r0 = calc(d.$top, d.top, top);
2214
- range.r1 = calc(d.$bottom, d.bottom, top);
2215
- range.c0 = calc(d.$left, d.left, left);
2216
- range.c1 = calc(d.$right, d.right, left);
2217
- range.$r0 = d.$top;
2218
- range.$r1 = d.$bottom;
2219
- range.$c0 = d.$left;
2220
- range.$c1 = d.$right;
2221
- if (d.trim) {
2222
- range.trim = d.trim;
2223
- }
2224
- ref.range = range;
2225
- token.value = stringifyR1C1RefXlsx(ref);
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
- const d = ref.range;
2519
- const range = { top: 0, left: 0 };
2520
- const r0 = toFixed(d.r0, d.$r0, top, MAX_ROWS, wrapEdges);
2521
- const r1 = toFixed(d.r1, d.$r1, top, MAX_ROWS, wrapEdges);
2522
- if (r0 > r1) {
2523
- range.top = r1;
2524
- range.$top = d.$r1;
2525
- range.bottom = r0;
2526
- range.$bottom = d.$r0;
2527
- } else {
2528
- range.top = r0;
2529
- range.$top = d.$r0;
2530
- range.bottom = r1;
2531
- range.$bottom = d.$r1;
2532
- }
2533
- const c0 = toFixed(d.c0, d.$c0, left, MAX_COLS, wrapEdges);
2534
- const c1 = toFixed(d.c1, d.$c1, left, MAX_COLS, wrapEdges);
2535
- if (c0 > c1) {
2536
- range.left = c1;
2537
- range.$left = d.$c1;
2538
- range.right = c0;
2539
- range.$right = d.$c0;
2540
- } else {
2541
- range.left = c0;
2542
- range.$left = d.$c0;
2543
- range.right = c1;
2544
- range.$right = d.$c1;
2545
- }
2546
- if (d.trim) {
2547
- range.trim = d.trim;
2548
- }
2549
- if (isNaN(r0) || isNaN(r1) || isNaN(c0) || isNaN(c1)) {
2550
- token.type = ERROR;
2551
- token.value = "#REF!";
2552
- delete token.groupId;
2553
- } else {
2554
- ref.range = range;
2555
- token.value = stringifyA1RefXlsx(ref);
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;