@xaendar/compiler 0.6.7 → 0.6.10
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/dist/xaendar-compiler.es.js +152 -205
- package/package.json +3 -3
|
@@ -1756,26 +1756,11 @@ function isValidIdentifier(name) {
|
|
|
1756
1756
|
* @returns The parsed `IfNode`.
|
|
1757
1757
|
*/
|
|
1758
1758
|
function parseIfControlFlow(cursor, parseNode, token) {
|
|
1759
|
-
return
|
|
1759
|
+
return parseIfOrElseIf(cursor, parseNode, token);
|
|
1760
1760
|
}
|
|
1761
|
-
function
|
|
1761
|
+
function parseElseIfRecursively(cursor, parseNode, token) {
|
|
1762
1762
|
switch (token.type) {
|
|
1763
|
-
case TokenType.
|
|
1764
|
-
case TokenType.ELSE_IF:
|
|
1765
|
-
cursor.advance();
|
|
1766
|
-
const conditionToken = cursor.peek();
|
|
1767
|
-
if (conditionToken.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after ${TokenType[token.type]}, got ${TokenType[conditionToken.type]}`);
|
|
1768
|
-
cursor.advance(2);
|
|
1769
|
-
const condition = conditionToken.parts[0];
|
|
1770
|
-
const validationResult = validateExpression(condition);
|
|
1771
|
-
const consequent = parseBlockChildren(cursor, parseNode);
|
|
1772
|
-
return {
|
|
1773
|
-
type: token.type === TokenType.IF ? ASTNodeType.If : ASTNodeType.ElseIf,
|
|
1774
|
-
condition,
|
|
1775
|
-
conditionNode: validationResult.node,
|
|
1776
|
-
consequent,
|
|
1777
|
-
alternate: parseIfRecursively(cursor, parseNode, cursor.peek())
|
|
1778
|
-
};
|
|
1763
|
+
case TokenType.ELSE_IF: return parseIfOrElseIf(cursor, parseNode, token);
|
|
1779
1764
|
case TokenType.ELSE:
|
|
1780
1765
|
cursor.advance(2);
|
|
1781
1766
|
const elseChildren = parseBlockChildren(cursor, parseNode);
|
|
@@ -1785,6 +1770,22 @@ function parseIfRecursively(cursor, parseNode, token) {
|
|
|
1785
1770
|
};
|
|
1786
1771
|
}
|
|
1787
1772
|
}
|
|
1773
|
+
function parseIfOrElseIf(cursor, parseNode, token) {
|
|
1774
|
+
cursor.advance();
|
|
1775
|
+
const conditionToken = cursor.peek();
|
|
1776
|
+
if (conditionToken.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after ${TokenType[token.type]}, got ${TokenType[conditionToken.type]}`);
|
|
1777
|
+
cursor.advance(2);
|
|
1778
|
+
const condition = conditionToken.parts[0];
|
|
1779
|
+
const validationResult = validateExpression(condition);
|
|
1780
|
+
const consequent = parseBlockChildren(cursor, parseNode);
|
|
1781
|
+
return {
|
|
1782
|
+
type: token.type === TokenType.IF ? ASTNodeType.If : ASTNodeType.ElseIf,
|
|
1783
|
+
condition,
|
|
1784
|
+
conditionNode: validationResult.node,
|
|
1785
|
+
consequent,
|
|
1786
|
+
alternate: parseElseIfRecursively(cursor, parseNode, cursor.peek())
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1788
1789
|
//#endregion
|
|
1789
1790
|
//#region ../packages/compiler/src/parser/states/parse-switch.state.ts
|
|
1790
1791
|
/**
|
|
@@ -1924,39 +1925,75 @@ var Parser = class {
|
|
|
1924
1925
|
}
|
|
1925
1926
|
};
|
|
1926
1927
|
//#endregion
|
|
1927
|
-
//#region ../packages/compiler/src/render-generator/
|
|
1928
|
+
//#region ../packages/compiler/src/render-generator/states/process-const-declaration.state.ts
|
|
1928
1929
|
/**
|
|
1929
|
-
*
|
|
1930
|
-
*
|
|
1931
|
-
*
|
|
1930
|
+
* Generates code for a `@const` declaration node.
|
|
1931
|
+
* Emits a `const name = expression;` JavaScript statement.
|
|
1932
|
+
*
|
|
1933
|
+
* @param node The `ConstDeclarationNode` to process.
|
|
1934
|
+
* @param _nodeName Unused node name.
|
|
1935
|
+
* @param _parentNode Unused parent node name.
|
|
1936
|
+
* @returns Array containing the generated const statement string.
|
|
1932
1937
|
*/
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1938
|
+
function processConstDeclaration(node, _nodeName, _parentNode) {
|
|
1939
|
+
return [`const ${node.varName} = ${node.varName};`];
|
|
1940
|
+
}
|
|
1941
|
+
//#endregion
|
|
1942
|
+
//#region ../packages/compiler/src/render-generator/states/process-element.state.ts
|
|
1943
|
+
/**
|
|
1944
|
+
* Generates code for an HTML element node: creates the DOM element, sets attributes,
|
|
1945
|
+
* attaches event listeners, appends it to the parent, and recursively processes children.
|
|
1946
|
+
*
|
|
1947
|
+
* @param node The `ElementNode` to process.
|
|
1948
|
+
* @param nodeName Variable name to use for the created DOM element.
|
|
1949
|
+
* @param parentNode Variable name of the parent DOM node to append to.
|
|
1950
|
+
* @returns Array of generated code lines.
|
|
1951
|
+
*/
|
|
1952
|
+
function processElement(node, nodeName, parentNode) {
|
|
1953
|
+
const attributes = mapAttributes(node.attributes);
|
|
1954
|
+
const events = mapEvents(node.events);
|
|
1955
|
+
const code = [`renderElement(${parentNode}, context, '${node.tagName}',`];
|
|
1956
|
+
attributes.length ? code.push(...indent([
|
|
1957
|
+
"[",
|
|
1958
|
+
...indent(attributes),
|
|
1959
|
+
"],"
|
|
1960
|
+
])) : code[code.length - 1] = `${code[code.length - 1]} [],`;
|
|
1961
|
+
events.length ? code.push(...indent([
|
|
1962
|
+
"[",
|
|
1963
|
+
...indent(events),
|
|
1964
|
+
"]"
|
|
1965
|
+
]), ")") : code[code.length - 1] = `${code[code.length - 1]} [])`;
|
|
1966
|
+
return code;
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Generates code that assigns attributes to a DOM element.
|
|
1970
|
+
*
|
|
1971
|
+
* Static (string) attribute values are set once via a direct `setAttribute` call,
|
|
1972
|
+
* while dynamic attribute values are wrapped in an `effect` so the attribute is
|
|
1973
|
+
* re-evaluated and updated whenever its underlying signal dependencies change.
|
|
1974
|
+
* The disposer returned by the `effect` is registered in `unwatchFns` for cleanup.
|
|
1975
|
+
*
|
|
1976
|
+
* @param attributes The attribute nodes to map onto the element.
|
|
1977
|
+
* @returns Array of generated code lines, one per attribute.
|
|
1978
|
+
*/
|
|
1979
|
+
function mapAttributes(attributes) {
|
|
1980
|
+
return attributes?.map(({ name, value }) => {
|
|
1981
|
+
const isLiteral = typeof value === "string";
|
|
1982
|
+
return `{ name: '${name}', value: '${isLiteral ? value : value.expression.text}', literal: ${isLiteral} },`;
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Generates code that attaches event listeners to a DOM element.
|
|
1987
|
+
*
|
|
1988
|
+
* For each event node an `addEventListener` call is emitted, binding the event
|
|
1989
|
+
* to the component instance handler and exposing the native event as `$event`.
|
|
1990
|
+
*
|
|
1991
|
+
* @param events The event nodes to bind to the element.
|
|
1992
|
+
* @returns Array of generated code lines, one per event listener.
|
|
1993
|
+
*/
|
|
1994
|
+
function mapEvents(events) {
|
|
1995
|
+
return events?.map((event) => `{ name: '${event.name}', handler: '${event.handler}' }`);
|
|
1996
|
+
}
|
|
1960
1997
|
//#endregion
|
|
1961
1998
|
//#region ../packages/compiler/src/render-generator/utils/render-generator.utils.ts
|
|
1962
1999
|
/**
|
|
@@ -2141,7 +2178,7 @@ var GLOBAL_IDENTIFIERS = new Set([
|
|
|
2141
2178
|
"Document",
|
|
2142
2179
|
"Window"
|
|
2143
2180
|
]);
|
|
2144
|
-
var ROOT_NODE = "
|
|
2181
|
+
var ROOT_NODE = "root";
|
|
2145
2182
|
/**
|
|
2146
2183
|
* Resolves references to component properties inside a template expression.
|
|
2147
2184
|
*
|
|
@@ -2168,8 +2205,8 @@ var ROOT_NODE = "this._root";
|
|
|
2168
2205
|
* // typeof id !== 'boolean' || pippo instanceof HTMLElement
|
|
2169
2206
|
* // → typeof this.id !== 'boolean' || this.pippo instanceof HTMLElement
|
|
2170
2207
|
*/
|
|
2171
|
-
function resolveExpression(expression
|
|
2172
|
-
return emitNode(expression, expression
|
|
2208
|
+
function resolveExpression(expression) {
|
|
2209
|
+
return emitNode(expression, expression);
|
|
2173
2210
|
}
|
|
2174
2211
|
/**
|
|
2175
2212
|
* Emits the resolved text for a node.
|
|
@@ -2180,14 +2217,13 @@ function resolveExpression(expression, context) {
|
|
|
2180
2217
|
* - If the node is a resolvable Identifier, emits the resolved name.
|
|
2181
2218
|
* - Otherwise recurses into children and concatenates their output.
|
|
2182
2219
|
*/
|
|
2183
|
-
function emitNode(node, parent
|
|
2184
|
-
if (ts.isIdentifier(node) && needsResolution(node, parent)) return context.getIdentifier(node.text) ?? `this.${node.text}`;
|
|
2220
|
+
function emitNode(node, parent) {
|
|
2185
2221
|
if (!containsResolvableIdentifier(node, parent)) return node.getText();
|
|
2186
2222
|
const sourceText = node.getSourceFile().text;
|
|
2187
2223
|
let result = "";
|
|
2188
2224
|
let lastEnd = node.getStart();
|
|
2189
2225
|
ts.forEachChild(node, (child) => {
|
|
2190
|
-
result = `${result}${sourceText.slice(lastEnd, child.getStart())}${emitNode(child, node
|
|
2226
|
+
result = `${result}${sourceText.slice(lastEnd, child.getStart())}${emitNode(child, node)}`;
|
|
2191
2227
|
lastEnd = child.getEnd();
|
|
2192
2228
|
});
|
|
2193
2229
|
return `${result}${sourceText.slice(lastEnd, node.getEnd())}`;
|
|
@@ -2223,93 +2259,13 @@ function needsResolution(node, parent) {
|
|
|
2223
2259
|
* @returns A string representing the unique variable name for the element.
|
|
2224
2260
|
*/
|
|
2225
2261
|
function getElementIdentifier(node, parentNode, index) {
|
|
2226
|
-
return (parentNode !== "
|
|
2262
|
+
return (parentNode !== "root" ? `${parentNode}_${node.tagName}${index}` : `${node.tagName}${index}`).replace(/-/g, "_");
|
|
2227
2263
|
}
|
|
2228
2264
|
function getTextIdentifier(parentNode, index, prefix = "text") {
|
|
2229
|
-
return (parentNode !== "
|
|
2265
|
+
return (parentNode !== "root" ? `${parentNode}_${prefix}${index}` : `${prefix}${index}`).replace(/-/g, "_");
|
|
2230
2266
|
}
|
|
2231
2267
|
function getBlockIdentifier(parentNode, index, prefix) {
|
|
2232
|
-
return (parentNode !== "
|
|
2233
|
-
}
|
|
2234
|
-
//#endregion
|
|
2235
|
-
//#region ../packages/compiler/src/render-generator/states/process-const-declaration.state.ts
|
|
2236
|
-
/**
|
|
2237
|
-
* Generates code for a `@const` declaration node.
|
|
2238
|
-
* Emits a `const name = expression;` JavaScript statement.
|
|
2239
|
-
*
|
|
2240
|
-
* @param node The `ConstDeclarationNode` to process.
|
|
2241
|
-
* @param _nodeName Unused node name.
|
|
2242
|
-
* @param _parentNode Unused parent node name.
|
|
2243
|
-
* @param _context Unused render context.
|
|
2244
|
-
* @returns Array containing the generated const statement string.
|
|
2245
|
-
*/
|
|
2246
|
-
function processConstDeclaration(node, _nodeName, _parentNode, context) {
|
|
2247
|
-
context.addIdentifier(node.varName);
|
|
2248
|
-
return [`const ${node.varName} = ${resolveExpression(node.expression, context)};`];
|
|
2249
|
-
}
|
|
2250
|
-
//#endregion
|
|
2251
|
-
//#region ../packages/compiler/src/render-generator/states/process-element.state.ts
|
|
2252
|
-
/**
|
|
2253
|
-
* Generates code for an HTML element node: creates the DOM element, sets attributes,
|
|
2254
|
-
* attaches event listeners, appends it to the parent, and recursively processes children.
|
|
2255
|
-
*
|
|
2256
|
-
* @param node The `ElementNode` to process.
|
|
2257
|
-
* @param nodeName Variable name to use for the created DOM element.
|
|
2258
|
-
* @param parentNode Variable name of the parent DOM node to append to.
|
|
2259
|
-
* @param context Current render scope context.
|
|
2260
|
-
* @returns Array of generated code lines.
|
|
2261
|
-
*/
|
|
2262
|
-
function processElement(node, nodeName, parentNode, context) {
|
|
2263
|
-
const childrenContext = new Context([], context);
|
|
2264
|
-
return [
|
|
2265
|
-
`const ${nodeName} = document.createElement("${node.tagName}");`,
|
|
2266
|
-
...mapAttributes(node.attributes, nodeName, context),
|
|
2267
|
-
...mapEvents(node.events, nodeName),
|
|
2268
|
-
`${parentNode}.appendChild(${nodeName});`,
|
|
2269
|
-
`unwatchFns.push(() => ${parentNode}.removeChild(${nodeName}));`,
|
|
2270
|
-
...node.children.map((child, i) => processNode(child, i.toString(), nodeName, childrenContext)).flat()
|
|
2271
|
-
];
|
|
2272
|
-
}
|
|
2273
|
-
/**
|
|
2274
|
-
* Generates code that assigns attributes to a DOM element.
|
|
2275
|
-
*
|
|
2276
|
-
* Static (string) attribute values are set once via a direct `setAttribute` call,
|
|
2277
|
-
* while dynamic attribute values are wrapped in an `effect` so the attribute is
|
|
2278
|
-
* re-evaluated and updated whenever its underlying signal dependencies change.
|
|
2279
|
-
* The disposer returned by the `effect` is registered in `unwatchFns` for cleanup.
|
|
2280
|
-
*
|
|
2281
|
-
* @param attributes The attribute nodes to map onto the element.
|
|
2282
|
-
* @param nodeName Variable name of the DOM element receiving the attributes.
|
|
2283
|
-
* @param context Current render scope context, used to resolve dynamic expressions.
|
|
2284
|
-
* @returns Array of generated code lines, one per attribute.
|
|
2285
|
-
*/
|
|
2286
|
-
function mapAttributes(attributes, nodeName, context) {
|
|
2287
|
-
const literalsAttributes = new Array();
|
|
2288
|
-
const bindingsAttributes = new Array();
|
|
2289
|
-
attributes?.forEach(({ name, value }) => typeof value === "string" ? literalsAttributes.push({
|
|
2290
|
-
name,
|
|
2291
|
-
value
|
|
2292
|
-
}) : bindingsAttributes.push({
|
|
2293
|
-
name,
|
|
2294
|
-
value
|
|
2295
|
-
}));
|
|
2296
|
-
const mappedAttributes = literalsAttributes.map((attr) => `${nodeName}.setAttribute("${attr.name}", "${attr.value}");`);
|
|
2297
|
-
const mappedBindingAttributes = bindingsAttributes.map((attr) => `effect(() => ${nodeName}.setAttribute("${attr.name}", ${resolveExpression(attr.value.expression, context)})),`);
|
|
2298
|
-
if (mappedBindingAttributes.length) mappedAttributes.push(`unwatchFns.push(`, ...indent(mappedBindingAttributes), `);`);
|
|
2299
|
-
return mappedAttributes;
|
|
2300
|
-
}
|
|
2301
|
-
/**
|
|
2302
|
-
* Generates code that attaches event listeners to a DOM element.
|
|
2303
|
-
*
|
|
2304
|
-
* For each event node an `addEventListener` call is emitted, binding the event
|
|
2305
|
-
* to the component instance handler and exposing the native event as `$event`.
|
|
2306
|
-
*
|
|
2307
|
-
* @param events The event nodes to bind to the element.
|
|
2308
|
-
* @param nodeName Variable name of the DOM element receiving the listeners.
|
|
2309
|
-
* @returns Array of generated code lines, one per event listener.
|
|
2310
|
-
*/
|
|
2311
|
-
function mapEvents(events, nodeName) {
|
|
2312
|
-
return events?.map((event) => `${nodeName}.addEventListener("${event.name}", ($event) => this.${event.handler});`) ?? [];
|
|
2268
|
+
return (parentNode !== "root" ? `${parentNode}_${prefix}${index}` : `${prefix}${index}`).replace(/-/g, "_");
|
|
2313
2269
|
}
|
|
2314
2270
|
//#endregion
|
|
2315
2271
|
//#region ../packages/compiler/src/render-generator/states/process-for.state.ts
|
|
@@ -2341,14 +2297,12 @@ function mapEvents(events, nodeName) {
|
|
|
2341
2297
|
* @param nodeName - Base variable name prefix used for child nodes and
|
|
2342
2298
|
* to produce a unique loop counter identifier.
|
|
2343
2299
|
* @param parentNode - Variable name of the parent DOM node.
|
|
2344
|
-
* @param parentContext - The enclosing scope context.
|
|
2345
2300
|
* @returns Array of generated code lines.
|
|
2346
2301
|
*/
|
|
2347
|
-
function processFor(node, nodeName, parentNode
|
|
2302
|
+
function processFor(node, nodeName, parentNode) {
|
|
2348
2303
|
const mainBlock = new Array();
|
|
2349
2304
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2350
2305
|
const iterableSource = node.iterableSource;
|
|
2351
|
-
const iterableExpr = parentContext.getIdentifier(iterableSource) ?? `this.${iterableSource}`;
|
|
2352
2306
|
const itemsName = getTextIdentifier(parentNode, nodeName, "items");
|
|
2353
2307
|
const counterName = getTextIdentifier(parentNode, nodeName, "i");
|
|
2354
2308
|
const indexName = resolveImplicit(node, "$index");
|
|
@@ -2356,20 +2310,17 @@ function processFor(node, nodeName, parentNode, parentContext) {
|
|
|
2356
2310
|
const lastName = resolveImplicit(node, "$last");
|
|
2357
2311
|
const evenName = resolveImplicit(node, "$even");
|
|
2358
2312
|
const oddName = resolveImplicit(node, "$odd");
|
|
2359
|
-
const forContext = new Context([
|
|
2360
|
-
node.itemAlias,
|
|
2361
|
-
indexName,
|
|
2362
|
-
firstName,
|
|
2363
|
-
lastName,
|
|
2364
|
-
evenName,
|
|
2365
|
-
oddName
|
|
2366
|
-
], parentContext);
|
|
2367
2313
|
const forKey = getBlockIdentifier(parentNode, nodeName, "for");
|
|
2368
2314
|
functionsToProcess.set(forKey, {
|
|
2369
|
-
code: [`const { ${node.itemAlias}, ${indexName}, ${firstName}, ${lastName}, ${evenName}, ${oddName} } = _iterationVariables(${itemsName}, ${counterName});`, ...node.children.flatMap((child, i) => processNode(child, `${nodeName}_${i}`, parentNode
|
|
2370
|
-
args: [
|
|
2315
|
+
code: [`const { ${node.itemAlias}, ${indexName}, ${firstName}, ${lastName}, ${evenName}, ${oddName} } = _iterationVariables(${itemsName}, ${counterName});`, ...node.children.flatMap((child, i) => processNode(child, `${nodeName}_${i}`, parentNode))],
|
|
2316
|
+
args: [
|
|
2317
|
+
parentNode,
|
|
2318
|
+
"parentContext",
|
|
2319
|
+
itemsName,
|
|
2320
|
+
counterName
|
|
2321
|
+
]
|
|
2371
2322
|
});
|
|
2372
|
-
mainBlock.push(`_for(
|
|
2323
|
+
mainBlock.push(`_for(${parentNode}, context, '${iterableSource}', this.${forKey}.bind(this));`);
|
|
2373
2324
|
return {
|
|
2374
2325
|
mainBlock,
|
|
2375
2326
|
fns: functionsToProcess
|
|
@@ -2399,41 +2350,46 @@ function resolveImplicit(node, implicit) {
|
|
|
2399
2350
|
* @param node The `IfNode` to process.
|
|
2400
2351
|
* @param nodeName Base variable name prefix for child nodes.
|
|
2401
2352
|
* @param parentNode Variable name of the parent DOM node.
|
|
2402
|
-
* @param context Current render scope context.
|
|
2403
2353
|
* @returns Array of generated code lines.
|
|
2404
2354
|
*/
|
|
2405
|
-
function processIf(node, nodeName, parentNode
|
|
2406
|
-
const ifContext = new Context([], context);
|
|
2355
|
+
function processIf(node, nodeName, parentNode) {
|
|
2407
2356
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2408
2357
|
const mainBlock = new Array();
|
|
2409
2358
|
const ifKey = getBlockIdentifier(parentNode, nodeName, "if");
|
|
2410
2359
|
mainBlock.push({
|
|
2411
|
-
condition: resolveExpression(node.conditionNode
|
|
2360
|
+
condition: resolveExpression(node.conditionNode),
|
|
2412
2361
|
block: `this.${ifKey}.bind(this)`
|
|
2413
2362
|
});
|
|
2414
|
-
functionsToProcess.set(ifKey,
|
|
2363
|
+
functionsToProcess.set(ifKey, {
|
|
2364
|
+
code: processConsequent(node, nodeName, parentNode),
|
|
2365
|
+
args: [parentNode, "parentContext"]
|
|
2366
|
+
});
|
|
2415
2367
|
let alt = node.alternate;
|
|
2416
2368
|
let index = 0;
|
|
2417
2369
|
while (alt?.type === ASTNodeType.ElseIf) {
|
|
2418
|
-
const elseIfContext = new Context([], context);
|
|
2419
2370
|
const keyElseIf = getBlockIdentifier(parentNode, `${nodeName}_${index}`, "elseIf");
|
|
2420
2371
|
const conditionNode = alt.conditionNode;
|
|
2421
2372
|
mainBlock.push({
|
|
2422
|
-
condition: resolveExpression(conditionNode
|
|
2373
|
+
condition: resolveExpression(conditionNode),
|
|
2423
2374
|
block: `this.${keyElseIf}.bind(this)`
|
|
2424
2375
|
});
|
|
2425
|
-
functionsToProcess.set(keyElseIf,
|
|
2376
|
+
functionsToProcess.set(keyElseIf, {
|
|
2377
|
+
code: processConsequent(alt, nodeName, parentNode),
|
|
2378
|
+
args: [parentNode, "parentContext"]
|
|
2379
|
+
});
|
|
2426
2380
|
alt = alt.alternate;
|
|
2427
2381
|
}
|
|
2428
2382
|
if (alt) {
|
|
2429
|
-
const elseContext = new Context([], context);
|
|
2430
2383
|
const keyElse = getBlockIdentifier(parentNode, nodeName, "else");
|
|
2431
2384
|
mainBlock.push({ block: `this.${keyElse}.bind(this)` });
|
|
2432
|
-
functionsToProcess.set(keyElse,
|
|
2385
|
+
functionsToProcess.set(keyElse, {
|
|
2386
|
+
code: processConsequent(alt, nodeName, parentNode),
|
|
2387
|
+
args: [parentNode, "parentContext"]
|
|
2388
|
+
});
|
|
2433
2389
|
}
|
|
2434
2390
|
return {
|
|
2435
2391
|
mainBlock: [
|
|
2436
|
-
|
|
2392
|
+
`_if(${parentNode}, context, [`,
|
|
2437
2393
|
...indent(mainBlock.map(({ condition, block }) => {
|
|
2438
2394
|
return [
|
|
2439
2395
|
"{",
|
|
@@ -2446,8 +2402,8 @@ function processIf(node, nodeName, parentNode, context) {
|
|
|
2446
2402
|
fns: functionsToProcess
|
|
2447
2403
|
};
|
|
2448
2404
|
}
|
|
2449
|
-
function processConsequent(node, nodeName, parentNode
|
|
2450
|
-
return node.consequent.map((child, i) => processNode(child, `${nodeName}_${i}`, parentNode
|
|
2405
|
+
function processConsequent(node, nodeName, parentNode) {
|
|
2406
|
+
return node.consequent.map((child, i) => processNode(child, `${nodeName}_${i}`, parentNode)).flat();
|
|
2451
2407
|
}
|
|
2452
2408
|
//#endregion
|
|
2453
2409
|
//#region ../packages/compiler/src/render-generator/states/process-switch.state.ts
|
|
@@ -2459,16 +2415,17 @@ function processConsequent(node, nodeName, parentNode, context) {
|
|
|
2459
2415
|
* @param node The `SwitchNode` to process.
|
|
2460
2416
|
* @param nodeName Base variable name prefix for child nodes.
|
|
2461
2417
|
* @param parentNode Variable name of the parent DOM node.
|
|
2462
|
-
* @param context Current render scope context.
|
|
2463
2418
|
* @returns Array of generated code lines.
|
|
2464
2419
|
*/
|
|
2465
|
-
function processSwitch(node, nodeName, parentNode
|
|
2420
|
+
function processSwitch(node, nodeName, parentNode) {
|
|
2466
2421
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2467
2422
|
const blocks = new Array();
|
|
2468
2423
|
node.cases.forEach((caseNode, i) => {
|
|
2469
|
-
const caseContext = new Context([], context);
|
|
2470
2424
|
const caseName = caseNode.condition ? getBlockIdentifier(parentNode, `${nodeName}_${i}`, "case") : getBlockIdentifier(parentNode, nodeName, "default");
|
|
2471
|
-
functionsToProcess.set(caseName,
|
|
2425
|
+
functionsToProcess.set(caseName, {
|
|
2426
|
+
code: caseNode.children.map((child, i) => processNode(child, `${nodeName}_${i}_${i}`, parentNode)).flat(),
|
|
2427
|
+
args: [parentNode, "parentContext"]
|
|
2428
|
+
});
|
|
2472
2429
|
blocks.push({
|
|
2473
2430
|
condition: caseNode.condition,
|
|
2474
2431
|
block: `this.${caseName}.bind(this)`
|
|
@@ -2476,7 +2433,7 @@ function processSwitch(node, nodeName, parentNode, context) {
|
|
|
2476
2433
|
});
|
|
2477
2434
|
return {
|
|
2478
2435
|
mainBlock: [
|
|
2479
|
-
`_switch(
|
|
2436
|
+
`_switch(${parentNode}, context, () => ${resolveExpression(node.expression)}, [`,
|
|
2480
2437
|
...indent(blocks.map(({ condition, block }) => {
|
|
2481
2438
|
return [
|
|
2482
2439
|
"{",
|
|
@@ -2497,18 +2454,12 @@ function processSwitch(node, nodeName, parentNode, context) {
|
|
|
2497
2454
|
* then appends it to the parent DOM node.
|
|
2498
2455
|
*
|
|
2499
2456
|
* @param node A `TextNode` or `InterpolationNode` to process.
|
|
2500
|
-
* @param nodeName
|
|
2457
|
+
* @param nodeName - The identifier for the Text Node created
|
|
2501
2458
|
* @param parentNode Variable name of the parent DOM node.
|
|
2502
|
-
* @param _context Unused render context.
|
|
2503
2459
|
* @returns Array of two generated code lines: the text node creation and the appendChild call.
|
|
2504
2460
|
*/
|
|
2505
|
-
function processTextAndInterpolation(node, nodeName, parentNode
|
|
2506
|
-
|
|
2507
|
-
return [
|
|
2508
|
-
`const ${nodeName} = document.createTextNode(${textValue});`,
|
|
2509
|
-
`${parentNode}.appendChild(${nodeName});`,
|
|
2510
|
-
`unwatchFns.push(effect(() => ${nodeName}.textContent = ${textValue}));`
|
|
2511
|
-
];
|
|
2461
|
+
function processTextAndInterpolation(node, nodeName, parentNode) {
|
|
2462
|
+
return [`${node.type === ASTNodeType.Text ? `renderLiteralText(${parentNode}, context, '${node.value}')` : `renderText(${parentNode}, context, '${node.expression.text}')`}`];
|
|
2512
2463
|
}
|
|
2513
2464
|
//#endregion
|
|
2514
2465
|
//#region ../packages/compiler/src/render-generator/render-generator.ts
|
|
@@ -2521,25 +2472,15 @@ var nodeToProcess = /* @__PURE__ */ new Map();
|
|
|
2521
2472
|
*/
|
|
2522
2473
|
function generateRenderFunction(ast, cssVariableName) {
|
|
2523
2474
|
nodeToProcess.clear();
|
|
2524
|
-
const context = new Context();
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
"let unwatchFns = [];",
|
|
2529
|
-
...ast.map((node, i) => [...processNode(node, i.toString(), ROOT_NODE, context)]).flat(),
|
|
2530
|
-
"return unwatchFns;"
|
|
2531
|
-
]), "}");
|
|
2532
|
-
while (nodeToProcess.size > 0) {
|
|
2475
|
+
const renderFunctions = ["_render() {", ...indent([`const ${ROOT_NODE} = this._root;`, "const context = new Context(this)"])];
|
|
2476
|
+
if (cssVariableName) renderFunctions.push(indent(`${ROOT_NODE}.adoptedStyleSheets = [${cssVariableName}];`));
|
|
2477
|
+
renderFunctions.push(...indent([...ast.map((node, i) => [...processNode(node, i.toString(), ROOT_NODE)]).flat(), "return context;"]), "}");
|
|
2478
|
+
while (nodeToProcess.size) {
|
|
2533
2479
|
const [key, fnData] = nodeToProcess.entries().next().value;
|
|
2534
|
-
|
|
2535
|
-
"
|
|
2480
|
+
renderFunctions.push(`${key}(${fnData.args.join(", ")}) {`, ...indent([
|
|
2481
|
+
"const context = new Context(this, parentContext)",
|
|
2536
2482
|
...fnData.fn(...fnData.args),
|
|
2537
|
-
"return
|
|
2538
|
-
]), "}");
|
|
2539
|
-
else renderFunctions.push(`${key}() {`, ...indent([
|
|
2540
|
-
"let unwatchFns = [];",
|
|
2541
|
-
...fnData.fn(),
|
|
2542
|
-
"return unwatchFns;"
|
|
2483
|
+
"return context"
|
|
2543
2484
|
]), "}");
|
|
2544
2485
|
nodeToProcess.delete(key);
|
|
2545
2486
|
}
|
|
@@ -2550,27 +2491,33 @@ function generateRenderFunction(ast, cssVariableName) {
|
|
|
2550
2491
|
* For flow control nodes no single var is produced; instead multiple children
|
|
2551
2492
|
* are appended directly inside the control flow block.
|
|
2552
2493
|
*/
|
|
2553
|
-
function processNode(node, nodeName, parentNode
|
|
2494
|
+
function processNode(node, nodeName, parentNode) {
|
|
2554
2495
|
switch (node.type) {
|
|
2555
2496
|
case ASTNodeType.Text:
|
|
2556
|
-
case ASTNodeType.Interpolation: return processTextAndInterpolation(node, getTextIdentifier(parentNode, nodeName), parentNode
|
|
2557
|
-
case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode
|
|
2497
|
+
case ASTNodeType.Interpolation: return processTextAndInterpolation(node, getTextIdentifier(parentNode, nodeName), parentNode);
|
|
2498
|
+
case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode);
|
|
2558
2499
|
case ASTNodeType.If:
|
|
2559
|
-
const conditionalBlockData = processIf(node, nodeName, parentNode
|
|
2560
|
-
conditionalBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2500
|
+
const conditionalBlockData = processIf(node, nodeName, parentNode);
|
|
2501
|
+
conditionalBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2502
|
+
fn: () => fnBody.code,
|
|
2503
|
+
args: fnBody.args
|
|
2504
|
+
}));
|
|
2561
2505
|
return conditionalBlockData.mainBlock;
|
|
2562
2506
|
case ASTNodeType.For:
|
|
2563
|
-
const forBlockData = processFor(node, nodeName, parentNode
|
|
2507
|
+
const forBlockData = processFor(node, nodeName, parentNode);
|
|
2564
2508
|
forBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2565
2509
|
fn: () => fnBody.code,
|
|
2566
2510
|
args: fnBody.args
|
|
2567
2511
|
}));
|
|
2568
2512
|
return forBlockData.mainBlock;
|
|
2569
2513
|
case ASTNodeType.Switch:
|
|
2570
|
-
const switchBlockData = processSwitch(node, nodeName, parentNode
|
|
2571
|
-
switchBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2514
|
+
const switchBlockData = processSwitch(node, nodeName, parentNode);
|
|
2515
|
+
switchBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2516
|
+
fn: () => fnBody.code,
|
|
2517
|
+
args: fnBody.args
|
|
2518
|
+
}));
|
|
2572
2519
|
return switchBlockData.mainBlock;
|
|
2573
|
-
case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode
|
|
2520
|
+
case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode);
|
|
2574
2521
|
default: return [];
|
|
2575
2522
|
}
|
|
2576
2523
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "A library for transpiling Xaendar Templates into JavaScript code",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@xaendar/common": "0.6.
|
|
20
|
-
"@xaendar/types": "0.6.
|
|
19
|
+
"@xaendar/common": "0.6.10",
|
|
20
|
+
"@xaendar/types": "0.6.10",
|
|
21
21
|
"typescript": "^6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|