@samuelbines/nunjucks 0.0.3 → 0.0.4
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/package.json +1 -1
- package/dist/tests/compiler.test.d.ts +0 -1
- package/dist/tests/compiler.test.js +0 -201
- package/dist/tests/enviornment.test.d.ts +0 -1
- package/dist/tests/enviornment.test.js +0 -279
- package/dist/tests/express.test.d.ts +0 -1
- package/dist/tests/express.test.js +0 -86
- package/dist/tests/filters.test.d.ts +0 -13
- package/dist/tests/filters.test.js +0 -286
- package/dist/tests/globals.test.d.ts +0 -1
- package/dist/tests/globals.test.js +0 -579
- package/dist/tests/interpreter.test.d.ts +0 -1
- package/dist/tests/interpreter.test.js +0 -208
- package/dist/tests/lexer.test.d.ts +0 -1
- package/dist/tests/lexer.test.js +0 -249
- package/dist/tests/lib.test.d.ts +0 -1
- package/dist/tests/lib.test.js +0 -236
- package/dist/tests/loader.test.d.ts +0 -1
- package/dist/tests/loader.test.js +0 -301
- package/dist/tests/nodes.test.d.ts +0 -1
- package/dist/tests/nodes.test.js +0 -137
- package/dist/tests/parser.test.d.ts +0 -1
- package/dist/tests/parser.test.js +0 -294
- package/dist/tests/precompile.test.d.ts +0 -1
- package/dist/tests/precompile.test.js +0 -224
- package/dist/tests/runtime.test.d.ts +0 -1
- package/dist/tests/runtime.test.js +0 -237
- package/dist/tests/transformer.test.d.ts +0 -1
- package/dist/tests/transformer.test.js +0 -125
package/dist/tests/nodes.test.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
// IMPORTANT: update this import path to where your nodes.ts exports live
|
|
5
|
-
const nodes_1 = require("../src/nodes");
|
|
6
|
-
(0, vitest_1.describe)('nodes: base Node init + fields normalization', () => {
|
|
7
|
-
(0, vitest_1.it)('Node.init assigns lineno/colno and maps fields from args (undefined -> null)', () => {
|
|
8
|
-
const n = new nodes_1.Pair(10, 20, 'k', undefined); // Pair.fields = ['key','value']
|
|
9
|
-
(0, vitest_1.expect)(n.lineno).toBe(10);
|
|
10
|
-
(0, vitest_1.expect)(n.colno).toBe(20);
|
|
11
|
-
(0, vitest_1.expect)(n.key).toBe('k');
|
|
12
|
-
(0, vitest_1.expect)(n.value).toBe(null); // normalized
|
|
13
|
-
(0, vitest_1.expect)(n.typename).toBe('Pair');
|
|
14
|
-
});
|
|
15
|
-
(0, vitest_1.it)('Value node sets value field', () => {
|
|
16
|
-
const v = new nodes_1.Literal(1, 2, 123);
|
|
17
|
-
(0, vitest_1.expect)(v.typename).toBe('Literal');
|
|
18
|
-
(0, vitest_1.expect)(v.value).toBe(123);
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
(0, vitest_1.describe)('nodes: NodeList behavior', () => {
|
|
22
|
-
(0, vitest_1.it)('NodeList.init stores children and addChild appends', () => {
|
|
23
|
-
const a = new nodes_1.Literal(0, 0, 'a');
|
|
24
|
-
const b = new nodes_1.Literal(0, 0, 'b');
|
|
25
|
-
const list = new nodes_1.NodeList(5, 6, [a]);
|
|
26
|
-
(0, vitest_1.expect)(list.typename).toBe('NodeList');
|
|
27
|
-
(0, vitest_1.expect)(list.children).toEqual([a]);
|
|
28
|
-
list.addChild(b);
|
|
29
|
-
(0, vitest_1.expect)(list.children).toEqual([a, b]);
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
(0, vitest_1.describe)('nodes: FromImport defaults names to NodeList', () => {
|
|
33
|
-
(0, vitest_1.it)('FromImport.init defaults names when falsy', () => {
|
|
34
|
-
const fi = new nodes_1.FromImport(1, 2, 'tmpl.njk', null, true);
|
|
35
|
-
(0, vitest_1.expect)(fi.typename).toBe('FromImport');
|
|
36
|
-
(0, vitest_1.expect)(fi.template).toBe('tmpl.njk');
|
|
37
|
-
(0, vitest_1.expect)(fi.withContext).toBe(true);
|
|
38
|
-
(0, vitest_1.expect)(fi.names).toBeInstanceOf(nodes_1.NodeList);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
(0, vitest_1.describe)('nodes: findAll traversal', () => {
|
|
42
|
-
(0, vitest_1.it)('findAll traverses fields for non-NodeList nodes', () => {
|
|
43
|
-
// If.fields = ['cond','body','else_']
|
|
44
|
-
const cond = new nodes_1.Symbol(1, 1, 'x');
|
|
45
|
-
const body = new nodes_1.Output(1, 2, [new nodes_1.Literal(1, 3, 'yes')]);
|
|
46
|
-
const elseBody = new nodes_1.Output(1, 4, [new nodes_1.Literal(1, 5, 'no')]);
|
|
47
|
-
const node = new nodes_1.If(0, 0, cond, body, elseBody);
|
|
48
|
-
const lits = node.findAll(nodes_1.Literal);
|
|
49
|
-
(0, vitest_1.expect)(lits.map((n) => n.value)).toEqual(['yes', 'no']);
|
|
50
|
-
const syms = node.findAll(nodes_1.Symbol);
|
|
51
|
-
(0, vitest_1.expect)(syms).toHaveLength(1);
|
|
52
|
-
(0, vitest_1.expect)(syms[0].value).toBe('x');
|
|
53
|
-
});
|
|
54
|
-
(0, vitest_1.it)('findAll traverses children for NodeList nodes', () => {
|
|
55
|
-
const out = new nodes_1.Output(0, 0, [
|
|
56
|
-
new nodes_1.Literal(0, 0, 'a'),
|
|
57
|
-
new nodes_1.Literal(0, 0, 'b'),
|
|
58
|
-
]);
|
|
59
|
-
const lits = out.findAll(nodes_1.Literal);
|
|
60
|
-
(0, vitest_1.expect)(lits.map((n) => n.value)).toEqual(['a', 'b']);
|
|
61
|
-
});
|
|
62
|
-
(0, vitest_1.it)('findAll returns empty when none found', () => {
|
|
63
|
-
const n = new nodes_1.Pair(0, 0, 'k', 'v');
|
|
64
|
-
(0, vitest_1.expect)(n.findAll(nodes_1.Symbol)).toEqual([]);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
(0, vitest_1.describe)('nodes: iterFields', () => {
|
|
68
|
-
(0, vitest_1.it)('iterFields iterates (value, fieldName) for each field', () => {
|
|
69
|
-
const p = new nodes_1.Pair(0, 0, 'k', 'v');
|
|
70
|
-
const seen = [];
|
|
71
|
-
p.iterFields((val, field) => {
|
|
72
|
-
seen.push([field, val]);
|
|
73
|
-
});
|
|
74
|
-
(0, vitest_1.expect)(seen).toEqual([
|
|
75
|
-
['key', 'k'],
|
|
76
|
-
['value', 'v'],
|
|
77
|
-
]);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
(0, vitest_1.describe)('nodes: extend() typename + inheritance', () => {
|
|
81
|
-
(0, vitest_1.it)('extended nodes report typename from __typename (not constructor.name)', () => {
|
|
82
|
-
const x = new nodes_1.Output(0, 0, []);
|
|
83
|
-
(0, vitest_1.expect)(x.typename).toBe('Output'); // __typename set on class definition
|
|
84
|
-
});
|
|
85
|
-
(0, vitest_1.it)('IfAsync extends If and preserves fields', () => {
|
|
86
|
-
// IfAsync = If.extend('IfAsync')
|
|
87
|
-
const cond = new nodes_1.Symbol(0, 0, 'c');
|
|
88
|
-
const body = new nodes_1.Output(0, 0, []);
|
|
89
|
-
const else_ = new nodes_1.Output(0, 0, []);
|
|
90
|
-
const n = new nodes_1.NodeCreator('IfAsync')(0, 0, cond, body, else_);
|
|
91
|
-
(0, vitest_1.expect)(n.typename).toBe('IfAsync');
|
|
92
|
-
// still has If fields assigned
|
|
93
|
-
(0, vitest_1.expect)(n.cond).toBe(cond);
|
|
94
|
-
(0, vitest_1.expect)(n.body).toBe(body);
|
|
95
|
-
(0, vitest_1.expect)(n.else_).toBe(else_);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
(0, vitest_1.describe)('nodes: CallExtension custom init uses parent + sets props', () => {
|
|
99
|
-
(0, vitest_1.it)('CallExtension.init sets extName/prop/args/contentArgs/autoescape and keeps lineno/colno', () => {
|
|
100
|
-
const ext = { __name: 'MyExt', autoescape: false };
|
|
101
|
-
const args = new nodes_1.Dict(9, 9, []);
|
|
102
|
-
const contentArgs = [new nodes_1.Output(1, 1, [new nodes_1.Literal(1, 1, 'x')])];
|
|
103
|
-
// Note: CallExtension.init signature differs: (ext, prop, args, contentArgs?)
|
|
104
|
-
const n = new nodes_1.CallExtension(3, 4, ext, 'doThing', args, contentArgs);
|
|
105
|
-
(0, vitest_1.expect)(n.typename).toBe('CallExtension');
|
|
106
|
-
(0, vitest_1.expect)(n.lineno).toBe(3);
|
|
107
|
-
(0, vitest_1.expect)(n.colno).toBe(4);
|
|
108
|
-
(0, vitest_1.expect)(n.extname).toBe('MyExt');
|
|
109
|
-
(0, vitest_1.expect)(n.prop).toBe('doThing');
|
|
110
|
-
(0, vitest_1.expect)(n.args).toBe(args);
|
|
111
|
-
(0, vitest_1.expect)(n.contentArgs).toBe(contentArgs);
|
|
112
|
-
(0, vitest_1.expect)(n.autoescape).toBe(false);
|
|
113
|
-
});
|
|
114
|
-
(0, vitest_1.it)('CallExtension defaults args to new NodeList when falsy', () => {
|
|
115
|
-
const ext = { __name: 'X', autoescape: true };
|
|
116
|
-
const n = new nodes_1.CallExtension(0, 0, ext, 'p', null, null);
|
|
117
|
-
(0, vitest_1.expect)(n.args).toBeInstanceOf(nodes_1.NodeList);
|
|
118
|
-
(0, vitest_1.expect)(n.contentArgs).toBeNull(); // because your init sets contentArgs param directly
|
|
119
|
-
});
|
|
120
|
-
(0, vitest_1.it)('CallExtensionAsync extends CallExtension', () => {
|
|
121
|
-
const ext = { __name: 'X', autoescape: true };
|
|
122
|
-
const n = new nodes_1.CallExtensionAsync(0, 0, ext, 'p', null, []);
|
|
123
|
-
(0, vitest_1.expect)(n.typename).toBe('CallExtensionAsync');
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
(0, vitest_1.describe)('NodeCreator', () => {
|
|
127
|
-
(0, vitest_1.it)('returns constructor for valid key', () => {
|
|
128
|
-
const Ctor = (0, nodes_1.NodeCreator)('Pair');
|
|
129
|
-
const p = new Ctor(1, 1, 'k', 'v');
|
|
130
|
-
(0, vitest_1.expect)(p).toBeInstanceOf(nodes_1.Pair);
|
|
131
|
-
(0, vitest_1.expect)(p.typename).toBe('Pair');
|
|
132
|
-
});
|
|
133
|
-
(0, vitest_1.it)('throws for invalid key', () => {
|
|
134
|
-
// NodeCreator throws a string in your implementation
|
|
135
|
-
(0, vitest_1.expect)(() => (0, nodes_1.NodeCreator)('Nope')).toThrow(/No node type found/i);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,294 +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
|
-
// test/parser.test.ts
|
|
37
|
-
const vitest_1 = require("vitest");
|
|
38
|
-
// IMPORTANT: update these imports to your project structure
|
|
39
|
-
const parser_1 = require("../src/parser");
|
|
40
|
-
const lexer = __importStar(require("../src/lexer"));
|
|
41
|
-
const nodes_1 = require("../src/nodes");
|
|
42
|
-
function parseRoot(src, opts = {}, extensions) {
|
|
43
|
-
return (0, parser_1.parse)(src, extensions, opts);
|
|
44
|
-
}
|
|
45
|
-
(0, vitest_1.describe)('parser.ts', () => {
|
|
46
|
-
(0, vitest_1.it)('parses plain text into Output(TemplateData)', () => {
|
|
47
|
-
const ast = parseRoot('hello');
|
|
48
|
-
(0, vitest_1.expect)(ast).toBeInstanceOf(nodes_1.Root);
|
|
49
|
-
(0, vitest_1.expect)(ast.children).toHaveLength(1);
|
|
50
|
-
const out = ast.children[0];
|
|
51
|
-
(0, vitest_1.expect)(out).toBeInstanceOf(nodes_1.Output);
|
|
52
|
-
(0, vitest_1.expect)(out.children).toHaveLength(1);
|
|
53
|
-
(0, vitest_1.expect)(out.children[0]).toBeInstanceOf(nodes_1.TemplateData);
|
|
54
|
-
(0, vitest_1.expect)(out.children[0].value).toBe('hello');
|
|
55
|
-
});
|
|
56
|
-
(0, vitest_1.it)('parses variable output: {{ 1 + 2 }}', () => {
|
|
57
|
-
const ast = parseRoot('{{ 1 + 2 }}');
|
|
58
|
-
const out = ast.children[0];
|
|
59
|
-
(0, vitest_1.expect)(out).toBeInstanceOf(nodes_1.Output);
|
|
60
|
-
(0, vitest_1.expect)(out.children[0]).toBeInstanceOf(nodes_1.Add);
|
|
61
|
-
const add = out.children[0];
|
|
62
|
-
(0, vitest_1.expect)(add.left).toBeInstanceOf(nodes_1.Literal);
|
|
63
|
-
(0, vitest_1.expect)(add.right).toBeInstanceOf(nodes_1.Literal);
|
|
64
|
-
(0, vitest_1.expect)(add.left.value).toBe(1);
|
|
65
|
-
(0, vitest_1.expect)(add.right.value).toBe(2);
|
|
66
|
-
});
|
|
67
|
-
(0, vitest_1.it)('parses filters: {{ name | title }} into Filter node with args list', () => {
|
|
68
|
-
const ast = parseRoot('{{ name | title }}');
|
|
69
|
-
const out = ast.children[0];
|
|
70
|
-
const filt = out.children[0];
|
|
71
|
-
(0, vitest_1.expect)(filt).toBeInstanceOf(nodes_1.Filter);
|
|
72
|
-
// Filter fields: ['name','args']
|
|
73
|
-
(0, vitest_1.expect)(filt.name).toBeInstanceOf(nodes_1.Symbol);
|
|
74
|
-
(0, vitest_1.expect)(filt.name.value).toBe('title');
|
|
75
|
-
const args = filt.args;
|
|
76
|
-
(0, vitest_1.expect)(args).toBeInstanceOf(nodes_1.NodeList);
|
|
77
|
-
// first arg is the piped expression (Symbol("name"))
|
|
78
|
-
(0, vitest_1.expect)(args.children[0]).toBeInstanceOf(nodes_1.Symbol);
|
|
79
|
-
(0, vitest_1.expect)(args.children[0].value).toBe('name');
|
|
80
|
-
});
|
|
81
|
-
(0, vitest_1.it)('parses filter with dotted name: {{ x | a.b.c }}', () => {
|
|
82
|
-
const ast = parseRoot('{{ x | a.b.c }}');
|
|
83
|
-
const filt = ast.children[0].children[0];
|
|
84
|
-
(0, vitest_1.expect)(filt).toBeInstanceOf(nodes_1.Filter);
|
|
85
|
-
(0, vitest_1.expect)(filt.name.value).toBe('a.b.c');
|
|
86
|
-
});
|
|
87
|
-
(0, vitest_1.it)('parses filter statement block: {% filter title %}Hi{% endfilter %}', () => {
|
|
88
|
-
const ast = parseRoot('{% filter title %}Hi{% endfilter %}');
|
|
89
|
-
(0, vitest_1.expect)(ast.children).toHaveLength(1);
|
|
90
|
-
const out = ast.children[0];
|
|
91
|
-
(0, vitest_1.expect)(out).toBeInstanceOf(nodes_1.Output);
|
|
92
|
-
const node = out.children[0];
|
|
93
|
-
(0, vitest_1.expect)(node).toBeInstanceOf(nodes_1.Filter);
|
|
94
|
-
const name = node.name;
|
|
95
|
-
(0, vitest_1.expect)(name).toBeInstanceOf(nodes_1.Symbol);
|
|
96
|
-
(0, vitest_1.expect)(name.value).toBe('title');
|
|
97
|
-
const args = node.args;
|
|
98
|
-
(0, vitest_1.expect)(args).toBeInstanceOf(nodes_1.NodeList);
|
|
99
|
-
// First arg is a Capture node containing the filtered body
|
|
100
|
-
const cap = args.children[0];
|
|
101
|
-
(0, vitest_1.expect)(cap).toBeInstanceOf(nodes_1.Capture);
|
|
102
|
-
const capBody = cap.body;
|
|
103
|
-
(0, vitest_1.expect)(capBody).toBeInstanceOf(nodes_1.NodeList);
|
|
104
|
-
(0, vitest_1.expect)(capBody.children[0]).toBeInstanceOf(nodes_1.Output);
|
|
105
|
-
(0, vitest_1.expect)(capBody.children[0].children[0]).toBeInstanceOf(nodes_1.TemplateData);
|
|
106
|
-
(0, vitest_1.expect)(capBody.children[0].children[0].value).toBe('Hi');
|
|
107
|
-
});
|
|
108
|
-
(0, vitest_1.it)('parses for-loop: {% for x in arr %}X{% endfor %}', () => {
|
|
109
|
-
const ast = parseRoot('{% for x in arr %}X{% endfor %}');
|
|
110
|
-
(0, vitest_1.expect)(ast.children).toHaveLength(1);
|
|
111
|
-
const n = ast.children[0];
|
|
112
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.For);
|
|
113
|
-
(0, vitest_1.expect)(n.name).toBeInstanceOf(nodes_1.Symbol);
|
|
114
|
-
(0, vitest_1.expect)(n.name.value).toBe('x');
|
|
115
|
-
(0, vitest_1.expect)(n.arr).toBeInstanceOf(nodes_1.Symbol);
|
|
116
|
-
(0, vitest_1.expect)(n.arr.value).toBe('arr');
|
|
117
|
-
const body = n.body;
|
|
118
|
-
(0, vitest_1.expect)(body).toBeInstanceOf(nodes_1.NodeList);
|
|
119
|
-
(0, vitest_1.expect)(body.children[0]).toBeInstanceOf(nodes_1.Output);
|
|
120
|
-
(0, vitest_1.expect)(body.children[0].children[0]).toBeInstanceOf(nodes_1.TemplateData);
|
|
121
|
-
(0, vitest_1.expect)(body.children[0].children[0].value).toBe('X');
|
|
122
|
-
});
|
|
123
|
-
(0, vitest_1.it)('parses for-loop with else: {% for x in arr %}A{% else %}B{% endfor %}', () => {
|
|
124
|
-
const ast = parseRoot('{% for x in arr %}A{% else %}B{% endfor %}');
|
|
125
|
-
const n = ast.children[0];
|
|
126
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.For);
|
|
127
|
-
const body = n.body;
|
|
128
|
-
const else_ = n.else_;
|
|
129
|
-
(0, vitest_1.expect)(body.children[0].children[0].value).toBe('A');
|
|
130
|
-
(0, vitest_1.expect)(else_.children[0].children[0].value).toBe('B');
|
|
131
|
-
});
|
|
132
|
-
(0, vitest_1.it)('parses if/elif/else nesting', () => {
|
|
133
|
-
const ast = parseRoot('{% if a %}A{% elif b %}B{% else %}C{% endif %}');
|
|
134
|
-
const n = ast.children[0];
|
|
135
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.If);
|
|
136
|
-
(0, vitest_1.expect)(n.cond).toBeInstanceOf(nodes_1.Symbol);
|
|
137
|
-
(0, vitest_1.expect)(n.cond.value).toBe('a');
|
|
138
|
-
// elif becomes else_ which is another If node
|
|
139
|
-
const elifNode = n.else_;
|
|
140
|
-
(0, vitest_1.expect)(elifNode).toBeInstanceOf(nodes_1.If);
|
|
141
|
-
(0, vitest_1.expect)(elifNode.cond.value).toBe('b');
|
|
142
|
-
// elif's else_ is the else body NodeList
|
|
143
|
-
const elseBody = elifNode.else_;
|
|
144
|
-
(0, vitest_1.expect)(elseBody).toBeInstanceOf(nodes_1.NodeList);
|
|
145
|
-
(0, vitest_1.expect)(elseBody.children[0].children[0].value).toBe('C');
|
|
146
|
-
});
|
|
147
|
-
(0, vitest_1.it)('parses include with ignore missing', () => {
|
|
148
|
-
const ast = parseRoot('{% include "a.njk" ignore missing %}');
|
|
149
|
-
const n = ast.children[0];
|
|
150
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.Include);
|
|
151
|
-
(0, vitest_1.expect)(n.template).toBeInstanceOf(nodes_1.Literal);
|
|
152
|
-
(0, vitest_1.expect)(n.template.value).toBe('a.njk');
|
|
153
|
-
(0, vitest_1.expect)(n.ignoreMissing).toBe(true);
|
|
154
|
-
});
|
|
155
|
-
(0, vitest_1.it)('parses extends', () => {
|
|
156
|
-
const ast = parseRoot('{% extends "base.njk" %}');
|
|
157
|
-
const n = ast.children[0];
|
|
158
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.Extends);
|
|
159
|
-
(0, vitest_1.expect)(n.template.value).toBe('base.njk');
|
|
160
|
-
});
|
|
161
|
-
(0, vitest_1.it)('parses set assignment: {% set x = 3 %}', () => {
|
|
162
|
-
const ast = parseRoot('{% set x = 3 %}');
|
|
163
|
-
const n = ast.children[0];
|
|
164
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.Set);
|
|
165
|
-
(0, vitest_1.expect)(n.targets).toHaveLength(1);
|
|
166
|
-
(0, vitest_1.expect)(n.targets[0]).toBeInstanceOf(nodes_1.Symbol);
|
|
167
|
-
(0, vitest_1.expect)(n.targets[0].value).toBe('x');
|
|
168
|
-
(0, vitest_1.expect)(n.value).toBeInstanceOf(nodes_1.Literal);
|
|
169
|
-
(0, vitest_1.expect)(n.value.value).toBe(3);
|
|
170
|
-
});
|
|
171
|
-
(0, vitest_1.it)('parses set capture form: {% set x %}Hi{% endset %}', () => {
|
|
172
|
-
const ast = parseRoot('{% set x %}Hi{% endset %}');
|
|
173
|
-
const n = ast.children[0];
|
|
174
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.Set);
|
|
175
|
-
(0, vitest_1.expect)(n.targets[0].value).toBe('x');
|
|
176
|
-
(0, vitest_1.expect)(n.value).toBeNull();
|
|
177
|
-
(0, vitest_1.expect)(n.body).toBeInstanceOf(nodes_1.Capture);
|
|
178
|
-
const capBody = n.body.body;
|
|
179
|
-
(0, vitest_1.expect)(capBody.children[0].children[0].value).toBe('Hi');
|
|
180
|
-
});
|
|
181
|
-
(0, vitest_1.it)('parses macro and its signature: {% macro m(a, b=2) %}X{% endmacro %}', () => {
|
|
182
|
-
const ast = parseRoot('{% macro m(a, b=2) %}X{% endmacro %}');
|
|
183
|
-
const n = ast.children[0];
|
|
184
|
-
(0, vitest_1.expect)(n).toBeInstanceOf(nodes_1.Macro);
|
|
185
|
-
// name is a Symbol
|
|
186
|
-
(0, vitest_1.expect)(n.name).toBeInstanceOf(nodes_1.Symbol);
|
|
187
|
-
(0, vitest_1.expect)(n.name.value).toBe('m');
|
|
188
|
-
// args is NodeList, last element KeywordArgs for b=2
|
|
189
|
-
const args = n.args;
|
|
190
|
-
(0, vitest_1.expect)(args).toBeInstanceOf(nodes_1.NodeList);
|
|
191
|
-
(0, vitest_1.expect)(args.children[0]).toBeInstanceOf(nodes_1.Symbol);
|
|
192
|
-
(0, vitest_1.expect)(args.children[0].value).toBe('a');
|
|
193
|
-
const last = args.children[args.children.length - 1];
|
|
194
|
-
(0, vitest_1.expect)(last).toBeInstanceOf(nodes_1.KeywordArgs);
|
|
195
|
-
(0, vitest_1.expect)(last.children[0]).toBeInstanceOf(nodes_1.Pair);
|
|
196
|
-
(0, vitest_1.expect)(last.children[0].key.value).toBe('b');
|
|
197
|
-
(0, vitest_1.expect)(last.children[0].value.value).toBe(2);
|
|
198
|
-
// body contains TemplateData("X")
|
|
199
|
-
(0, vitest_1.expect)(n.body.children[0].children[0].value).toBe('X');
|
|
200
|
-
});
|
|
201
|
-
(0, vitest_1.it)('parses call block into Output(FunCall) with caller kwarg', () => {
|
|
202
|
-
const src = '{% call(x) foo(1) %}Body{% endcall %}';
|
|
203
|
-
const ast = parseRoot(src);
|
|
204
|
-
const out = ast.children[0];
|
|
205
|
-
(0, vitest_1.expect)(out).toBeInstanceOf(nodes_1.Output);
|
|
206
|
-
const fun = out.children[0];
|
|
207
|
-
(0, vitest_1.expect)(fun).toBeInstanceOf(nodes_1.FunCall);
|
|
208
|
-
const args = fun.args.children;
|
|
209
|
-
// last arg becomes KeywordArgs with caller Pair injected
|
|
210
|
-
const last = args[args.length - 1];
|
|
211
|
-
(0, vitest_1.expect)(last).toBeInstanceOf(nodes_1.KeywordArgs);
|
|
212
|
-
const pair = last.children.find((p) => p.key?.value === 'caller');
|
|
213
|
-
(0, vitest_1.expect)(pair).toBeTruthy();
|
|
214
|
-
(0, vitest_1.expect)(pair.value).toBeInstanceOf(nodes_1.Caller);
|
|
215
|
-
// callerNode.body should contain "Body"
|
|
216
|
-
const callerBody = pair.value.body;
|
|
217
|
-
(0, vitest_1.expect)(callerBody.children[0].children[0].value).toBe('Body');
|
|
218
|
-
});
|
|
219
|
-
(0, vitest_1.it)('parses aggregates: (1,2), [1,2], {a:1}', () => {
|
|
220
|
-
const ast1 = parseRoot('{{ (1, 2) }}');
|
|
221
|
-
(0, vitest_1.expect)(ast1.children[0].children[0]).toBeInstanceOf(nodes_1.Group);
|
|
222
|
-
(0, vitest_1.expect)(ast1.children[0].children[0].children).toHaveLength(2);
|
|
223
|
-
const ast2 = parseRoot('{{ [1, 2] }}');
|
|
224
|
-
(0, vitest_1.expect)(ast2.children[0].children[0]).toBeInstanceOf(nodes_1.ArrayNode);
|
|
225
|
-
(0, vitest_1.expect)(ast2.children[0].children[0].children).toHaveLength(2);
|
|
226
|
-
const ast3 = parseRoot('{{ {"a": 1} }}');
|
|
227
|
-
(0, vitest_1.expect)(ast3.children[0].children[0]).toBeInstanceOf(nodes_1.Dict);
|
|
228
|
-
const dictChildren = ast3.children[0].children[0].children;
|
|
229
|
-
(0, vitest_1.expect)(dictChildren).toHaveLength(1);
|
|
230
|
-
(0, vitest_1.expect)(dictChildren[0]).toBeInstanceOf(nodes_1.Pair);
|
|
231
|
-
(0, vitest_1.expect)(dictChildren[0].key.value).toBe('a');
|
|
232
|
-
(0, vitest_1.expect)(dictChildren[0].value.value).toBe(1);
|
|
233
|
-
});
|
|
234
|
-
(0, vitest_1.it)('parsePostfix: foo(1).bar[0]', () => {
|
|
235
|
-
const ast = parseRoot('{{ foo(1).bar[0] }}');
|
|
236
|
-
const expr = ast.children[0].children[0];
|
|
237
|
-
// should end up as LookupVal(LookupVal(FunCall(Symbol(foo), [1]), Literal("bar")), Literal(0))
|
|
238
|
-
(0, vitest_1.expect)(expr).toBeInstanceOf(nodes_1.LookupVal);
|
|
239
|
-
const outer = expr;
|
|
240
|
-
(0, vitest_1.expect)(outer.val).toBeInstanceOf(nodes_1.Literal);
|
|
241
|
-
(0, vitest_1.expect)(outer.val.value).toBe(0);
|
|
242
|
-
(0, vitest_1.expect)(outer.target).toBeInstanceOf(nodes_1.LookupVal);
|
|
243
|
-
const inner = outer.target;
|
|
244
|
-
(0, vitest_1.expect)(inner.val).toBeInstanceOf(nodes_1.Literal);
|
|
245
|
-
(0, vitest_1.expect)(inner.val.value).toBe('bar');
|
|
246
|
-
(0, vitest_1.expect)(inner.target).toBeInstanceOf(nodes_1.FunCall);
|
|
247
|
-
(0, vitest_1.expect)(inner.target.name).toBeInstanceOf(nodes_1.Symbol);
|
|
248
|
-
(0, vitest_1.expect)(inner.target.name.value).toBe('foo');
|
|
249
|
-
});
|
|
250
|
-
(0, vitest_1.it)('whitespace control: {%- ... -%} trims adjacent data', () => {
|
|
251
|
-
const ast = parseRoot('A {%- if x -%}\n B \n{%- endif -%} C', {
|
|
252
|
-
trimBlocks: true,
|
|
253
|
-
lstripBlocks: true,
|
|
254
|
-
});
|
|
255
|
-
// Expect the outer text nodes to be trimmed around the control blocks.
|
|
256
|
-
// This is intentionally "loose" because exact whitespace behavior depends on lexer opts.
|
|
257
|
-
const templateData = ast
|
|
258
|
-
.findAll(nodes_1.TemplateData)
|
|
259
|
-
.map((n) => n.value);
|
|
260
|
-
(0, vitest_1.expect)(templateData.join('')).toContain('A');
|
|
261
|
-
(0, vitest_1.expect)(templateData.join('')).toContain('B');
|
|
262
|
-
(0, vitest_1.expect)(templateData.join('')).toContain('C');
|
|
263
|
-
// Ensure we did not keep leading newline after -%} when trimBlocks enabled
|
|
264
|
-
// (again, loose check)
|
|
265
|
-
(0, vitest_1.expect)(templateData.join('')).not.toContain('\n B \n');
|
|
266
|
-
});
|
|
267
|
-
(0, vitest_1.it)('extensions: unknown tag handled by extension.parse', () => {
|
|
268
|
-
const ext = {
|
|
269
|
-
tags: ['hello'],
|
|
270
|
-
parse(p, ns, lx) {
|
|
271
|
-
// consume tag name, then advance past block end
|
|
272
|
-
p.nextToken(); // symbol "hello"
|
|
273
|
-
p.advanceAfterBlockEnd('hello');
|
|
274
|
-
return new ns.Output(0, 0, [new ns.TemplateData(0, 0, 'EXT')]);
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
const ast = parseRoot('{% hello %}', {}, [ext]);
|
|
278
|
-
(0, vitest_1.expect)(ast.children[0]).toBeInstanceOf(nodes_1.Output);
|
|
279
|
-
(0, vitest_1.expect)(ast.children[0].children[0]).toBeInstanceOf(nodes_1.TemplateData);
|
|
280
|
-
(0, vitest_1.expect)(ast.children[0].children[0].value).toBe('EXT');
|
|
281
|
-
});
|
|
282
|
-
(0, vitest_1.it)('throws on unknown block tag', () => {
|
|
283
|
-
(0, vitest_1.expect)(() => parseRoot('{% doesnotexist %}')).toThrow(/unknown block tag/i);
|
|
284
|
-
});
|
|
285
|
-
(0, vitest_1.it)('advanceAfterVariableEnd throws if missing variable end', () => {
|
|
286
|
-
// Use Parser directly so we can call method
|
|
287
|
-
const toks = lexer.lex('{{ 1 ', {});
|
|
288
|
-
const p = new parser_1.Parser(toks);
|
|
289
|
-
// consume VARIABLE_START
|
|
290
|
-
p.nextToken();
|
|
291
|
-
p.parseExpression();
|
|
292
|
-
(0, vitest_1.expect)(() => p.advanceAfterVariableEnd()).toThrow(/expected variable end/i);
|
|
293
|
-
});
|
|
294
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
// test/precompile.test.ts
|
|
4
|
-
const vitest_1 = require("vitest");
|
|
5
|
-
const precompile_1 = require("../src/precompile");
|
|
6
|
-
function makeStat(kind) {
|
|
7
|
-
return {
|
|
8
|
-
isFile: () => kind === 'file',
|
|
9
|
-
isDirectory: () => kind === 'dir',
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
// In-memory fs tree for deterministic tests
|
|
13
|
-
let TREE;
|
|
14
|
-
function getNode(p) {
|
|
15
|
-
const parts = p.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
16
|
-
let cur = TREE;
|
|
17
|
-
for (const part of parts) {
|
|
18
|
-
if (cur.type !== 'dir')
|
|
19
|
-
throw new Error(`Not a directory: ${p}`);
|
|
20
|
-
const next = cur.children[part];
|
|
21
|
-
if (!next)
|
|
22
|
-
throw new Error(`ENOENT: ${p}`);
|
|
23
|
-
cur = next;
|
|
24
|
-
}
|
|
25
|
-
return cur;
|
|
26
|
-
}
|
|
27
|
-
function listDir(p) {
|
|
28
|
-
const node = getNode(p);
|
|
29
|
-
if (node.type !== 'dir')
|
|
30
|
-
throw new Error(`ENOTDIR: ${p}`);
|
|
31
|
-
return Object.keys(node.children);
|
|
32
|
-
}
|
|
33
|
-
function readFile(p) {
|
|
34
|
-
const node = getNode(p);
|
|
35
|
-
if (node.type !== 'file')
|
|
36
|
-
throw new Error(`EISDIR: ${p}`);
|
|
37
|
-
return node.content;
|
|
38
|
-
}
|
|
39
|
-
vitest_1.vi.mock('fs', () => {
|
|
40
|
-
return {
|
|
41
|
-
default: {
|
|
42
|
-
statSync: (p) => {
|
|
43
|
-
const n = getNode(p);
|
|
44
|
-
return makeStat(n.type === 'file' ? 'file' : 'dir');
|
|
45
|
-
},
|
|
46
|
-
readdirSync: (p) => listDir(p),
|
|
47
|
-
readFileSync: (p, _enc) => readFile(p),
|
|
48
|
-
},
|
|
49
|
-
statSync: (p) => {
|
|
50
|
-
const n = getNode(p);
|
|
51
|
-
return makeStat(n.type === 'file' ? 'file' : 'dir');
|
|
52
|
-
},
|
|
53
|
-
readdirSync: (p) => listDir(p),
|
|
54
|
-
readFileSync: (p, _enc) => readFile(p),
|
|
55
|
-
};
|
|
56
|
-
});
|
|
57
|
-
const compileMock = vitest_1.vi.fn();
|
|
58
|
-
vitest_1.vi.mock('../src/compiler', () => {
|
|
59
|
-
return { compile: (...args) => compileMock(...args) };
|
|
60
|
-
});
|
|
61
|
-
const prettifyMock = vitest_1.vi.fn((name, _a, err) => {
|
|
62
|
-
// Keep it simple and easy to assert:
|
|
63
|
-
const e = new Error(`PRETTY:${name}:${String(err?.message || err)}`);
|
|
64
|
-
return e;
|
|
65
|
-
});
|
|
66
|
-
const templateErrorMock = vitest_1.vi.fn((e) => {
|
|
67
|
-
// Make sure errors have `.message`
|
|
68
|
-
return e instanceof Error ? e : new Error(String(e));
|
|
69
|
-
});
|
|
70
|
-
vitest_1.vi.mock('../src/lib', () => {
|
|
71
|
-
return {
|
|
72
|
-
_prettifyError: (...args) => prettifyMock(...args),
|
|
73
|
-
TemplateError: (...args) => templateErrorMock(...args),
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
class FakeEnv {
|
|
77
|
-
asyncFilters = [];
|
|
78
|
-
extensionsList = [];
|
|
79
|
-
throwOnUndefined = false;
|
|
80
|
-
constructor(_loaders) { }
|
|
81
|
-
}
|
|
82
|
-
vitest_1.vi.mock('../src/environment', () => {
|
|
83
|
-
return { Environment: FakeEnv, Template: class Template {
|
|
84
|
-
} };
|
|
85
|
-
});
|
|
86
|
-
const wrapperMock = vitest_1.vi.fn((templates, opts) => ({
|
|
87
|
-
templates,
|
|
88
|
-
opts,
|
|
89
|
-
}));
|
|
90
|
-
vitest_1.vi.mock('../src/globals', () => {
|
|
91
|
-
return { precompileGlobal: (...args) => wrapperMock(...args) };
|
|
92
|
-
});
|
|
93
|
-
// Module under test (import AFTER mocks)
|
|
94
|
-
// --------------------
|
|
95
|
-
// Tests
|
|
96
|
-
// --------------------
|
|
97
|
-
(0, vitest_1.describe)('precompile.ts', () => {
|
|
98
|
-
(0, vitest_1.beforeEach)(() => {
|
|
99
|
-
vitest_1.vi.clearAllMocks();
|
|
100
|
-
// default compile behavior
|
|
101
|
-
compileMock.mockImplementation((_src, _async, _ext, name) => {
|
|
102
|
-
return `CODE:${name}`;
|
|
103
|
-
});
|
|
104
|
-
// default fs tree
|
|
105
|
-
TREE = {
|
|
106
|
-
type: 'dir',
|
|
107
|
-
children: {
|
|
108
|
-
templates: {
|
|
109
|
-
type: 'dir',
|
|
110
|
-
children: {
|
|
111
|
-
'a.njk': { type: 'file', content: 'A' },
|
|
112
|
-
'b.txt': { type: 'file', content: 'B' },
|
|
113
|
-
sub: {
|
|
114
|
-
type: 'dir',
|
|
115
|
-
children: {
|
|
116
|
-
'c.njk': { type: 'file', content: 'C' },
|
|
117
|
-
'ignore.njk': { type: 'file', content: 'NO' },
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
skipdir: {
|
|
121
|
-
type: 'dir',
|
|
122
|
-
children: {
|
|
123
|
-
'd.njk': { type: 'file', content: 'D' },
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
'single.njk': { type: 'file', content: 'SINGLE' },
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
(0, vitest_1.describe)('default export precompile()', () => {
|
|
133
|
-
(0, vitest_1.it)('precompiles a single file path', () => {
|
|
134
|
-
const env = new FakeEnv([]);
|
|
135
|
-
const out = (0, precompile_1.precompile)('single.njk', {
|
|
136
|
-
isString: false,
|
|
137
|
-
env,
|
|
138
|
-
name: 'myname.njk',
|
|
139
|
-
wrapper: wrapperMock,
|
|
140
|
-
});
|
|
141
|
-
// wrapper called with a single precompiled template
|
|
142
|
-
(0, vitest_1.expect)(wrapperMock).toHaveBeenCalledTimes(1);
|
|
143
|
-
(0, vitest_1.expect)(out.templates).toHaveLength(1);
|
|
144
|
-
(0, vitest_1.expect)(out.templates[0]).toEqual({
|
|
145
|
-
name: 'myname.njk',
|
|
146
|
-
template: 'CODE:myname.njk',
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
(0, vitest_1.it)('precompiles a directory: includes files matching include patterns and traverses subdirs not excluded', () => {
|
|
150
|
-
const env = new FakeEnv([]);
|
|
151
|
-
const out = (0, precompile_1.precompile)('templates', {
|
|
152
|
-
isString: false,
|
|
153
|
-
env,
|
|
154
|
-
include: [/\.njk$/], // only *.njk
|
|
155
|
-
exclude: [/skipdir\//, /sub\/ignore\.njk$/], // skip skipdir folder + one file in sub
|
|
156
|
-
wrapper: wrapperMock,
|
|
157
|
-
});
|
|
158
|
-
// Expect only: a.njk and sub/c.njk (ignore skipdir/d.njk and sub/ignore.njk)
|
|
159
|
-
const names = out.templates.map((t) => t.name).sort();
|
|
160
|
-
(0, vitest_1.expect)(names).toEqual(['a.njk', 'sub/c.njk']);
|
|
161
|
-
// compile called for each included template with its relative name
|
|
162
|
-
const compiledNames = compileMock.mock.calls.map((c) => c[3]).sort();
|
|
163
|
-
(0, vitest_1.expect)(compiledNames).toEqual(['a.njk', 'sub/c.njk']);
|
|
164
|
-
});
|
|
165
|
-
(0, vitest_1.it)('when force=false (default), a compile error in a directory aborts', () => {
|
|
166
|
-
compileMock.mockImplementation((_src, _a, _e, name) => {
|
|
167
|
-
if (name === 'sub/c.njk')
|
|
168
|
-
throw new Error('bad');
|
|
169
|
-
return `CODE:${name}`;
|
|
170
|
-
});
|
|
171
|
-
(0, vitest_1.expect)(() => (0, precompile_1.precompile)('templates', {
|
|
172
|
-
isString: false,
|
|
173
|
-
include: [/\.njk$/],
|
|
174
|
-
exclude: [/skipdir\//],
|
|
175
|
-
wrapper: wrapperMock,
|
|
176
|
-
})).toThrowError(/PRETTY:sub\/c\.njk/);
|
|
177
|
-
// wrapper should not be called because it aborted
|
|
178
|
-
(0, vitest_1.expect)(wrapperMock).not.toHaveBeenCalled();
|
|
179
|
-
});
|
|
180
|
-
(0, vitest_1.it)('when force=true, a compile error in a directory is logged and compilation continues', () => {
|
|
181
|
-
const errSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
182
|
-
compileMock.mockImplementation((_src, _a, _e, name) => {
|
|
183
|
-
if (name === 'sub/c.njk')
|
|
184
|
-
throw new Error('bad');
|
|
185
|
-
return `CODE:${name}`;
|
|
186
|
-
});
|
|
187
|
-
const out = (0, precompile_1.precompile)('templates', {
|
|
188
|
-
isString: false,
|
|
189
|
-
include: [/\.njk$/],
|
|
190
|
-
exclude: [/skipdir\//],
|
|
191
|
-
force: true,
|
|
192
|
-
wrapper: wrapperMock,
|
|
193
|
-
});
|
|
194
|
-
// a.njk compiled, sub/c.njk failed and is skipped
|
|
195
|
-
const names = out.templates.map((t) => t.name).sort();
|
|
196
|
-
(0, vitest_1.expect)(names).toEqual(['a.njk', 'sub/ignore.njk']); // NOTE: include matches *.njk, and we didn't exclude ignore.njk here
|
|
197
|
-
(0, vitest_1.expect)(errSpy).toHaveBeenCalled(); // logged error
|
|
198
|
-
errSpy.mockRestore();
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
(0, vitest_1.describe)('precompileString', () => {
|
|
202
|
-
(0, vitest_1.it)('throws if called with isString=true and no name (current bug path)', () => {
|
|
203
|
-
// Your code intends to throw when opts.name missing, but currently checks `_precompile.name`
|
|
204
|
-
// which is truthy, so it will fall through and then crash later.
|
|
205
|
-
(0, vitest_1.expect)(() => (0, precompile_1.precompile)('Hello', {
|
|
206
|
-
isString: true,
|
|
207
|
-
// name intentionally missing
|
|
208
|
-
wrapper: wrapperMock,
|
|
209
|
-
})).toThrow();
|
|
210
|
-
});
|
|
211
|
-
(0, vitest_1.it)('compiles a string when name is provided', () => {
|
|
212
|
-
const out = (0, precompile_1.precompile)('Hello', {
|
|
213
|
-
isString: true,
|
|
214
|
-
name: 'inline.njk',
|
|
215
|
-
env: new FakeEnv([]),
|
|
216
|
-
wrapper: wrapperMock,
|
|
217
|
-
});
|
|
218
|
-
(0, vitest_1.expect)(wrapperMock).toHaveBeenCalledTimes(1);
|
|
219
|
-
(0, vitest_1.expect)(out.templates).toHaveLength(1);
|
|
220
|
-
(0, vitest_1.expect)(out.templates[0].name).toBe('inline.njk');
|
|
221
|
-
(0, vitest_1.expect)(out.templates[0].template).toBe('CODE:inline.njk');
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|