@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.
@@ -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
- [REF_RANGE, ":", REF_RANGE],
108
- [REF_RANGE, ".:", REF_RANGE],
109
- [REF_RANGE, ":.", REF_RANGE],
110
- [REF_RANGE, ".:.", REF_RANGE],
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, "!", REF_RANGE, ":", REF_RANGE],
115
- [CONTEXT, "!", REF_RANGE, ".:", REF_RANGE],
116
- [CONTEXT, "!", REF_RANGE, ":.", REF_RANGE],
117
- [CONTEXT, "!", REF_RANGE, ".:.", REF_RANGE],
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, "!", REF_RANGE, ":", REF_RANGE],
122
- [CONTEXT_QUOTE, "!", REF_RANGE, ".:", REF_RANGE],
123
- [CONTEXT_QUOTE, "!", REF_RANGE, ":.", REF_RANGE],
124
- [CONTEXT_QUOTE, "!", REF_RANGE, ".:.", REF_RANGE],
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 key = token.type === OPERATOR ? token.value : token.type;
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 EXCL2 = 33;
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) !== EXCL2) {
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 EXCL3 = 33;
968
+ var EXCL4 = 33;
961
969
  function lexRefOp(str, pos, opts) {
962
- if (str.charCodeAt(pos) === EXCL3) {
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 EXCL4 = 33;
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 === EXCL4 && cntx) {
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
- if (token.type === OPERATOR) {
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 && token.type === UNKNOWN && /^[rc]$/.test(token.value)) {
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.value.length === 1) {
1191
- const valLC = token.value.toLowerCase();
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 += +reBannedChars.test(workbookName);
1853
+ quote += needQuotes(workbookName);
1821
1854
  }
1822
1855
  if (sheetName) {
1823
1856
  pre += sheetName;
1824
- quote += +reBannedChars.test(sheetName);
1857
+ quote += needQuotes(sheetName);
1825
1858
  }
1826
1859
  if (quote) {
1827
- pre = "'" + pre.replace(/'/g, "''") + "'";
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
- const d = ref.range;
2282
- const range = {};
2283
- range.r0 = calc(d.$top, d.top, top);
2284
- range.r1 = calc(d.$bottom, d.bottom, top);
2285
- range.c0 = calc(d.$left, d.left, left);
2286
- range.c1 = calc(d.$right, d.right, left);
2287
- range.$r0 = d.$top;
2288
- range.$r1 = d.$bottom;
2289
- range.$c0 = d.$left;
2290
- range.$c1 = d.$right;
2291
- if (d.trim) {
2292
- range.trim = d.trim;
2293
- }
2294
- ref.range = range;
2295
- token.value = stringifyR1C1RefXlsx(ref);
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
- const d = ref.range;
2589
- const range = { top: 0, left: 0 };
2590
- const r0 = toFixed(d.r0, d.$r0, top, MAX_ROWS, wrapEdges);
2591
- const r1 = toFixed(d.r1, d.$r1, top, MAX_ROWS, wrapEdges);
2592
- if (r0 > r1) {
2593
- range.top = r1;
2594
- range.$top = d.$r1;
2595
- range.bottom = r0;
2596
- range.$bottom = d.$r0;
2597
- } else {
2598
- range.top = r0;
2599
- range.$top = d.$r0;
2600
- range.bottom = r1;
2601
- range.$bottom = d.$r1;
2602
- }
2603
- const c0 = toFixed(d.c0, d.$c0, left, MAX_COLS, wrapEdges);
2604
- const c1 = toFixed(d.c1, d.$c1, left, MAX_COLS, wrapEdges);
2605
- if (c0 > c1) {
2606
- range.left = c1;
2607
- range.$left = d.$c1;
2608
- range.right = c0;
2609
- range.$right = d.$c0;
2610
- } else {
2611
- range.left = c0;
2612
- range.$left = d.$c0;
2613
- range.right = c1;
2614
- range.$right = d.$c1;
2615
- }
2616
- if (d.trim) {
2617
- range.trim = d.trim;
2618
- }
2619
- if (isNaN(r0) || isNaN(r1) || isNaN(c0) || isNaN(c1)) {
2620
- token.type = ERROR;
2621
- token.value = "#REF!";
2622
- delete token.groupId;
2623
- } else {
2624
- ref.range = range;
2625
- token.value = stringifyA1RefXlsx(ref);
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;