@rhinostone/swig 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changes/v2.2.0.md +8 -0
- package/HISTORY.md +9 -0
- package/ROADMAP.md +7 -0
- package/dist/swig.js +120 -41
- package/dist/swig.min.js +2 -2
- package/dist/swig.min.js.map +1 -1
- package/lib/filters.js +23 -20
- package/lib/swig.js +13 -2
- package/lib/tags/import.js +42 -21
- package/lib/tags/include.js +4 -0
- package/package.json +2 -2
package/lib/swig.js
CHANGED
|
@@ -10,11 +10,11 @@ var utils = require('./utils'),
|
|
|
10
10
|
/**
|
|
11
11
|
* Swig version number as a string.
|
|
12
12
|
* @example
|
|
13
|
-
* if (swig.version === "2.
|
|
13
|
+
* if (swig.version === "2.2.0") { ... }
|
|
14
14
|
*
|
|
15
15
|
* @type {String}
|
|
16
16
|
*/
|
|
17
|
-
exports.version = "2.
|
|
17
|
+
exports.version = "2.2.0";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Swig Options Object. This object can be passed to many of the API-level Swig methods to control various aspects of the engine. All keys are optional.
|
|
@@ -201,6 +201,11 @@ exports.Swig = function (opts) {
|
|
|
201
201
|
* pre-resolved and will throw at render time as they would on the sync
|
|
202
202
|
* path.
|
|
203
203
|
*
|
|
204
|
+
* @deprecated since 2.2.0 — use {@link Swig#renderFile} with a loader that
|
|
205
|
+
* sets <code>loader.async === true</code>. The async-codegen dispatch
|
|
206
|
+
* handles dynamic include paths the pre-walker cannot. This method will
|
|
207
|
+
* be removed in 3.0.
|
|
208
|
+
*
|
|
204
209
|
* @example
|
|
205
210
|
* swig.setDefaults({ loader: myAsyncLoader });
|
|
206
211
|
* swig.renderFileAsync('page.html', { name: 'world' }, function (err, output) {
|
|
@@ -260,6 +265,12 @@ exports.Swig = function (opts) {
|
|
|
260
265
|
* temporarily swaps the loader on each call, so subsequent runtime
|
|
261
266
|
* <var>include</var>s resolve correctly without re-running the pre-walk.
|
|
262
267
|
*
|
|
268
|
+
* @deprecated since 2.2.0 — use {@link Swig#compileFile} with
|
|
269
|
+
* <code>options.codegenMode === 'async'</code> on a loader that sets
|
|
270
|
+
* <code>loader.async === true</code>. The returned compiled function
|
|
271
|
+
* yields a <code>Promise<{output, exports}></code> instead of a
|
|
272
|
+
* string. This method will be removed in 3.0.
|
|
273
|
+
*
|
|
263
274
|
* @example
|
|
264
275
|
* swig.compileFileAsync('page.html', {}, function (err, fn) {
|
|
265
276
|
* if (err) { return done(err); }
|
package/lib/tags/import.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var utils = require('../utils'),
|
|
2
|
+
ir = require('@rhinostone/swig-core/lib/ir'),
|
|
2
3
|
backend = require('@rhinostone/swig-core/lib/backend');
|
|
3
4
|
|
|
4
5
|
// CVE-2023-25345: prototype-chain properties that must not be used as import
|
|
@@ -26,7 +27,19 @@ var _dangerousProps = require('@rhinostone/swig-core/lib/security').dangerousPro
|
|
|
26
27
|
* @param {literal} as Literally, "as".
|
|
27
28
|
* @param {literal} varname Local-accessible object name to assign the macros to.
|
|
28
29
|
*/
|
|
29
|
-
exports.compile = function (compiler, args) {
|
|
30
|
+
exports.compile = function (compiler, args, content, parents, options) {
|
|
31
|
+
// Phase 2 (#T22): async-codegen branch. Parse stashed `[{path}, alias]`
|
|
32
|
+
// (no macro pre-render in async mode); emit IRImportDeferred so the
|
|
33
|
+
// backend's `_swig.getTemplate` + `.exports` bind happens at runtime.
|
|
34
|
+
if (options && options.codegenMode === 'async') {
|
|
35
|
+
var asyncAlias = args[args.length - 1];
|
|
36
|
+
var asyncPath = args[0].path;
|
|
37
|
+
return ir.importDeferred(
|
|
38
|
+
ir.literal('string', asyncPath),
|
|
39
|
+
asyncAlias,
|
|
40
|
+
options.filename || ''
|
|
41
|
+
);
|
|
42
|
+
}
|
|
30
43
|
var ctx = args.pop(),
|
|
31
44
|
allMacros = utils.map(args, function (arg) {
|
|
32
45
|
return arg.name;
|
|
@@ -56,37 +69,45 @@ exports.parse = function (str, line, parser, types, stack, opts, swig) {
|
|
|
56
69
|
var compiler = require('../parser').compile,
|
|
57
70
|
parseOpts = { resolveFrom: opts.filename },
|
|
58
71
|
compileOpts = utils.extend({}, opts, parseOpts),
|
|
59
|
-
|
|
72
|
+
isAsync = !!(opts && opts.codegenMode === 'async'),
|
|
73
|
+
importPath,
|
|
60
74
|
ctx;
|
|
61
75
|
|
|
62
76
|
parser.on(types.STRING, function (token) {
|
|
63
77
|
var self = this;
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// Phase 2 (#T15): macro.compile now returns an IRMacro node
|
|
74
|
-
// rather than a JS source string. Render it through the shared
|
|
75
|
-
// backend so import.js still gets the JS source it performs
|
|
76
|
-
// regex-surgery on for namespace-prefixing. The +'\n' trailing
|
|
77
|
-
// newline matches the pre-Phase-2 compile output exactly.
|
|
78
|
-
out += backend.compile([token.compile(compiler, token.args, token.content, [], compileOpts)], [], compileOpts) + '\n';
|
|
79
|
-
self.out.push({compiled: out, name: macroName});
|
|
80
|
-
});
|
|
78
|
+
if (importPath !== undefined) {
|
|
79
|
+
throw new Error('Unexpected string ' + token.match + ' on line ' + line + '.');
|
|
80
|
+
}
|
|
81
|
+
importPath = token.match.replace(/^("|')|("|')$/g, '');
|
|
82
|
+
|
|
83
|
+
if (isAsync) {
|
|
84
|
+
// Async mode: skip the sync parseFile + macro pre-render. Stash
|
|
85
|
+
// just the path; compile() emits IRImportDeferred.
|
|
86
|
+
self.out.push({ path: importPath });
|
|
81
87
|
return;
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
|
|
90
|
+
var tokens = swig.parseFile(importPath, parseOpts).tokens;
|
|
91
|
+
utils.each(tokens, function (token) {
|
|
92
|
+
var out = '',
|
|
93
|
+
macroName;
|
|
94
|
+
if (!token || token.name !== 'macro' || !token.compile) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
macroName = token.args[0];
|
|
98
|
+
// Phase 2 (#T15): macro.compile now returns an IRMacro node
|
|
99
|
+
// rather than a JS source string. Render it through the shared
|
|
100
|
+
// backend so import.js still gets the JS source it performs
|
|
101
|
+
// regex-surgery on for namespace-prefixing. The +'\n' trailing
|
|
102
|
+
// newline matches the pre-Phase-2 compile output exactly.
|
|
103
|
+
out += backend.compile([token.compile(compiler, token.args, token.content, [], compileOpts)], [], compileOpts) + '\n';
|
|
104
|
+
self.out.push({compiled: out, name: macroName});
|
|
105
|
+
});
|
|
85
106
|
});
|
|
86
107
|
|
|
87
108
|
parser.on(types.VAR, function (token) {
|
|
88
109
|
var self = this;
|
|
89
|
-
if (
|
|
110
|
+
if (importPath === undefined || ctx) {
|
|
90
111
|
throw new Error('Unexpected variable "' + token.match + '" on line ' + line + '.');
|
|
91
112
|
}
|
|
92
113
|
|
package/lib/tags/include.js
CHANGED
|
@@ -48,6 +48,10 @@ exports.compile = function (compiler, args, content, parents, options, blockName
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
if (options && options.codegenMode === 'async') {
|
|
52
|
+
return ir.includeDeferred(file, w || undefined, !!onlyCtx, !!ignoreMissing, parentFile);
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
return ir.include(file, w || undefined, !!onlyCtx, !!ignoreMissing, parentFile);
|
|
52
56
|
};
|
|
53
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhinostone/swig",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A simple, powerful, and extendable templating engine for node.js and browsers, similar to Django, Jinja2, and Twig.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"template",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"Rhinostone <contact@gina.io>"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@rhinostone/swig-core": "2.
|
|
24
|
+
"@rhinostone/swig-core": "2.2.0",
|
|
25
25
|
"terser": "^5.46.1",
|
|
26
26
|
"yargs": "^17.7.2"
|
|
27
27
|
},
|