@samuelbines/nunjucks 0.0.3
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/LICENSE +26 -0
- package/README.md +55 -0
- package/dist/scripts/smoke.d.ts +1 -0
- package/dist/scripts/smoke.js +95 -0
- package/dist/src/compiler.d.ts +12 -0
- package/dist/src/compiler.js +1050 -0
- package/dist/src/environment.d.ts +103 -0
- package/dist/src/environment.js +621 -0
- package/dist/src/express-app.d.ts +2 -0
- package/dist/src/express-app.js +33 -0
- package/dist/src/filters.d.ts +44 -0
- package/dist/src/filters.js +424 -0
- package/dist/src/globals.d.ts +14 -0
- package/dist/src/globals.js +342 -0
- package/dist/src/index.d.ts +28 -0
- package/dist/src/index.js +116 -0
- package/dist/src/interpreter.d.ts +16 -0
- package/dist/src/interpreter.js +489 -0
- package/dist/src/lexer.d.ts +72 -0
- package/dist/src/lexer.js +480 -0
- package/dist/src/lib.d.ts +74 -0
- package/dist/src/lib.js +237 -0
- package/dist/src/loader.d.ts +80 -0
- package/dist/src/loader.js +175 -0
- package/dist/src/nodes.d.ts +362 -0
- package/dist/src/nodes.js +894 -0
- package/dist/src/parser.d.ts +66 -0
- package/dist/src/parser.js +1068 -0
- package/dist/src/precompile.d.ts +15 -0
- package/dist/src/precompile.js +108 -0
- package/dist/src/runtime.d.ts +33 -0
- package/dist/src/runtime.js +314 -0
- package/dist/src/transformer.d.ts +3 -0
- package/dist/src/transformer.js +161 -0
- package/dist/src/types.d.ts +27 -0
- package/dist/src/types.js +2 -0
- package/dist/tests/compiler.test.d.ts +1 -0
- package/dist/tests/compiler.test.js +201 -0
- package/dist/tests/enviornment.test.d.ts +1 -0
- package/dist/tests/enviornment.test.js +279 -0
- package/dist/tests/express.test.d.ts +1 -0
- package/dist/tests/express.test.js +86 -0
- package/dist/tests/filters.test.d.ts +13 -0
- package/dist/tests/filters.test.js +286 -0
- package/dist/tests/globals.test.d.ts +1 -0
- package/dist/tests/globals.test.js +579 -0
- package/dist/tests/interpreter.test.d.ts +1 -0
- package/dist/tests/interpreter.test.js +208 -0
- package/dist/tests/lexer.test.d.ts +1 -0
- package/dist/tests/lexer.test.js +249 -0
- package/dist/tests/lib.test.d.ts +1 -0
- package/dist/tests/lib.test.js +236 -0
- package/dist/tests/loader.test.d.ts +1 -0
- package/dist/tests/loader.test.js +301 -0
- package/dist/tests/nodes.test.d.ts +1 -0
- package/dist/tests/nodes.test.js +137 -0
- package/dist/tests/parser.test.d.ts +1 -0
- package/dist/tests/parser.test.js +294 -0
- package/dist/tests/precompile.test.d.ts +1 -0
- package/dist/tests/precompile.test.js +224 -0
- package/dist/tests/runtime.test.d.ts +1 -0
- package/dist/tests/runtime.test.js +237 -0
- package/dist/tests/transformer.test.d.ts +1 -0
- package/dist/tests/transformer.test.js +125 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,621 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Template = exports.Context = exports.Environment = void 0;
|
|
40
|
+
//TODO: Sun 4th Jan 2026
|
|
41
|
+
const events_1 = __importDefault(require("events"));
|
|
42
|
+
const lib_1 = require("./lib");
|
|
43
|
+
const compiler = __importStar(require("./compiler"));
|
|
44
|
+
const filters = __importStar(require("./filters"));
|
|
45
|
+
const loader_1 = require("./loader");
|
|
46
|
+
const globals_1 = require("./globals");
|
|
47
|
+
const runtime_1 = require("./runtime");
|
|
48
|
+
const express_app_1 = require("./express-app");
|
|
49
|
+
const runtime = __importStar(require("./runtime"));
|
|
50
|
+
// const rootHelper: RootRenderFunctionProps = (cb) => (env, context, frame, runtime, cb) => {
|
|
51
|
+
// try {
|
|
52
|
+
// cb(null, 'hello');
|
|
53
|
+
// } catch (e) {
|
|
54
|
+
// cb(e, null);
|
|
55
|
+
// }
|
|
56
|
+
// };
|
|
57
|
+
const root = (env, context, frame, runtime, cb) => {
|
|
58
|
+
try {
|
|
59
|
+
cb(null, 'hello');
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
cb(e, null);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const noopTmplSrc = {
|
|
66
|
+
type: 'code',
|
|
67
|
+
obj: {
|
|
68
|
+
root: root,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
class Environment extends events_1.default {
|
|
72
|
+
//State
|
|
73
|
+
ctx;
|
|
74
|
+
globals;
|
|
75
|
+
throwOnUndefined = false;
|
|
76
|
+
trimBlocks = false;
|
|
77
|
+
lstripBlocks = false;
|
|
78
|
+
dev = true;
|
|
79
|
+
autoescape = true;
|
|
80
|
+
loaders = [new loader_1.FileSystemLoader(['views'])];
|
|
81
|
+
asyncFilters = [];
|
|
82
|
+
path;
|
|
83
|
+
// TODO: figure out types here
|
|
84
|
+
extensionsList = [];
|
|
85
|
+
extensions = {};
|
|
86
|
+
filters = {}; //typeof filters to set later
|
|
87
|
+
cache = {};
|
|
88
|
+
constructor(opts) {
|
|
89
|
+
super();
|
|
90
|
+
this.path = opts?.path || 'views';
|
|
91
|
+
this.dev = opts?.dev || true;
|
|
92
|
+
this.throwOnUndefined = opts?.throwOnUndefined || false;
|
|
93
|
+
this.trimBlocks = opts?.trimBlocks || false;
|
|
94
|
+
this.lstripBlocks = opts?.lstripBlocks || false;
|
|
95
|
+
this.autoescape = opts?.autoescape || true;
|
|
96
|
+
this.loaders = opts?.loaders || [new loader_1.FileSystemLoader([this.path])];
|
|
97
|
+
if (typeof window !== 'undefined' && window.nunjucksPrecompiled) {
|
|
98
|
+
this.loaders.unshift(new loader_1.PrecompiledLoader(window.nunjucksPrecompiled));
|
|
99
|
+
}
|
|
100
|
+
this._initLoaders();
|
|
101
|
+
this.globals = (0, globals_1.globals)();
|
|
102
|
+
// TODO: Running on init before initialized? Surely not used
|
|
103
|
+
Object.entries(filters).forEach(([name, filter]) => this.addFilter(name, filter));
|
|
104
|
+
}
|
|
105
|
+
_initLoaders() {
|
|
106
|
+
this.loaders.forEach((loader) => {
|
|
107
|
+
// Caching and cache busting
|
|
108
|
+
loader.cache = {};
|
|
109
|
+
if (typeof loader.on === 'function') {
|
|
110
|
+
loader.on('update', (name, fullname) => {
|
|
111
|
+
loader.cache[name] = null;
|
|
112
|
+
this.emit('update', name, fullname, loader);
|
|
113
|
+
});
|
|
114
|
+
loader.on('load', (name, source) => {
|
|
115
|
+
this.emit('load', name, source, loader);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
invalidateCache() {
|
|
121
|
+
this.loaders.forEach((loader) => {
|
|
122
|
+
loader.cache = {};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
addExtension(name, extension) {
|
|
126
|
+
extension.__name = name;
|
|
127
|
+
this.extensions[name] = extension;
|
|
128
|
+
this.extensionsList?.push(extension);
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
removeExtension(name) {
|
|
132
|
+
var extension = this.getExtension(name);
|
|
133
|
+
if (!extension) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.extensionsList = (0, lib_1.without)(this.extensionsList, extension);
|
|
137
|
+
delete this.extensions[name];
|
|
138
|
+
}
|
|
139
|
+
getExtension(name) {
|
|
140
|
+
return this.extensions[name];
|
|
141
|
+
}
|
|
142
|
+
hasExtension(name) {
|
|
143
|
+
return !!this.extensions[name];
|
|
144
|
+
}
|
|
145
|
+
addFilter(name, func, async) {
|
|
146
|
+
if (async) {
|
|
147
|
+
this.asyncFilters?.push(name);
|
|
148
|
+
}
|
|
149
|
+
this.filters[name] = func;
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
getFilter(name) {
|
|
153
|
+
if (!this.filters[name]) {
|
|
154
|
+
lib_1.p.err('filter not found: ' + name);
|
|
155
|
+
throw new Error('filter not found: ' + name);
|
|
156
|
+
}
|
|
157
|
+
return this.filters[name];
|
|
158
|
+
}
|
|
159
|
+
resolveTemplate(loader, parentName, filename) {
|
|
160
|
+
let isRelative = loader.isRelative && parentName ? loader.isRelative(filename) : false;
|
|
161
|
+
lib_1.p.warn('Is relative: ', isRelative, parentName, loader, '\n', loader.typename);
|
|
162
|
+
return isRelative && loader.resolve
|
|
163
|
+
? loader.resolve(parentName, filename)
|
|
164
|
+
: filename;
|
|
165
|
+
}
|
|
166
|
+
getTemplateInfo(name, opts, cb) {
|
|
167
|
+
const parentName = opts?.parentName || null;
|
|
168
|
+
const ignoreMissing = opts?.ignoreMissing || false;
|
|
169
|
+
const that = this;
|
|
170
|
+
let syncResult;
|
|
171
|
+
const done = (err, info) => {
|
|
172
|
+
if (!info && !err && !ignoreMissing)
|
|
173
|
+
err = new Error("template not found: " + name);
|
|
174
|
+
if (err) {
|
|
175
|
+
if (cb)
|
|
176
|
+
return cb(err);
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
const out = { src: info.src, path: info.path || "", noCache: info.noCache, loader: info.loader };
|
|
180
|
+
if (cb)
|
|
181
|
+
cb(null, out);
|
|
182
|
+
else
|
|
183
|
+
syncResult = out;
|
|
184
|
+
};
|
|
185
|
+
(0, lib_1.asyncIter)(this.loaders, (loader, _i, next, finish) => {
|
|
186
|
+
function handle(err, src) {
|
|
187
|
+
if (err)
|
|
188
|
+
finish(err);
|
|
189
|
+
else if (src) {
|
|
190
|
+
src.loader = loader;
|
|
191
|
+
finish(null, src);
|
|
192
|
+
}
|
|
193
|
+
else
|
|
194
|
+
next();
|
|
195
|
+
}
|
|
196
|
+
const resolved = that.resolveTemplate(loader, parentName, name);
|
|
197
|
+
if (loader.async)
|
|
198
|
+
loader.getSource(resolved, handle);
|
|
199
|
+
else
|
|
200
|
+
handle(null, loader.getSource(resolved));
|
|
201
|
+
}, done);
|
|
202
|
+
return syncResult;
|
|
203
|
+
}
|
|
204
|
+
getTemplate(name, cb, opts) {
|
|
205
|
+
lib_1.p.log('Getting template');
|
|
206
|
+
let that = this;
|
|
207
|
+
let tmpl = null;
|
|
208
|
+
const parentName = opts?.parentName || null;
|
|
209
|
+
lib_1.p.err('Parent name is: ', parentName, name);
|
|
210
|
+
const eagerCompile = opts?.eagerCompile || false;
|
|
211
|
+
const ignoreMissing = opts?.ignoreMissing || false;
|
|
212
|
+
if (name && name.raw) {
|
|
213
|
+
name = name.raw;
|
|
214
|
+
}
|
|
215
|
+
if (name instanceof Template) {
|
|
216
|
+
tmpl = name;
|
|
217
|
+
}
|
|
218
|
+
else if (!(0, lib_1.isString)(name)) {
|
|
219
|
+
lib_1.p.err('template names must be a string: ' + name);
|
|
220
|
+
throw new Error('template names must be a string: ' + name);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
for (let i = 0; i < this.loaders?.length; i++) {
|
|
224
|
+
const loader = this.loaders[i];
|
|
225
|
+
tmpl = loader.cache[this.resolveTemplate(loader, parentName, name)];
|
|
226
|
+
if (tmpl) {
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (tmpl) {
|
|
232
|
+
if (eagerCompile) {
|
|
233
|
+
tmpl.compile();
|
|
234
|
+
}
|
|
235
|
+
if (cb) {
|
|
236
|
+
cb(null, tmpl);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
return tmpl;
|
|
240
|
+
}
|
|
241
|
+
let syncResult;
|
|
242
|
+
const createTemplate = (err, info) => {
|
|
243
|
+
if (!info && !err && !ignoreMissing) {
|
|
244
|
+
err = new Error('template not found: ' + name);
|
|
245
|
+
}
|
|
246
|
+
if (err) {
|
|
247
|
+
if (cb) {
|
|
248
|
+
cb(err);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
const newTmpl = new Template(info?.src || noopTmplSrc, this, info.path || '', eagerCompile);
|
|
254
|
+
if (!info.noCache) {
|
|
255
|
+
info.loader.cache[name] = newTmpl;
|
|
256
|
+
}
|
|
257
|
+
if (cb) {
|
|
258
|
+
cb(null, newTmpl);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
syncResult = newTmpl;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
(0, lib_1.asyncIter)(this.loaders, (loader, _i, next, done) => {
|
|
265
|
+
function handle(err, src) {
|
|
266
|
+
if (err) {
|
|
267
|
+
done(err);
|
|
268
|
+
}
|
|
269
|
+
else if (src) {
|
|
270
|
+
src.loader = loader;
|
|
271
|
+
done(null, src);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
next();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
name = that.resolveTemplate(loader, parentName, name);
|
|
278
|
+
lib_1.p.log('Name is: ', name, parentName, loader);
|
|
279
|
+
if (loader.async) {
|
|
280
|
+
loader.getSource(name, handle);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
handle(null, loader.getSource(name));
|
|
284
|
+
}
|
|
285
|
+
}, createTemplate);
|
|
286
|
+
return syncResult;
|
|
287
|
+
}
|
|
288
|
+
express(app) {
|
|
289
|
+
return (0, express_app_1.express)(this, app);
|
|
290
|
+
}
|
|
291
|
+
render(name, ctx, cb) {
|
|
292
|
+
lib_1.p.warn('TRYING TO RENDER', ctx);
|
|
293
|
+
if ((0, lib_1.isFunction)(ctx)) {
|
|
294
|
+
cb = ctx;
|
|
295
|
+
ctx = null;
|
|
296
|
+
}
|
|
297
|
+
// We support a synchronous API to make it easier to migrate
|
|
298
|
+
// existing code to async. This works because if you don't do
|
|
299
|
+
// anything async work, the whole thing is actually run
|
|
300
|
+
// synchronously.
|
|
301
|
+
let syncResult = null;
|
|
302
|
+
this.getTemplate(name, (err, tmpl) => {
|
|
303
|
+
if (err && cb) {
|
|
304
|
+
cb(err);
|
|
305
|
+
}
|
|
306
|
+
else if (err) {
|
|
307
|
+
throw err;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
lib_1.p.log('Getting template');
|
|
311
|
+
syncResult = tmpl.render(ctx, cb);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
// p.log('ALREADY RETURNED', syncResult);
|
|
315
|
+
// return syncResult;
|
|
316
|
+
}
|
|
317
|
+
renderString(src, ctx, opts, cb) {
|
|
318
|
+
if ((0, lib_1.isFunction)(opts)) {
|
|
319
|
+
cb = opts;
|
|
320
|
+
opts = {};
|
|
321
|
+
}
|
|
322
|
+
opts = opts || {};
|
|
323
|
+
return new Template(src, this, opts.path).render(ctx, cb);
|
|
324
|
+
}
|
|
325
|
+
get typename() {
|
|
326
|
+
return this.constructor.name;
|
|
327
|
+
}
|
|
328
|
+
waterfall(tasks, callback, forceAsync) {
|
|
329
|
+
return function waterfall(tasks, done) {
|
|
330
|
+
let i = 0;
|
|
331
|
+
function next(err, res) {
|
|
332
|
+
if (err) {
|
|
333
|
+
lib_1.p.err(err);
|
|
334
|
+
return done(err);
|
|
335
|
+
}
|
|
336
|
+
const task = tasks[i++];
|
|
337
|
+
if (!task)
|
|
338
|
+
return done(null, res);
|
|
339
|
+
// first task: (cb), others: (res, cb)
|
|
340
|
+
if (task?.length <= 1)
|
|
341
|
+
task(next);
|
|
342
|
+
else
|
|
343
|
+
task(res, next);
|
|
344
|
+
}
|
|
345
|
+
next(null, undefined);
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
exports.Environment = Environment;
|
|
350
|
+
class Context {
|
|
351
|
+
ctx;
|
|
352
|
+
blocks;
|
|
353
|
+
env;
|
|
354
|
+
lineno;
|
|
355
|
+
colno;
|
|
356
|
+
exported = [];
|
|
357
|
+
compiled = false;
|
|
358
|
+
constructor(ctx = {}, blocks = {}, env = new Environment(), lineno = 0, colno = 0) {
|
|
359
|
+
this.ctx = ctx;
|
|
360
|
+
this.blocks = blocks;
|
|
361
|
+
this.env = env;
|
|
362
|
+
this.lineno = lineno;
|
|
363
|
+
this.colno = colno;
|
|
364
|
+
this.ctx = { ...ctx };
|
|
365
|
+
Object.keys(blocks).forEach((name) => {
|
|
366
|
+
this.addBlock(name, blocks[name]);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
get typename() {
|
|
370
|
+
return 'Context';
|
|
371
|
+
}
|
|
372
|
+
lookup(name) {
|
|
373
|
+
// This is one of the most called functions, so optimize for
|
|
374
|
+
// the typical case where the name isn't in the globals
|
|
375
|
+
if (name in this.env.globals && !(name in this.ctx)) {
|
|
376
|
+
return this.env.globals[name];
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
lib_1.p.debug('ctx local:', this.ctx, name);
|
|
380
|
+
return this.ctx[name];
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
setVariable(name, val) {
|
|
384
|
+
this.ctx[name] = val;
|
|
385
|
+
}
|
|
386
|
+
getVariables() {
|
|
387
|
+
return this.ctx;
|
|
388
|
+
}
|
|
389
|
+
addBlock(name, block) {
|
|
390
|
+
this.blocks[name] = this.blocks[name] || [];
|
|
391
|
+
lib_1.p.warn('\nBlocks added are: ', this.blocks[name], block);
|
|
392
|
+
if (typeof this.blocks[name]?.push === 'function')
|
|
393
|
+
this.blocks[name]?.push(block);
|
|
394
|
+
return this;
|
|
395
|
+
}
|
|
396
|
+
getBlock(name) {
|
|
397
|
+
if (!this.blocks[name]) {
|
|
398
|
+
throw new Error('unknown block "' + name + '"');
|
|
399
|
+
}
|
|
400
|
+
return this.blocks[name][0];
|
|
401
|
+
}
|
|
402
|
+
// TODO: fix any here
|
|
403
|
+
getSuper(env, name, block, frame, runtime, cb) {
|
|
404
|
+
var idx = (this.blocks[name] || []).indexOf(block);
|
|
405
|
+
var blk = this.blocks[name][idx + 1];
|
|
406
|
+
var context = this;
|
|
407
|
+
if (idx === -1 || !blk) {
|
|
408
|
+
throw new Error('no super block available for "' + name + '"');
|
|
409
|
+
}
|
|
410
|
+
blk(env, context, frame, runtime, cb);
|
|
411
|
+
}
|
|
412
|
+
addExport(name) {
|
|
413
|
+
this.exported?.push(name);
|
|
414
|
+
}
|
|
415
|
+
getExported() {
|
|
416
|
+
var exported = {};
|
|
417
|
+
this.exported.forEach((name) => {
|
|
418
|
+
exported[name] = this.ctx[name];
|
|
419
|
+
});
|
|
420
|
+
return exported;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
exports.Context = Context;
|
|
424
|
+
class Template {
|
|
425
|
+
lineno;
|
|
426
|
+
colno;
|
|
427
|
+
env = new Environment();
|
|
428
|
+
tmplProps;
|
|
429
|
+
tmplStr = {};
|
|
430
|
+
path = '';
|
|
431
|
+
blocks;
|
|
432
|
+
compiled = false;
|
|
433
|
+
rootRenderFunction;
|
|
434
|
+
constructor(src, env = new Environment(), path, eagerCompile, lineno = 0, colno = 0) {
|
|
435
|
+
this.lineno = lineno;
|
|
436
|
+
this.colno = colno;
|
|
437
|
+
this.env = env;
|
|
438
|
+
if ((0, lib_1.isString)(src)) {
|
|
439
|
+
this.tmplStr = src;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
switch (src.type) {
|
|
443
|
+
case 'code':
|
|
444
|
+
this.tmplProps = src.obj;
|
|
445
|
+
break;
|
|
446
|
+
case 'string':
|
|
447
|
+
this.tmplStr = src.obj;
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
lib_1.p.err(src);
|
|
451
|
+
throw new Error(`Unexpected template object type ${src.type}; expected 'code', or 'string'`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
this.path = path;
|
|
455
|
+
if (eagerCompile) {
|
|
456
|
+
try {
|
|
457
|
+
this._compile();
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
throw (0, lib_1._prettifyError)(this.path, this.env.dev, err);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
this.compiled = false;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
render(ctx, parentFrame, cb) {
|
|
468
|
+
if (typeof ctx === 'function') {
|
|
469
|
+
cb = ctx;
|
|
470
|
+
ctx = {};
|
|
471
|
+
}
|
|
472
|
+
else if (typeof parentFrame === 'function') {
|
|
473
|
+
lib_1.p.log('Parent frame set as cb');
|
|
474
|
+
cb = parentFrame;
|
|
475
|
+
parentFrame = null;
|
|
476
|
+
}
|
|
477
|
+
// If there is a parent frame, we are being called from internal
|
|
478
|
+
// code of another template, and the internal system
|
|
479
|
+
// depends on the sync/async nature of the parent template
|
|
480
|
+
// to be inherited, so force an async callback
|
|
481
|
+
// Catch compile errors for async rendering
|
|
482
|
+
try {
|
|
483
|
+
this.compile();
|
|
484
|
+
}
|
|
485
|
+
catch (e) {
|
|
486
|
+
const err = (0, lib_1._prettifyError)(this.path, this.env.dev, e);
|
|
487
|
+
if (cb) {
|
|
488
|
+
return cb(err);
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
throw err;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const context = new Context(ctx || {}, this.blocks, this.env);
|
|
495
|
+
const frame = parentFrame ? parentFrame?.push(true) : new runtime_1.Frame();
|
|
496
|
+
frame.topLevel = true;
|
|
497
|
+
let syncResult = null;
|
|
498
|
+
let didError = false;
|
|
499
|
+
// p.log(
|
|
500
|
+
// 'Before setup: ',
|
|
501
|
+
// this.env,
|
|
502
|
+
// '\nctx:',
|
|
503
|
+
// context,
|
|
504
|
+
// '\nFrame: ',
|
|
505
|
+
// frame,
|
|
506
|
+
// '\nRuntime: ',
|
|
507
|
+
// runtime
|
|
508
|
+
// );
|
|
509
|
+
// p.log(this.env, context, frame, runtime);
|
|
510
|
+
if (!this.rootRenderFunction)
|
|
511
|
+
this.rootRenderFunction = root;
|
|
512
|
+
this.rootRenderFunction(this.env, context, frame, runtime, (err, res) => {
|
|
513
|
+
// TODO: this is actually a bug in the compiled template (because waterfall
|
|
514
|
+
// tasks are both not passing errors up the chain of callbacks AND are not
|
|
515
|
+
// causing a return from the top-most render function). But fixing that
|
|
516
|
+
// will require a more substantial change to the compiler.
|
|
517
|
+
// if (cb && typeof res !== 'undefined') {
|
|
518
|
+
// // prevent multiple calls to cb
|
|
519
|
+
// p.log('SOMEHOW HERE');
|
|
520
|
+
// resolve('Somehow here');
|
|
521
|
+
// return;
|
|
522
|
+
// }
|
|
523
|
+
if (didError && cb && typeof res !== 'undefined') {
|
|
524
|
+
// prevent multiple calls to cb
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
if (err) {
|
|
528
|
+
lib_1.p.err('err: ', err);
|
|
529
|
+
err = (0, lib_1._prettifyError)(this.path, this.env.dev, err);
|
|
530
|
+
cb(err);
|
|
531
|
+
didError = true;
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (cb) {
|
|
535
|
+
cb(err, res);
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
syncResult = res;
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
return syncResult;
|
|
542
|
+
}
|
|
543
|
+
getExported(ctx, parentFrame, cb) {
|
|
544
|
+
// eslint-disable-line consistent-return
|
|
545
|
+
if (typeof ctx === 'function') {
|
|
546
|
+
cb = ctx;
|
|
547
|
+
ctx = {};
|
|
548
|
+
}
|
|
549
|
+
if (typeof parentFrame === 'function') {
|
|
550
|
+
cb = parentFrame;
|
|
551
|
+
parentFrame = null;
|
|
552
|
+
}
|
|
553
|
+
// Catch compile errors for async rendering
|
|
554
|
+
try {
|
|
555
|
+
this.compile();
|
|
556
|
+
}
|
|
557
|
+
catch (e) {
|
|
558
|
+
if (cb) {
|
|
559
|
+
return cb(e);
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
throw e;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const frame = parentFrame ? parentFrame?.push() : new runtime_1.Frame();
|
|
566
|
+
frame.topLevel = true;
|
|
567
|
+
// Run the rootRenderFunc to populate the context with exported vars
|
|
568
|
+
const context = new Context(ctx || {}, this.blocks, this.env);
|
|
569
|
+
// p.log(
|
|
570
|
+
// 'Before setup: ',
|
|
571
|
+
// this.env,
|
|
572
|
+
// '\nctx:',
|
|
573
|
+
// context,
|
|
574
|
+
// '\nFrame: ',
|
|
575
|
+
// frame,
|
|
576
|
+
// '\nRuntime: ',
|
|
577
|
+
// runtime
|
|
578
|
+
// );
|
|
579
|
+
// p.log('rootRenderFunc: ', this.rootRenderFunc);
|
|
580
|
+
if (!this.rootRenderFunction)
|
|
581
|
+
this.rootRenderFunction = root;
|
|
582
|
+
lib_1.p.err('rootRenderFunction', this.rootRenderFunction);
|
|
583
|
+
this.rootRenderFunction(this.env, context, frame, runtime, (err) => {
|
|
584
|
+
if (err) {
|
|
585
|
+
cb(err, null);
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
cb(null, context.getExported());
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
compile() {
|
|
593
|
+
if (!this.compiled)
|
|
594
|
+
this._compile();
|
|
595
|
+
}
|
|
596
|
+
_compile() {
|
|
597
|
+
let props;
|
|
598
|
+
if (this.tmplProps) {
|
|
599
|
+
props = this.tmplProps;
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
const source = compiler.compile(this.tmplStr, this.env.asyncFilters, this.env.extensionsList, this.path, {});
|
|
603
|
+
lib_1.p.log('Source is: ', source);
|
|
604
|
+
const func = new Function(source); // eslint-disable-line no-new-func
|
|
605
|
+
props = func();
|
|
606
|
+
}
|
|
607
|
+
this.blocks = this._getBlocks(props);
|
|
608
|
+
this.rootRenderFunction = props.root;
|
|
609
|
+
this.compiled = true;
|
|
610
|
+
}
|
|
611
|
+
_getBlocks(props) {
|
|
612
|
+
var blocks = {};
|
|
613
|
+
Object.keys(props).forEach((k) => {
|
|
614
|
+
if (k.slice(0, 2) === 'b_') {
|
|
615
|
+
blocks[k.slice(2)] = props[k];
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
return blocks;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
exports.Template = Template;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.express = express;
|
|
7
|
+
//DONE: Sun 4th Jan 2026
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const lib_1 = require("./lib");
|
|
10
|
+
function express(env, app) {
|
|
11
|
+
let ext = '.html';
|
|
12
|
+
function NunjucksView(_name, opts) {
|
|
13
|
+
this.name = _name;
|
|
14
|
+
this.path = _name;
|
|
15
|
+
this.ext = path_1.default.extname(_name);
|
|
16
|
+
lib_1.p.err(_name, this.ext);
|
|
17
|
+
if (!this.ext) {
|
|
18
|
+
this.ext = '.html';
|
|
19
|
+
this.name = _name + this.ext;
|
|
20
|
+
lib_1.p.err(_name, path_1.default.extname(_name));
|
|
21
|
+
// throw new Error(
|
|
22
|
+
// 'No default engine was specified and no extension was provided.'
|
|
23
|
+
// );
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
NunjucksView.prototype.render = function render(opts, cb) {
|
|
27
|
+
lib_1.p.log('Trying to render');
|
|
28
|
+
env.render(this.name, opts, cb);
|
|
29
|
+
};
|
|
30
|
+
app.set('view', NunjucksView);
|
|
31
|
+
app.set('nunjucksEnv', env);
|
|
32
|
+
return env;
|
|
33
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare function batch(arr: any, lineCount: number, fillWith: number): any[];
|
|
2
|
+
export declare function center(str?: string, width?: number): string;
|
|
3
|
+
export declare function default_(val: any, def: any, bool?: boolean): any;
|
|
4
|
+
export declare const d: typeof default_;
|
|
5
|
+
export declare function dictsort(val: any, caseSensitive: boolean, by?: 'key' | 'value'): any[];
|
|
6
|
+
export declare const _escape: (str: string) => string;
|
|
7
|
+
export declare const e: (val: string) => string;
|
|
8
|
+
export declare const safe: (str?: string) => any;
|
|
9
|
+
export declare function forceescape(str: string): any;
|
|
10
|
+
export declare function groupby(this: any, arr: any[], attr: string): Record<string, any>;
|
|
11
|
+
export declare function indent(str: string, width: number, indentfirst: boolean): string;
|
|
12
|
+
export declare function join(arr: any[], del?: string, attr?: string): string;
|
|
13
|
+
export declare function length(str: string | Map<any, any> | Object | any[] | Set<any>): number;
|
|
14
|
+
export declare function list(val: string | object | any[]): any[];
|
|
15
|
+
export declare const random: (arr: any[]) => any;
|
|
16
|
+
export declare const reject: (a: any[], s: string, b: any) => any[];
|
|
17
|
+
export declare const select: (a: any[], s: string, b: any) => any[];
|
|
18
|
+
export declare function rejectattr(arr: any[], attr: string): any[];
|
|
19
|
+
export declare function selectattr(arr: any[], attr: string): any[];
|
|
20
|
+
export declare function replace(str: string | number, old: RegExp | number | string, new_: string, maxCount: number): string | number;
|
|
21
|
+
export declare function reverse(val?: any[]): string | any[];
|
|
22
|
+
export declare function round(val: number, precision?: number, method?: 'ceil' | 'floor' | 'round'): number;
|
|
23
|
+
export declare function slice(arr: any[], slices: number, fillWith?: boolean): any[];
|
|
24
|
+
export declare function sum(arr: any, attr: string, start?: number): any;
|
|
25
|
+
export declare const sort: (this: any, ...macroArgs: any[]) => any;
|
|
26
|
+
export declare const string: (obj: any) => string;
|
|
27
|
+
export declare function striptags(input?: string, preserveLinebreaks?: boolean): string;
|
|
28
|
+
export declare const title: (str?: string) => string;
|
|
29
|
+
export declare function truncate(input?: string, length?: number, killwords?: boolean, end?: string): string;
|
|
30
|
+
export declare const capitalize: (str?: string) => string;
|
|
31
|
+
export declare const upper: (str?: string) => string;
|
|
32
|
+
export declare const isUpper: (str: string) => boolean;
|
|
33
|
+
export declare function urlencode(obj: string | object | any[]): string;
|
|
34
|
+
export declare function urlize(str: string, length: number, nofollow: boolean): string;
|
|
35
|
+
export declare const wordcount: (str?: string) => number | null;
|
|
36
|
+
export declare function float(val: string, def: number): number;
|
|
37
|
+
export declare const isInt: (n: any) => boolean;
|
|
38
|
+
export declare const isFloat: (n: any) => boolean;
|
|
39
|
+
export declare const int: (this: any, ...macroArgs: any[]) => any;
|
|
40
|
+
export declare const trim: (str: string) => string;
|
|
41
|
+
export declare const first: (arr?: any[]) => any;
|
|
42
|
+
export declare const last: (arr?: any[]) => any;
|
|
43
|
+
export declare const lower: (str: string) => string;
|
|
44
|
+
export declare const nl2br: (str?: string) => string;
|