@rhinostone/swig-twig 2.0.0-alpha.5 → 2.0.0-alpha.8
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/README.md +53 -0
- package/lib/filters.js +0 -4
- package/lib/index.js +0 -32
- package/lib/parser.js +1 -2
- package/lib/tags/block.js +1 -2
- package/lib/tags/import.js +2 -4
- package/lib/tags/macro.js +2 -3
- package/lib/tags/set.js +1 -2
- package/lib/tokentypes.js +0 -3
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@rhinostone/swig-twig
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.org/package/@rhinostone/swig-twig) [](https://socket.dev/npm/package/@rhinostone/swig-twig)
|
|
5
|
+
|
|
6
|
+
> **Experimental alpha.** The render pipeline is wired end-to-end and the Twig render corpus passes, but the IR ABI is not stable across alpha minors. `2.0.0` stable is the target for production use.
|
|
7
|
+
|
|
8
|
+
Twig frontend for the [@rhinostone/swig-core](https://www.npmjs.com/package/@rhinostone/swig-core) template engine. See #T16 in [ROADMAP.md](https://github.com/gina-io/swig/blob/develop/ROADMAP.md) for the multi-flavor roadmap.
|
|
9
|
+
|
|
10
|
+
Installation
|
|
11
|
+
------------
|
|
12
|
+
|
|
13
|
+
npm install @rhinostone/swig-twig@alpha
|
|
14
|
+
|
|
15
|
+
This pulls in `@rhinostone/swig-core` as a peer dependency, pinned to the matching alpha version. Do not mix alpha minors — lockstep only.
|
|
16
|
+
|
|
17
|
+
Basic example
|
|
18
|
+
-------------
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
var swig = require('@rhinostone/swig-twig');
|
|
22
|
+
|
|
23
|
+
var out = swig.render('Hello, {{ name|upper }}!', {
|
|
24
|
+
locals: { name: 'world' }
|
|
25
|
+
});
|
|
26
|
+
// => Hello, WORLD!
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Supported surface (as of 2.0.0-alpha.5)
|
|
30
|
+
---------------------------------------
|
|
31
|
+
|
|
32
|
+
* **Tags** — `apply`, `block`, `extends`, `for`, `from`, `if`, `import`, `include`, `macro`, `set`, `verbatim`, `with`.
|
|
33
|
+
* **Operators** — `..` range, `??` null-coalescing, `~` string concat, `is <test>` / `is not <test>`.
|
|
34
|
+
* **Built-in `is` tests** — `defined`, `null`, `empty`, `iterable`, `odd`, `even`, `divisibleby`.
|
|
35
|
+
* **Filters** — the Twig core overlaps (length, lower, upper, first, last, join, reverse, sort, striptags, url_encode, json_encode, raw, escape / e, slice, split, batch, trim, number_format, replace, keys, format, merge, date). See `lib/filters.js` for the full list.
|
|
36
|
+
|
|
37
|
+
Explicitly unsupported (parse-time throw)
|
|
38
|
+
-----------------------------------------
|
|
39
|
+
|
|
40
|
+
* `{% sandbox %}` — security-sandbox tag, out of scope.
|
|
41
|
+
* Macro kwargs — use positional args.
|
|
42
|
+
* `{% use %}` — not implemented.
|
|
43
|
+
* `{% deprecated %}` — not implemented; use comment pragmas.
|
|
44
|
+
|
|
45
|
+
Repository
|
|
46
|
+
----------
|
|
47
|
+
|
|
48
|
+
Source: [gina-io/swig/packages/swig-twig](https://github.com/gina-io/swig/tree/develop/packages/swig-twig). File issues and PRs at [gina-io/swig](https://github.com/gina-io/swig).
|
|
49
|
+
|
|
50
|
+
License
|
|
51
|
+
-------
|
|
52
|
+
|
|
53
|
+
MIT. See [LICENSE](https://github.com/gina-io/swig/blob/develop/LICENSE) in the monorepo root.
|
package/lib/filters.js
CHANGED
|
@@ -16,10 +16,6 @@ var utils = require('@rhinostone/swig-core/lib/utils'),
|
|
|
16
16
|
* prototype chain, so CVE-2023-25345 guards don't apply at this layer.
|
|
17
17
|
* Filter arg expressions inherit the expression parser's existing
|
|
18
18
|
* `_dangerousProps` guards.
|
|
19
|
-
*
|
|
20
|
-
* See .claude/architecture/tags-and-filters.md § Filters and
|
|
21
|
-
* .claude/architecture/multi-flavor-ir.md § Filter catalogs stay
|
|
22
|
-
* per-flavor.
|
|
23
19
|
*/
|
|
24
20
|
|
|
25
21
|
/**
|
package/lib/index.js
CHANGED
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
* exposes a Twig constructor + default instance via `engine.install(self,
|
|
6
6
|
* frontend)` from @rhinostone/swig-core, so callers can `render(source,
|
|
7
7
|
* locals)` / `renderFile(path, locals, cb)` directly against Twig syntax.
|
|
8
|
-
*
|
|
9
|
-
* See .claude/architecture/multi-flavor-ir.md § Phase 3 for the per-flavor
|
|
10
|
-
* split decision.
|
|
11
8
|
*/
|
|
12
9
|
|
|
13
10
|
var utils = require('@rhinostone/swig-core/lib/utils'),
|
|
@@ -192,32 +189,3 @@ exports.invalidateCache = defaultInstance.invalidateCache;
|
|
|
192
189
|
* app.set('view engine', 'twig');
|
|
193
190
|
*/
|
|
194
191
|
exports.__express = defaultInstance.renderFile;
|
|
195
|
-
|
|
196
|
-
var _parseDeprecationWarned = false;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Parse a Twig source string into the parse-tree shape consumed by
|
|
200
|
-
* swig-core's `engine.compile`: `{ name, parent, tokens, blocks }`.
|
|
201
|
-
*
|
|
202
|
-
* @deprecated since 2.0.0-alpha.4 — use `new exports.Twig(opts)` and the
|
|
203
|
-
* per-instance `precompile` / `compile` / `render` surface installed by
|
|
204
|
-
* `engine.install`. Slated for removal in `2.0.0` stable. The full-instance
|
|
205
|
-
* path uses closure-captured tag/filter maps and honors `setFilter` /
|
|
206
|
-
* `setTag` overrides; this Path B wrapper does not.
|
|
207
|
-
*
|
|
208
|
-
* @param {string} source Twig template source.
|
|
209
|
-
* @param {object} [options] Per-call options.
|
|
210
|
-
* @return {object} `{ name, parent, tokens, blocks }`.
|
|
211
|
-
*/
|
|
212
|
-
exports.parse = function (source, options) {
|
|
213
|
-
if (!_parseDeprecationWarned) {
|
|
214
|
-
_parseDeprecationWarned = true;
|
|
215
|
-
if (typeof console !== 'undefined' && console.warn) {
|
|
216
|
-
console.warn('[@rhinostone/swig-twig] exports.parse is deprecated and will be removed in 2.0.0. Use `new twig.Twig(opts)` and the per-instance precompile/compile/render API instead.');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
options = options || {};
|
|
220
|
-
var tags = options.tags || exports.tags;
|
|
221
|
-
var filters = options.filters || exports.filters;
|
|
222
|
-
return exports.parser.parse(undefined, source, options, tags, filters);
|
|
223
|
-
};
|
package/lib/parser.js
CHANGED
|
@@ -32,8 +32,7 @@ var _reserved = ['break', 'case', 'catch', 'continue', 'debugger', 'default', 'd
|
|
|
32
32
|
* CVE-2023-25345 guards (`_dangerousProps`) fire on VAR path segments,
|
|
33
33
|
* DOTKEY matches, STRING-inside-BRACKETOPEN values, and
|
|
34
34
|
* FUNCTION/FUNCTIONEMPTY callee names — same checkpoints as the native
|
|
35
|
-
* frontend.
|
|
36
|
-
* across layers.
|
|
35
|
+
* frontend.
|
|
37
36
|
*
|
|
38
37
|
* Binding-power table:
|
|
39
38
|
*
|
package/lib/tags/block.js
CHANGED
|
@@ -22,8 +22,7 @@
|
|
|
22
22
|
* `_dangerousProps`. A `{% block __proto__ %}` in native Swig would
|
|
23
23
|
* key the blocks map by that name; the override path does not currently
|
|
24
24
|
* reach the prototype chain but the cross-layer invariant is to guard
|
|
25
|
-
* anyway.
|
|
26
|
-
* Session 9 native hardening follow-up.
|
|
25
|
+
* anyway.
|
|
27
26
|
*/
|
|
28
27
|
|
|
29
28
|
var ir = require('@rhinostone/swig-core/lib/ir');
|
package/lib/tags/import.js
CHANGED
|
@@ -26,10 +26,8 @@
|
|
|
26
26
|
*
|
|
27
27
|
* The alias is a bare identifier — dotted paths are rejected at parse
|
|
28
28
|
* time, and CVE-2023-25345 prototype-chain names are rejected before
|
|
29
|
-
* the namespace assignment.
|
|
30
|
-
*
|
|
31
|
-
* binding slots reject any `.` in the match before the
|
|
32
|
-
* `_dangerousProps` check.
|
|
29
|
+
* the namespace assignment. Single-name binding slots reject any `.`
|
|
30
|
+
* in the match before the `_dangerousProps` check.
|
|
33
31
|
*/
|
|
34
32
|
|
|
35
33
|
var utils = require('@rhinostone/swig-core/lib/utils');
|
package/lib/tags/macro.js
CHANGED
|
@@ -13,9 +13,8 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Param names and the macro name are bare identifiers — dotted paths
|
|
15
15
|
* (`foo.bar`) and CVE-2023-25345 prototype-chain names (`__proto__`,
|
|
16
|
-
* `constructor`, `prototype`) are rejected at parse time.
|
|
17
|
-
*
|
|
18
|
-
* single-name binding slots reject any `.` in the match before the
|
|
16
|
+
* `constructor`, `prototype`) are rejected at parse time. Single-name
|
|
17
|
+
* binding slots reject any `.` in the match before the
|
|
19
18
|
* `_dangerousProps` check.
|
|
20
19
|
*
|
|
21
20
|
* Twig kwargs (`{% macro foo(a=1, b="x") %}`) are deferred — Phase 4 with
|
package/lib/tags/set.js
CHANGED
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
*
|
|
33
33
|
* CVE-2023-25345 checkpoints apply twice — here on the LHS path
|
|
34
34
|
* segments, and again in the backend `checkDangerousSegment` walk —
|
|
35
|
-
*
|
|
36
|
-
* is duplicated across layers.
|
|
35
|
+
* intentional defense-in-depth during the migration.
|
|
37
36
|
*/
|
|
38
37
|
|
|
39
38
|
var ir = require('@rhinostone/swig-core/lib/ir');
|
package/lib/tokentypes.js
CHANGED
|
@@ -15,9 +15,6 @@
|
|
|
15
15
|
* rules without renumbering. Keeping the layout stable up front avoids
|
|
16
16
|
* silent ID collisions across in-flight flavor work.
|
|
17
17
|
*
|
|
18
|
-
* See .claude/architecture/multi-flavor-ir.md § Phase 3 for the
|
|
19
|
-
* per-flavor split decision.
|
|
20
|
-
*
|
|
21
18
|
* @readonly
|
|
22
19
|
* @enum {number}
|
|
23
20
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhinostone/swig-twig",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.8",
|
|
4
4
|
"description": "Twig frontend for the @rhinostone/swig-core template engine. Phase 3 of the multi-flavor architecture (see @rhinostone/swig #T16).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"template",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"node": ">=12"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@rhinostone/swig-core": "2.0.0-alpha.
|
|
25
|
+
"@rhinostone/swig-core": "2.0.0-alpha.8"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|