@borgar/fx 4.13.0 → 5.0.0

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.
Files changed (141) hide show
  1. package/dist/index-BMr6cTgc.d.cts +1444 -0
  2. package/dist/index-BMr6cTgc.d.ts +1444 -0
  3. package/dist/index.cjs +3054 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +2984 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/xlsx/index.cjs +3120 -0
  10. package/dist/xlsx/index.cjs.map +1 -0
  11. package/dist/xlsx/index.d.cts +55 -0
  12. package/dist/xlsx/index.d.ts +55 -0
  13. package/dist/xlsx/index.js +3049 -0
  14. package/dist/xlsx/index.js.map +1 -0
  15. package/docs/API.md +2959 -718
  16. package/docs/AST_format.md +2 -2
  17. package/eslint.config.mjs +40 -0
  18. package/lib/a1.spec.ts +32 -0
  19. package/lib/a1.ts +26 -0
  20. package/lib/addA1RangeBounds.ts +50 -0
  21. package/lib/addTokenMeta.spec.ts +166 -0
  22. package/lib/{addTokenMeta.js → addTokenMeta.ts} +53 -33
  23. package/lib/astTypes.ts +211 -0
  24. package/lib/cloneToken.ts +29 -0
  25. package/lib/{constants.js → constants.ts} +6 -3
  26. package/lib/fixRanges.spec.ts +220 -0
  27. package/lib/fixRanges.ts +260 -0
  28. package/lib/fromCol.spec.ts +15 -0
  29. package/lib/{fromCol.js → fromCol.ts} +1 -1
  30. package/lib/index.spec.ts +119 -0
  31. package/lib/index.ts +76 -0
  32. package/lib/isNodeType.ts +151 -0
  33. package/lib/isType.spec.ts +208 -0
  34. package/lib/{isType.js → isType.ts} +26 -25
  35. package/lib/lexers/{advRangeOp.js → advRangeOp.ts} +1 -1
  36. package/lib/lexers/{canEndRange.js → canEndRange.ts} +2 -2
  37. package/lib/lexers/{lexBoolean.js → lexBoolean.ts} +25 -6
  38. package/lib/lexers/{lexContext.js → lexContext.ts} +14 -6
  39. package/lib/lexers/{lexError.js → lexError.ts} +3 -3
  40. package/lib/lexers/{lexFunction.js → lexFunction.ts} +3 -2
  41. package/lib/lexers/lexNameFuncCntx.ts +112 -0
  42. package/lib/lexers/{lexNamed.js → lexNamed.ts} +4 -4
  43. package/lib/lexers/{lexNewLine.js → lexNewLine.ts} +3 -2
  44. package/lib/lexers/{lexNumber.js → lexNumber.ts} +4 -3
  45. package/lib/lexers/{lexOperator.js → lexOperator.ts} +5 -4
  46. package/lib/lexers/lexRange.ts +15 -0
  47. package/lib/lexers/{lexRangeA1.js → lexRangeA1.ts} +11 -7
  48. package/lib/lexers/{lexRangeR1C1.js → lexRangeR1C1.ts} +10 -6
  49. package/lib/lexers/{lexRangeTrim.js → lexRangeTrim.ts} +3 -2
  50. package/lib/lexers/{lexRefOp.js → lexRefOp.ts} +4 -3
  51. package/lib/lexers/{lexString.js → lexString.ts} +3 -3
  52. package/lib/lexers/{lexStructured.js → lexStructured.ts} +5 -5
  53. package/lib/lexers/{lexWhitespace.js → lexWhitespace.ts} +3 -2
  54. package/lib/lexers/sets.ts +51 -0
  55. package/lib/mergeRefTokens.spec.ts +141 -0
  56. package/lib/{mergeRefTokens.js → mergeRefTokens.ts} +14 -9
  57. package/lib/nodeTypes.ts +54 -0
  58. package/lib/parse.spec.ts +1410 -0
  59. package/lib/{parser.js → parse.ts} +81 -63
  60. package/lib/parseA1Range.spec.ts +233 -0
  61. package/lib/parseA1Range.ts +206 -0
  62. package/lib/parseA1Ref.spec.ts +337 -0
  63. package/lib/parseA1Ref.ts +115 -0
  64. package/lib/parseR1C1Range.ts +191 -0
  65. package/lib/parseR1C1Ref.spec.ts +323 -0
  66. package/lib/parseR1C1Ref.ts +127 -0
  67. package/lib/parseRef.spec.ts +90 -0
  68. package/lib/parseRef.ts +240 -0
  69. package/lib/{parseSRange.js → parseSRange.ts} +15 -10
  70. package/lib/parseStructRef.spec.ts +168 -0
  71. package/lib/parseStructRef.ts +76 -0
  72. package/lib/stringifyA1Range.spec.ts +72 -0
  73. package/lib/stringifyA1Range.ts +72 -0
  74. package/lib/stringifyA1Ref.spec.ts +64 -0
  75. package/lib/stringifyA1Ref.ts +59 -0
  76. package/lib/{stringifyPrefix.js → stringifyPrefix.ts} +17 -2
  77. package/lib/stringifyR1C1Range.spec.ts +92 -0
  78. package/lib/stringifyR1C1Range.ts +73 -0
  79. package/lib/stringifyR1C1Ref.spec.ts +63 -0
  80. package/lib/stringifyR1C1Ref.ts +67 -0
  81. package/lib/stringifyStructRef.spec.ts +124 -0
  82. package/lib/stringifyStructRef.ts +113 -0
  83. package/lib/stringifyTokens.ts +15 -0
  84. package/lib/toCol.spec.ts +11 -0
  85. package/lib/{toCol.js → toCol.ts} +4 -4
  86. package/lib/tokenTypes.ts +76 -0
  87. package/lib/tokenize-srefs.spec.ts +429 -0
  88. package/lib/tokenize.spec.ts +2103 -0
  89. package/lib/tokenize.ts +346 -0
  90. package/lib/translate.spec.ts +35 -0
  91. package/lib/translateToA1.spec.ts +247 -0
  92. package/lib/translateToA1.ts +231 -0
  93. package/lib/translateToR1C1.spec.ts +227 -0
  94. package/lib/translateToR1C1.ts +145 -0
  95. package/lib/types.ts +179 -0
  96. package/lib/xlsx/index.spec.ts +27 -0
  97. package/lib/xlsx/index.ts +32 -0
  98. package/package.json +45 -31
  99. package/tsconfig.json +28 -0
  100. package/typedoc-ignore-links.ts +17 -0
  101. package/typedoc.json +41 -0
  102. package/.eslintrc +0 -22
  103. package/benchmark/benchmark.js +0 -48
  104. package/benchmark/formulas.json +0 -15677
  105. package/dist/fx.d.ts +0 -823
  106. package/dist/fx.js +0 -2
  107. package/dist/package.json +0 -1
  108. package/lib/a1.js +0 -348
  109. package/lib/a1.spec.js +0 -458
  110. package/lib/addTokenMeta.spec.js +0 -153
  111. package/lib/astTypes.js +0 -96
  112. package/lib/extraTypes.js +0 -74
  113. package/lib/fixRanges.js +0 -104
  114. package/lib/fixRanges.spec.js +0 -171
  115. package/lib/fromCol.spec.js +0 -11
  116. package/lib/index.js +0 -134
  117. package/lib/index.spec.js +0 -67
  118. package/lib/isType.spec.js +0 -168
  119. package/lib/lexer-srefs.spec.js +0 -324
  120. package/lib/lexer.js +0 -264
  121. package/lib/lexer.spec.js +0 -1953
  122. package/lib/lexers/lexRange.js +0 -8
  123. package/lib/lexers/sets.js +0 -38
  124. package/lib/mergeRefTokens.spec.js +0 -121
  125. package/lib/package.json +0 -1
  126. package/lib/parseRef.js +0 -157
  127. package/lib/parseRef.spec.js +0 -71
  128. package/lib/parseStructRef.js +0 -48
  129. package/lib/parseStructRef.spec.js +0 -164
  130. package/lib/parser.spec.js +0 -1208
  131. package/lib/rc.js +0 -341
  132. package/lib/rc.spec.js +0 -403
  133. package/lib/stringifyStructRef.js +0 -80
  134. package/lib/stringifyStructRef.spec.js +0 -182
  135. package/lib/toCol.spec.js +0 -11
  136. package/lib/translate-toA1.spec.js +0 -214
  137. package/lib/translate-toRC.spec.js +0 -197
  138. package/lib/translate.js +0 -239
  139. package/lib/translate.spec.js +0 -21
  140. package/rollup.config.mjs +0 -22
  141. package/tsd.json +0 -12
@@ -0,0 +1,260 @@
1
+ import { isRange } from './isType.ts';
2
+ import { parseA1Ref, parseA1RefXlsx } from './parseA1Ref.ts';
3
+ import { stringifyA1Ref, stringifyA1RefXlsx } from './stringifyA1Ref.ts';
4
+ import { addA1RangeBounds } from './addA1RangeBounds.ts';
5
+ import { parseStructRef, parseStructRefXlsx } from './parseStructRef.ts';
6
+ import { stringifyStructRef, stringifyStructRefXlsx } from './stringifyStructRef.ts';
7
+ import { tokenize, type OptsTokenize, tokenizeXlsx } from './tokenize.ts';
8
+ import { REF_STRUCT } from './constants.ts';
9
+ import type { ReferenceA1, ReferenceA1Xlsx, Token } from './types.ts';
10
+ import { cloneToken } from './cloneToken.ts';
11
+ import { stringifyTokens } from './stringifyTokens.ts';
12
+
13
+ // There is no R1C1 counterpart to this. This is because without an anchor cell
14
+ // it is impossible to determine if a relative+absolute range (R[1]C[1]:R5C5)
15
+ // needs to be flipped or not. The solution is to convert to A1 first:
16
+ // translateToRC(fixRanges(translateToA1(...)))
17
+
18
+ /**
19
+ * Options for {@link fixTokenRanges} and {@link fixFormulaRanges}.
20
+ */
21
+ export type OptsFixRanges = {
22
+ /**
23
+ * Fill in any undefined bounds of range objects. Top to 0, bottom to 1048575, left to 0, and right to 16383.
24
+ * @defaultValue false
25
+ */
26
+ addBounds?: boolean,
27
+ /**
28
+ * Enforces using the `[#This Row]` instead of the `@` shorthand when serializing structured ranges.
29
+ * @defaultValue false
30
+ */
31
+ thisRow?: boolean,
32
+ };
33
+
34
+ /**
35
+ * Normalizes A1 style ranges and structured references in a list of tokens.
36
+ *
37
+ * It ensures that that the top and left coordinates of an A1 range are on the
38
+ * left-hand side of a colon operator:
39
+ *
40
+ * ```
41
+ * B2:A1 → A1:B2
42
+ * 1:A1 → A1:1
43
+ * A:A1 → A1:A
44
+ * B:A → A:B
45
+ * 2:1 → 1:2
46
+ * A1:A1 → A1
47
+ * ```
48
+ *
49
+ * When `{ addBounds }` option is set to true, the missing bounds are also added.
50
+ * This can be done to ensure Excel compatible ranges. The fixes then additionally include:
51
+ *
52
+ * ```
53
+ * 1:A1 → A1:1 → 1:1
54
+ * A:A1 → A1:A → A:A
55
+ * A1:A → A:A
56
+ * A1:1 → A:1
57
+ * B2:B → B2:1048576
58
+ * B2:2 → B2:XFD2
59
+ * ```
60
+ *
61
+ * Structured ranges are normalized to have consistent order and capitalization
62
+ * of sections as well as removing redundant ones.
63
+ *
64
+ * Returns a new array of tokens with values and position data updated.
65
+ *
66
+ * @see {@link OptsFixRanges}
67
+ * @param tokens A list of tokens to be adjusted.
68
+ * @param [options] Options.
69
+ * @returns A token list with ranges adjusted.
70
+ */
71
+ export function fixTokenRanges (
72
+ tokens: Token[],
73
+ options: OptsFixRanges = {}
74
+ ): Token[] {
75
+ if (!Array.isArray(tokens)) {
76
+ throw new Error('fixRanges expects an array of tokens');
77
+ }
78
+ const { addBounds, thisRow } = options;
79
+ let offsetSkew = 0;
80
+ const output: Token[] = [];
81
+ for (const t of tokens) {
82
+ const token = cloneToken(t);
83
+ let offsetDelta = 0;
84
+ if (token.type === REF_STRUCT) {
85
+ const sref = parseStructRef(token.value);
86
+ const newValue = stringifyStructRef(sref, { thisRow });
87
+ offsetDelta = newValue.length - token.value.length;
88
+ token.value = newValue;
89
+ }
90
+ else if (isRange(token)) {
91
+ const ref = parseA1Ref(token.value, { allowTernary: true }) as ReferenceA1;
92
+ const range = ref.range;
93
+ // fill missing dimensions?
94
+ if (addBounds) {
95
+ addA1RangeBounds(range);
96
+ }
97
+ const newValue = stringifyA1Ref(ref);
98
+ offsetDelta = newValue.length - token.value.length;
99
+ token.value = newValue;
100
+ }
101
+ // ensure that positioning is still correct
102
+ if (offsetSkew || offsetDelta) {
103
+ if (token.loc) {
104
+ token.loc[0] += offsetSkew;
105
+ }
106
+ offsetSkew += offsetDelta;
107
+ if (token.loc) {
108
+ token.loc[1] += offsetSkew;
109
+ }
110
+ }
111
+ else {
112
+ offsetSkew += offsetDelta;
113
+ }
114
+ output.push(token);
115
+ }
116
+
117
+ return output;
118
+ }
119
+
120
+ /**
121
+ * Normalizes A1 style ranges and structured references in a list of tokens.
122
+ *
123
+ * It ensures that that the top and left coordinates of an A1 range are on the
124
+ * left-hand side of a colon operator:
125
+ *
126
+ * ```
127
+ * B2:A1 → A1:B2
128
+ * 1:A1 → A1:1
129
+ * A:A1 → A1:A
130
+ * B:A → A:B
131
+ * 2:1 → 1:2
132
+ * A1:A1 → A1
133
+ * ```
134
+ *
135
+ * When `{ addBounds }` option is set to true, the missing bounds are also added.
136
+ * This can be done to ensure Excel compatible ranges. The fixes then additionally include:
137
+ *
138
+ * ```
139
+ * 1:A1 → A1:1 → 1:1
140
+ * A:A1 → A1:A → A:A
141
+ * A1:A → A:A
142
+ * A1:1 → A:1
143
+ * B2:B → B2:1048576
144
+ * B2:2 → B2:XFD2
145
+ * ```
146
+ *
147
+ * Structured ranges are normalized to have consistent order and capitalization
148
+ * of sections as well as removing redundant ones.
149
+ *
150
+ * Returns a new array of tokens with values and position data updated.
151
+ *
152
+ * @see {@link OptsFixRanges}
153
+ * @param tokens A list of tokens to be adjusted.
154
+ * @param [options] Options.
155
+ * @returns A token list with ranges adjusted.
156
+ */
157
+ export function fixTokenRangesXlsx (
158
+ tokens: Token[],
159
+ options: OptsFixRanges = {}
160
+ ): Token[] {
161
+ if (!Array.isArray(tokens)) {
162
+ throw new Error('fixRanges expects an array of tokens');
163
+ }
164
+ const { addBounds, thisRow } = options;
165
+ let offsetSkew = 0;
166
+ const output: Token[] = [];
167
+ for (const t of tokens) {
168
+ const token = cloneToken(t);
169
+ let offsetDelta = 0;
170
+ if (token.type === REF_STRUCT) {
171
+ const sref = parseStructRefXlsx(token.value);
172
+ const newValue = stringifyStructRefXlsx(sref, { thisRow });
173
+ offsetDelta = newValue.length - token.value.length;
174
+ token.value = newValue;
175
+ }
176
+ else if (isRange(token)) {
177
+ const ref = parseA1RefXlsx(token.value, { allowTernary: true }) as ReferenceA1Xlsx;
178
+ const range = ref.range;
179
+ // fill missing dimensions?
180
+ if (addBounds) {
181
+ addA1RangeBounds(range);
182
+ }
183
+ const newValue = stringifyA1RefXlsx(ref);
184
+ offsetDelta = newValue.length - token.value.length;
185
+ token.value = newValue;
186
+ }
187
+ // ensure that positioning is still correct
188
+ if (offsetSkew || offsetDelta) {
189
+ if (token.loc) {
190
+ token.loc[0] += offsetSkew;
191
+ }
192
+ offsetSkew += offsetDelta;
193
+ if (token.loc) {
194
+ token.loc[1] += offsetSkew;
195
+ }
196
+ }
197
+ else {
198
+ offsetSkew += offsetDelta;
199
+ }
200
+ output.push(token);
201
+ }
202
+
203
+ return output;
204
+ }
205
+
206
+ /**
207
+ * Normalizes A1 style ranges and structured references in a formula.
208
+ *
209
+ * Internally it uses {@link fixTokenRanges} so see it's documentation for details.
210
+ *
211
+ * Returns the same formula with the ranges updated. If an array of tokens was
212
+ * supplied, then a new array is returned.
213
+ *
214
+ * @see {@link OptsFixRanges} & {@link OptsTokenize}
215
+ * @param formula A string (an Excel formula) or a token list that should be adjusted.
216
+ * @param [options] Options
217
+ * @returns A formula string with ranges adjusted
218
+ */
219
+ export function fixFormulaRanges (
220
+ formula: string,
221
+ options: OptsFixRanges & OptsTokenize = {}
222
+ ): string {
223
+ if (typeof formula !== 'string') {
224
+ throw new Error('fixFormulaRanges expects a string formula');
225
+ }
226
+ return stringifyTokens(
227
+ fixTokenRanges(
228
+ tokenize(formula, options),
229
+ options
230
+ )
231
+ );
232
+ }
233
+
234
+ /**
235
+ * Normalizes A1 style ranges and structured references in a formula.
236
+ *
237
+ * Internally it uses {@link fixTokenRanges} so see it's documentation for details.
238
+ *
239
+ * Returns the same formula with the ranges updated. If an array of tokens was
240
+ * supplied, then a new array is returned.
241
+ *
242
+ * @see {@link OptsFixRanges} & {@link OptsTokenize}
243
+ * @param formula A string (an Excel formula) or a token list that should be adjusted.
244
+ * @param [options] Options
245
+ * @returns A formula string with ranges adjusted
246
+ */
247
+ export function fixFormulaRangesXlsx (
248
+ formula: string,
249
+ options: OptsFixRanges & OptsTokenize = {}
250
+ ): string {
251
+ if (typeof formula !== 'string') {
252
+ throw new Error('fixFormulaRanges expects a string formula');
253
+ }
254
+ return stringifyTokens(
255
+ fixTokenRangesXlsx(
256
+ tokenizeXlsx(formula, options),
257
+ options
258
+ )
259
+ );
260
+ }
@@ -0,0 +1,15 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { fromCol } from './fromCol.ts';
3
+
4
+ describe('fromCol parses column id strings to numbers', () => {
5
+ test('single letter columns', () => {
6
+ expect(fromCol('a')).toBe(0);
7
+ expect(fromCol('A')).toBe(0);
8
+ });
9
+
10
+ test('multi-letter columns', () => {
11
+ expect(fromCol('AA')).toBe(26);
12
+ expect(fromCol('zz')).toBe(701);
13
+ expect(fromCol('ZZZ')).toBe(18277);
14
+ });
15
+ });
@@ -9,7 +9,7 @@
9
9
  * @param {string} columnString The column string identifier
10
10
  * @returns {number} Zero based column index number
11
11
  */
12
- export function fromCol (columnString) {
12
+ export function fromCol (columnString: string): number {
13
13
  const x = (columnString || '');
14
14
  const l = x.length;
15
15
  let n = 0;
@@ -0,0 +1,119 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ addA1RangeBounds,
4
+ fixTokenRanges,
5
+ fixFormulaRanges,
6
+ fromCol,
7
+ isError,
8
+ isFunction,
9
+ isFxPrefix,
10
+ isLiteral,
11
+ isOperator,
12
+ isRange,
13
+ isReference,
14
+ isWhitespace,
15
+ mergeRefTokens,
16
+ nodeTypes,
17
+ parse,
18
+ parseA1Ref,
19
+ parseR1C1Ref,
20
+ parseStructRef,
21
+ stringifyA1Ref,
22
+ stringifyR1C1Ref,
23
+ stringifyStructRef,
24
+ toCol,
25
+ tokenize,
26
+ tokenTypes,
27
+ translateFormulaToA1,
28
+ translateTokensToA1,
29
+ translateFormulaToR1C1,
30
+ translateTokensToR1C1
31
+ } from './index.ts';
32
+
33
+ // What happens when B2:A1 -> should work!
34
+ describe('fx main interface', () => {
35
+ it('addA1RangeBounds exists', () => {
36
+ expect(typeof addA1RangeBounds === 'function').toBeTruthy();
37
+ });
38
+ it('fixTokenRanges exists', () => {
39
+ expect(typeof fixTokenRanges === 'function').toBeTruthy();
40
+ });
41
+ it('fixFormulaRanges exists', () => {
42
+ expect(typeof fixFormulaRanges === 'function').toBeTruthy();
43
+ });
44
+ it('fromCol exists', () => {
45
+ expect(typeof fromCol === 'function').toBeTruthy();
46
+ });
47
+ it('isError exists', () => {
48
+ expect(typeof isError === 'function').toBeTruthy();
49
+ });
50
+ it('isFunction exists', () => {
51
+ expect(typeof isFunction === 'function').toBeTruthy();
52
+ });
53
+ it('isFxPrefix exists', () => {
54
+ expect(typeof isFxPrefix === 'function').toBeTruthy();
55
+ });
56
+ it('isLiteral exists', () => {
57
+ expect(typeof isLiteral === 'function').toBeTruthy();
58
+ });
59
+ it('isOperator exists', () => {
60
+ expect(typeof isOperator === 'function').toBeTruthy();
61
+ });
62
+ it('isRange exists', () => {
63
+ expect(typeof isRange === 'function').toBeTruthy();
64
+ });
65
+ it('isReference exists', () => {
66
+ expect(typeof isReference === 'function').toBeTruthy();
67
+ });
68
+ it('isWhitespace exists', () => {
69
+ expect(typeof isWhitespace === 'function').toBeTruthy();
70
+ });
71
+ it('mergeRefTokens exists', () => {
72
+ expect(typeof mergeRefTokens === 'function').toBeTruthy();
73
+ });
74
+ it('parse exists', () => {
75
+ expect(typeof parse === 'function').toBeTruthy();
76
+ });
77
+ it('parseA1Ref exists', () => {
78
+ expect(typeof parseA1Ref === 'function').toBeTruthy();
79
+ });
80
+ it('parseR1C1Ref exists', () => {
81
+ expect(typeof parseR1C1Ref === 'function').toBeTruthy();
82
+ });
83
+ it('parseStructRef exists', () => {
84
+ expect(typeof parseStructRef === 'function').toBeTruthy();
85
+ });
86
+ it('stringifyA1Ref exists', () => {
87
+ expect(typeof stringifyA1Ref === 'function').toBeTruthy();
88
+ });
89
+ it('stringifyR1C1Ref exists', () => {
90
+ expect(typeof stringifyR1C1Ref === 'function').toBeTruthy();
91
+ });
92
+ it('stringifyStructRef exists', () => {
93
+ expect(typeof stringifyStructRef === 'function').toBeTruthy();
94
+ });
95
+ it('toCol exists', () => {
96
+ expect(typeof toCol === 'function').toBeTruthy();
97
+ });
98
+ it('tokenize exists', () => {
99
+ expect(typeof tokenize === 'function').toBeTruthy();
100
+ });
101
+ it('translateFormulaToA1 exists', () => {
102
+ expect(typeof translateFormulaToA1 === 'function').toBeTruthy();
103
+ });
104
+ it('translateTokensToA1 exists', () => {
105
+ expect(typeof translateTokensToA1 === 'function').toBeTruthy();
106
+ });
107
+ it('translateFormulaToR1C1 exists', () => {
108
+ expect(typeof translateFormulaToR1C1 === 'function').toBeTruthy();
109
+ });
110
+ it('translateTokensToR1C1 exists', () => {
111
+ expect(typeof translateTokensToR1C1 === 'function').toBeTruthy();
112
+ });
113
+ it('nodeTypes exists', () => {
114
+ expect(typeof nodeTypes === 'object').toBeTruthy();
115
+ });
116
+ it('tokenTypes exists', () => {
117
+ expect(typeof tokenTypes === 'object').toBeTruthy();
118
+ });
119
+ });
package/lib/index.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * A tokenizer, parser, and other utilities to work with Excel formula code.
3
+ *
4
+ * The base entry-point methods expect and return the variant of references that uses contexts.
5
+ * If you are using xlsx files or otherwise want to work with the xlsx-file variant of references
6
+ * you should use the {@link fx/xlsx} variant methods.
7
+ *
8
+ * See [Prefixes.md](./Prefixes.md) for documentation on how scopes work in Fx.
9
+ *
10
+ * @packageDocumentation
11
+ * @module fx
12
+ */
13
+
14
+ export { tokenize, type OptsTokenize } from './tokenize.ts';
15
+ export { parse, type OptsParse } from './parse.ts';
16
+ export { translateFormulaToR1C1, translateTokensToR1C1, type OptsTranslateToR1C1 } from './translateToR1C1.ts';
17
+ export {
18
+ translateFormulaToA1, type OptsTranslateFormulaToA1,
19
+ translateTokensToA1, type OptsTranslateTokensToA1
20
+ } from './translateToA1.ts';
21
+ export { MAX_COLS, MAX_ROWS } from './constants.ts';
22
+ export { mergeRefTokens } from './mergeRefTokens.ts';
23
+ export { fixTokenRanges, fixFormulaRanges, type OptsFixRanges } from './fixRanges.ts';
24
+ export {
25
+ isError,
26
+ isFunction,
27
+ isFxPrefix,
28
+ isLiteral,
29
+ isOperator,
30
+ isRange,
31
+ isReference,
32
+ isWhitespace
33
+ } from './isType.ts';
34
+ export {
35
+ isArrayNode,
36
+ isBinaryNode,
37
+ isCallNode,
38
+ isErrorNode,
39
+ isExpressionNode,
40
+ isIdentifierNode,
41
+ isLambdaNode,
42
+ isLetDeclaratorNode,
43
+ isLetNode,
44
+ isLiteralNode,
45
+ isReferenceNode,
46
+ isUnaryNode
47
+ } from './isNodeType.ts';
48
+ export { addA1RangeBounds } from './addA1RangeBounds.ts';
49
+ export { toCol } from './toCol.ts';
50
+ export { fromCol } from './fromCol.ts';
51
+ export { parseA1Range } from './parseA1Range.ts';
52
+ export { parseA1Ref, type OptsParseA1Ref } from './parseA1Ref.ts';
53
+ export { parseR1C1Range } from './parseR1C1Range.ts';
54
+ export { parseR1C1Ref, type OptsParseR1C1Ref } from './parseR1C1Ref.ts';
55
+ export { parseStructRef } from './parseStructRef.ts';
56
+ export { stringifyA1Ref } from './stringifyA1Ref.ts';
57
+ export { stringifyR1C1Ref } from './stringifyR1C1Ref.ts';
58
+ export { stringifyStructRef, type OptsStringifyStructRef } from './stringifyStructRef.ts';
59
+ export { stringifyTokens } from './stringifyTokens.ts';
60
+ export type {
61
+ RangeA1,
62
+ RangeR1C1,
63
+ Token,
64
+ TokenEnhanced,
65
+ ReferenceA1,
66
+ ReferenceA1Xlsx,
67
+ ReferenceR1C1,
68
+ ReferenceR1C1Xlsx,
69
+ ReferenceStruct,
70
+ ReferenceStructXlsx,
71
+ ReferenceName,
72
+ ReferenceNameXlsx
73
+ } from './types.ts';
74
+ export type * from './astTypes.ts';
75
+ export { tokenTypes } from './tokenTypes.ts';
76
+ export { nodeTypes } from './nodeTypes.ts';
@@ -0,0 +1,151 @@
1
+ import type {
2
+ Node,
3
+ Identifier,
4
+ ReferenceIdentifier,
5
+ Literal,
6
+ ErrorLiteral,
7
+ UnaryExpression,
8
+ BinaryExpression,
9
+ CallExpression,
10
+ ArrayExpression,
11
+ LambdaExpression,
12
+ LetExpression,
13
+ LetDeclarator,
14
+ AstExpression
15
+ } from './astTypes.ts';
16
+ import {
17
+ ARRAY,
18
+ BINARY,
19
+ CALL,
20
+ ERROR,
21
+ ERROR_LITERAL,
22
+ IDENTIFIER,
23
+ LAMBDA,
24
+ LET,
25
+ LET_DECL,
26
+ LITERAL,
27
+ REFERENCE,
28
+ UNARY
29
+ } from './constants.ts';
30
+
31
+ /**
32
+ * Determines whether the specified node is an Identifier.
33
+ * @param node An AST node.
34
+ * @returns True if the specified token is an Identifier, False otherwise.
35
+ */
36
+ export function isIdentifierNode (node?: Node | null): node is Identifier {
37
+ return node?.type === IDENTIFIER;
38
+ }
39
+
40
+ /**
41
+ * Determines whether the specified node is a ReferenceIdentifier.
42
+ * @param node An AST node.
43
+ * @returns True if the specified token is a ReferenceIdentifier, False otherwise.
44
+ */
45
+ export function isReferenceNode (node?: Node | null): node is ReferenceIdentifier {
46
+ return node?.type === REFERENCE;
47
+ }
48
+
49
+ /**
50
+ * Determines whether the specified node is a Literal.
51
+ * @param node An AST node.
52
+ * @returns True if the specified token is a Literal, False otherwise.
53
+ */
54
+ export function isLiteralNode (node?: Node | null): node is Literal {
55
+ return node?.type === LITERAL;
56
+ }
57
+
58
+ /**
59
+ * Determines whether the specified node is an ErrorLiteral.
60
+ * @param node An AST node.
61
+ * @returns True if the specified token is an ErrorLiteral, False otherwise.
62
+ */
63
+ export function isErrorNode (node?: Node | null): node is ErrorLiteral {
64
+ return node?.type === ERROR_LITERAL;
65
+ }
66
+
67
+ /**
68
+ * Determines whether the specified node is a UnaryExpression.
69
+ * @param node An AST node.
70
+ * @returns True if the specified token is a UnaryExpression, False otherwise.
71
+ */
72
+ export function isUnaryNode (node?: Node | null): node is UnaryExpression {
73
+ return node?.type === UNARY;
74
+ }
75
+
76
+ /**
77
+ * Determines whether the specified node is a BinaryExpression.
78
+ * @param node An AST node.
79
+ * @returns True if the specified token is a BinaryExpression, False otherwise.
80
+ */
81
+ export function isBinaryNode (node?: Node | null): node is BinaryExpression {
82
+ return node?.type === BINARY;
83
+ }
84
+
85
+ /**
86
+ * Determines whether the specified node is a CallExpression.
87
+ * @param node An AST node.
88
+ * @returns True if the specified token is a CallExpression, False otherwise.
89
+ */
90
+ export function isCallNode (node?: Node | null): node is CallExpression {
91
+ return node?.type === CALL;
92
+ }
93
+
94
+ /**
95
+ * Determines whether the specified node is a ArrayExpression.
96
+ * @param node An AST node.
97
+ * @returns True if the specified token is a ArrayExpression, False otherwise.
98
+ */
99
+ export function isArrayNode (node?: Node | null): node is ArrayExpression {
100
+ return node?.type === ARRAY;
101
+ }
102
+
103
+ /**
104
+ * Determines whether the specified node is a LambdaExpression.
105
+ * @param node An AST node.
106
+ * @returns True if the specified token is a LambdaExpression, False otherwise.
107
+ */
108
+ export function isLambdaNode (node?: Node | null): node is LambdaExpression {
109
+ return node?.type === ARRAY;
110
+ }
111
+
112
+ /**
113
+ * Determines whether the specified node is a LetExpression.
114
+ * @param node An AST node.
115
+ * @returns True if the specified token is a LetExpression, False otherwise.
116
+ */
117
+ export function isLetNode (node?: Node | null): node is LetExpression {
118
+ return node?.type === LET;
119
+ }
120
+
121
+ /**
122
+ * Determines whether the specified node is a LetDeclarator.
123
+ * @param node An AST node.
124
+ * @returns True if the specified token is a LetDeclarator, False otherwise.
125
+ */
126
+ export function isLetDeclaratorNode (node?: Node | null): node is LetDeclarator {
127
+ return node?.type === LET_DECL;
128
+ }
129
+
130
+ /**
131
+ * Determines whether the specified node is a AstExpression.
132
+ * @param node An AST node.
133
+ * @returns True if the specified token is a AstExpression, False otherwise.
134
+ */
135
+ export function isExpressionNode (node?: Node | null): node is AstExpression {
136
+ const type = node?.type;
137
+ if (type) {
138
+ return (
139
+ type === REFERENCE ||
140
+ type === LITERAL ||
141
+ type === ERROR ||
142
+ type === UNARY ||
143
+ type === BINARY ||
144
+ type === CALL ||
145
+ type === ARRAY ||
146
+ type === LAMBDA ||
147
+ type === LET
148
+ );
149
+ }
150
+ return false;
151
+ }