@rhinostone/swig-twig 2.0.0-alpha.8 → 2.0.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 CHANGED
@@ -1,18 +1,16 @@
1
1
  @rhinostone/swig-twig
2
2
  =====================
3
3
 
4
- [![NPM version](http://img.shields.io/npm/v/@rhinostone/swig-twig.svg?style=flat)](https://www.npmjs.org/package/@rhinostone/swig-twig) [![Socket Badge](https://socket.dev/api/badge/npm/package/@rhinostone/swig-twig)](https://socket.dev/npm/package/@rhinostone/swig-twig)
4
+ [![NPM version](http://img.shields.io/npm/v/@rhinostone/swig-twig.svg?style=flat)](https://www.npmjs.com/package/@rhinostone/swig-twig) [![Socket Badge](https://socket.dev/api/badge/npm/package/@rhinostone/swig-twig)](https://socket.dev/npm/package/@rhinostone/swig-twig)
5
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.
6
+ Twig-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.
9
7
 
10
8
  Installation
11
9
  ------------
12
10
 
13
- npm install @rhinostone/swig-twig@alpha
11
+ npm install @rhinostone/swig-twig
14
12
 
15
- This pulls in `@rhinostone/swig-core` as a peer dependency, pinned to the matching alpha version. Do not mix alpha minors lockstep only.
13
+ This pulls in `@rhinostone/swig-core` as a peer dependency, pinned to the matching version. Frontends and the core release in lockstep — do not mix versions.
16
14
 
17
15
  Basic example
18
16
  -------------
@@ -26,8 +24,8 @@ var out = swig.render('Hello, {{ name|upper }}!', {
26
24
  // => Hello, WORLD!
27
25
  ```
28
26
 
29
- Supported surface (as of 2.0.0-alpha.5)
30
- ---------------------------------------
27
+ Supported surface (as of 2.0.0)
28
+ -------------------------------
31
29
 
32
30
  * **Tags** — `apply`, `block`, `extends`, `for`, `from`, `if`, `import`, `include`, `macro`, `set`, `verbatim`, `with`.
33
31
  * **Operators** — `..` range, `??` null-coalescing, `~` string concat, `is <test>` / `is not <test>`.
package/lib/lexer.js CHANGED
@@ -221,7 +221,7 @@ var rules = [
221
221
  {
222
222
  type: TYPES.NUMBER,
223
223
  regex: [
224
- /^[+\-]?\d+(\.\d+)?/
224
+ /^\d+(\.\d+)?/
225
225
  ]
226
226
  },
227
227
  {
package/lib/parser.js CHANGED
@@ -515,8 +515,16 @@ exports.parse = function (swig, source, opts, tags, filters) {
515
515
  escapeRegExp(cmtOpen) + anyChar + escapeRegExp(cmtClose) +
516
516
  ')'
517
517
  );
518
- var tagStrip = new RegExp('^' + escapeRegExp(tagOpen) + '\\s*|\\s*' + escapeRegExp(tagClose) + '$', 'g');
519
- var varStrip = new RegExp('^' + escapeRegExp(varOpen) + '\\s*|\\s*' + escapeRegExp(varClose) + '$', 'g');
518
+ // Twig/Jinja2 whitespace-control. `{{- -}}` / `{%- -%}` strip
519
+ // surrounding whitespace; the `-?` lives only adjacent to the open /
520
+ // close marker (post-#T23 shape — drop the inner `-?` after `\s*` so
521
+ // `{{ -5 }}` doesn't have its expression-`-` eaten as a strip marker).
522
+ var tagStrip = new RegExp('^' + escapeRegExp(tagOpen) + '-?\\s*|\\s*-?' + escapeRegExp(tagClose) + '$', 'g');
523
+ var varStrip = new RegExp('^' + escapeRegExp(varOpen) + '-?\\s*|\\s*-?' + escapeRegExp(varClose) + '$', 'g');
524
+ var tagStripBefore = new RegExp('^' + escapeRegExp(tagOpen) + '-');
525
+ var tagStripAfter = new RegExp('-' + escapeRegExp(tagClose) + '$');
526
+ var varStripBefore = new RegExp('^' + escapeRegExp(varOpen) + '-');
527
+ var varStripAfter = new RegExp('-' + escapeRegExp(varClose) + '$');
520
528
 
521
529
  var line = 1;
522
530
  var stack = [];
@@ -524,6 +532,29 @@ exports.parse = function (swig, source, opts, tags, filters) {
524
532
  var tokens = [];
525
533
  var blocks = {};
526
534
  var inVerbatim = false;
535
+ // Carries `-}}` / `-%}` strip-after intent across the chunk boundary.
536
+ // Consumed by the next text chunk (leading whitespace stripped, flag
537
+ // reset). Mirrors native lib/parser.js's closure-scoped `stripNext`.
538
+ var stripNext = false;
539
+
540
+ /**
541
+ * If the previous token is a Text IR node, strip its trailing
542
+ * whitespace in-place. No-op for non-Text tokens.
543
+ *
544
+ * Mirrors lib/parser.js's stripPrevToken — same one-level-deep
545
+ * limitation: a `{%- endif %}` only strips the trailing whitespace of
546
+ * the last child of the immediately enclosing tag, not deeper.
547
+ *
548
+ * @param {object} token IR node (typed), possibly a Text node.
549
+ * @return {object} Same node; mutated when `type === 'Text'`.
550
+ * @private
551
+ */
552
+ function stripPrevToken(token) {
553
+ if (token && token.type === 'Text' && typeof token.value === 'string') {
554
+ token.value = token.value.replace(/\s*$/, '');
555
+ }
556
+ return token;
557
+ }
527
558
 
528
559
  /**
529
560
  * Build an IROutput node for a `{{ … }}` chunk.
@@ -628,13 +659,17 @@ exports.parse = function (swig, source, opts, tags, filters) {
628
659
  }
629
660
 
630
661
  utils.each(source.split(splitter), function (chunk) {
631
- var token, lines;
662
+ var token, lines, stripPrev, prevToken, prevChildToken;
632
663
 
633
664
  if (!chunk) { return; }
634
665
 
635
666
  if (!inVerbatim && utils.startsWith(chunk, varOpen) && utils.endsWith(chunk, varClose)) {
667
+ stripPrev = varStripBefore.test(chunk);
668
+ stripNext = varStripAfter.test(chunk);
636
669
  token = parseVariable(chunk.replace(varStrip, ''), line);
637
670
  } else if (utils.startsWith(chunk, tagOpen) && utils.endsWith(chunk, tagClose)) {
671
+ stripPrev = tagStripBefore.test(chunk);
672
+ stripNext = tagStripAfter.test(chunk);
638
673
  token = parseTag(chunk.replace(tagStrip, ''), line);
639
674
  if (token) {
640
675
  if (token.name === 'extends') {
@@ -654,9 +689,28 @@ exports.parse = function (swig, source, opts, tags, filters) {
654
689
  line += lines ? lines.length : 0;
655
690
  return;
656
691
  } else {
692
+ if (stripNext) {
693
+ chunk = chunk.replace(/^\s*/, '');
694
+ stripNext = false;
695
+ }
657
696
  token = ir.text(chunk);
658
697
  }
659
698
 
699
+ // `{{-` / `{%-` strips the previous text chunk's trailing whitespace.
700
+ // Mirrors lib/parser.js: pop tokens.last; if it's a Text node strip
701
+ // it directly, else if it carries `.content` (a tag with body) drill
702
+ // one level into its last child. One-level-deep — matches native.
703
+ if (stripPrev && tokens.length) {
704
+ prevToken = tokens.pop();
705
+ if (prevToken && prevToken.type === 'Text') {
706
+ prevToken = stripPrevToken(prevToken);
707
+ } else if (prevToken && prevToken.content && prevToken.content.length) {
708
+ prevChildToken = stripPrevToken(prevToken.content.pop());
709
+ prevToken.content.push(prevChildToken);
710
+ }
711
+ tokens.push(prevToken);
712
+ }
713
+
660
714
  if (token) {
661
715
  if (stack.length) {
662
716
  stack[stack.length - 1].content.push(token);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rhinostone/swig-twig",
3
- "version": "2.0.0-alpha.8",
4
- "description": "Twig frontend for the @rhinostone/swig-core template engine. Phase 3 of the multi-flavor architecture (see @rhinostone/swig #T16).",
3
+ "version": "2.0.1",
4
+ "description": "Twig-syntax frontend for the @rhinostone/swig-core template engine. Part of the @rhinostone/swig multi-flavor family.",
5
5
  "keywords": [
6
6
  "template",
7
7
  "templating",
@@ -22,7 +22,7 @@
22
22
  "node": ">=12"
23
23
  },
24
24
  "peerDependencies": {
25
- "@rhinostone/swig-core": "2.0.0-alpha.8"
25
+ "@rhinostone/swig-core": "2.0.1"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"