@rhinostone/swig-jinja2 2.8.4 → 2.9.1
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 +1 -1
- package/lib/filters.js +26 -10
- package/lib/index.js +1 -1
- package/lib/lexer.js +1 -1
- package/lib/parser.js +26 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@rhinostone/swig-jinja2
|
|
2
2
|
=======================
|
|
3
3
|
|
|
4
|
-
[](https://www.npmjs.com/package/@rhinostone/swig-jinja2) [](https://socket.dev/npm/package/@rhinostone/swig-jinja2)
|
|
4
|
+
[](https://www.npmjs.com/package/@rhinostone/swig-jinja2) [](https://socket.dev/npm/package/@rhinostone/swig-jinja2) [](https://scorecard.dev/viewer/?uri=github.com/gina-io/swig)
|
|
5
5
|
|
|
6
6
|
Jinja2-syntax frontend for the [@rhinostone/swig-core](https://www.npmjs.com/package/@rhinostone/swig-core) template engine. Part of the multi-flavor architecture introduced in `2.0.0` — see [ROADMAP.md](https://github.com/gina-io/swig/blob/develop/ROADMAP.md) for the release narrative.
|
|
7
7
|
|
package/lib/filters.js
CHANGED
|
@@ -611,11 +611,16 @@ exports.striptags = function (input) {
|
|
|
611
611
|
if (out !== undefined) {
|
|
612
612
|
return out;
|
|
613
613
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
614
|
+
// The comment and tag regexes take time quadratic in the input length on
|
|
615
|
+
// many <!-- or < with no --> or > after them, and the trailing \s+$ on a
|
|
616
|
+
// long run of whitespace; the swig-core helpers give the same output in
|
|
617
|
+
// linear time.
|
|
618
|
+
// return String(input)
|
|
619
|
+
// .replace(/<!--[\s\S]*?-->/g, '')
|
|
620
|
+
// .replace(/<[^>]*>/g, '')
|
|
621
|
+
// .replace(/\s+/g, ' ')
|
|
622
|
+
// .replace(/^\s+|\s+$/g, '');
|
|
623
|
+
return utils.strip(utils.stripTags(utils.stripComments(String(input)), true).replace(/\s+/g, ' '));
|
|
619
624
|
};
|
|
620
625
|
|
|
621
626
|
/**
|
|
@@ -645,9 +650,13 @@ exports.trim = function (input, chars) {
|
|
|
645
650
|
} else {
|
|
646
651
|
pattern = '[' + String(chars).replace(/[\\\[\]\^\-]/g, '\\$&') + ']';
|
|
647
652
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
653
|
+
// A pattern + '+$' regex takes quadratic time on a long run of trimmed
|
|
654
|
+
// characters inside the string; trimEnd removes the same code units in
|
|
655
|
+
// linear time.
|
|
656
|
+
// return input
|
|
657
|
+
// .replace(new RegExp('^' + pattern + '+'), '')
|
|
658
|
+
// .replace(new RegExp(pattern + '+$'), '');
|
|
659
|
+
return utils.trimEnd(input.replace(new RegExp('^' + pattern + '+'), ''), pattern === '\\s' ? undefined : String(chars));
|
|
651
660
|
};
|
|
652
661
|
|
|
653
662
|
/**
|
|
@@ -753,7 +762,14 @@ function formatGeneral(num, prec) {
|
|
|
753
762
|
*/
|
|
754
763
|
function sprintf(fmt, args) {
|
|
755
764
|
var idx = 0;
|
|
756
|
-
|
|
765
|
+
// The flags and the width both take zeros, so on a % followed by a long run
|
|
766
|
+
// of zeros and no conversion this regex backtracked over every split,
|
|
767
|
+
// taking quadratic time. Each lookahead below captures its run once and
|
|
768
|
+
// the backreference consumes it, so nothing backtracks; the matches are
|
|
769
|
+
// the same, except that an absent width is "" instead of undefined, which
|
|
770
|
+
// the callback reads the same way.
|
|
771
|
+
// return fmt.replace(/%([-+ 0]*)(\d+)?(?:\.(\d+))?([sdiufFeEgGxXoc%])/g, function (m, flags, width, prec, conv) {
|
|
772
|
+
return fmt.replace(/%(?=([-+ 0]*))\1(?=(\d*))\2(?:\.(?=(\d+))\3)?([sdiufFeEgGxXoc%])/g, function (m, flags, width, prec, conv) {
|
|
757
773
|
var arg, hasPrec, sign, s, num, pad;
|
|
758
774
|
|
|
759
775
|
function withSign(value) {
|
|
@@ -1179,7 +1195,7 @@ exports.slice = function (input, slices, fill) {
|
|
|
1179
1195
|
* and `reverse` flips the order.
|
|
1180
1196
|
*
|
|
1181
1197
|
* @example
|
|
1182
|
-
* {% for
|
|
1198
|
+
* {% for p in {"b":2,"a":1}|dictsort %}{{ p[0] }}={{ p[1] }};{% endfor %}
|
|
1183
1199
|
* // => a=1;b=2;
|
|
1184
1200
|
*
|
|
1185
1201
|
* @param {object} input
|
package/lib/index.js
CHANGED
package/lib/lexer.js
CHANGED
package/lib/parser.js
CHANGED
|
@@ -21,6 +21,27 @@ function escapeRegExp(str) {
|
|
|
21
21
|
*/
|
|
22
22
|
var _reserved = ['break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new', 'return', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with'];
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Build the IR of `left in right`, or of `left not in right` when `negate`
|
|
26
|
+
* is set: a BinaryOp `in` flagged with this flavor's name, so swig-core
|
|
27
|
+
* emits Jinja2's membership test (`_utils.isIn`) instead of the JavaScript
|
|
28
|
+
* `in` operator, which tests keys.
|
|
29
|
+
*
|
|
30
|
+
* @param {object} left The needle.
|
|
31
|
+
* @param {object} right The container.
|
|
32
|
+
* @param {boolean} [negate] The `not in` form.
|
|
33
|
+
* @return {object} IRBinaryOp.
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
function membership(left, right, negate) {
|
|
37
|
+
var node = ir.binaryOp('in', left, right);
|
|
38
|
+
node.membership = 'jinja2';
|
|
39
|
+
if (negate) {
|
|
40
|
+
node.negate = true;
|
|
41
|
+
}
|
|
42
|
+
return node;
|
|
43
|
+
}
|
|
44
|
+
|
|
24
45
|
/**
|
|
25
46
|
* Jinja2 expression parser — Pratt-style recursive descent.
|
|
26
47
|
*
|
|
@@ -110,6 +131,9 @@ exports.parseExpr = function (tokens, filters, _posOut) {
|
|
|
110
131
|
if (m === '===' || m === '!==' || m === '==' || m === '!=') {
|
|
111
132
|
return { op: m, prec: 3 };
|
|
112
133
|
}
|
|
134
|
+
if (/^not\s+in$/.test(m)) {
|
|
135
|
+
return { op: 'not in', prec: 4 };
|
|
136
|
+
}
|
|
113
137
|
return { op: m, prec: 4 };
|
|
114
138
|
}
|
|
115
139
|
if (tok.type === _t.OPERATOR) {
|
|
@@ -468,6 +492,8 @@ exports.parseExpr = function (tokens, filters, _posOut) {
|
|
|
468
492
|
// Math.floor(a / b). Matches Python `//` for ints and floats,
|
|
469
493
|
// including negative operands (floors toward negative infinity).
|
|
470
494
|
left = ir.fnCall(ir.varRef(['Math', 'floor']), [ir.binaryOp('/', left, right)]);
|
|
495
|
+
} else if (info.op === 'in' || info.op === 'not in') {
|
|
496
|
+
left = membership(left, right, info.op === 'not in');
|
|
471
497
|
} else {
|
|
472
498
|
left = ir.binaryOp(info.op, left, right);
|
|
473
499
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhinostone/swig-jinja2",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"description": "Jinja2-syntax frontend for the @rhinostone/swig-core template engine. Part of the @rhinostone/swig multi-flavor family.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"template",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"node": ">=12"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@rhinostone/swig-core": "2.
|
|
26
|
+
"@rhinostone/swig-core": "2.9.1"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|