edgexpress 3.0.1 → 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.
- package/eslint.config.cjs +6 -0
- package/examples/index.js +41 -0
- package/examples/views/components/layout/main.edge +26 -0
- package/examples/views/components/modal.edge +27 -0
- package/examples/views/home.edge +84 -0
- package/examples/views/partials/button.edge +1 -0
- package/examples/views/partials/home-footer.edge +49 -0
- package/examples/views/partials/home-header.edge +61 -0
- package/examples/views/welcome.edge +22 -0
- package/index.d.ts +7 -0
- package/package.json +3 -3
- package/src/cache_manager.d.ts +28 -0
- package/src/cache_manager.js +58 -0
- package/src/compiler.d.ts +73 -0
- package/src/compiler.js +319 -0
- package/src/component/props.d.ts +53 -0
- package/src/component/props.js +110 -0
- package/src/edge/globals.d.ts +5 -0
- package/src/edge/globals.js +95 -0
- package/src/edge/main.d.ts +192 -0
- package/src/edge/main.js +334 -0
- package/src/edge/renderer.d.ts +44 -0
- package/src/edge/renderer.js +85 -0
- package/src/edge/stacks.d.ts +22 -0
- package/src/edge/stacks.js +98 -0
- package/src/loader.d.ts +138 -0
- package/src/loader.js +347 -0
- package/src/migrate/globals.d.ts +1 -0
- package/src/migrate/globals.js +100 -0
- package/src/migrate/plugin.d.ts +2 -0
- package/src/migrate/plugin.js +58 -0
- package/src/migrate/props.d.ts +66 -0
- package/src/migrate/props.js +129 -0
- package/src/migrate/tags/layout.d.ts +6 -0
- package/src/migrate/tags/layout.js +25 -0
- package/src/migrate/tags/main.d.ts +4 -0
- package/src/migrate/tags/main.js +19 -0
- package/src/migrate/tags/section.d.ts +6 -0
- package/src/migrate/tags/section.js +23 -0
- package/src/migrate/tags/set.d.ts +26 -0
- package/src/migrate/tags/set.js +104 -0
- package/src/migrate/tags/super.d.ts +9 -0
- package/src/migrate/tags/super.js +31 -0
- package/src/plugins/supercharged.d.ts +4 -0
- package/src/plugins/supercharged.js +88 -0
- package/src/processor.d.ts +42 -0
- package/src/processor.js +86 -0
- package/src/tags/assign.d.ts +5 -0
- package/src/tags/assign.js +42 -0
- package/src/tags/component.d.ts +6 -0
- package/src/tags/component.js +299 -0
- package/src/tags/debugger.d.ts +5 -0
- package/src/tags/debugger.js +26 -0
- package/src/tags/each.d.ts +20 -0
- package/src/tags/each.js +185 -0
- package/src/tags/else.d.ts +2 -0
- package/src/tags/else.js +22 -0
- package/src/tags/else_if.d.ts +7 -0
- package/src/tags/else_if.js +39 -0
- package/src/tags/eval.d.ts +7 -0
- package/src/tags/eval.js +30 -0
- package/src/tags/if.d.ts +5 -0
- package/src/tags/if.js +45 -0
- package/src/tags/include.d.ts +27 -0
- package/src/tags/include.js +78 -0
- package/src/tags/include_if.d.ts +10 -0
- package/src/tags/include_if.js +61 -0
- package/src/tags/inject.d.ts +6 -0
- package/src/tags/inject.js +40 -0
- package/src/tags/let.d.ts +6 -0
- package/src/tags/let.js +69 -0
- package/src/tags/main.d.ts +18 -0
- package/src/tags/main.js +47 -0
- package/src/tags/new_error.d.ts +6 -0
- package/src/tags/new_error.js +47 -0
- package/src/tags/push_once_to.d.ts +13 -0
- package/src/tags/push_once_to.js +65 -0
- package/src/tags/push_to.d.ts +7 -0
- package/src/tags/push_to.js +62 -0
- package/src/tags/slot.d.ts +6 -0
- package/src/tags/slot.js +29 -0
- package/src/tags/stack.d.ts +5 -0
- package/src/tags/stack.js +38 -0
- package/src/tags/unless.d.ts +12 -0
- package/src/tags/unless.js +52 -0
- package/src/template.d.ts +127 -0
- package/src/template.js +203 -0
- package/src/types.d.ts +144 -0
- package/src/types.js +10 -0
- package/src/utils.d.ts +96 -0
- package/src/utils.js +297 -0
- package/tsconfig.json +16 -0
package/src/processor.js
ADDED
|
@@ -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,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,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,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
|
package/src/tags/each.js
ADDED
|
@@ -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
|
+
};
|