@samuelbines/nunjucks 0.0.3 → 0.0.5

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.
@@ -1,208 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- const vitest_1 = require("vitest");
37
- const interpreter_1 = require("../src/interpreter");
38
- const Runtime = __importStar(require("../src/runtime"));
39
- const environment_1 = require("../src/environment");
40
- const loader_1 = require("../src/loader");
41
- const nodes_1 = require("../src/nodes");
42
- const parser_1 = require("../src/parser"); // whatever your parse entry is
43
- const transformer_1 = require("../src/transformer");
44
- function makeEnv() {
45
- const env = new environment_1.Environment({
46
- autoescape: true,
47
- throwOnUndefined: false,
48
- });
49
- // add a couple baseline filters
50
- env.addFilter?.('upper', (s) => String(s).toUpperCase());
51
- env.addFilter?.('join', (arr, sep = ',') => (arr ?? []).join(sep));
52
- return env;
53
- }
54
- async function renderString(src, ctx = {}, env = makeEnv()) {
55
- const ast = (0, transformer_1.transform)((0, parser_1.parse)(src, [], env), []); // adjust args to your parse/transform signatures
56
- return (0, interpreter_1.renderAST)(env, ast, ctx, Runtime);
57
- }
58
- (0, vitest_1.describe)('renderAST (manual AST)', () => {
59
- (0, vitest_1.it)('renders template data', async () => {
60
- const env = new environment_1.Environment();
61
- const ast = new nodes_1.Root(0, 0);
62
- ast.children = [new nodes_1.Output(0, 0, [new nodes_1.TemplateData(0, 0, 'hello')])];
63
- const out = await (0, interpreter_1.renderAST)(env, ast, {}, Runtime);
64
- (0, vitest_1.expect)(out).toBe('hello');
65
- });
66
- (0, vitest_1.it)('renders a variable lookup', async () => {
67
- const env = new environment_1.Environment();
68
- const ast = new nodes_1.Root(0, 0);
69
- ast.children = [new nodes_1.Output(0, 0, [new nodes_1.Symbol(0, 0, 'name')])];
70
- const out = await (0, interpreter_1.renderAST)(env, ast, { name: 'Sam' }, Runtime);
71
- (0, vitest_1.expect)(out).toBe('Sam');
72
- });
73
- (0, vitest_1.it)('renders an expression', async () => {
74
- const env = new environment_1.Environment();
75
- const ast = new nodes_1.Root(0, 0);
76
- ast.children = [
77
- new nodes_1.Output(0, 0, [
78
- new nodes_1.Add(0, 0, new nodes_1.Literal(0, 0, 1), new nodes_1.Literal(0, 0, 2)),
79
- ]),
80
- ];
81
- const out = await (0, interpreter_1.renderAST)(env, ast, {}, Runtime);
82
- (0, vitest_1.expect)(out).toBe('3');
83
- });
84
- });
85
- (0, vitest_1.describe)('renderString', () => {
86
- (0, vitest_1.it)('renders interpolation', async () => {
87
- const out = await renderString('Hello {{ name }}', { name: 'Sam' });
88
- (0, vitest_1.expect)(out).toBe('Hello Sam');
89
- });
90
- (0, vitest_1.it)('renders if', async () => {
91
- const out = await renderString('{% if ok %}YES{% else %}NO{% endif %}', {
92
- ok: true,
93
- });
94
- (0, vitest_1.expect)(out).toBe('YES');
95
- });
96
- (0, vitest_1.it)('renders for over array', async () => {
97
- const out = await renderString('{% for x in xs %}{{ x }}{% endfor %}', {
98
- xs: [1, 2, 3],
99
- });
100
- (0, vitest_1.expect)(out).toBe('123');
101
- });
102
- (0, vitest_1.it)('renders for over dict', async () => {
103
- const out = await renderString('{% for k,v in obj %}{{k}}={{v}};{% endfor %}', { obj: { a: 1, b: 2 } });
104
- // order not guaranteed
105
- (0, vitest_1.expect)(out === 'a=1;b=2;' || out === 'b=2;a=1;').toBe(true);
106
- });
107
- });
108
- (0, vitest_1.describe)('Basic helpers', () => {
109
- (0, vitest_1.it)('renders a variable', async () => {
110
- const out = await renderString('Hello {{ name }}', { name: 'Sam' });
111
- (0, vitest_1.expect)(out).toBe('Hello Sam');
112
- });
113
- (0, vitest_1.it)('autoescapes by default', async () => {
114
- const out = await renderString('{{ x }}', { x: '<strong>hi</strong>' });
115
- (0, vitest_1.expect)(out).toBe('&lt;strong&gt;hi&lt;/strong&gt;');
116
- });
117
- (0, vitest_1.it)('supports arithmetic', async () => {
118
- const out = await renderString('{{ 2 + 3 * 4 }}');
119
- (0, vitest_1.expect)(out).toBe('14');
120
- });
121
- (0, vitest_1.it)('supports concat', async () => {
122
- const out = await renderString("{{ 'a' ~ 1 ~ 'b' }}");
123
- (0, vitest_1.expect)(out).toBe('a1b');
124
- });
125
- (0, vitest_1.it)('supports member lookup', async () => {
126
- const out = await renderString('{{ user.name }}', {
127
- user: { name: 'James' },
128
- });
129
- (0, vitest_1.expect)(out).toBe('James');
130
- });
131
- (0, vitest_1.it)('supports dynamic member lookup', async () => {
132
- const out = await renderString('{{ user[key] }}', {
133
- user: { a: 1 },
134
- key: 'a',
135
- });
136
- (0, vitest_1.expect)(out).toBe('1');
137
- });
138
- (0, vitest_1.it)('runs filters', async () => {
139
- const out = await renderString('{{ name | upper }}', { name: 'sam' });
140
- (0, vitest_1.expect)(out).toBe('SAM');
141
- });
142
- (0, vitest_1.it)('passes filter args', async () => {
143
- const out = await renderString("{{ xs | join(';') }}", { xs: [1, 2, 3] });
144
- (0, vitest_1.expect)(out).toBe('1;2;3');
145
- });
146
- (0, vitest_1.it)('supports if/else', async () => {
147
- const out = await renderString('{% if ok %}YES{% else %}NO{% endif %}', {
148
- ok: true,
149
- });
150
- (0, vitest_1.expect)(out).toBe('YES');
151
- });
152
- (0, vitest_1.it)('supports inline if', async () => {
153
- const out = await renderString("{{ ok ? 'Y' : 'N' }}", { ok: false });
154
- (0, vitest_1.expect)(out).toBe('N');
155
- });
156
- (0, vitest_1.it)('loops arrays', async () => {
157
- const out = await renderString('{% for x in xs %}{{ x }}{% endfor %}', {
158
- xs: [1, 2, 3],
159
- });
160
- (0, vitest_1.expect)(out).toBe('123');
161
- });
162
- (0, vitest_1.it)('for-else triggers on empty', async () => {
163
- const out = await renderString('{% for x in xs %}X{% else %}EMPTY{% endfor %}', { xs: [] });
164
- (0, vitest_1.expect)(out).toBe('EMPTY');
165
- });
166
- (0, vitest_1.it)('set assigns variables', async () => {
167
- const out = await renderString('{% set a = 5 %}{{ a }}');
168
- (0, vitest_1.expect)(out).toBe('5');
169
- });
170
- (0, vitest_1.it)('set capture assigns rendered string', async () => {
171
- const out = await renderString('{% set x %}hi {{ name }}{% endset %}{{ x }}', { name: 'Sam' });
172
- (0, vitest_1.expect)(out).toBe('hi Sam');
173
- });
174
- (0, vitest_1.it)('callExtension outputs content', async () => {
175
- const env = makeEnv();
176
- env.addExtension?.('testExt', {
177
- shout(_ctx, s) {
178
- return String(s).toUpperCase() + '!';
179
- },
180
- });
181
- const out = await renderString("{% call testExt.shout('hi') %}{% endcall %}", {}, env);
182
- (0, vitest_1.expect)(out).toContain('HI!');
183
- });
184
- (0, vitest_1.it)('include works', async () => {
185
- const env = new environment_1.Environment({
186
- loaders: [
187
- new loader_1.MemoryLoader({
188
- 'a.html': "A{% include 'b.html' %}C",
189
- 'b.html': 'B',
190
- }),
191
- ],
192
- });
193
- const out = (await env.render?.('a.html', {})) ?? ''; // or your env.getTemplate+render
194
- (0, vitest_1.expect)(out).toBe('ABC');
195
- });
196
- (0, vitest_1.it)('extends + blocks override', async () => {
197
- const env = new environment_1.Environment({
198
- loaders: [
199
- new loader_1.MemoryLoader({
200
- 'base.html': 'X{% block content %}BASE{% endblock %}Y',
201
- 'child.html': "{% extends 'base.html' %}{% block content %}CHILD{% endblock %}",
202
- }),
203
- ],
204
- });
205
- const out = (await env.render?.('child.html', {})) ?? '';
206
- (0, vitest_1.expect)(out).toBe('XCHILDY');
207
- });
208
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,249 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const lexer_1 = require("../src/lexer");
5
- function allTokens(t) {
6
- const out = [];
7
- for (;;) {
8
- const tok = t.nextToken();
9
- if (!tok)
10
- break;
11
- out.push(tok);
12
- }
13
- return out;
14
- }
15
- (0, vitest_1.describe)('lexer basic tokenization', () => {
16
- (0, vitest_1.it)('emits DATA outside of tags', () => {
17
- const t = (0, lexer_1.lex)('hello world', {});
18
- const toks = allTokens(t);
19
- (0, vitest_1.expect)(toks).toHaveLength(1);
20
- (0, vitest_1.expect)(toks[0].type).toBe(lexer_1.TOKEN_DATA);
21
- (0, vitest_1.expect)(toks[0].value).toBe('hello world');
22
- (0, vitest_1.expect)(toks[0].lineno).toBe(0);
23
- (0, vitest_1.expect)(toks[0].colno).toBe(0);
24
- });
25
- (0, vitest_1.it)('tokenizes a variable tag start/end and symbol inside', () => {
26
- const t = (0, lexer_1.lex)('Hi {{ name }}!', {});
27
- const toks = allTokens(t);
28
- (0, vitest_1.expect)(toks.map((x) => x.type)).toEqual([
29
- lexer_1.TOKEN_DATA,
30
- lexer_1.TOKEN_VARIABLE_START,
31
- lexer_1.TOKEN_WHITESPACE,
32
- lexer_1.TOKEN_SYMBOL,
33
- lexer_1.TOKEN_WHITESPACE,
34
- lexer_1.TOKEN_VARIABLE_END,
35
- lexer_1.TOKEN_DATA,
36
- ]);
37
- (0, vitest_1.expect)(toks[0].value).toBe('Hi ');
38
- (0, vitest_1.expect)(toks[1].value).toBe(lexer_1.VARIABLE_START);
39
- (0, vitest_1.expect)(toks[3].value).toBe('name');
40
- (0, vitest_1.expect)(toks[5].value).toBe(lexer_1.VARIABLE_END);
41
- (0, vitest_1.expect)(toks[6].value).toBe('!');
42
- });
43
- (0, vitest_1.it)('tokenizes a block tag start/end and symbols inside', () => {
44
- const t = (0, lexer_1.lex)('{% if ok %}YES{% endif %}', {});
45
- const toks = allTokens(t);
46
- (0, vitest_1.expect)(toks.map((x) => x.type)).toEqual([
47
- lexer_1.TOKEN_BLOCK_START,
48
- lexer_1.TOKEN_WHITESPACE,
49
- lexer_1.TOKEN_SYMBOL,
50
- lexer_1.TOKEN_WHITESPACE,
51
- lexer_1.TOKEN_SYMBOL,
52
- lexer_1.TOKEN_WHITESPACE,
53
- lexer_1.TOKEN_BLOCK_END,
54
- lexer_1.TOKEN_DATA,
55
- lexer_1.TOKEN_BLOCK_START,
56
- lexer_1.TOKEN_WHITESPACE,
57
- lexer_1.TOKEN_SYMBOL,
58
- lexer_1.TOKEN_WHITESPACE,
59
- lexer_1.TOKEN_BLOCK_END,
60
- ]);
61
- (0, vitest_1.expect)(toks[0].value).toBe(lexer_1.BLOCK_START);
62
- (0, vitest_1.expect)(toks[6].value).toBe(lexer_1.BLOCK_END);
63
- (0, vitest_1.expect)(toks[7].value).toBe('YES');
64
- });
65
- (0, vitest_1.it)('tokenizes comments as TOKEN_COMMENT and does not enter code', () => {
66
- const t = (0, lexer_1.lex)('a{# hi #}b', {});
67
- const toks = allTokens(t);
68
- (0, vitest_1.expect)(toks.map((x) => x.type)).toEqual([
69
- lexer_1.TOKEN_DATA,
70
- lexer_1.TOKEN_COMMENT,
71
- lexer_1.TOKEN_DATA,
72
- ]);
73
- (0, vitest_1.expect)(toks[0].value).toBe('a');
74
- (0, vitest_1.expect)(toks[1].value).toBe(lexer_1.COMMENT_START + ' hi ' + lexer_1.COMMENT_END);
75
- (0, vitest_1.expect)(toks[2].value).toBe('b');
76
- });
77
- (0, vitest_1.it)('throws on unexpected end of comment', () => {
78
- const t = (0, lexer_1.lex)('a{# no end', {});
79
- (0, vitest_1.expect)(() => allTokens(t)).toThrow(/expected end of comment/i);
80
- });
81
- (0, vitest_1.it)('throws on unexpected end-of-comment when not in comment', () => {
82
- const t = (0, lexer_1.lex)('oops #}', {});
83
- (0, vitest_1.expect)(() => allTokens(t)).toThrow(/unexpected end of comment/i);
84
- });
85
- });
86
- (0, vitest_1.describe)('lexer: strings + escapes in code', () => {
87
- (0, vitest_1.it)('parses double-quoted strings with escapes', () => {
88
- const t = (0, lexer_1.lex)('{{ "a\\n\\t\\r\\\\b" }}', {});
89
- const toks = allTokens(t);
90
- const strTok = toks.find((x) => x.type === lexer_1.TOKEN_STRING);
91
- (0, vitest_1.expect)(strTok.value).toBe('a\n\t\r\\b');
92
- });
93
- (0, vitest_1.it)('parses single-quoted strings with escapes', () => {
94
- const t = (0, lexer_1.lex)("{{ 'x\\nY' }}", {});
95
- const toks = allTokens(t);
96
- const strTok = toks.find((x) => x.type === lexer_1.TOKEN_STRING);
97
- (0, vitest_1.expect)(strTok.value).toBe('x\nY');
98
- });
99
- });
100
- (0, vitest_1.describe)('lexer: numbers, booleans, none/null', () => {
101
- (0, vitest_1.it)('parses ints and floats', () => {
102
- const t = (0, lexer_1.lex)('{{ 10 3.14 -2 +7 }}', {});
103
- const toks = allTokens(t);
104
- const typesAndVals = toks
105
- .filter((x) => [lexer_1.TOKEN_INT, lexer_1.TOKEN_FLOAT].includes(x.type))
106
- .map((x) => [x.type, x.value]);
107
- (0, vitest_1.expect)(typesAndVals).toEqual([
108
- [lexer_1.TOKEN_INT, '10'],
109
- [lexer_1.TOKEN_FLOAT, '3.14'],
110
- [lexer_1.TOKEN_INT, '-2'],
111
- [lexer_1.TOKEN_INT, '+7'],
112
- ]);
113
- });
114
- (0, vitest_1.it)('parses booleans', () => {
115
- const t = (0, lexer_1.lex)('{{ true false }}', {});
116
- const toks = allTokens(t);
117
- const bools = toks
118
- .filter((x) => x.type === lexer_1.TOKEN_BOOLEAN)
119
- .map((x) => x.value);
120
- (0, vitest_1.expect)(bools).toEqual(['true', 'false']);
121
- });
122
- (0, vitest_1.it)('parses none and null as TOKEN_NONE', () => {
123
- const t = (0, lexer_1.lex)('{{ none null }}', {});
124
- const toks = allTokens(t);
125
- const nones = toks.filter((x) => x.type === lexer_1.TOKEN_NONE).map((x) => x.value);
126
- (0, vitest_1.expect)(nones).toEqual(['none', 'null']);
127
- });
128
- });
129
- (0, vitest_1.describe)('lexer: delimiters/operators', () => {
130
- (0, vitest_1.it)('parses parens/brackets/braces, comma, colon, tilde, pipe', () => {
131
- const t = (0, lexer_1.lex)('{{ (a)[b]{c},:~| }}', {});
132
- const toks = allTokens(t);
133
- // extract only delimiter/operator-ish tokens (ignore whitespace + start/end)
134
- const filtered = toks
135
- .filter((x) => ![
136
- lexer_1.TOKEN_VARIABLE_START,
137
- lexer_1.TOKEN_VARIABLE_END,
138
- lexer_1.TOKEN_WHITESPACE,
139
- lexer_1.TOKEN_SYMBOL,
140
- ].includes(x.type))
141
- .map((x) => [x.type, x.value]);
142
- (0, vitest_1.expect)(filtered).toEqual([
143
- [lexer_1.TOKEN_LEFT_PAREN, '('],
144
- [lexer_1.TOKEN_RIGHT_PAREN, ')'],
145
- [lexer_1.TOKEN_LEFT_BRACKET, '['],
146
- [lexer_1.TOKEN_RIGHT_BRACKET, ']'],
147
- [lexer_1.TOKEN_LEFT_CURLY, '{'],
148
- [lexer_1.TOKEN_RIGHT_CURLY, '}'],
149
- [lexer_1.TOKEN_COMMA, ','],
150
- [lexer_1.TOKEN_COLON, ':'],
151
- [lexer_1.TOKEN_TILDE, '~'],
152
- [lexer_1.TOKEN_PIPE, '|'],
153
- ]);
154
- });
155
- (0, vitest_1.it)('parses operators as TOKEN_OPERATOR', () => {
156
- const t = (0, lexer_1.lex)('{{ a + b * c - d / e }}', {});
157
- const toks = allTokens(t);
158
- const ops = toks
159
- .filter((x) => x.type === lexer_1.TOKEN_OPERATOR)
160
- .map((x) => x.value);
161
- // at least these should appear; exact set depends on spacing but these are delimiters
162
- (0, vitest_1.expect)(ops).toEqual(vitest_1.expect.arrayContaining(['+', '*', '-', '/']));
163
- });
164
- });
165
- (0, vitest_1.describe)('lexer: regex literal', () => {
166
- (0, vitest_1.it)('parses regex r/.../ with flags', () => {
167
- const t = (0, lexer_1.lex)('{{ r/ab\\//gim }}', {});
168
- const toks = allTokens(t);
169
- const r = toks.find((x) => x.type === lexer_1.TOKEN_REGEX);
170
- (0, vitest_1.expect)(r).toBeTruthy();
171
- (0, vitest_1.expect)(r.value).toEqual({
172
- body: 'ab\\/',
173
- flags: 'gim',
174
- });
175
- });
176
- (0, vitest_1.it)('stops regex body at unescaped /', () => {
177
- const t = (0, lexer_1.lex)('{{ r/a\\/b/ }}', {});
178
- const toks = allTokens(t);
179
- const r = toks.find((x) => x.type === lexer_1.TOKEN_REGEX);
180
- (0, vitest_1.expect)(r.value.body).toBe('a\\/b');
181
- (0, vitest_1.expect)(r.value.flags).toBe('');
182
- });
183
- });
184
- (0, vitest_1.describe)('lexer: trimBlocks and lstripBlocks', () => {
185
- (0, vitest_1.it)('trimBlocks removes newline right after BLOCK_END', () => {
186
- const t = (0, lexer_1.lex)('{% if x %}\nhello', { trimBlocks: true });
187
- const toks = allTokens(t);
188
- // Expect: BLOCK_START ... BLOCK_END then DATA without leading newline
189
- const data = toks.find((x) => x.type === lexer_1.TOKEN_DATA)?.value;
190
- (0, vitest_1.expect)(data).toBe('hello');
191
- });
192
- (0, vitest_1.it)('trimBlocks handles CRLF right after BLOCK_END', () => {
193
- const t = (0, lexer_1.lex)('{% if x %}\r\nhello', { trimBlocks: true });
194
- const toks = allTokens(t);
195
- const data = toks.find((x) => x.type === lexer_1.TOKEN_DATA)?.value;
196
- (0, vitest_1.expect)(data).toBe('hello');
197
- });
198
- (0, vitest_1.it)('lstripBlocks strips whitespace before a block start on the same line', () => {
199
- // there is leading whitespace before the block on the same line
200
- const t = (0, lexer_1.lex)('x\n {% if y %}Z{% endif %}', { lstripBlocks: true });
201
- const toks = allTokens(t);
202
- // The DATA token should be "x\n" (no trailing spaces before the block)
203
- // Then immediately a BLOCK_START (because the whitespace was stripped away)
204
- (0, vitest_1.expect)(toks[0].type).toBe(lexer_1.TOKEN_DATA);
205
- (0, vitest_1.expect)(toks[0].value).toBe('x\n');
206
- (0, vitest_1.expect)(toks[1].type).toBe(lexer_1.TOKEN_BLOCK_START);
207
- });
208
- });
209
- (0, vitest_1.describe)('lexer: custom tag delimiters', () => {
210
- (0, vitest_1.it)('supports custom tags via opts.tags', () => {
211
- const t = (0, lexer_1.lex)('A << name >> B', {
212
- tags: {
213
- variableStart: '<<',
214
- variableEnd: '>>',
215
- },
216
- });
217
- const toks = allTokens(t);
218
- (0, vitest_1.expect)(toks.map((x) => x.type)).toEqual([
219
- lexer_1.TOKEN_DATA,
220
- lexer_1.TOKEN_VARIABLE_START,
221
- lexer_1.TOKEN_WHITESPACE,
222
- lexer_1.TOKEN_SYMBOL,
223
- lexer_1.TOKEN_WHITESPACE,
224
- lexer_1.TOKEN_VARIABLE_END,
225
- lexer_1.TOKEN_DATA,
226
- ]);
227
- (0, vitest_1.expect)(toks[1].value).toBe('<<');
228
- (0, vitest_1.expect)(toks[5].value).toBe('>>');
229
- });
230
- });
231
- (0, vitest_1.describe)('lexer: line/col tracking', () => {
232
- (0, vitest_1.it)('updates lineno/colno across newlines', () => {
233
- const t = (0, lexer_1.lex)('a\n{{ x }}\n', {});
234
- const toks = allTokens(t);
235
- const firstData = toks[0];
236
- (0, vitest_1.expect)(firstData.type).toBe(lexer_1.TOKEN_DATA);
237
- (0, vitest_1.expect)(firstData.lineno).toBe(0);
238
- (0, vitest_1.expect)(firstData.colno).toBe(0);
239
- const varStart = toks.find((x) => x.type === lexer_1.TOKEN_VARIABLE_START);
240
- // after "a\n" we are on line 1, col 0
241
- (0, vitest_1.expect)(varStart.lineno).toBe(1);
242
- (0, vitest_1.expect)(varStart.colno).toBe(0);
243
- const lastData = toks.at(-1);
244
- (0, vitest_1.expect)(lastData.type).toBe(lexer_1.TOKEN_DATA);
245
- (0, vitest_1.expect)(lastData.value).toBe('\n');
246
- // the final '\n' token should start on line 1 after the tag ends (depends on content)
247
- (0, vitest_1.expect)(lastData.lineno).toBeGreaterThanOrEqual(1);
248
- });
249
- });
@@ -1 +0,0 @@
1
- export {};