@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.
- package/dist/index-BMr6cTgc.d.cts +1444 -0
- package/dist/index-BMr6cTgc.d.ts +1444 -0
- package/dist/index.cjs +3054 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2984 -0
- package/dist/index.js.map +1 -0
- package/dist/xlsx/index.cjs +3120 -0
- package/dist/xlsx/index.cjs.map +1 -0
- package/dist/xlsx/index.d.cts +55 -0
- package/dist/xlsx/index.d.ts +55 -0
- package/dist/xlsx/index.js +3049 -0
- package/dist/xlsx/index.js.map +1 -0
- package/docs/API.md +2959 -718
- package/docs/AST_format.md +2 -2
- package/eslint.config.mjs +40 -0
- package/lib/a1.spec.ts +32 -0
- package/lib/a1.ts +26 -0
- package/lib/addA1RangeBounds.ts +50 -0
- package/lib/addTokenMeta.spec.ts +166 -0
- package/lib/{addTokenMeta.js → addTokenMeta.ts} +53 -33
- package/lib/astTypes.ts +211 -0
- package/lib/cloneToken.ts +29 -0
- package/lib/{constants.js → constants.ts} +6 -3
- package/lib/fixRanges.spec.ts +220 -0
- package/lib/fixRanges.ts +260 -0
- package/lib/fromCol.spec.ts +15 -0
- package/lib/{fromCol.js → fromCol.ts} +1 -1
- package/lib/index.spec.ts +119 -0
- package/lib/index.ts +76 -0
- package/lib/isNodeType.ts +151 -0
- package/lib/isType.spec.ts +208 -0
- package/lib/{isType.js → isType.ts} +26 -25
- package/lib/lexers/{advRangeOp.js → advRangeOp.ts} +1 -1
- package/lib/lexers/{canEndRange.js → canEndRange.ts} +2 -2
- package/lib/lexers/{lexBoolean.js → lexBoolean.ts} +25 -6
- package/lib/lexers/{lexContext.js → lexContext.ts} +14 -6
- package/lib/lexers/{lexError.js → lexError.ts} +3 -3
- package/lib/lexers/{lexFunction.js → lexFunction.ts} +3 -2
- package/lib/lexers/lexNameFuncCntx.ts +112 -0
- package/lib/lexers/{lexNamed.js → lexNamed.ts} +4 -4
- package/lib/lexers/{lexNewLine.js → lexNewLine.ts} +3 -2
- package/lib/lexers/{lexNumber.js → lexNumber.ts} +4 -3
- package/lib/lexers/{lexOperator.js → lexOperator.ts} +5 -4
- package/lib/lexers/lexRange.ts +15 -0
- package/lib/lexers/{lexRangeA1.js → lexRangeA1.ts} +11 -7
- package/lib/lexers/{lexRangeR1C1.js → lexRangeR1C1.ts} +10 -6
- package/lib/lexers/{lexRangeTrim.js → lexRangeTrim.ts} +3 -2
- package/lib/lexers/{lexRefOp.js → lexRefOp.ts} +4 -3
- package/lib/lexers/{lexString.js → lexString.ts} +3 -3
- package/lib/lexers/{lexStructured.js → lexStructured.ts} +5 -5
- package/lib/lexers/{lexWhitespace.js → lexWhitespace.ts} +3 -2
- package/lib/lexers/sets.ts +51 -0
- package/lib/mergeRefTokens.spec.ts +141 -0
- package/lib/{mergeRefTokens.js → mergeRefTokens.ts} +14 -9
- package/lib/nodeTypes.ts +54 -0
- package/lib/parse.spec.ts +1410 -0
- package/lib/{parser.js → parse.ts} +81 -63
- package/lib/parseA1Range.spec.ts +233 -0
- package/lib/parseA1Range.ts +206 -0
- package/lib/parseA1Ref.spec.ts +337 -0
- package/lib/parseA1Ref.ts +115 -0
- package/lib/parseR1C1Range.ts +191 -0
- package/lib/parseR1C1Ref.spec.ts +323 -0
- package/lib/parseR1C1Ref.ts +127 -0
- package/lib/parseRef.spec.ts +90 -0
- package/lib/parseRef.ts +240 -0
- package/lib/{parseSRange.js → parseSRange.ts} +15 -10
- package/lib/parseStructRef.spec.ts +168 -0
- package/lib/parseStructRef.ts +76 -0
- package/lib/stringifyA1Range.spec.ts +72 -0
- package/lib/stringifyA1Range.ts +72 -0
- package/lib/stringifyA1Ref.spec.ts +64 -0
- package/lib/stringifyA1Ref.ts +59 -0
- package/lib/{stringifyPrefix.js → stringifyPrefix.ts} +17 -2
- package/lib/stringifyR1C1Range.spec.ts +92 -0
- package/lib/stringifyR1C1Range.ts +73 -0
- package/lib/stringifyR1C1Ref.spec.ts +63 -0
- package/lib/stringifyR1C1Ref.ts +67 -0
- package/lib/stringifyStructRef.spec.ts +124 -0
- package/lib/stringifyStructRef.ts +113 -0
- package/lib/stringifyTokens.ts +15 -0
- package/lib/toCol.spec.ts +11 -0
- package/lib/{toCol.js → toCol.ts} +4 -4
- package/lib/tokenTypes.ts +76 -0
- package/lib/tokenize-srefs.spec.ts +429 -0
- package/lib/tokenize.spec.ts +2103 -0
- package/lib/tokenize.ts +346 -0
- package/lib/translate.spec.ts +35 -0
- package/lib/translateToA1.spec.ts +247 -0
- package/lib/translateToA1.ts +231 -0
- package/lib/translateToR1C1.spec.ts +227 -0
- package/lib/translateToR1C1.ts +145 -0
- package/lib/types.ts +179 -0
- package/lib/xlsx/index.spec.ts +27 -0
- package/lib/xlsx/index.ts +32 -0
- package/package.json +45 -31
- package/tsconfig.json +28 -0
- package/typedoc-ignore-links.ts +17 -0
- package/typedoc.json +41 -0
- package/.eslintrc +0 -22
- package/benchmark/benchmark.js +0 -48
- package/benchmark/formulas.json +0 -15677
- package/dist/fx.d.ts +0 -823
- package/dist/fx.js +0 -2
- package/dist/package.json +0 -1
- package/lib/a1.js +0 -348
- package/lib/a1.spec.js +0 -458
- package/lib/addTokenMeta.spec.js +0 -153
- package/lib/astTypes.js +0 -96
- package/lib/extraTypes.js +0 -74
- package/lib/fixRanges.js +0 -104
- package/lib/fixRanges.spec.js +0 -171
- package/lib/fromCol.spec.js +0 -11
- package/lib/index.js +0 -134
- package/lib/index.spec.js +0 -67
- package/lib/isType.spec.js +0 -168
- package/lib/lexer-srefs.spec.js +0 -324
- package/lib/lexer.js +0 -264
- package/lib/lexer.spec.js +0 -1953
- package/lib/lexers/lexRange.js +0 -8
- package/lib/lexers/sets.js +0 -38
- package/lib/mergeRefTokens.spec.js +0 -121
- package/lib/package.json +0 -1
- package/lib/parseRef.js +0 -157
- package/lib/parseRef.spec.js +0 -71
- package/lib/parseStructRef.js +0 -48
- package/lib/parseStructRef.spec.js +0 -164
- package/lib/parser.spec.js +0 -1208
- package/lib/rc.js +0 -341
- package/lib/rc.spec.js +0 -403
- package/lib/stringifyStructRef.js +0 -80
- package/lib/stringifyStructRef.spec.js +0 -182
- package/lib/toCol.spec.js +0 -11
- package/lib/translate-toA1.spec.js +0 -214
- package/lib/translate-toRC.spec.js +0 -197
- package/lib/translate.js +0 -239
- package/lib/translate.spec.js +0 -21
- package/rollup.config.mjs +0 -22
- package/tsd.json +0 -12
package/lib/lexers/lexRange.js
DELETED
package/lib/lexers/sets.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { lexError } from './lexError.js';
|
|
2
|
-
import { lexRangeTrim } from './lexRangeTrim.js';
|
|
3
|
-
import { lexOperator } from './lexOperator.js';
|
|
4
|
-
import { lexFunction } from './lexFunction.js';
|
|
5
|
-
import { lexBoolean } from './lexBoolean.js';
|
|
6
|
-
import { lexNewLine } from './lexNewLine.js';
|
|
7
|
-
import { lexWhitespace } from './lexWhitespace.js';
|
|
8
|
-
import { lexString } from './lexString.js';
|
|
9
|
-
import { lexContext } from './lexContext.js';
|
|
10
|
-
import { lexRange } from './lexRange.js';
|
|
11
|
-
import { lexStructured } from './lexStructured.js';
|
|
12
|
-
import { lexNumber } from './lexNumber.js';
|
|
13
|
-
import { lexNamed } from './lexNamed.js';
|
|
14
|
-
import { lexRefOp } from './lexRefOp.js';
|
|
15
|
-
|
|
16
|
-
export const lexers = [
|
|
17
|
-
lexError,
|
|
18
|
-
lexRangeTrim,
|
|
19
|
-
lexOperator,
|
|
20
|
-
lexFunction,
|
|
21
|
-
lexBoolean,
|
|
22
|
-
lexNewLine,
|
|
23
|
-
lexWhitespace,
|
|
24
|
-
lexString,
|
|
25
|
-
lexContext,
|
|
26
|
-
lexRange,
|
|
27
|
-
lexStructured,
|
|
28
|
-
lexNumber,
|
|
29
|
-
lexNamed
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
export const lexersRefs = [
|
|
33
|
-
lexRefOp,
|
|
34
|
-
lexContext,
|
|
35
|
-
lexRange,
|
|
36
|
-
lexStructured,
|
|
37
|
-
lexNamed
|
|
38
|
-
];
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { CONTEXT, FUNCTION, FX_PREFIX, OPERATOR, REF_RANGE, REF_BEAM, REF_NAMED, REF_TERNARY, UNKNOWN } from './constants.js';
|
|
2
|
-
import { test } from 'tape';
|
|
3
|
-
import { mergeRefTokens } from './mergeRefTokens.js';
|
|
4
|
-
import { tokenize } from './lexer.js';
|
|
5
|
-
|
|
6
|
-
test('mergeRefTokens basics', t => {
|
|
7
|
-
const list = tokenize('=SUM([Wb1]Sheet1!A1:B2)', { mergeRefs: false, withLocation: true });
|
|
8
|
-
|
|
9
|
-
t.deepEqual(list, [
|
|
10
|
-
{ type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
|
|
11
|
-
{ type: FUNCTION, value: 'SUM', loc: [ 1, 4 ] },
|
|
12
|
-
{ type: OPERATOR, value: '(', loc: [ 4, 5 ] },
|
|
13
|
-
|
|
14
|
-
{ type: CONTEXT, value: '[Wb1]Sheet1', loc: [ 5, 16 ] },
|
|
15
|
-
{ type: OPERATOR, value: '!', loc: [ 16, 17 ] },
|
|
16
|
-
{ type: REF_RANGE, value: 'A1', loc: [ 17, 19 ] },
|
|
17
|
-
{ type: OPERATOR, value: ':', loc: [ 19, 20 ] },
|
|
18
|
-
{ type: REF_RANGE, value: 'B2', loc: [ 20, 22 ] },
|
|
19
|
-
|
|
20
|
-
{ type: OPERATOR, value: ')', loc: [ 22, 23 ] }
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
// set IDs on all tokens about to be joined
|
|
24
|
-
list[3].id = 'id1';
|
|
25
|
-
list[4].id = 'id2';
|
|
26
|
-
list[5].id = 'id3';
|
|
27
|
-
list[6].id = 'id4';
|
|
28
|
-
list[7].id = 'id5';
|
|
29
|
-
|
|
30
|
-
const mergedList = mergeRefTokens(list);
|
|
31
|
-
t.deepEqual(mergedList, [
|
|
32
|
-
{ type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
|
|
33
|
-
{ type: FUNCTION, value: 'SUM', loc: [ 1, 4 ] },
|
|
34
|
-
{ type: OPERATOR, value: '(', loc: [ 4, 5 ] },
|
|
35
|
-
{ type: REF_RANGE,
|
|
36
|
-
id: 'id5', // token has the id of the first one
|
|
37
|
-
value: '[Wb1]Sheet1!A1:B2',
|
|
38
|
-
loc: [ 5, 22 ] },
|
|
39
|
-
{ type: OPERATOR, value: ')', loc: [ 22, 23 ] }
|
|
40
|
-
]);
|
|
41
|
-
|
|
42
|
-
t.end();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('mergeRefTokens cases', t => {
|
|
46
|
-
const opts = { mergeRefs: true, allowTernary: true };
|
|
47
|
-
t.deepEqual(tokenize('A1', opts), [
|
|
48
|
-
{ type: REF_RANGE, value: 'A1' }
|
|
49
|
-
]);
|
|
50
|
-
t.deepEqual(tokenize('A1:A1', opts), [
|
|
51
|
-
{ type: REF_RANGE, value: 'A1:A1' }
|
|
52
|
-
]);
|
|
53
|
-
t.deepEqual(tokenize('A:A', opts), [
|
|
54
|
-
{ type: REF_BEAM, value: 'A:A' }
|
|
55
|
-
]);
|
|
56
|
-
t.deepEqual(tokenize('A1:A', opts), [
|
|
57
|
-
{ type: REF_TERNARY, value: 'A1:A' }
|
|
58
|
-
]);
|
|
59
|
-
|
|
60
|
-
t.deepEqual(tokenize('\'Sheet1\'!A1', opts), [
|
|
61
|
-
{ type: REF_RANGE, value: '\'Sheet1\'!A1' }
|
|
62
|
-
]);
|
|
63
|
-
t.deepEqual(tokenize('\'Sheet1\'!A:A', opts), [
|
|
64
|
-
{ type: REF_BEAM, value: '\'Sheet1\'!A:A' }
|
|
65
|
-
]);
|
|
66
|
-
t.deepEqual(tokenize('\'Sheet1\'!A1:A', opts), [
|
|
67
|
-
{ type: REF_TERNARY, value: '\'Sheet1\'!A1:A' }
|
|
68
|
-
]);
|
|
69
|
-
t.deepEqual(tokenize('\'Sheet1\'!A1:A', opts), [
|
|
70
|
-
{ type: REF_TERNARY, value: '\'Sheet1\'!A1:A' }
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
t.deepEqual(tokenize('Sheet1!A1', opts), [
|
|
74
|
-
{ type: REF_RANGE, value: 'Sheet1!A1' }
|
|
75
|
-
]);
|
|
76
|
-
t.deepEqual(tokenize('Sheet1!A:A', opts), [
|
|
77
|
-
{ type: REF_BEAM, value: 'Sheet1!A:A' }
|
|
78
|
-
]);
|
|
79
|
-
t.deepEqual(tokenize('Sheet1!A1:A', opts), [
|
|
80
|
-
{ type: REF_TERNARY, value: 'Sheet1!A1:A' }
|
|
81
|
-
]);
|
|
82
|
-
t.deepEqual(tokenize('Sheet1!A1:A', opts), [
|
|
83
|
-
{ type: REF_TERNARY, value: 'Sheet1!A1:A' }
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
t.deepEqual(tokenize('[WB]Sheet1!A1', opts), [
|
|
87
|
-
{ type: REF_RANGE, value: '[WB]Sheet1!A1' }
|
|
88
|
-
]);
|
|
89
|
-
t.deepEqual(tokenize('[WB]Sheet1!A:A', opts), [
|
|
90
|
-
{ type: REF_BEAM, value: '[WB]Sheet1!A:A' }
|
|
91
|
-
]);
|
|
92
|
-
t.deepEqual(tokenize('[WB]Sheet1!A1:A', opts), [
|
|
93
|
-
{ type: REF_TERNARY, value: '[WB]Sheet1!A1:A' }
|
|
94
|
-
]);
|
|
95
|
-
t.deepEqual(tokenize('[WB]Sheet1!A1:A', opts), [
|
|
96
|
-
{ type: REF_TERNARY, value: '[WB]Sheet1!A1:A' }
|
|
97
|
-
]);
|
|
98
|
-
t.deepEqual(tokenize('[WB]Sheet1!A1.:.C3', opts), [
|
|
99
|
-
{ type: REF_RANGE, value: '[WB]Sheet1!A1.:.C3' }
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
t.deepEqual(tokenize('foo', opts), [
|
|
103
|
-
{ type: REF_NAMED, value: 'foo' }
|
|
104
|
-
]);
|
|
105
|
-
t.deepEqual(tokenize('\'quoted\'!foo', opts), [
|
|
106
|
-
{ type: REF_NAMED, value: '\'quoted\'!foo' }
|
|
107
|
-
]);
|
|
108
|
-
t.deepEqual(tokenize('Sheet1!foo', opts), [
|
|
109
|
-
{ type: REF_NAMED, value: 'Sheet1!foo' }
|
|
110
|
-
]);
|
|
111
|
-
t.deepEqual(tokenize('[path]!foo', opts), [
|
|
112
|
-
{ type: UNKNOWN, value: '[path]' },
|
|
113
|
-
{ type: OPERATOR, value: '!' },
|
|
114
|
-
{ type: REF_NAMED, value: 'foo' }
|
|
115
|
-
]);
|
|
116
|
-
t.deepEqual(tokenize('[path]prefix!foo', opts), [
|
|
117
|
-
{ type: REF_NAMED, value: '[path]prefix!foo' }
|
|
118
|
-
]);
|
|
119
|
-
|
|
120
|
-
t.end();
|
|
121
|
-
});
|
package/lib/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "type": "module" }
|
package/lib/parseRef.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FX_PREFIX,
|
|
3
|
-
CONTEXT,
|
|
4
|
-
CONTEXT_QUOTE,
|
|
5
|
-
REF_RANGE,
|
|
6
|
-
REF_TERNARY,
|
|
7
|
-
REF_NAMED,
|
|
8
|
-
REF_BEAM,
|
|
9
|
-
REF_STRUCT,
|
|
10
|
-
OPERATOR
|
|
11
|
-
} from './constants.js';
|
|
12
|
-
import { lexersRefs } from './lexers/sets.js';
|
|
13
|
-
import { getTokens } from './lexer.js';
|
|
14
|
-
|
|
15
|
-
// Liberally split a context string up into parts.
|
|
16
|
-
// Permits any combination of braced and unbraced items.
|
|
17
|
-
export function splitPrefix (str, stringsOnly = false) {
|
|
18
|
-
let inBrace = false;
|
|
19
|
-
let currStr = '';
|
|
20
|
-
const parts = [];
|
|
21
|
-
const flush = () => {
|
|
22
|
-
if (currStr) {
|
|
23
|
-
parts.push(
|
|
24
|
-
stringsOnly
|
|
25
|
-
? currStr
|
|
26
|
-
: { value: currStr, braced: inBrace }
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
currStr = '';
|
|
30
|
-
};
|
|
31
|
-
for (let i = 0; i < str.length; i++) {
|
|
32
|
-
const char = str[i];
|
|
33
|
-
if (char === '[') {
|
|
34
|
-
flush();
|
|
35
|
-
inBrace = true;
|
|
36
|
-
}
|
|
37
|
-
else if (char === ']') {
|
|
38
|
-
flush();
|
|
39
|
-
inBrace = false;
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
currStr += char;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
flush();
|
|
46
|
-
return parts;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function splitContext (contextString) {
|
|
50
|
-
return { context: splitPrefix(contextString, true) };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function splitContextXlsx (contextString) {
|
|
54
|
-
const context = {};
|
|
55
|
-
const ctx = splitPrefix(contextString);
|
|
56
|
-
if (ctx.length > 1) {
|
|
57
|
-
context.workbookName = ctx[ctx.length - 2].value;
|
|
58
|
-
context.sheetName = ctx[ctx.length - 1].value;
|
|
59
|
-
}
|
|
60
|
-
else if (ctx.length === 1) {
|
|
61
|
-
const item = ctx[0];
|
|
62
|
-
if (item.braced) {
|
|
63
|
-
context.workbookName = item.value;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
context.sheetName = item.value;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return context;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const unquote = d => d.slice(1, -1).replace(/''/g, "'");
|
|
73
|
-
|
|
74
|
-
const pRangeOp = t => t && (t.value === ':' || t.value === '.:' || t.value === ':.' || t.value === '.:.') && { operator: t.value };
|
|
75
|
-
const pRange = t => t && t.type === REF_RANGE && { r0: t.value };
|
|
76
|
-
const pPartial = t => t && t.type === REF_TERNARY && { r0: t.value };
|
|
77
|
-
const pRange2 = t => t && t.type === REF_RANGE && { r1: t.value };
|
|
78
|
-
const pBang = t => t && t.type === OPERATOR && t.value === '!' && {};
|
|
79
|
-
const pBeam = t => t && t.type === REF_BEAM && { r0: t.value };
|
|
80
|
-
const pStrucured = t => t && t.type === REF_STRUCT && { struct: t.value };
|
|
81
|
-
const pContext = (t, opts) => {
|
|
82
|
-
const splitter = opts.xlsx ? splitContextXlsx : splitContext;
|
|
83
|
-
if (t && t.type === CONTEXT) {
|
|
84
|
-
return splitter(t.value);
|
|
85
|
-
}
|
|
86
|
-
if (t && t.type === CONTEXT_QUOTE) {
|
|
87
|
-
return splitter(unquote(t.value));
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
const pNamed = t => t && t.type === REF_NAMED && { name: t.value };
|
|
91
|
-
|
|
92
|
-
const validRuns = [
|
|
93
|
-
[ pPartial ],
|
|
94
|
-
[ pRange, pRangeOp, pRange2 ],
|
|
95
|
-
[ pRange ],
|
|
96
|
-
[ pBeam ],
|
|
97
|
-
[ pContext, pBang, pPartial ],
|
|
98
|
-
[ pContext, pBang, pRange, pRangeOp, pRange2 ],
|
|
99
|
-
[ pContext, pBang, pRange ],
|
|
100
|
-
[ pContext, pBang, pBeam ]
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
const validRunsNamed = validRuns.concat([
|
|
104
|
-
[ pNamed ],
|
|
105
|
-
[ pContext, pBang, pNamed ],
|
|
106
|
-
[ pStrucured ],
|
|
107
|
-
[ pNamed, pStrucured ],
|
|
108
|
-
[ pContext, pBang, pNamed, pStrucured ]
|
|
109
|
-
]);
|
|
110
|
-
|
|
111
|
-
export function parseRef (ref, opts) {
|
|
112
|
-
const options = {
|
|
113
|
-
withLocation: false,
|
|
114
|
-
mergeRefs: false,
|
|
115
|
-
allowTernary: false,
|
|
116
|
-
allowNamed: true,
|
|
117
|
-
r1c1: false,
|
|
118
|
-
xlsx: false,
|
|
119
|
-
...opts
|
|
120
|
-
};
|
|
121
|
-
const tokens = getTokens(ref, lexersRefs, options);
|
|
122
|
-
const refData = options.xlsx
|
|
123
|
-
? {
|
|
124
|
-
workbookName: '',
|
|
125
|
-
sheetName: '',
|
|
126
|
-
r0: '',
|
|
127
|
-
r1: '',
|
|
128
|
-
name: '',
|
|
129
|
-
operator: ''
|
|
130
|
-
}
|
|
131
|
-
: {
|
|
132
|
-
context: [],
|
|
133
|
-
r0: '',
|
|
134
|
-
r1: '',
|
|
135
|
-
name: '',
|
|
136
|
-
operator: ''
|
|
137
|
-
};
|
|
138
|
-
// discard the "="-prefix if it is there
|
|
139
|
-
if (tokens.length && tokens[0].type === FX_PREFIX) {
|
|
140
|
-
tokens.shift();
|
|
141
|
-
}
|
|
142
|
-
const runs = options.allowNamed ? validRunsNamed : validRuns;
|
|
143
|
-
for (let i = 0; i < runs.length; i++) {
|
|
144
|
-
const data = { ...refData };
|
|
145
|
-
if (runs[i].length === tokens.length) {
|
|
146
|
-
const valid = runs[i].every((parse, j) => {
|
|
147
|
-
const d = parse(tokens[j], options);
|
|
148
|
-
Object.assign(data, d);
|
|
149
|
-
return d;
|
|
150
|
-
});
|
|
151
|
-
if (valid) {
|
|
152
|
-
return data;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return null;
|
|
157
|
-
}
|
package/lib/parseRef.spec.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { test } from 'tape';
|
|
2
|
-
import { splitPrefix } from './parseRef.js';
|
|
3
|
-
|
|
4
|
-
test('splitPrefix', t => {
|
|
5
|
-
const testStr = (str, opt, expected) => {
|
|
6
|
-
t.deepEqual(splitPrefix(str, opt), expected, str);
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
testStr('[foo][bar][baz]', true, [ 'foo', 'bar', 'baz' ]);
|
|
10
|
-
testStr('foo[bar][baz]', true, [ 'foo', 'bar', 'baz' ]);
|
|
11
|
-
testStr('[foo]bar[baz]', true, [ 'foo', 'bar', 'baz' ]);
|
|
12
|
-
testStr('[foo][bar]baz', true, [ 'foo', 'bar', 'baz' ]);
|
|
13
|
-
testStr('foo[bar]baz', true, [ 'foo', 'bar', 'baz' ]);
|
|
14
|
-
testStr('[foo]bar[baz]', true, [ 'foo', 'bar', 'baz' ]);
|
|
15
|
-
testStr('[foo]bar', true, [ 'foo', 'bar' ]);
|
|
16
|
-
testStr('foo[bar]', true, [ 'foo', 'bar' ]);
|
|
17
|
-
testStr('[foo][bar]', true, [ 'foo', 'bar' ]);
|
|
18
|
-
testStr('[foo]', true, [ 'foo' ]);
|
|
19
|
-
testStr('foo', true, [ 'foo' ]);
|
|
20
|
-
|
|
21
|
-
testStr('[foo][bar][baz]', false, [
|
|
22
|
-
{ value: 'foo', braced: true },
|
|
23
|
-
{ value: 'bar', braced: true },
|
|
24
|
-
{ value: 'baz', braced: true }
|
|
25
|
-
]);
|
|
26
|
-
testStr('foo[bar][baz]', false, [
|
|
27
|
-
{ value: 'foo', braced: false },
|
|
28
|
-
{ value: 'bar', braced: true },
|
|
29
|
-
{ value: 'baz', braced: true }
|
|
30
|
-
]);
|
|
31
|
-
testStr('[foo]bar[baz]', false, [
|
|
32
|
-
{ value: 'foo', braced: true },
|
|
33
|
-
{ value: 'bar', braced: false },
|
|
34
|
-
{ value: 'baz', braced: true }
|
|
35
|
-
]);
|
|
36
|
-
testStr('[foo][bar]baz', false, [
|
|
37
|
-
{ value: 'foo', braced: true },
|
|
38
|
-
{ value: 'bar', braced: true },
|
|
39
|
-
{ value: 'baz', braced: false }
|
|
40
|
-
]);
|
|
41
|
-
testStr('foo[bar]baz', false, [
|
|
42
|
-
{ value: 'foo', braced: false },
|
|
43
|
-
{ value: 'bar', braced: true },
|
|
44
|
-
{ value: 'baz', braced: false }
|
|
45
|
-
]);
|
|
46
|
-
testStr('[foo]bar[baz]', false, [
|
|
47
|
-
{ value: 'foo', braced: true },
|
|
48
|
-
{ value: 'bar', braced: false },
|
|
49
|
-
{ value: 'baz', braced: true }
|
|
50
|
-
]);
|
|
51
|
-
testStr('[foo]bar', false, [
|
|
52
|
-
{ value: 'foo', braced: true },
|
|
53
|
-
{ value: 'bar', braced: false }
|
|
54
|
-
]);
|
|
55
|
-
testStr('foo[bar]', false, [
|
|
56
|
-
{ value: 'foo', braced: false },
|
|
57
|
-
{ value: 'bar', braced: true }
|
|
58
|
-
]);
|
|
59
|
-
testStr('[foo][bar]', false, [
|
|
60
|
-
{ value: 'foo', braced: true },
|
|
61
|
-
{ value: 'bar', braced: true }
|
|
62
|
-
]);
|
|
63
|
-
testStr('[foo]', false, [
|
|
64
|
-
{ value: 'foo', braced: true }
|
|
65
|
-
]);
|
|
66
|
-
testStr('foo', false, [
|
|
67
|
-
{ value: 'foo', braced: false }
|
|
68
|
-
]);
|
|
69
|
-
|
|
70
|
-
t.end();
|
|
71
|
-
});
|
package/lib/parseStructRef.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { parseRef } from './parseRef.js';
|
|
2
|
-
import { parseSRange } from './parseSRange.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Parse a structured reference string into an object representing it.
|
|
6
|
-
*
|
|
7
|
-
* ```js
|
|
8
|
-
* parseStructRef('workbook.xlsx!tableName[[#Data],[Column1]:[Column2]]');
|
|
9
|
-
* // => {
|
|
10
|
-
* // context: [ 'workbook.xlsx' ],
|
|
11
|
-
* // sections: [ 'data' ],
|
|
12
|
-
* // columns: [ 'my column', '@foo' ],
|
|
13
|
-
* // table: 'tableName',
|
|
14
|
-
* // }
|
|
15
|
-
* ```
|
|
16
|
-
*
|
|
17
|
-
* For A:A or A1:A style ranges, `null` will be used for any dimensions that the
|
|
18
|
-
* syntax does not specify:
|
|
19
|
-
*
|
|
20
|
-
* @tutorial References.md
|
|
21
|
-
* @param {string} ref A structured reference string
|
|
22
|
-
* @param {object} [options={}] Options
|
|
23
|
-
* @param {boolean} [options.xlsx=false] Switches to the `[1]Sheet1!A1` or `[1]!name` prefix syntax form for external workbooks. See: [Prefixes.md](./Prefixes.md)
|
|
24
|
-
* @returns {(ReferenceStruct|null)} An object representing a valid reference or null if it is invalid.
|
|
25
|
-
*/
|
|
26
|
-
export function parseStructRef (ref, options = { xlsx: false }) {
|
|
27
|
-
const r = parseRef(ref, options);
|
|
28
|
-
if (r && r.struct) {
|
|
29
|
-
const structData = parseSRange(r.struct);
|
|
30
|
-
if (structData && structData.length === r.struct.length) {
|
|
31
|
-
return options.xlsx
|
|
32
|
-
? {
|
|
33
|
-
workbookName: r.workbookName,
|
|
34
|
-
sheetName: r.sheetName,
|
|
35
|
-
table: r.name,
|
|
36
|
-
columns: structData.columns,
|
|
37
|
-
sections: structData.sections
|
|
38
|
-
}
|
|
39
|
-
: {
|
|
40
|
-
context: r.context,
|
|
41
|
-
table: r.name,
|
|
42
|
-
columns: structData.columns,
|
|
43
|
-
sections: structData.sections
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/* eslint-disable object-property-newline, object-curly-newline */
|
|
2
|
-
import { test, Test } from 'tape';
|
|
3
|
-
import { parseStructRef } from './parseStructRef.js';
|
|
4
|
-
|
|
5
|
-
Test.prototype.isSREqual = function isSREqual (expr, expect, opts) {
|
|
6
|
-
if (expect) {
|
|
7
|
-
expect = opts?.xlsx
|
|
8
|
-
? {
|
|
9
|
-
workbookName: '',
|
|
10
|
-
sheetName: '',
|
|
11
|
-
table: '',
|
|
12
|
-
columns: [],
|
|
13
|
-
sections: [],
|
|
14
|
-
...expect
|
|
15
|
-
}
|
|
16
|
-
: {
|
|
17
|
-
context: [],
|
|
18
|
-
table: '',
|
|
19
|
-
columns: [],
|
|
20
|
-
sections: [],
|
|
21
|
-
...expect
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
this.deepEqual(parseStructRef(expr, opts), expect, expr);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
test('parse structured references', t => {
|
|
28
|
-
t.isSREqual('table[col]', {
|
|
29
|
-
table: 'table',
|
|
30
|
-
columns: [ 'col' ]
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
t.isSREqual('table[]', {
|
|
34
|
-
table: 'table'
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
t.isSREqual('[#All]', {
|
|
38
|
-
sections: [ 'all' ]
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
t.isSREqual('[column name]', {
|
|
42
|
-
columns: [ 'column name' ]
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
t.isSREqual('[column name]!foo', null);
|
|
46
|
-
t.isSREqual('[foo]bar', null);
|
|
47
|
-
|
|
48
|
-
t.isSREqual('[[my column]]', {
|
|
49
|
-
columns: [ 'my column' ]
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
t.isSREqual('[[my column]:otherColumn]', {
|
|
53
|
-
columns: [ 'my column', 'otherColumn' ]
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
t.isSREqual('[ [my column]:otherColumn ]', {
|
|
57
|
-
columns: [ 'my column', 'otherColumn ' ]
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
t.isSREqual('[ [my column]: otherColumn ]', {
|
|
61
|
-
columns: [ 'my column', ' otherColumn ' ]
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
t.isSREqual('[ @[ my column ]: otherColumn ]', {
|
|
65
|
-
columns: [ ' my column ', ' otherColumn ' ],
|
|
66
|
-
sections: [ 'this row' ]
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
t.isSREqual('[[#Data], [my column]:otherColumn]', {
|
|
70
|
-
columns: [ 'my column', 'otherColumn' ],
|
|
71
|
-
sections: [ 'data' ]
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
t.isSREqual('[ [#Data], [my column]:[\'@foo] ]', {
|
|
75
|
-
columns: [ 'my column', '@foo' ],
|
|
76
|
-
sections: [ 'data' ]
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
t.isSREqual('workbook.xlsx!tableName[ [#Data], [my column]:[\'@foo] ]', {
|
|
80
|
-
columns: [ 'my column', '@foo' ],
|
|
81
|
-
sections: [ 'data' ],
|
|
82
|
-
table: 'tableName',
|
|
83
|
-
context: [ 'workbook.xlsx' ]
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
t.isSREqual('[[#Data],[#data],[#Data],[#Data],[#Totals],[#Totals],[#Totals],foo]', {
|
|
87
|
-
columns: [ 'foo' ],
|
|
88
|
-
sections: [ 'data', 'totals' ]
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
t.isSREqual("'Sheet'!Table[Column]", {
|
|
92
|
-
columns: [ 'Column' ],
|
|
93
|
-
table: 'Table',
|
|
94
|
-
context: [ 'Sheet' ]
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
t.isSREqual("Sheet1!Table1[foo '[bar']]", {
|
|
98
|
-
columns: [ 'foo [bar]' ],
|
|
99
|
-
table: 'Table1',
|
|
100
|
-
context: [ 'Sheet1' ]
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
t.isSREqual('[myworkbook.xlsx]Sheet1!TMP8w0habhr[#All]', {
|
|
104
|
-
columns: [],
|
|
105
|
-
table: 'TMP8w0habhr',
|
|
106
|
-
context: [ 'myworkbook.xlsx', 'Sheet1' ],
|
|
107
|
-
sections: [ 'all' ]
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
t.end();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('structured references parse in xlsx mode', t => {
|
|
114
|
-
t.isSREqual('[Workbook.xlsx]!Table[#Data]', {
|
|
115
|
-
workbookName: 'Workbook.xlsx',
|
|
116
|
-
table: 'Table',
|
|
117
|
-
sections: [ 'data' ]
|
|
118
|
-
}, { xlsx: true });
|
|
119
|
-
|
|
120
|
-
t.isSREqual('[Workbook.xlsx]Sheet1!Table[#Data]', {
|
|
121
|
-
workbookName: 'Workbook.xlsx',
|
|
122
|
-
sheetName: 'Sheet1',
|
|
123
|
-
table: 'Table',
|
|
124
|
-
sections: [ 'data' ]
|
|
125
|
-
}, { xlsx: true });
|
|
126
|
-
|
|
127
|
-
t.isSREqual('Sheet1!Table[#Data]', {
|
|
128
|
-
sheetName: 'Sheet1',
|
|
129
|
-
table: 'Table',
|
|
130
|
-
sections: [ 'data' ]
|
|
131
|
-
}, { xlsx: true });
|
|
132
|
-
|
|
133
|
-
t.end();
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('longform prase (in xlsx mode)', t => {
|
|
137
|
-
// thisRow should have no effect when parsing
|
|
138
|
-
t.isSREqual('Table2[[#This Row],[col1]]', {
|
|
139
|
-
table: 'Table2',
|
|
140
|
-
columns: [ 'col1' ],
|
|
141
|
-
sections: [ 'this row' ]
|
|
142
|
-
}, { xlsx: true, thisRow: true });
|
|
143
|
-
|
|
144
|
-
t.isSREqual('Table2[[#This Row],[col1]]', {
|
|
145
|
-
table: 'Table2',
|
|
146
|
-
columns: [ 'col1' ],
|
|
147
|
-
sections: [ 'this row' ]
|
|
148
|
-
}, { xlsx: true, thisRow: false });
|
|
149
|
-
|
|
150
|
-
t.isSREqual('Table2[[#This Row],[col1]]', {
|
|
151
|
-
table: 'Table2',
|
|
152
|
-
columns: [ 'col1' ],
|
|
153
|
-
sections: [ 'this row' ]
|
|
154
|
-
}, { xlsx: false, thisRow: true });
|
|
155
|
-
|
|
156
|
-
t.isSREqual('Table2[[#This Row],[col1]]', {
|
|
157
|
-
table: 'Table2',
|
|
158
|
-
columns: [ 'col1' ],
|
|
159
|
-
sections: [ 'this row' ]
|
|
160
|
-
}, { xlsx: false, thisRow: false });
|
|
161
|
-
|
|
162
|
-
t.end();
|
|
163
|
-
});
|
|
164
|
-
|