edgexpress 3.0.0 → 3.0.2

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.
Files changed (92) hide show
  1. package/eslint.config.cjs +6 -0
  2. package/examples/index.js +41 -0
  3. package/examples/views/components/layout/main.edge +26 -0
  4. package/examples/views/components/modal.edge +27 -0
  5. package/examples/views/home.edge +84 -0
  6. package/examples/views/partials/button.edge +1 -0
  7. package/examples/views/partials/home-footer.edge +49 -0
  8. package/examples/views/partials/home-header.edge +61 -0
  9. package/examples/views/welcome.edge +22 -0
  10. package/index.d.ts +7 -0
  11. package/package.json +12 -4
  12. package/src/cache_manager.d.ts +28 -0
  13. package/src/cache_manager.js +58 -0
  14. package/src/compiler.d.ts +73 -0
  15. package/src/compiler.js +319 -0
  16. package/src/component/props.d.ts +53 -0
  17. package/src/component/props.js +110 -0
  18. package/src/edge/globals.d.ts +5 -0
  19. package/src/edge/globals.js +95 -0
  20. package/src/edge/main.d.ts +192 -0
  21. package/src/edge/main.js +334 -0
  22. package/src/edge/renderer.d.ts +44 -0
  23. package/src/edge/renderer.js +85 -0
  24. package/src/edge/stacks.d.ts +22 -0
  25. package/src/edge/stacks.js +98 -0
  26. package/src/loader.d.ts +138 -0
  27. package/src/loader.js +347 -0
  28. package/src/migrate/globals.d.ts +1 -0
  29. package/src/migrate/globals.js +100 -0
  30. package/src/migrate/plugin.d.ts +2 -0
  31. package/src/migrate/plugin.js +58 -0
  32. package/src/migrate/props.d.ts +66 -0
  33. package/src/migrate/props.js +129 -0
  34. package/src/migrate/tags/layout.d.ts +6 -0
  35. package/src/migrate/tags/layout.js +25 -0
  36. package/src/migrate/tags/main.d.ts +4 -0
  37. package/src/migrate/tags/main.js +19 -0
  38. package/src/migrate/tags/section.d.ts +6 -0
  39. package/src/migrate/tags/section.js +23 -0
  40. package/src/migrate/tags/set.d.ts +26 -0
  41. package/src/migrate/tags/set.js +104 -0
  42. package/src/migrate/tags/super.d.ts +9 -0
  43. package/src/migrate/tags/super.js +31 -0
  44. package/src/plugins/supercharged.d.ts +4 -0
  45. package/src/plugins/supercharged.js +88 -0
  46. package/src/processor.d.ts +42 -0
  47. package/src/processor.js +86 -0
  48. package/src/tags/assign.d.ts +5 -0
  49. package/src/tags/assign.js +42 -0
  50. package/src/tags/component.d.ts +6 -0
  51. package/src/tags/component.js +299 -0
  52. package/src/tags/debugger.d.ts +5 -0
  53. package/src/tags/debugger.js +26 -0
  54. package/src/tags/each.d.ts +20 -0
  55. package/src/tags/each.js +185 -0
  56. package/src/tags/else.d.ts +2 -0
  57. package/src/tags/else.js +22 -0
  58. package/src/tags/else_if.d.ts +7 -0
  59. package/src/tags/else_if.js +39 -0
  60. package/src/tags/eval.d.ts +7 -0
  61. package/src/tags/eval.js +30 -0
  62. package/src/tags/if.d.ts +5 -0
  63. package/src/tags/if.js +45 -0
  64. package/src/tags/include.d.ts +27 -0
  65. package/src/tags/include.js +78 -0
  66. package/src/tags/include_if.d.ts +10 -0
  67. package/src/tags/include_if.js +61 -0
  68. package/src/tags/inject.d.ts +6 -0
  69. package/src/tags/inject.js +40 -0
  70. package/src/tags/let.d.ts +6 -0
  71. package/src/tags/let.js +69 -0
  72. package/src/tags/main.d.ts +18 -0
  73. package/src/tags/main.js +47 -0
  74. package/src/tags/new_error.d.ts +6 -0
  75. package/src/tags/new_error.js +47 -0
  76. package/src/tags/push_once_to.d.ts +13 -0
  77. package/src/tags/push_once_to.js +65 -0
  78. package/src/tags/push_to.d.ts +7 -0
  79. package/src/tags/push_to.js +62 -0
  80. package/src/tags/slot.d.ts +6 -0
  81. package/src/tags/slot.js +29 -0
  82. package/src/tags/stack.d.ts +5 -0
  83. package/src/tags/stack.js +38 -0
  84. package/src/tags/unless.d.ts +12 -0
  85. package/src/tags/unless.js +52 -0
  86. package/src/template.d.ts +127 -0
  87. package/src/template.js +203 -0
  88. package/src/types.d.ts +144 -0
  89. package/src/types.js +10 -0
  90. package/src/utils.d.ts +96 -0
  91. package/src/utils.js +297 -0
  92. package/tsconfig.json +16 -0
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.Processor = void 0;
12
+ /**
13
+ * Exposes the API to register a set of handlers to process the
14
+ * templates output at different stages
15
+ */
16
+ class Processor {
17
+ #handlers = new Map();
18
+ /**
19
+ * Execute tag handler
20
+ */
21
+ executeTag(data) {
22
+ const handlers = this.#handlers.get('tag');
23
+ if (!handlers) {
24
+ return;
25
+ }
26
+ handlers.forEach((handler) => {
27
+ handler(data);
28
+ });
29
+ }
30
+ /**
31
+ * Execute raw handlers
32
+ */
33
+ executeRaw(data) {
34
+ const handlers = this.#handlers.get('raw');
35
+ if (!handlers) {
36
+ return data.raw;
37
+ }
38
+ handlers.forEach((handler) => {
39
+ const output = handler(data);
40
+ if (output !== undefined) {
41
+ data.raw = output;
42
+ }
43
+ });
44
+ return data.raw;
45
+ }
46
+ /**
47
+ * Execute compiled handlers
48
+ */
49
+ executeCompiled(data) {
50
+ const handlers = this.#handlers.get('compiled');
51
+ if (!handlers) {
52
+ return data.compiled;
53
+ }
54
+ handlers.forEach((handler) => {
55
+ const output = handler(data);
56
+ if (output !== undefined) {
57
+ data.compiled = output;
58
+ }
59
+ });
60
+ return data.compiled;
61
+ }
62
+ /**
63
+ * Execute output handlers
64
+ */
65
+ executeOutput(data) {
66
+ const handlers = this.#handlers.get('output');
67
+ if (!handlers) {
68
+ return data.output;
69
+ }
70
+ handlers.forEach((handler) => {
71
+ const output = handler(data);
72
+ if (output !== undefined) {
73
+ data.output = output;
74
+ }
75
+ });
76
+ return data.output;
77
+ }
78
+ process(event, handler) {
79
+ if (!this.#handlers.has(event)) {
80
+ this.#handlers.set(event, new Set());
81
+ }
82
+ this.#handlers.get(event).add(handler);
83
+ return this;
84
+ }
85
+ }
86
+ exports.Processor = Processor;
@@ -0,0 +1,5 @@
1
+ import { type TagContract } from '../types.js'
2
+ /**
3
+ * The assign tag is used to re-assign value to an existing variable
4
+ */
5
+ export declare const assignTag: TagContract
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.assignTag = void 0;
15
+ const edge_parser_1 = require("edge-parser");
16
+ const lodash_1 = __importDefault(require("@poppinss/utils/lodash"));
17
+ const utils_js_1 = require("../utils.js");
18
+ /**
19
+ * The assign tag is used to re-assign value to an existing variable
20
+ */
21
+ exports.assignTag = {
22
+ block: false,
23
+ seekable: true,
24
+ tagName: 'assign',
25
+ noNewLine: true,
26
+ /**
27
+ * Compiles else block node to Javascript else statement
28
+ */
29
+ compile(parser, buffer, token) {
30
+ const parsed = (0, utils_js_1.parseJsArg)(parser, token);
31
+ (0, utils_js_1.isSubsetOf)(parsed, [edge_parser_1.expressions.AssignmentExpression], () => {
32
+ throw (0, utils_js_1.unallowedExpression)(`Invalid expression for the @assign tag`, token.filename, parser.utils.getExpressionLoc(parsed));
33
+ });
34
+ buffer.writeExpression(parser.utils.stringify(parsed), token.filename, token.loc.start.line);
35
+ },
36
+ /**
37
+ * Add methods to the template for running the loop
38
+ */
39
+ boot(template) {
40
+ template.macro('setValue', lodash_1.default.set);
41
+ },
42
+ };
@@ -0,0 +1,6 @@
1
+ import type { TagContract } from '../types.js'
2
+ /**
3
+ * The component tag implementation. It is one of the most complex tags and
4
+ * can be used as a reference for creating other tags.
5
+ */
6
+ export declare const componentTag: TagContract
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.componentTag = void 0;
45
+ const edge_error_1 = require("edge-error");
46
+ const lexerUtils = __importStar(require("edge-lexer/utils"));
47
+ const edge_parser_1 = require("edge-parser");
48
+ const utils_js_1 = require("../utils.js");
49
+ /**
50
+ * A list of allowed expressions for the component name
51
+ */
52
+ const ALLOWED_EXPRESSION_FOR_COMPONENT_NAME = [
53
+ edge_parser_1.expressions.Identifier,
54
+ edge_parser_1.expressions.Literal,
55
+ edge_parser_1.expressions.LogicalExpression,
56
+ edge_parser_1.expressions.MemberExpression,
57
+ edge_parser_1.expressions.ConditionalExpression,
58
+ edge_parser_1.expressions.CallExpression,
59
+ edge_parser_1.expressions.TemplateLiteral,
60
+ ];
61
+ /**
62
+ * Returns the component name and props by parsing the component jsArg expression
63
+ */
64
+ function getComponentNameAndProps(expression, parser, filename) {
65
+ let name;
66
+ /**
67
+ * Use the first expression inside the sequence expression as the name
68
+ * of the component
69
+ */
70
+ if (expression.type === edge_parser_1.expressions.SequenceExpression) {
71
+ name = expression.expressions.shift();
72
+ }
73
+ else {
74
+ name = expression;
75
+ }
76
+ /**
77
+ * Ensure the component name is a literal value or an expression that
78
+ * outputs a literal value
79
+ */
80
+ (0, utils_js_1.isSubsetOf)(name, ALLOWED_EXPRESSION_FOR_COMPONENT_NAME, () => {
81
+ (0, utils_js_1.unallowedExpression)(`"${parser.utils.stringify(name)}" is not a valid argument for component name`, filename, parser.utils.getExpressionLoc(name));
82
+ });
83
+ /**
84
+ * Parse rest of sequence expressions as an objectified string.
85
+ */
86
+ if (expression.type === edge_parser_1.expressions.SequenceExpression) {
87
+ /**
88
+ * We only need to entertain the first expression of the sequence
89
+ * expression, as components allows a max of two arguments
90
+ */
91
+ const firstSequenceExpression = expression.expressions[0];
92
+ return [parser.utils.stringify(name), parser.utils.stringify(firstSequenceExpression)];
93
+ }
94
+ /**
95
+ * When top level expression is not a sequence expression, then we assume props
96
+ * as empty stringified object.
97
+ */
98
+ return [parser.utils.stringify(name), '{}'];
99
+ }
100
+ /**
101
+ * Parses the slot component to fetch it's name and props
102
+ */
103
+ function getSlotNameAndProps(token, parser) {
104
+ /**
105
+ * We just generate the acorn AST only, since we don't want parser to transform
106
+ * ast to edge statements for a `@slot` tag.
107
+ */
108
+ const parsed = parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename).expression;
109
+ (0, utils_js_1.isSubsetOf)(parsed, [edge_parser_1.expressions.Literal, edge_parser_1.expressions.SequenceExpression], () => {
110
+ (0, utils_js_1.unallowedExpression)(`"${token.properties.jsArg}" is not a valid argument type for the @slot tag`, token.filename, parser.utils.getExpressionLoc(parsed));
111
+ });
112
+ /**
113
+ * Fetch the slot name
114
+ */
115
+ let name;
116
+ if (parsed.type === edge_parser_1.expressions.SequenceExpression) {
117
+ name = parsed.expressions[0];
118
+ }
119
+ else {
120
+ name = parsed;
121
+ }
122
+ /**
123
+ * Validating the slot name to be a literal value, since slot names cannot be dynamic
124
+ */
125
+ (0, utils_js_1.isSubsetOf)(name, [edge_parser_1.expressions.Literal], () => {
126
+ (0, utils_js_1.unallowedExpression)('slot name must be a valid string literal', token.filename, parser.utils.getExpressionLoc(name));
127
+ });
128
+ /**
129
+ * Return the slot name with empty props, when the expression is a literal
130
+ * value.
131
+ */
132
+ if (parsed.type === edge_parser_1.expressions.Literal) {
133
+ return [name.raw, null];
134
+ }
135
+ /**
136
+ * Make sure the sequence expression has only 2 arguments in it. Though it doesn't hurt
137
+ * the rendering of component, we must not run code with false expectations.
138
+ */
139
+ if (parsed.expressions.length > 2) {
140
+ throw new edge_error_1.EdgeError('maximum of 2 arguments are allowed for @slot tag', 'E_MAX_ARGUMENTS', {
141
+ line: parsed.loc.start.line,
142
+ col: parsed.loc.start.column,
143
+ filename: token.filename,
144
+ });
145
+ }
146
+ (0, utils_js_1.isSubsetOf)(parsed.expressions[1], [edge_parser_1.expressions.Identifier], () => {
147
+ (0, utils_js_1.unallowedExpression)(`"${parser.utils.stringify(parsed.expressions[1])}" is not valid prop identifier for @slot tag`, token.filename, parser.utils.getExpressionLoc(parsed.expressions[1]));
148
+ });
149
+ /**
150
+ * Returning the slot name and slot props name
151
+ */
152
+ return [name.raw, parsed.expressions[1].name];
153
+ }
154
+ /**
155
+ * The component tag implementation. It is one of the most complex tags and
156
+ * can be used as a reference for creating other tags.
157
+ */
158
+ exports.componentTag = {
159
+ block: true,
160
+ seekable: true,
161
+ tagName: 'component',
162
+ compile(parser, buffer, token) {
163
+ const asyncKeyword = parser.asyncMode ? 'async ' : '';
164
+ const awaitKeyword = parser.asyncMode ? 'await ' : '';
165
+ const parsed = (0, utils_js_1.parseJsArg)(parser, token);
166
+ /**
167
+ * Check component jsProps for allowed expressions
168
+ */
169
+ (0, utils_js_1.isSubsetOf)(parsed, ALLOWED_EXPRESSION_FOR_COMPONENT_NAME.concat(edge_parser_1.expressions.SequenceExpression), () => {
170
+ (0, utils_js_1.unallowedExpression)(`"${token.properties.jsArg}" is not a valid argument type for the @component tag`, token.filename, parser.utils.getExpressionLoc(parsed));
171
+ });
172
+ /**
173
+ * Pulling the name and props for the component. The underlying method will
174
+ * ensure that the arguments passed to component tag are valid
175
+ */
176
+ const [name, props] = getComponentNameAndProps(parsed, parser, token.filename);
177
+ /**
178
+ * Loop over all the children and set them as part of slots. If no slot
179
+ * is defined, then the content will be part of the main slot
180
+ */
181
+ const slots = {};
182
+ /**
183
+ * Main slot collects everything that is out of the named slots
184
+ * inside a component
185
+ */
186
+ const mainSlot = {
187
+ outputVar: 'slot_main',
188
+ props: {},
189
+ buffer: buffer.create(token.filename, {
190
+ outputVar: 'slot_main',
191
+ }),
192
+ line: -1,
193
+ filename: token.filename,
194
+ };
195
+ let slotsCounter = 0;
196
+ /**
197
+ * Loop over all the component children
198
+ */
199
+ token.children.forEach((child) => {
200
+ /**
201
+ * If children is not a slot, then add it to the main slot
202
+ */
203
+ if (!lexerUtils.isTag(child, 'slot')) {
204
+ /**
205
+ * Ignore first newline inside the unnamed main slot
206
+ */
207
+ if (mainSlot.buffer.size === 0 && child.type === 'newline') {
208
+ return;
209
+ }
210
+ parser.processToken(child, mainSlot.buffer);
211
+ return;
212
+ }
213
+ /**
214
+ * Fetch slot and props
215
+ */
216
+ const [slotName, slotProps] = getSlotNameAndProps(child, parser);
217
+ slotsCounter++;
218
+ /**
219
+ * Create a new slot with buffer to process the children
220
+ */
221
+ if (!slots[slotName]) {
222
+ /**
223
+ * Slot buffer points to the component file name, since slots doesn't
224
+ * have their own file names.
225
+ */
226
+ slots[slotName] = {
227
+ outputVar: `slot_${slotsCounter}`,
228
+ buffer: buffer.create(token.filename, {
229
+ outputVar: `slot_${slotsCounter}`,
230
+ }),
231
+ props: slotProps,
232
+ line: -1,
233
+ filename: token.filename,
234
+ };
235
+ /**
236
+ * Only start the frame, when there are props in use for a given slot.
237
+ */
238
+ if (slotProps) {
239
+ parser.stack.defineScope();
240
+ parser.stack.defineVariable(slotProps);
241
+ }
242
+ }
243
+ /**
244
+ * Self process the slot children.
245
+ */
246
+ child.children.forEach((grandChildren) => {
247
+ parser.processToken(grandChildren, slots[slotName].buffer);
248
+ });
249
+ /**
250
+ * Close the frame after process the slot children
251
+ */
252
+ if (slotProps) {
253
+ parser.stack.clearScope();
254
+ }
255
+ });
256
+ const obj = new utils_js_1.StringifiedObject();
257
+ /**
258
+ * Creating a shallow copy of context for the component slots and its children
259
+ */
260
+ obj.add('$context', 'Object.assign({}, $context)');
261
+ /**
262
+ * Add main slot to the stringified object, when main slot
263
+ * is not defined otherwise.
264
+ */
265
+ if (!slots['main']) {
266
+ if (mainSlot.buffer.size) {
267
+ mainSlot.buffer.wrap(`${asyncKeyword}function () { const $context = this.$context;`, '}');
268
+ obj.add('main', mainSlot.buffer.disableFileAndLineVariables().flush());
269
+ }
270
+ else {
271
+ obj.add('main', 'function () { return "" }');
272
+ }
273
+ }
274
+ /**
275
+ * We convert the slots to an objectified string, that is passed to `template.renderWithState`,
276
+ * which will pass it to the component as it's local state.
277
+ */
278
+ Object.keys(slots).forEach((slotName) => {
279
+ if (slots[slotName].buffer.size) {
280
+ const fnCall = slots[slotName].props
281
+ ? `${asyncKeyword}function (${slots[slotName].props}) { const $context = this.$context;`
282
+ : `${asyncKeyword}function () { const $context = this.$context;`;
283
+ slots[slotName].buffer.wrap(fnCall, '}');
284
+ obj.add(slotName, slots[slotName].buffer.disableFileAndLineVariables().flush());
285
+ }
286
+ else {
287
+ obj.add(slotName, 'function () { return "" }');
288
+ }
289
+ });
290
+ const caller = new utils_js_1.StringifiedObject();
291
+ caller.add('filename', '$filename');
292
+ caller.add('line', '$lineNumber');
293
+ caller.add('col', 0);
294
+ /**
295
+ * Write the line to render the component with it's own state
296
+ */
297
+ buffer.outputExpression(`${awaitKeyword}template.compileComponent(${name})(template, template.getComponentState(${props}, ${obj.flush()}, ${caller.flush()}), $context)`, token.filename, token.loc.start.line, false);
298
+ },
299
+ };
@@ -0,0 +1,5 @@
1
+ import type { TagContract } from '../types.js'
2
+ /**
3
+ * Add debugger break point to the compiled template
4
+ */
5
+ export declare const debuggerTag: TagContract
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.debuggerTag = void 0;
12
+ /**
13
+ * Add debugger break point to the compiled template
14
+ */
15
+ exports.debuggerTag = {
16
+ block: false,
17
+ seekable: false,
18
+ tagName: 'debugger',
19
+ noNewLine: true,
20
+ /**
21
+ * Compiles `@debugger` tags
22
+ */
23
+ compile(_, buffer, token) {
24
+ buffer.writeExpression('debugger', token.filename, token.loc.start.line);
25
+ },
26
+ };
@@ -0,0 +1,20 @@
1
+ import type lodash from '@poppinss/utils/lodash'
2
+ import { type TagContract } from '../types.js'
3
+ import { type asyncEach, type each } from '../utils.js'
4
+ declare module '../template.js' {
5
+ interface Template {
6
+ loopAsync: typeof asyncEach
7
+ loop: typeof each
8
+ size: (typeof lodash)['size']
9
+ }
10
+ }
11
+ /**
12
+ * Each tag is used to run a foreach loop on arrays and even objects.
13
+ *
14
+ * ```edge
15
+ * @each((user, index) in users)
16
+ * {{ user }} {{ index }}
17
+ * @endeach
18
+ * ```
19
+ */
20
+ export declare const eachTag: TagContract
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /*
3
+ * edge.js
4
+ *
5
+ * (c) EdgeJS
6
+ *
7
+ * For the full copyright and license information, please view the LICENSE
8
+ * file that was distributed with this source code.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ var __importDefault = (this && this.__importDefault) || function (mod) {
44
+ return (mod && mod.__esModule) ? mod : { "default": mod };
45
+ };
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.eachTag = void 0;
48
+ const lodash_1 = __importDefault(require("@poppinss/utils/lodash"));
49
+ const lexerUtils = __importStar(require("edge-lexer/utils"));
50
+ const edge_parser_1 = require("edge-parser");
51
+ const utils_js_1 = require("../utils.js");
52
+ /**
53
+ * Returns the list to loop over for the each binary expression
54
+ */
55
+ function getLoopList(rhsExpression, parser, filename) {
56
+ return parser.utils.stringify(parser.utils.transformAst(rhsExpression, filename, parser));
57
+ }
58
+ /**
59
+ * Returns loop item and the index for the each binary expression
60
+ */
61
+ function getLoopItemAndIndex(lhsExpression, parser, filename) {
62
+ /**
63
+ * Ensure the LHS content inside `@each()` curly braces is a `SequenceExpression` or
64
+ * `Identifier`. Anything else is not allowed.
65
+ *
66
+ * For example:
67
+ *
68
+ * - In `@each(user in users)`, `user` is an indentifier
69
+ * - In `@each((user, index) in users)`, `(user, index)` is a sequence expression
70
+ */
71
+ (0, utils_js_1.isSubsetOf)(lhsExpression, [edge_parser_1.expressions.SequenceExpression, edge_parser_1.expressions.Identifier], () => {
72
+ (0, utils_js_1.unallowedExpression)(`invalid left hand side "${lhsExpression.type}" expression for the @each tag`, filename, parser.utils.getExpressionLoc(lhsExpression));
73
+ });
74
+ /**
75
+ * Return list index from the sequence expression
76
+ */
77
+ if (lhsExpression.type === 'SequenceExpression') {
78
+ /**
79
+ * First item of the sequence expression must be an idenifier
80
+ */
81
+ (0, utils_js_1.isSubsetOf)(lhsExpression.expressions[0], [edge_parser_1.expressions.Identifier], () => {
82
+ (0, utils_js_1.unallowedExpression)(`"${lhsExpression.expressions[0]}.type" is not allowed as value identifier for @each tag`, filename, parser.utils.getExpressionLoc(lhsExpression.expressions[0]));
83
+ });
84
+ /**
85
+ * Second item of the sequence expression must be an idenifier
86
+ */
87
+ (0, utils_js_1.isSubsetOf)(lhsExpression.expressions[1], [edge_parser_1.expressions.Identifier], () => {
88
+ (0, utils_js_1.unallowedExpression)(`"${lhsExpression.expressions[1]}.type" is not allowed as key identifier for @each tag`, filename, parser.utils.getExpressionLoc(lhsExpression.expressions[1]));
89
+ });
90
+ return [lhsExpression.expressions[0].name, lhsExpression.expressions[1].name];
91
+ }
92
+ /**
93
+ * There is no key, just the value
94
+ */
95
+ return [lhsExpression.name];
96
+ }
97
+ /**
98
+ * Each tag is used to run a foreach loop on arrays and even objects.
99
+ *
100
+ * ```edge
101
+ * @each((user, index) in users)
102
+ * {{ user }} {{ index }}
103
+ * @endeach
104
+ * ```
105
+ */
106
+ exports.eachTag = {
107
+ block: true,
108
+ seekable: true,
109
+ tagName: 'each',
110
+ /**
111
+ * Compile the template
112
+ */
113
+ compile(parser, buffer, token) {
114
+ const awaitKeyword = parser.asyncMode ? 'await ' : '';
115
+ const loopFunctionName = parser.asyncMode ? 'loopAsync' : 'loop';
116
+ const asyncKeyword = parser.asyncMode ? 'async ' : '';
117
+ /**
118
+ * We just generate the AST and do not transform it, since the transform
119
+ * function attempts to resolve identifiers and we don't want that
120
+ */
121
+ const { expression } = parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename);
122
+ /**
123
+ * Each tag only accepts the binary expression or sequence expression. ie `user in users`
124
+ */
125
+ (0, utils_js_1.isSubsetOf)(expression, [edge_parser_1.expressions.BinaryExpression], () => {
126
+ (0, utils_js_1.unallowedExpression)(`"${token.properties.jsArg}" is not valid expression for the @each tag`, token.filename, parser.utils.getExpressionLoc(expression));
127
+ });
128
+ /**
129
+ * Finding if an else child exists inside the each tag
130
+ */
131
+ const elseIndex = token.children.findIndex((child) => lexerUtils.isTag(child, 'else'));
132
+ const elseChildren = elseIndex > -1 ? token.children.splice(elseIndex) : [];
133
+ /**
134
+ * Fetching the item,index and list for the each loop
135
+ */
136
+ const list = getLoopList(expression.right, parser, token.filename);
137
+ const [item, index] = getLoopItemAndIndex(expression.left, parser, token.filename);
138
+ /**
139
+ * If there is an else statement, then wrap the loop inside the `if` statement first
140
+ */
141
+ if (elseIndex > -1) {
142
+ buffer.writeStatement(`if(template.size(${list})) {`, token.filename, token.loc.start.line);
143
+ }
144
+ /**
145
+ * Write the loop statement to the template
146
+ */
147
+ const loopCallbackArgs = (index ? [item, index] : [item]).join(',');
148
+ buffer.writeStatement(`${awaitKeyword}template.${loopFunctionName}(${list}, ${asyncKeyword}function (${loopCallbackArgs}) {`, token.filename, token.loc.start.line);
149
+ /**
150
+ * Start a new parser scope. So that all variable resolutions for the `item`
151
+ * are pointing to the local variable and not the template `state`.
152
+ */
153
+ parser.stack.defineScope();
154
+ parser.stack.defineVariable(item);
155
+ index && parser.stack.defineVariable(index);
156
+ /**
157
+ * Process all children
158
+ */
159
+ token.children.forEach((child) => parser.processToken(child, buffer));
160
+ /**
161
+ * Clear scope
162
+ */
163
+ parser.stack.clearScope();
164
+ /**
165
+ * Close each loop
166
+ */
167
+ buffer.writeExpression('})', token.filename, -1);
168
+ /**
169
+ * If there is an else statement, then process
170
+ * else childs and close the if block
171
+ */
172
+ if (elseIndex > -1) {
173
+ elseChildren.forEach((elseChild) => parser.processToken(elseChild, buffer));
174
+ buffer.writeStatement('}', token.filename, -1);
175
+ }
176
+ },
177
+ /**
178
+ * Add methods to the template for running the loop
179
+ */
180
+ boot(template) {
181
+ template.macro('loopAsync', utils_js_1.asyncEach);
182
+ template.macro('loop', utils_js_1.each);
183
+ template.macro('size', lodash_1.default.size);
184
+ },
185
+ };
@@ -0,0 +1,2 @@
1
+ import { type TagContract } from '../types.js'
2
+ export declare const elseTag: TagContract