@handlebars/parser 2.1.0 → 2.2.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.
@@ -1,11 +1,11 @@
1
- import Visitor from './visitor';
1
+ import Visitor from './visitor.js';
2
2
 
3
3
  function WhitespaceControl(options = {}) {
4
4
  this.options = options;
5
5
  }
6
6
  WhitespaceControl.prototype = new Visitor();
7
7
 
8
- WhitespaceControl.prototype.Program = function(program) {
8
+ WhitespaceControl.prototype.Program = function (program) {
9
9
  const doStandalone = !this.options.ignoreStandalone;
10
10
 
11
11
  let isRoot = !this.isRootSeen;
@@ -62,88 +62,87 @@ WhitespaceControl.prototype.Program = function(program) {
62
62
  return program;
63
63
  };
64
64
 
65
- WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function(
66
- block
67
- ) {
68
- this.accept(block.program);
69
- this.accept(block.inverse);
70
-
71
- // Find the inverse program that is involed with whitespace stripping.
72
- let program = block.program || block.inverse,
73
- inverse = block.program && block.inverse,
74
- firstInverse = inverse,
75
- lastInverse = inverse;
76
-
77
- if (inverse && inverse.chained) {
78
- firstInverse = inverse.body[0].program;
79
-
80
- // Walk the inverse chain to find the last inverse that is actually in the chain.
81
- while (lastInverse.chained) {
82
- lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
83
- }
84
- }
65
+ WhitespaceControl.prototype.BlockStatement =
66
+ WhitespaceControl.prototype.DecoratorBlock =
67
+ WhitespaceControl.prototype.PartialBlockStatement =
68
+ function (block) {
69
+ this.accept(block.program);
70
+ this.accept(block.inverse);
71
+
72
+ // Find the inverse program that is involved with whitespace stripping.
73
+ let program = block.program || block.inverse,
74
+ inverse = block.program && block.inverse,
75
+ firstInverse = inverse,
76
+ lastInverse = inverse;
77
+
78
+ if (inverse && inverse.chained) {
79
+ firstInverse = inverse.body[0].program;
80
+
81
+ // Walk the inverse chain to find the last inverse that is actually in the chain.
82
+ while (lastInverse.chained) {
83
+ lastInverse = lastInverse.body[lastInverse.body.length - 1].program;
84
+ }
85
+ }
85
86
 
86
- let strip = {
87
- open: block.openStrip.open,
88
- close: block.closeStrip.close,
87
+ let strip = {
88
+ open: block.openStrip.open,
89
+ close: block.closeStrip.close,
89
90
 
90
- // Determine the standalone candiacy. Basically flag our content as being possibly standalone
91
- // so our parent can determine if we actually are standalone
92
- openStandalone: isNextWhitespace(program.body),
93
- closeStandalone: isPrevWhitespace((firstInverse || program).body)
94
- };
91
+ // Determine the standalone candidacy. Basically flag our content as being possibly standalone
92
+ // so our parent can determine if we actually are standalone
93
+ openStandalone: isNextWhitespace(program.body),
94
+ closeStandalone: isPrevWhitespace((firstInverse || program).body),
95
+ };
95
96
 
96
- if (block.openStrip.close) {
97
- omitRight(program.body, null, true);
98
- }
97
+ if (block.openStrip.close) {
98
+ omitRight(program.body, null, true);
99
+ }
99
100
 
100
- if (inverse) {
101
- let inverseStrip = block.inverseStrip;
101
+ if (inverse) {
102
+ let inverseStrip = block.inverseStrip;
102
103
 
103
- if (inverseStrip.open) {
104
- omitLeft(program.body, null, true);
105
- }
104
+ if (inverseStrip.open) {
105
+ omitLeft(program.body, null, true);
106
+ }
106
107
 
107
- if (inverseStrip.close) {
108
- omitRight(firstInverse.body, null, true);
109
- }
110
- if (block.closeStrip.open) {
111
- omitLeft(lastInverse.body, null, true);
112
- }
108
+ if (inverseStrip.close) {
109
+ omitRight(firstInverse.body, null, true);
110
+ }
111
+ if (block.closeStrip.open) {
112
+ omitLeft(lastInverse.body, null, true);
113
+ }
113
114
 
114
- // Find standalone else statments
115
- if (
116
- !this.options.ignoreStandalone &&
117
- isPrevWhitespace(program.body) &&
118
- isNextWhitespace(firstInverse.body)
119
- ) {
120
- omitLeft(program.body);
121
- omitRight(firstInverse.body);
122
- }
123
- } else if (block.closeStrip.open) {
124
- omitLeft(program.body, null, true);
125
- }
115
+ // Find standalone else statements
116
+ if (
117
+ !this.options.ignoreStandalone &&
118
+ isPrevWhitespace(program.body) &&
119
+ isNextWhitespace(firstInverse.body)
120
+ ) {
121
+ omitLeft(program.body);
122
+ omitRight(firstInverse.body);
123
+ }
124
+ } else if (block.closeStrip.open) {
125
+ omitLeft(program.body, null, true);
126
+ }
126
127
 
127
- return strip;
128
- };
128
+ return strip;
129
+ };
129
130
 
130
- WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function(
131
- mustache
132
- ) {
133
- return mustache.strip;
134
- };
131
+ WhitespaceControl.prototype.Decorator =
132
+ WhitespaceControl.prototype.MustacheStatement = function (mustache) {
133
+ return mustache.strip;
134
+ };
135
135
 
136
- WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function(
137
- node
138
- ) {
139
- /* istanbul ignore next */
140
- let strip = node.strip || {};
141
- return {
142
- inlineStandalone: true,
143
- open: strip.open,
144
- close: strip.close
136
+ WhitespaceControl.prototype.PartialStatement =
137
+ WhitespaceControl.prototype.CommentStatement = function (node) {
138
+ /* istanbul ignore next */
139
+ let strip = node.strip || {};
140
+ return {
141
+ inlineStandalone: true,
142
+ open: strip.open,
143
+ close: strip.close,
144
+ };
145
145
  };
146
- };
147
146
 
148
147
  function isPrevWhitespace(body, i, isRoot) {
149
148
  if (i === undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@handlebars/parser",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "The parser for the Handlebars language",
5
5
  "homepage": "https://github.com/handlebars-lang/handlebars-parser#readme",
6
6
  "bugs": {
@@ -12,56 +12,61 @@
12
12
  },
13
13
  "license": "ISC",
14
14
  "author": "",
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "require": {
19
+ "types": "./types/index.d.ts",
20
+ "default": "./dist/cjs/index.js"
21
+ },
22
+ "import": {
23
+ "types": "./types/index.d.ts",
24
+ "default": "./dist/esm/index.js"
25
+ },
26
+ "default": {
27
+ "types": "./types/index.d.ts",
28
+ "default": "./dist/cjs/index.js"
29
+ }
30
+ }
31
+ },
15
32
  "main": "dist/cjs/index.js",
16
33
  "module": "dist/esm/index.js",
17
34
  "types": "types/index.d.ts",
18
- "scripts": {
19
- "lint": "eslint .",
20
- "prepublishOnly": "npm run build",
21
- "build": "npm-run-all build:parser build:esm build:cjs",
22
- "build:cjs": "tsc --module commonjs --target es5 --outDir dist/cjs",
23
- "build:esm": "tsc --module es2015 --target es5 --outDir dist/esm",
24
- "build:jison": "jison -m js src/handlebars.yy src/handlebars.l -o lib/parser.js",
25
- "build:parser": "npm-run-all build:jison build:parser-suffix",
26
- "build:parser-suffix": "combine-files lib/parser.js,src/parser-suffix.js lib/parser.js",
27
- "test": "npm run build && mocha spec --require esm"
28
- },
29
35
  "prettier": {
30
- "tabWidth": 2,
31
36
  "semi": true,
32
- "singleQuote": true
37
+ "singleQuote": true,
38
+ "tabWidth": 2
33
39
  },
34
40
  "devDependencies": {
35
41
  "combine-files": "^1.1.8",
36
- "eslint": "^7.8.1",
37
- "eslint-config-prettier": "^6.11.0",
38
- "eslint-plugin-compat": "^3.8.0",
39
- "esm": "^3.2.25",
42
+ "eslint": "^8.57.1",
43
+ "eslint-config-prettier": "^8.10.0",
44
+ "eslint-plugin-compat": "^6.0.1",
40
45
  "jison": "^0.4.18",
41
- "mocha": "^8.1.3",
46
+ "mocha": "^10.7.3",
42
47
  "npm-run-all": "^4.1.5",
43
48
  "prettier": "^2.1.1",
44
- "release-it": "^14.0.2",
45
- "release-it-lerna-changelog": "^2.4.0",
46
- "typescript": "^4.0.2"
49
+ "release-plan": "^0.16.0",
50
+ "typescript": "^5.6.3"
51
+ },
52
+ "engines": {
53
+ "node": "^18 || ^20 || ^22 || >=24"
47
54
  },
48
55
  "publishConfig": {
49
56
  "access": "public",
50
57
  "registry": "https://registry.npmjs.org"
51
58
  },
52
- "release-it": {
53
- "plugins": {
54
- "release-it-lerna-changelog": {
55
- "infile": "CHANGELOG.md",
56
- "launchEditor": true
57
- }
58
- },
59
- "git": {
60
- "tagName": "v${version}"
61
- },
62
- "github": {
63
- "release": true,
64
- "tokenRef": "GITHUB_AUTH"
65
- }
59
+ "scripts": {
60
+ "lint": "eslint .",
61
+ "build": "npm-run-all build:parser build:esm build:cjs",
62
+ "build:cjs": "tsc --module nodenext --moduleResolution nodenext --target es5 --outDir dist/cjs",
63
+ "build:esm": "tsc --module es2015 --target es5 --outDir dist/esm",
64
+ "build:jison": "jison -m js src/handlebars.yy src/handlebars.l -o lib/parser.js",
65
+ "build:parser": "npm-run-all build:jison build:parser-suffix",
66
+ "build:parser-suffix": "combine-files lib/parser.js,src/parser-suffix.js lib/parser.js",
67
+ "pretest": "pnpm run build",
68
+ "test": "mocha --inline-diffs spec",
69
+ "pretest:bail": "pnpm run build",
70
+ "test:bail": "mocha --bail --inline-diffs spec"
66
71
  }
67
- }
72
+ }
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- extends: ['../.eslintrc.js'],
2
+ extends: ['../.eslintrc.cjs'],
3
3
  env: {
4
4
  mocha: true,
5
5
  },
package/spec/ast.js CHANGED
@@ -1,17 +1,17 @@
1
- import { parse, parseWithoutProcessing } from '../dist/esm';
2
- import { equals } from './utils';
1
+ import { parse, parseWithoutProcessing } from '../dist/esm/index.js';
2
+ import { equals } from './utils.js';
3
3
 
4
- describe('ast', function() {
5
- describe('whitespace control', function() {
6
- describe('parse', function() {
7
- it('mustache', function() {
4
+ describe('ast', function () {
5
+ describe('whitespace control', function () {
6
+ describe('parse', function () {
7
+ it('mustache', function () {
8
8
  let ast = parse(' {{~comment~}} ');
9
9
 
10
10
  equals(ast.body[0].value, '');
11
11
  equals(ast.body[2].value, '');
12
12
  });
13
13
 
14
- it('block statements', function() {
14
+ it('block statements', function () {
15
15
  let ast = parse(' {{# comment~}} \nfoo\n {{~/comment}}');
16
16
 
17
17
  equals(ast.body[0].value, '');
@@ -19,15 +19,15 @@ describe('ast', function() {
19
19
  });
20
20
  });
21
21
 
22
- describe('parseWithoutProcessing', function() {
23
- it('mustache', function() {
22
+ describe('parseWithoutProcessing', function () {
23
+ it('mustache', function () {
24
24
  let ast = parseWithoutProcessing(' {{~comment~}} ');
25
25
 
26
26
  equals(ast.body[0].value, ' ');
27
27
  equals(ast.body[2].value, ' ');
28
28
  });
29
29
 
30
- it('block statements', function() {
30
+ it('block statements', function () {
31
31
  let ast = parseWithoutProcessing(
32
32
  ' {{# comment~}} \nfoo\n {{~/comment}}'
33
33
  );
@@ -38,16 +38,68 @@ describe('ast', function() {
38
38
  });
39
39
  });
40
40
 
41
- describe('standalone flags', function() {
42
- describe('mustache', function() {
43
- it('does not mark mustaches as standalone', function() {
41
+ describe('node details', function () {
42
+ describe('paths', function () {
43
+ it('{{this}}', function () {
44
+ let path = parse('{{this}}').body[0].path;
45
+ equals(path.original, 'this');
46
+ equals(path.head, undefined);
47
+ equals(path.tail.length, 0);
48
+ equals(path.parts.length, 0);
49
+ });
50
+
51
+ it('{{this.bar}}', function () {
52
+ let path = parse('{{this.bar}}').body[0].path;
53
+ equals(path.original, 'this.bar');
54
+ equals(path.head, 'bar');
55
+ equals(path.tail.length, 0);
56
+ equals(path.parts.length, 1);
57
+ equals(path.parts[0], 'bar');
58
+ });
59
+
60
+ it('{{this.#bar}}', function () {
61
+ let path = parse('{{this.#bar}}').body[0].path;
62
+ equals(path.original, 'this.#bar');
63
+ equals(path.head, '#bar');
64
+ equals(path.tail.length, 0);
65
+ equals(path.parts.length, 1);
66
+ equals(path.parts[0], '#bar');
67
+ });
68
+
69
+ it('{{foo.bar}}', function () {
70
+ let path = parse('{{foo.bar}}').body[0].path;
71
+ equals(path.original, 'foo.bar');
72
+ equals(path.head, 'foo');
73
+ equals(path.tail.length, 1);
74
+ equals(path.tail[0], 'bar');
75
+ equals(path.parts.length, 2);
76
+ equals(path.parts[0], 'foo');
77
+ equals(path.parts[1], 'bar');
78
+ });
79
+
80
+ it('{{foo.#bar}}', function () {
81
+ let path = parse('{{foo.#bar}}').body[0].path;
82
+ equals(path.original, 'foo.#bar');
83
+ equals(path.head, 'foo');
84
+ equals(path.tail.length, 1);
85
+ equals(path.tail[0], '#bar');
86
+ equals(path.parts.length, 2);
87
+ equals(path.parts[0], 'foo');
88
+ equals(path.parts[1], '#bar');
89
+ });
90
+ });
91
+ });
92
+
93
+ describe('standalone flags', function () {
94
+ describe('mustache', function () {
95
+ it('does not mark mustaches as standalone', function () {
44
96
  let ast = parse(' {{comment}} ');
45
97
  equals(!!ast.body[0].value, true);
46
98
  equals(!!ast.body[2].value, true);
47
99
  });
48
100
  });
49
- describe('blocks - parseWithoutProcessing', function() {
50
- it('block mustaches', function() {
101
+ describe('blocks - parseWithoutProcessing', function () {
102
+ it('block mustaches', function () {
51
103
  let ast = parseWithoutProcessing(
52
104
  ' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '
53
105
  ),
@@ -60,15 +112,13 @@ describe('ast', function() {
60
112
 
61
113
  equals(ast.body[2].value, ' ');
62
114
  });
63
- it('initial block mustaches', function() {
64
- let ast = parseWithoutProcessing(
65
- '{{# comment}} \nfoo\n {{/comment}}'
66
- ),
115
+ it('initial block mustaches', function () {
116
+ let ast = parseWithoutProcessing('{{# comment}} \nfoo\n {{/comment}}'),
67
117
  block = ast.body[0];
68
118
 
69
119
  equals(block.program.body[0].value, ' \nfoo\n ');
70
120
  });
71
- it('mustaches with children', function() {
121
+ it('mustaches with children', function () {
72
122
  let ast = parseWithoutProcessing(
73
123
  '{{# comment}} \n{{foo}}\n {{/comment}}'
74
124
  ),
@@ -78,7 +128,7 @@ describe('ast', function() {
78
128
  equals(block.program.body[1].path.original, 'foo');
79
129
  equals(block.program.body[2].value, '\n ');
80
130
  });
81
- it('nested block mustaches', function() {
131
+ it('nested block mustaches', function () {
82
132
  let ast = parseWithoutProcessing(
83
133
  '{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} \n{{/foo}}'
84
134
  ),
@@ -90,7 +140,7 @@ describe('ast', function() {
90
140
  equals(block.program.body[0].value, ' \nfoo\n ');
91
141
  equals(block.inverse.body[0].value, ' \n bar \n ');
92
142
  });
93
- it('column 0 block mustaches', function() {
143
+ it('column 0 block mustaches', function () {
94
144
  let ast = parseWithoutProcessing(
95
145
  'test\n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '
96
146
  ),
@@ -104,8 +154,8 @@ describe('ast', function() {
104
154
  equals(ast.body[2].value, ' ');
105
155
  });
106
156
  });
107
- describe('blocks', function() {
108
- it('marks block mustaches as standalone', function() {
157
+ describe('blocks', function () {
158
+ it('marks block mustaches as standalone', function () {
109
159
  let ast = parse(
110
160
  ' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '
111
161
  ),
@@ -118,13 +168,13 @@ describe('ast', function() {
118
168
 
119
169
  equals(ast.body[2].value, '');
120
170
  });
121
- it('marks initial block mustaches as standalone', function() {
171
+ it('marks initial block mustaches as standalone', function () {
122
172
  let ast = parse('{{# comment}} \nfoo\n {{/comment}}'),
123
173
  block = ast.body[0];
124
174
 
125
175
  equals(block.program.body[0].value, 'foo\n');
126
176
  });
127
- it('marks mustaches with children as standalone', function() {
177
+ it('marks mustaches with children as standalone', function () {
128
178
  let ast = parse('{{# comment}} \n{{foo}}\n {{/comment}}'),
129
179
  block = ast.body[0];
130
180
 
@@ -132,7 +182,7 @@ describe('ast', function() {
132
182
  equals(block.program.body[1].path.original, 'foo');
133
183
  equals(block.program.body[2].value, '\n');
134
184
  });
135
- it('marks nested block mustaches as standalone', function() {
185
+ it('marks nested block mustaches as standalone', function () {
136
186
  let ast = parse(
137
187
  '{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} \n{{/foo}}'
138
188
  ),
@@ -146,7 +196,7 @@ describe('ast', function() {
146
196
 
147
197
  equals(body[0].value, '');
148
198
  });
149
- it('does not mark nested block mustaches as standalone', function() {
199
+ it('does not mark nested block mustaches as standalone', function () {
150
200
  let ast = parse(
151
201
  '{{#foo}} {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} {{/foo}}'
152
202
  ),
@@ -160,7 +210,7 @@ describe('ast', function() {
160
210
 
161
211
  equals(body[0].omit, undefined);
162
212
  });
163
- it('does not mark nested initial block mustaches as standalone', function() {
213
+ it('does not mark nested initial block mustaches as standalone', function () {
164
214
  let ast = parse(
165
215
  '{{#foo}}{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}}{{/foo}}'
166
216
  ),
@@ -173,7 +223,7 @@ describe('ast', function() {
173
223
  equals(body[0].omit, undefined);
174
224
  });
175
225
 
176
- it('marks column 0 block mustaches as standalone', function() {
226
+ it('marks column 0 block mustaches as standalone', function () {
177
227
  let ast = parse(
178
228
  'test\n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '
179
229
  ),
@@ -187,30 +237,30 @@ describe('ast', function() {
187
237
  equals(ast.body[2].value, '');
188
238
  });
189
239
  });
190
- describe('partials - parseWithoutProcessing', function() {
191
- it('simple partial', function() {
240
+ describe('partials - parseWithoutProcessing', function () {
241
+ it('simple partial', function () {
192
242
  let ast = parseWithoutProcessing('{{> partial }} ');
193
243
  equals(ast.body[1].value, ' ');
194
244
  });
195
- it('indented partial', function() {
245
+ it('indented partial', function () {
196
246
  let ast = parseWithoutProcessing(' {{> partial }} ');
197
247
  equals(ast.body[0].value, ' ');
198
248
  equals(ast.body[1].indent, '');
199
249
  equals(ast.body[2].value, ' ');
200
250
  });
201
251
  });
202
- describe('partials', function() {
203
- it('marks partial as standalone', function() {
252
+ describe('partials', function () {
253
+ it('marks partial as standalone', function () {
204
254
  let ast = parse('{{> partial }} ');
205
255
  equals(ast.body[1].value, '');
206
256
  });
207
- it('marks indented partial as standalone', function() {
257
+ it('marks indented partial as standalone', function () {
208
258
  let ast = parse(' {{> partial }} ');
209
259
  equals(ast.body[0].value, '');
210
260
  equals(ast.body[1].indent, ' ');
211
261
  equals(ast.body[2].value, '');
212
262
  });
213
- it('marks those around content as not standalone', function() {
263
+ it('marks those around content as not standalone', function () {
214
264
  let ast = parse('a{{> partial }}');
215
265
  equals(ast.body[0].omit, undefined);
216
266
 
@@ -218,28 +268,28 @@ describe('ast', function() {
218
268
  equals(ast.body[1].omit, undefined);
219
269
  });
220
270
  });
221
- describe('comments - parseWithoutProcessing', function() {
222
- it('simple comment', function() {
271
+ describe('comments - parseWithoutProcessing', function () {
272
+ it('simple comment', function () {
223
273
  let ast = parseWithoutProcessing('{{! comment }} ');
224
274
  equals(ast.body[1].value, ' ');
225
275
  });
226
- it('indented comment', function() {
276
+ it('indented comment', function () {
227
277
  let ast = parseWithoutProcessing(' {{! comment }} ');
228
278
  equals(ast.body[0].value, ' ');
229
279
  equals(ast.body[2].value, ' ');
230
280
  });
231
281
  });
232
- describe('comments', function() {
233
- it('marks comment as standalone', function() {
282
+ describe('comments', function () {
283
+ it('marks comment as standalone', function () {
234
284
  let ast = parse('{{! comment }} ');
235
285
  equals(ast.body[1].value, '');
236
286
  });
237
- it('marks indented comment as standalone', function() {
287
+ it('marks indented comment as standalone', function () {
238
288
  let ast = parse(' {{! comment }} ');
239
289
  equals(ast.body[0].value, '');
240
290
  equals(ast.body[2].value, '');
241
291
  });
242
- it('marks those around content as not standalone', function() {
292
+ it('marks those around content as not standalone', function () {
243
293
  let ast = parse('a{{! comment }}');
244
294
  equals(ast.body[0].omit, undefined);
245
295