@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.
Files changed (66) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +55 -0
  3. package/dist/scripts/smoke.d.ts +1 -0
  4. package/dist/scripts/smoke.js +95 -0
  5. package/dist/src/compiler.d.ts +12 -0
  6. package/dist/src/compiler.js +1050 -0
  7. package/dist/src/environment.d.ts +103 -0
  8. package/dist/src/environment.js +621 -0
  9. package/dist/src/express-app.d.ts +2 -0
  10. package/dist/src/express-app.js +33 -0
  11. package/dist/src/filters.d.ts +44 -0
  12. package/dist/src/filters.js +424 -0
  13. package/dist/src/globals.d.ts +14 -0
  14. package/dist/src/globals.js +342 -0
  15. package/dist/src/index.d.ts +28 -0
  16. package/dist/src/index.js +116 -0
  17. package/dist/src/interpreter.d.ts +16 -0
  18. package/dist/src/interpreter.js +489 -0
  19. package/dist/src/lexer.d.ts +72 -0
  20. package/dist/src/lexer.js +480 -0
  21. package/dist/src/lib.d.ts +74 -0
  22. package/dist/src/lib.js +237 -0
  23. package/dist/src/loader.d.ts +80 -0
  24. package/dist/src/loader.js +175 -0
  25. package/dist/src/nodes.d.ts +362 -0
  26. package/dist/src/nodes.js +894 -0
  27. package/dist/src/parser.d.ts +66 -0
  28. package/dist/src/parser.js +1068 -0
  29. package/dist/src/precompile.d.ts +15 -0
  30. package/dist/src/precompile.js +108 -0
  31. package/dist/src/runtime.d.ts +33 -0
  32. package/dist/src/runtime.js +314 -0
  33. package/dist/src/transformer.d.ts +3 -0
  34. package/dist/src/transformer.js +161 -0
  35. package/dist/src/types.d.ts +27 -0
  36. package/dist/src/types.js +2 -0
  37. package/dist/tests/compiler.test.d.ts +1 -0
  38. package/dist/tests/compiler.test.js +201 -0
  39. package/dist/tests/enviornment.test.d.ts +1 -0
  40. package/dist/tests/enviornment.test.js +279 -0
  41. package/dist/tests/express.test.d.ts +1 -0
  42. package/dist/tests/express.test.js +86 -0
  43. package/dist/tests/filters.test.d.ts +13 -0
  44. package/dist/tests/filters.test.js +286 -0
  45. package/dist/tests/globals.test.d.ts +1 -0
  46. package/dist/tests/globals.test.js +579 -0
  47. package/dist/tests/interpreter.test.d.ts +1 -0
  48. package/dist/tests/interpreter.test.js +208 -0
  49. package/dist/tests/lexer.test.d.ts +1 -0
  50. package/dist/tests/lexer.test.js +249 -0
  51. package/dist/tests/lib.test.d.ts +1 -0
  52. package/dist/tests/lib.test.js +236 -0
  53. package/dist/tests/loader.test.d.ts +1 -0
  54. package/dist/tests/loader.test.js +301 -0
  55. package/dist/tests/nodes.test.d.ts +1 -0
  56. package/dist/tests/nodes.test.js +137 -0
  57. package/dist/tests/parser.test.d.ts +1 -0
  58. package/dist/tests/parser.test.js +294 -0
  59. package/dist/tests/precompile.test.d.ts +1 -0
  60. package/dist/tests/precompile.test.js +224 -0
  61. package/dist/tests/runtime.test.d.ts +1 -0
  62. package/dist/tests/runtime.test.js +237 -0
  63. package/dist/tests/transformer.test.d.ts +1 -0
  64. package/dist/tests/transformer.test.js +125 -0
  65. package/dist/tsconfig.tsbuildinfo +1 -0
  66. 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,2 @@
1
+ import { Environment } from './environment';
2
+ export declare function express(env: Environment, app: any): Environment;
@@ -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;