@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
@@ -1,8 +0,0 @@
1
- import { lexRangeA1 } from './lexRangeA1.js';
2
- import { lexRangeR1C1 } from './lexRangeR1C1.js';
3
-
4
- export function lexRange (str, pos, options) {
5
- return options.r1c1
6
- ? lexRangeR1C1(str, pos, options)
7
- : lexRangeA1(str, pos, options);
8
- }
@@ -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
- }
@@ -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
- });
@@ -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
-