@xaendar/compiler 0.6.11 → 0.6.13
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 +173 -108
- package/package.json +3 -3
|
@@ -390,23 +390,34 @@ function consumeEvent(cursor, _context) {
|
|
|
390
390
|
let read = true;
|
|
391
391
|
let event = "";
|
|
392
392
|
let retVal;
|
|
393
|
+
let deep = 0;
|
|
393
394
|
cursor.advance();
|
|
394
395
|
while (read) switch (cursor.peek()) {
|
|
395
396
|
case 32:
|
|
396
397
|
case 47:
|
|
397
398
|
case 62:
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
399
|
+
if (deep === 0) {
|
|
400
|
+
retVal = {
|
|
401
|
+
state: LexerState.TAG_BODY,
|
|
402
|
+
tokens: [{
|
|
403
|
+
type: TokenType.EVENT,
|
|
404
|
+
parts: [event]
|
|
405
|
+
}]
|
|
406
|
+
};
|
|
407
|
+
read = false;
|
|
408
|
+
}
|
|
409
|
+
break;
|
|
410
|
+
case 40:
|
|
411
|
+
deep++;
|
|
412
|
+
cursor.advance();
|
|
413
|
+
break;
|
|
414
|
+
case 41:
|
|
415
|
+
deep--;
|
|
416
|
+
cursor.advance();
|
|
406
417
|
break;
|
|
407
418
|
default:
|
|
408
419
|
cursor.advance();
|
|
409
|
-
event = `${event}${cursor.currentChar.value}`;
|
|
420
|
+
if (deep === 0) event = `${event}${cursor.currentChar.value}`;
|
|
410
421
|
}
|
|
411
422
|
return retVal;
|
|
412
423
|
}
|
|
@@ -1925,76 +1936,6 @@ var Parser = class {
|
|
|
1925
1936
|
}
|
|
1926
1937
|
};
|
|
1927
1938
|
//#endregion
|
|
1928
|
-
//#region ../packages/compiler/src/render-generator/states/process-const-declaration.state.ts
|
|
1929
|
-
/**
|
|
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.
|
|
1937
|
-
*/
|
|
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
|
-
}
|
|
1997
|
-
//#endregion
|
|
1998
1939
|
//#region ../packages/compiler/src/render-generator/utils/render-generator.utils.ts
|
|
1999
1940
|
/**
|
|
2000
1941
|
* Complete set of JavaScript global identifiers up to ES2026.
|
|
@@ -2192,7 +2133,7 @@ var ROOT_NODE = "root";
|
|
|
2192
2133
|
*
|
|
2193
2134
|
* @param expression - Either a raw identifier string or a validated
|
|
2194
2135
|
* `ts.Expression` node produced by `validateExpression`.
|
|
2195
|
-
* @param
|
|
2136
|
+
* @param compilerContext - The active template scope context.
|
|
2196
2137
|
* @returns The resolved expression as a JavaScript string ready for codegen.
|
|
2197
2138
|
*
|
|
2198
2139
|
* @example
|
|
@@ -2205,8 +2146,8 @@ var ROOT_NODE = "root";
|
|
|
2205
2146
|
* // typeof id !== 'boolean' || pippo instanceof HTMLElement
|
|
2206
2147
|
* // → typeof this.id !== 'boolean' || this.pippo instanceof HTMLElement
|
|
2207
2148
|
*/
|
|
2208
|
-
function resolveExpression(expression) {
|
|
2209
|
-
return emitNode(expression, expression);
|
|
2149
|
+
function resolveExpression(expression, compilerContext) {
|
|
2150
|
+
return emitNode(expression, expression, compilerContext);
|
|
2210
2151
|
}
|
|
2211
2152
|
/**
|
|
2212
2153
|
* Emits the resolved text for a node.
|
|
@@ -2217,13 +2158,14 @@ function resolveExpression(expression) {
|
|
|
2217
2158
|
* - If the node is a resolvable Identifier, emits the resolved name.
|
|
2218
2159
|
* - Otherwise recurses into children and concatenates their output.
|
|
2219
2160
|
*/
|
|
2220
|
-
function emitNode(node, parent) {
|
|
2161
|
+
function emitNode(node, parent, compilerContext) {
|
|
2162
|
+
if (ts.isIdentifier(node) && needsResolution(node, parent)) return compilerContext.hasIdentifier(node.text) ? node.text : `this.${node.text}`;
|
|
2221
2163
|
if (!containsResolvableIdentifier(node, parent)) return node.getText();
|
|
2222
2164
|
const sourceText = node.getSourceFile().text;
|
|
2223
2165
|
let result = "";
|
|
2224
2166
|
let lastEnd = node.getStart();
|
|
2225
2167
|
ts.forEachChild(node, (child) => {
|
|
2226
|
-
result = `${result}${sourceText.slice(lastEnd, child.getStart())}${emitNode(child, node)}`;
|
|
2168
|
+
result = `${result}${sourceText.slice(lastEnd, child.getStart())}${emitNode(child, node, compilerContext)}`;
|
|
2227
2169
|
lastEnd = child.getEnd();
|
|
2228
2170
|
});
|
|
2229
2171
|
return `${result}${sourceText.slice(lastEnd, node.getEnd())}`;
|
|
@@ -2268,6 +2210,114 @@ function getBlockIdentifier(parentNode, index, prefix) {
|
|
|
2268
2210
|
return (parentNode !== "root" ? `${parentNode}_${prefix}${index}` : `${prefix}${index}`).replace(/-/g, "_");
|
|
2269
2211
|
}
|
|
2270
2212
|
//#endregion
|
|
2213
|
+
//#region ../packages/compiler/src/render-generator/states/process-const-declaration.state.ts
|
|
2214
|
+
/**
|
|
2215
|
+
* Generates code for a `@const` declaration node.
|
|
2216
|
+
* Emits a `const name = expression;` JavaScript statement.
|
|
2217
|
+
*
|
|
2218
|
+
* @param node The `ConstDeclarationNode` to process.
|
|
2219
|
+
* @param _nodeName Unused node name.
|
|
2220
|
+
* @param _parentNode Unused parent node name.
|
|
2221
|
+
* @param _context Unused render context.
|
|
2222
|
+
* @returns Array containing the generated const statement string.
|
|
2223
|
+
*/
|
|
2224
|
+
function processConstDeclaration(node, _nodeName, _parentNode, compilerContext) {
|
|
2225
|
+
compilerContext.addIdentifier(node.varName);
|
|
2226
|
+
return [`declareConst(context, ${node.varName}, () => ${resolveExpression(node.expression, compilerContext)});`];
|
|
2227
|
+
}
|
|
2228
|
+
//#endregion
|
|
2229
|
+
//#region ../packages/compiler/src/render-generator/states/process-element.state.ts
|
|
2230
|
+
/**
|
|
2231
|
+
* Generates code for an HTML element node: creates the DOM element, sets attributes,
|
|
2232
|
+
* attaches event listeners, appends it to the parent, and recursively processes children.
|
|
2233
|
+
*
|
|
2234
|
+
* @param node The `ElementNode` to process.
|
|
2235
|
+
* @param nodeName Variable name to use for the created DOM element.
|
|
2236
|
+
* @param parentNode Variable name of the parent DOM node to append to.
|
|
2237
|
+
* @param compilerContext Current render scope context.
|
|
2238
|
+
* @returns Array of generated code lines.
|
|
2239
|
+
*/
|
|
2240
|
+
function processElement(node, nodeName, parentNode, compilerContext) {
|
|
2241
|
+
const attributes = mapAttributes(node.attributes, compilerContext);
|
|
2242
|
+
const events = mapEvents(node.events);
|
|
2243
|
+
const code = [`const ${nodeName} = _renderElement(${parentNode}, context, '${node.tagName}',`];
|
|
2244
|
+
attributes.length ? code.push(...indent([
|
|
2245
|
+
"[",
|
|
2246
|
+
...indent(attributes),
|
|
2247
|
+
"],"
|
|
2248
|
+
])) : code[code.length - 1] = `${code[code.length - 1]} [],`;
|
|
2249
|
+
events.length ? code.push(...indent([
|
|
2250
|
+
"[",
|
|
2251
|
+
...indent(events),
|
|
2252
|
+
"]"
|
|
2253
|
+
]), ")") : code[code.length - 1] = `${code[code.length - 1]} [])`;
|
|
2254
|
+
code.push(...node.children.map((child, i) => processNode(child, i.toString(), nodeName, compilerContext)).flat());
|
|
2255
|
+
return code;
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Generates code that assigns attributes to a DOM element.
|
|
2259
|
+
*
|
|
2260
|
+
* Static (string) attribute values are set once via a direct `setAttribute` call,
|
|
2261
|
+
* while dynamic attribute values are wrapped in an `effect` so the attribute is
|
|
2262
|
+
* re-evaluated and updated whenever its underlying signal dependencies change.
|
|
2263
|
+
* The disposer returned by the `effect` is registered in `unwatchFns` for cleanup.
|
|
2264
|
+
*
|
|
2265
|
+
* @param attributes The attribute nodes to map onto the element.
|
|
2266
|
+
* @returns Array of generated code lines, one per attribute.
|
|
2267
|
+
*/
|
|
2268
|
+
function mapAttributes(attributes, compilerContext) {
|
|
2269
|
+
return attributes?.map(({ name, value }) => {
|
|
2270
|
+
const isLiteral = typeof value === "string";
|
|
2271
|
+
return `{ name: '${name}', value: () => ${isLiteral ? `'${value}'` : resolveExpression(value.expression, compilerContext)}, literal: ${isLiteral} },`;
|
|
2272
|
+
});
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Generates code that attaches event listeners to a DOM element.
|
|
2276
|
+
*
|
|
2277
|
+
* For each event node an `addEventListener` call is emitted, binding the event
|
|
2278
|
+
* to the component instance handler and exposing the native event as `$event`.
|
|
2279
|
+
*
|
|
2280
|
+
* @param events The event nodes to bind to the element.
|
|
2281
|
+
* @returns Array of generated code lines, one per event listener.
|
|
2282
|
+
*/
|
|
2283
|
+
function mapEvents(events) {
|
|
2284
|
+
return events?.map((event) => `{ name: '${event.name}', handler: '${event.handler}' }`);
|
|
2285
|
+
}
|
|
2286
|
+
//#endregion
|
|
2287
|
+
//#region ../packages/compiler/src/render-generator/models/compiler-context.model.ts
|
|
2288
|
+
/**
|
|
2289
|
+
* Tracks identifier scope during render code generation.
|
|
2290
|
+
* Each `Context` instance represents one lexical scope (e.g. a `@for` loop body)
|
|
2291
|
+
* and can be chained to a parent context for outer-scope resolution.
|
|
2292
|
+
*/
|
|
2293
|
+
var CompilerContext = class {
|
|
2294
|
+
_identifiers;
|
|
2295
|
+
_parent;
|
|
2296
|
+
/**
|
|
2297
|
+
* Creates a new scope context.
|
|
2298
|
+
*
|
|
2299
|
+
* @param _identifiers List of loop variable names declared in this scope.
|
|
2300
|
+
* @param _parent Optional parent context representing the enclosing scope.
|
|
2301
|
+
*/
|
|
2302
|
+
constructor(_identifiers = new Array(), _parent) {
|
|
2303
|
+
this._identifiers = _identifiers;
|
|
2304
|
+
this._parent = _parent;
|
|
2305
|
+
}
|
|
2306
|
+
addIdentifier(name) {
|
|
2307
|
+
if (this.hasIdentifier(name)) throw new Error(`Identifier "${name}" is already declared in this scope.`);
|
|
2308
|
+
this._identifiers.push(name);
|
|
2309
|
+
}
|
|
2310
|
+
/**
|
|
2311
|
+
* Returns the innermost identifier in the current scope chain, or
|
|
2312
|
+
* delegates to the parent context if none is found in this scope.
|
|
2313
|
+
*
|
|
2314
|
+
* @returns The most recently declared identifier name, or `undefined` if none exists.
|
|
2315
|
+
*/
|
|
2316
|
+
hasIdentifier(name) {
|
|
2317
|
+
return this._identifiers.includes(name) || (this._parent?.hasIdentifier(name) ?? false);
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
//#endregion
|
|
2271
2321
|
//#region ../packages/compiler/src/render-generator/states/process-for.state.ts
|
|
2272
2322
|
/**
|
|
2273
2323
|
* Generates code for a `@for` iteration node.
|
|
@@ -2297,12 +2347,14 @@ function getBlockIdentifier(parentNode, index, prefix) {
|
|
|
2297
2347
|
* @param nodeName - Base variable name prefix used for child nodes and
|
|
2298
2348
|
* to produce a unique loop counter identifier.
|
|
2299
2349
|
* @param parentNode - Variable name of the parent DOM node.
|
|
2350
|
+
* @param compilerContext - The enclosing scope context.
|
|
2300
2351
|
* @returns Array of generated code lines.
|
|
2301
2352
|
*/
|
|
2302
|
-
function processFor(node, nodeName, parentNode) {
|
|
2353
|
+
function processFor(node, nodeName, parentNode, compilerContext) {
|
|
2303
2354
|
const mainBlock = new Array();
|
|
2304
2355
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2305
2356
|
const iterableSource = node.iterableSource;
|
|
2357
|
+
compilerContext.hasIdentifier(iterableSource) || `${iterableSource}`;
|
|
2306
2358
|
const itemsName = getTextIdentifier(parentNode, nodeName, "items");
|
|
2307
2359
|
const counterName = getTextIdentifier(parentNode, nodeName, "i");
|
|
2308
2360
|
const indexName = resolveImplicit(node, "$index");
|
|
@@ -2310,9 +2362,17 @@ function processFor(node, nodeName, parentNode) {
|
|
|
2310
2362
|
const lastName = resolveImplicit(node, "$last");
|
|
2311
2363
|
const evenName = resolveImplicit(node, "$even");
|
|
2312
2364
|
const oddName = resolveImplicit(node, "$odd");
|
|
2365
|
+
const forContext = new CompilerContext([
|
|
2366
|
+
node.itemAlias,
|
|
2367
|
+
indexName,
|
|
2368
|
+
firstName,
|
|
2369
|
+
lastName,
|
|
2370
|
+
evenName,
|
|
2371
|
+
oddName
|
|
2372
|
+
], compilerContext);
|
|
2313
2373
|
const forKey = getBlockIdentifier(parentNode, nodeName, "for");
|
|
2314
2374
|
functionsToProcess.set(forKey, {
|
|
2315
|
-
code: [`const { ${node.itemAlias}, ${indexName}, ${firstName}, ${lastName}, ${evenName}, ${oddName} } = _iterationVariables(${itemsName}, ${counterName});`, ...node.children.flatMap((child, i) => processNode(child, `${nodeName}_${i}`, parentNode))],
|
|
2375
|
+
code: [`const { ${node.itemAlias}, ${indexName}, ${firstName}, ${lastName}, ${evenName}, ${oddName} } = _iterationVariables(${itemsName}, ${counterName});`, ...node.children.flatMap((child, i) => processNode(child, `${nodeName}_${i}`, parentNode, forContext))],
|
|
2316
2376
|
args: [
|
|
2317
2377
|
parentNode,
|
|
2318
2378
|
"parentContext",
|
|
@@ -2320,7 +2380,7 @@ function processFor(node, nodeName, parentNode) {
|
|
|
2320
2380
|
counterName
|
|
2321
2381
|
]
|
|
2322
2382
|
});
|
|
2323
|
-
mainBlock.push(`_for(${parentNode}, context, '${iterableSource}', this.${forKey}.bind(this));`);
|
|
2383
|
+
mainBlock.push(`_for(${parentNode}, context, context.getIdentifier('${iterableSource}'), this.${forKey}.bind(this));`);
|
|
2324
2384
|
return {
|
|
2325
2385
|
mainBlock,
|
|
2326
2386
|
fns: functionsToProcess
|
|
@@ -2352,38 +2412,41 @@ function resolveImplicit(node, implicit) {
|
|
|
2352
2412
|
* @param parentNode Variable name of the parent DOM node.
|
|
2353
2413
|
* @returns Array of generated code lines.
|
|
2354
2414
|
*/
|
|
2355
|
-
function processIf(node, nodeName, parentNode) {
|
|
2415
|
+
function processIf(node, nodeName, parentNode, compilerContext) {
|
|
2416
|
+
const ifContext = new CompilerContext([], compilerContext);
|
|
2356
2417
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2357
2418
|
const mainBlock = new Array();
|
|
2358
2419
|
const ifKey = getBlockIdentifier(parentNode, nodeName, "if");
|
|
2359
2420
|
mainBlock.push({
|
|
2360
|
-
condition: resolveExpression(node.conditionNode),
|
|
2421
|
+
condition: resolveExpression(node.conditionNode, compilerContext),
|
|
2361
2422
|
block: `this.${ifKey}.bind(this)`
|
|
2362
2423
|
});
|
|
2363
2424
|
functionsToProcess.set(ifKey, {
|
|
2364
|
-
code: processConsequent(node, nodeName, parentNode),
|
|
2425
|
+
code: processConsequent(node, nodeName, parentNode, ifContext),
|
|
2365
2426
|
args: [parentNode, "parentContext"]
|
|
2366
2427
|
});
|
|
2367
2428
|
let alt = node.alternate;
|
|
2368
2429
|
let index = 0;
|
|
2369
2430
|
while (alt?.type === ASTNodeType.ElseIf) {
|
|
2431
|
+
const elseIfContext = new CompilerContext([], compilerContext);
|
|
2370
2432
|
const keyElseIf = getBlockIdentifier(parentNode, `${nodeName}_${index}`, "elseIf");
|
|
2371
2433
|
const conditionNode = alt.conditionNode;
|
|
2372
2434
|
mainBlock.push({
|
|
2373
|
-
condition: resolveExpression(conditionNode),
|
|
2435
|
+
condition: resolveExpression(conditionNode, compilerContext),
|
|
2374
2436
|
block: `this.${keyElseIf}.bind(this)`
|
|
2375
2437
|
});
|
|
2376
2438
|
functionsToProcess.set(keyElseIf, {
|
|
2377
|
-
code: processConsequent(alt, nodeName, parentNode),
|
|
2439
|
+
code: processConsequent(alt, nodeName, parentNode, elseIfContext),
|
|
2378
2440
|
args: [parentNode, "parentContext"]
|
|
2379
2441
|
});
|
|
2380
2442
|
alt = alt.alternate;
|
|
2381
2443
|
}
|
|
2382
2444
|
if (alt) {
|
|
2445
|
+
const elseContext = new CompilerContext([], compilerContext);
|
|
2383
2446
|
const keyElse = getBlockIdentifier(parentNode, nodeName, "else");
|
|
2384
2447
|
mainBlock.push({ block: `this.${keyElse}.bind(this)` });
|
|
2385
2448
|
functionsToProcess.set(keyElse, {
|
|
2386
|
-
code: processConsequent(alt, nodeName, parentNode),
|
|
2449
|
+
code: processConsequent(alt, nodeName, parentNode, elseContext),
|
|
2387
2450
|
args: [parentNode, "parentContext"]
|
|
2388
2451
|
});
|
|
2389
2452
|
}
|
|
@@ -2402,8 +2465,8 @@ function processIf(node, nodeName, parentNode) {
|
|
|
2402
2465
|
fns: functionsToProcess
|
|
2403
2466
|
};
|
|
2404
2467
|
}
|
|
2405
|
-
function processConsequent(node, nodeName, parentNode) {
|
|
2406
|
-
return node.consequent.map((child, i) => processNode(child, `${nodeName}_${i}`, parentNode)).flat();
|
|
2468
|
+
function processConsequent(node, nodeName, parentNode, compilerContext) {
|
|
2469
|
+
return node.consequent.map((child, i) => processNode(child, `${nodeName}_${i}`, parentNode, compilerContext)).flat();
|
|
2407
2470
|
}
|
|
2408
2471
|
//#endregion
|
|
2409
2472
|
//#region ../packages/compiler/src/render-generator/states/process-switch.state.ts
|
|
@@ -2415,15 +2478,17 @@ function processConsequent(node, nodeName, parentNode) {
|
|
|
2415
2478
|
* @param node The `SwitchNode` to process.
|
|
2416
2479
|
* @param nodeName Base variable name prefix for child nodes.
|
|
2417
2480
|
* @param parentNode Variable name of the parent DOM node.
|
|
2481
|
+
* @param compilerContext - Current render scope context.
|
|
2418
2482
|
* @returns Array of generated code lines.
|
|
2419
2483
|
*/
|
|
2420
|
-
function processSwitch(node, nodeName, parentNode) {
|
|
2484
|
+
function processSwitch(node, nodeName, parentNode, compilerContext) {
|
|
2421
2485
|
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2422
2486
|
const blocks = new Array();
|
|
2423
2487
|
node.cases.forEach((caseNode, i) => {
|
|
2488
|
+
const caseContext = new CompilerContext([], compilerContext);
|
|
2424
2489
|
const caseName = caseNode.condition ? getBlockIdentifier(parentNode, `${nodeName}_${i}`, "case") : getBlockIdentifier(parentNode, nodeName, "default");
|
|
2425
2490
|
functionsToProcess.set(caseName, {
|
|
2426
|
-
code: caseNode.children.map((child, i) => processNode(child, `${nodeName}_${i}_${i}`, parentNode)).flat(),
|
|
2491
|
+
code: caseNode.children.map((child, i) => processNode(child, `${nodeName}_${i}_${i}`, parentNode, caseContext)).flat(),
|
|
2427
2492
|
args: [parentNode, "parentContext"]
|
|
2428
2493
|
});
|
|
2429
2494
|
blocks.push({
|
|
@@ -2433,7 +2498,7 @@ function processSwitch(node, nodeName, parentNode) {
|
|
|
2433
2498
|
});
|
|
2434
2499
|
return {
|
|
2435
2500
|
mainBlock: [
|
|
2436
|
-
`_switch(${parentNode}, context, () => ${resolveExpression(node.expression)}, [`,
|
|
2501
|
+
`_switch(${parentNode}, context, () => ${resolveExpression(node.expression, compilerContext)}, [`,
|
|
2437
2502
|
...indent(blocks.map(({ condition, block }) => {
|
|
2438
2503
|
return [
|
|
2439
2504
|
"{",
|
|
@@ -2454,11 +2519,10 @@ function processSwitch(node, nodeName, parentNode) {
|
|
|
2454
2519
|
* then appends it to the parent DOM node.
|
|
2455
2520
|
*
|
|
2456
2521
|
* @param node A `TextNode` or `InterpolationNode` to process.
|
|
2457
|
-
* @param nodeName - The identifier for the Text Node created
|
|
2458
2522
|
* @param parentNode Variable name of the parent DOM node.
|
|
2459
2523
|
* @returns Array of two generated code lines: the text node creation and the appendChild call.
|
|
2460
2524
|
*/
|
|
2461
|
-
function processTextAndInterpolation(node,
|
|
2525
|
+
function processTextAndInterpolation(node, parentNode) {
|
|
2462
2526
|
return [`${node.type === ASTNodeType.Text ? `_renderLiteralText(${parentNode}, context, '${node.value}')` : `_renderText(${parentNode}, context, '${node.expression.text}')`}`];
|
|
2463
2527
|
}
|
|
2464
2528
|
//#endregion
|
|
@@ -2472,9 +2536,10 @@ var nodeToProcess = /* @__PURE__ */ new Map();
|
|
|
2472
2536
|
*/
|
|
2473
2537
|
function generateRenderFunction(ast, cssVariableName) {
|
|
2474
2538
|
nodeToProcess.clear();
|
|
2539
|
+
const compilerContext = new CompilerContext();
|
|
2475
2540
|
const renderFunctions = ["_render() {", ...indent([`const ${ROOT_NODE} = this._root;`, "const context = new Context(this)"])];
|
|
2476
2541
|
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;"]), "}");
|
|
2542
|
+
renderFunctions.push(...indent([...ast.map((node, i) => [...processNode(node, i.toString(), ROOT_NODE, compilerContext)]).flat(), "return context;"]), "}");
|
|
2478
2543
|
while (nodeToProcess.size) {
|
|
2479
2544
|
const [key, fnData] = nodeToProcess.entries().next().value;
|
|
2480
2545
|
renderFunctions.push(`${key}(${fnData.args.join(", ")}) {`, ...indent([
|
|
@@ -2491,33 +2556,33 @@ function generateRenderFunction(ast, cssVariableName) {
|
|
|
2491
2556
|
* For flow control nodes no single var is produced; instead multiple children
|
|
2492
2557
|
* are appended directly inside the control flow block.
|
|
2493
2558
|
*/
|
|
2494
|
-
function processNode(node, nodeName, parentNode) {
|
|
2559
|
+
function processNode(node, nodeName, parentNode, compilerContext) {
|
|
2495
2560
|
switch (node.type) {
|
|
2496
2561
|
case ASTNodeType.Text:
|
|
2497
|
-
case ASTNodeType.Interpolation: return processTextAndInterpolation(node,
|
|
2498
|
-
case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode);
|
|
2562
|
+
case ASTNodeType.Interpolation: return processTextAndInterpolation(node, parentNode);
|
|
2563
|
+
case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode, compilerContext);
|
|
2499
2564
|
case ASTNodeType.If:
|
|
2500
|
-
const conditionalBlockData = processIf(node, nodeName, parentNode);
|
|
2565
|
+
const conditionalBlockData = processIf(node, nodeName, parentNode, compilerContext);
|
|
2501
2566
|
conditionalBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2502
2567
|
fn: () => fnBody.code,
|
|
2503
2568
|
args: fnBody.args
|
|
2504
2569
|
}));
|
|
2505
2570
|
return conditionalBlockData.mainBlock;
|
|
2506
2571
|
case ASTNodeType.For:
|
|
2507
|
-
const forBlockData = processFor(node, nodeName, parentNode);
|
|
2572
|
+
const forBlockData = processFor(node, nodeName, parentNode, compilerContext);
|
|
2508
2573
|
forBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2509
2574
|
fn: () => fnBody.code,
|
|
2510
2575
|
args: fnBody.args
|
|
2511
2576
|
}));
|
|
2512
2577
|
return forBlockData.mainBlock;
|
|
2513
2578
|
case ASTNodeType.Switch:
|
|
2514
|
-
const switchBlockData = processSwitch(node, nodeName, parentNode);
|
|
2579
|
+
const switchBlockData = processSwitch(node, nodeName, parentNode, compilerContext);
|
|
2515
2580
|
switchBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2516
2581
|
fn: () => fnBody.code,
|
|
2517
2582
|
args: fnBody.args
|
|
2518
2583
|
}));
|
|
2519
2584
|
return switchBlockData.mainBlock;
|
|
2520
|
-
case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode);
|
|
2585
|
+
case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode, compilerContext);
|
|
2521
2586
|
default: return [];
|
|
2522
2587
|
}
|
|
2523
2588
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.13",
|
|
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.13",
|
|
20
|
+
"@xaendar/types": "0.6.13",
|
|
21
21
|
"typescript": "^6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|