@xaendar/compiler 0.4.6 → 0.4.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 +81 -41
- package/package.json +3 -3
|
@@ -2222,10 +2222,11 @@ function processElement(node, nodeName, parentNode, context) {
|
|
|
2222
2222
|
`const ${nodeName} = document.createElement("${node.tagName}");`,
|
|
2223
2223
|
...node.attributes?.map((attr) => {
|
|
2224
2224
|
const value = attr.value;
|
|
2225
|
-
return typeof value === "string" ? `${nodeName}.setAttribute('${attr.name}', ${value});` : `effect(() => ${nodeName}.setAttribute('${attr.name}', ${resolveExpression(value.expression, context)}));`;
|
|
2225
|
+
return typeof value === "string" ? `${nodeName}.setAttribute('${attr.name}', ${value});` : `unwatchFns.push(effect(() => ${nodeName}.setAttribute('${attr.name}', ${resolveExpression(value.expression, context)})));`;
|
|
2226
2226
|
}) || [],
|
|
2227
2227
|
...node.events?.map((event) => `${nodeName}.addEventListener("${event.name}", ($event) => this.${event.handler});`) || [],
|
|
2228
2228
|
`${parentNode}.appendChild(${nodeName});`,
|
|
2229
|
+
`unwatchFns.push(() => ${parentNode}.removeChild(${nodeName}));`,
|
|
2229
2230
|
...node.children.map((child, i) => processNode(child, i.toString(), nodeName, childrenContext)).flat()
|
|
2230
2231
|
];
|
|
2231
2232
|
}
|
|
@@ -2263,6 +2264,8 @@ function processElement(node, nodeName, parentNode, context) {
|
|
|
2263
2264
|
* @returns Array of generated code lines.
|
|
2264
2265
|
*/
|
|
2265
2266
|
function processFor(node, nodeName, parentNode, parentContext) {
|
|
2267
|
+
const mainBlock = new Array();
|
|
2268
|
+
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2266
2269
|
const iterableSource = node.iterableSource;
|
|
2267
2270
|
const iterableExpr = parentContext.getIdentifier(iterableSource) ?? `this.${iterableSource}`;
|
|
2268
2271
|
const itemsName = getTextIdentifier(parentNode, nodeName, "items");
|
|
@@ -2280,13 +2283,23 @@ function processFor(node, nodeName, parentNode, parentContext) {
|
|
|
2280
2283
|
evenName,
|
|
2281
2284
|
oddName
|
|
2282
2285
|
], parentContext);
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2286
|
+
functionsToProcess.set(`for_${nodeName}`, {
|
|
2287
|
+
code: [
|
|
2288
|
+
`const ${node.itemAlias} = ${itemsName}[${counterName}];`,
|
|
2289
|
+
`const ${indexName} = ${counterName};`,
|
|
2290
|
+
`const ${firstName} = ${counterName} === 0;`,
|
|
2291
|
+
`const ${lastName} = ${counterName} === ${itemsName}.length - 1;`,
|
|
2292
|
+
`const ${evenName} = ${counterName} % 2 === 0;`,
|
|
2293
|
+
`const ${oddName} = !${evenName};`,
|
|
2294
|
+
...node.children.flatMap((child, i) => indent(...processNode(child, `${nodeName}_${i}`, parentNode, forContext)))
|
|
2295
|
+
],
|
|
2296
|
+
args: [itemsName, counterName]
|
|
2297
|
+
});
|
|
2298
|
+
mainBlock.push("(() => {", ...indent("let localUnwatchFns = [];", "const unwatch = () => {", ...indent("localUnwatchFns?.forEach(fn => fn());", "localUnwatchFns = [];", "unwatchFns = unwatchFns.filter(fn => !localUnwatchFns.includes(fn));"), "};", "unwatchFns.push(", ...indent("effect(() => {", ...indent("unwatch();", `const ${itemsName} = ${iterableExpr};`, "Signal.subtle.untrack(() => {", ...indent(`for (let ${counterName} = 0; ${counterName} < ${itemsName}.length; ${counterName}++) {`, ...indent(`localUnwatchFns.push(...this.for_${nodeName}(${counterName}));`, "unwatchFns.push(...localUnwatchFns);"), "}"), "});"), "})"), ");"), "})();");
|
|
2299
|
+
return {
|
|
2300
|
+
mainBlock,
|
|
2301
|
+
fns: functionsToProcess
|
|
2302
|
+
};
|
|
2290
2303
|
}
|
|
2291
2304
|
/**
|
|
2292
2305
|
* Resolves the name that should be used in generated code for a given
|
|
@@ -2317,27 +2330,39 @@ function resolveImplicit(node, implicit) {
|
|
|
2317
2330
|
*/
|
|
2318
2331
|
function processIf(node, nodeName, parentNode, context) {
|
|
2319
2332
|
const ifContext = new Context([], context);
|
|
2320
|
-
const
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2333
|
+
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2334
|
+
const mainBlock = new Array();
|
|
2335
|
+
const ifKey = `if_${nodeName}`;
|
|
2336
|
+
mainBlock.push(`if (${resolveExpression(node.conditionNode, context)}) {`, ...indent(`checkAndUpdateState(0, this.${ifKey}.bind(this));`), "}");
|
|
2337
|
+
functionsToProcess.set(ifKey, processConsequent(node, nodeName, parentNode, ifContext));
|
|
2325
2338
|
let alt = node.alternate;
|
|
2339
|
+
let index = 0;
|
|
2326
2340
|
while (alt?.type === ASTNodeType.ElseIf) {
|
|
2327
2341
|
const elseIfContext = new Context([], context);
|
|
2328
|
-
|
|
2329
|
-
|
|
2342
|
+
const keyElseIf = `elseIf_${nodeName}_${index}`;
|
|
2343
|
+
mainBlock[mainBlock.length - 1] += ` else if (${resolveExpression(alt.conditionNode, context)}) {`;
|
|
2344
|
+
mainBlock.push(...indent(`checkAndUpdateState(${++index}, this.${keyElseIf}.bind(this));`), "}");
|
|
2345
|
+
functionsToProcess.set(keyElseIf, processConsequent(alt, nodeName, parentNode, elseIfContext));
|
|
2330
2346
|
alt = alt.alternate;
|
|
2331
2347
|
}
|
|
2332
2348
|
if (alt) {
|
|
2333
2349
|
const elseContext = new Context([], context);
|
|
2334
|
-
|
|
2335
|
-
|
|
2350
|
+
const keyElse = `else_${nodeName}`;
|
|
2351
|
+
mainBlock[mainBlock.length - 1] += " else {";
|
|
2352
|
+
mainBlock.push(...indent(`checkAndUpdateState(${++index}, this.${keyElse}.bind(this));`), "}");
|
|
2353
|
+
functionsToProcess.set(keyElse, processConsequent(alt, nodeName, parentNode, elseContext));
|
|
2336
2354
|
}
|
|
2337
|
-
return
|
|
2355
|
+
return {
|
|
2356
|
+
mainBlock: [
|
|
2357
|
+
"(() => {",
|
|
2358
|
+
...indent("let state;", "let localUnwatchFns = []", "const checkAndUpdateState = (newState, fn) => {", ...indent("if (state === newState) {", ...indent("return;"), "}", "state = newState;", "unwatch();", "localUnwatchFns = Signal.subtle.untrack(fn);", "unwatchFns.push(...localUnwatchFns);"), "};", "const unwatch = () => {", ...indent("localUnwatchFns?.forEach(fn => fn());", "unwatchFns = unwatchFns.filter(fn => !localUnwatchFns.includes(fn));", "localUnwatchFns = [];"), "}", "unwatchFns.push(", ...indent("effect(() => {", ...indent(...mainBlock), "})"), ");"),
|
|
2359
|
+
"})();"
|
|
2360
|
+
],
|
|
2361
|
+
fns: functionsToProcess
|
|
2362
|
+
};
|
|
2338
2363
|
}
|
|
2339
2364
|
function processConsequent(node, nodeName, parentNode, context) {
|
|
2340
|
-
return node.consequent.map((child, i) =>
|
|
2365
|
+
return node.consequent.map((child, i) => processNode(child, `${nodeName}_${i}`, parentNode, context)).flat();
|
|
2341
2366
|
}
|
|
2342
2367
|
//#endregion
|
|
2343
2368
|
//#region ../packages/compiler/src/render-generator/states/process-switch.state.ts
|
|
@@ -2353,11 +2378,24 @@ function processConsequent(node, nodeName, parentNode, context) {
|
|
|
2353
2378
|
* @returns Array of generated code lines.
|
|
2354
2379
|
*/
|
|
2355
2380
|
function processSwitch(node, nodeName, parentNode, context) {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2381
|
+
const mainBlock = new Array();
|
|
2382
|
+
const functionsToProcess = /* @__PURE__ */ new Map();
|
|
2383
|
+
mainBlock.push(`switch (${resolveExpression(node.expression, context)}) {`);
|
|
2384
|
+
node.cases.forEach((caseNode, i) => {
|
|
2385
|
+
const caseContext = new Context([], context);
|
|
2386
|
+
const caseName = caseNode.condition ? `case_${nodeName}_${i}` : `default_${nodeName}`;
|
|
2387
|
+
functionsToProcess.set(caseName, caseNode.children.map((child, i) => processNode(child, `${nodeName}_${i}_${i}`, parentNode, caseContext)).flat());
|
|
2388
|
+
mainBlock.push(...indent(...!caseNode.condition ? ["default: {"] : caseNode.condition.map((cond, i, arr) => `case ${cond}:${i === arr.length - 1 ? " {" : ""}`), ...indent(`localUnwatchFns = Signal.subtle.untrack(this.${caseName}.bind(this));`, "unwatchFns.push(...localUnwatchFns);", "break;"), "}"));
|
|
2389
|
+
});
|
|
2390
|
+
mainBlock.push("}");
|
|
2391
|
+
return {
|
|
2392
|
+
mainBlock: [
|
|
2393
|
+
"(() => {",
|
|
2394
|
+
...indent("let localUnwatchFns = []", "const checkAndUpdateState = (newState, fn) => {", ...indent("unwatch();", "localUnwatchFns = Signal.subtle.untrack(fn);", "unwatchFns.push(...localUnwatchFns);"), "};", "const unwatch = () => {", ...indent("localUnwatchFns?.forEach(fn => fn());", "unwatchFns = unwatchFns.filter(fn => !localUnwatchFns.includes(fn));", "localUnwatchFns = [];"), "}", "unwatchFns.push(", ...indent("effect(() => {", ...indent("unwatch();", ...mainBlock), "})"), ");"),
|
|
2395
|
+
"})();"
|
|
2396
|
+
],
|
|
2397
|
+
fns: functionsToProcess
|
|
2398
|
+
};
|
|
2361
2399
|
}
|
|
2362
2400
|
//#endregion
|
|
2363
2401
|
//#region ../packages/compiler/src/render-generator/states/process-text-and-interpolation.state.ts
|
|
@@ -2377,7 +2415,7 @@ function processTextAndInterpolation(node, nodeName, parentNode, context) {
|
|
|
2377
2415
|
return [
|
|
2378
2416
|
`const ${nodeName} = document.createTextNode(${textValue});`,
|
|
2379
2417
|
`${parentNode}.appendChild(${nodeName});`,
|
|
2380
|
-
`effect(() => ${nodeName}.textContent = ${textValue});`
|
|
2418
|
+
`unwatchFns.push(effect(() => ${nodeName}.textContent = ${textValue}));`
|
|
2381
2419
|
];
|
|
2382
2420
|
}
|
|
2383
2421
|
//#endregion
|
|
@@ -2392,14 +2430,13 @@ var nodeToProcess = /* @__PURE__ */ new Map();
|
|
|
2392
2430
|
function generateRenderFunction(ast, cssVariableName) {
|
|
2393
2431
|
nodeToProcess.clear();
|
|
2394
2432
|
const context = new Context();
|
|
2395
|
-
const renderFunctions = [
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
"}"
|
|
2399
|
-
];
|
|
2433
|
+
const renderFunctions = ["_render() {"];
|
|
2434
|
+
if (cssVariableName) renderFunctions.push(` this._root.adoptedStyleSheets = [${cssVariableName}];`);
|
|
2435
|
+
renderFunctions.push(" let unwatchFns = [];", ...indent(...ast.map((node, i) => [...processNode(node, i.toString(), ROOT_NODE, context)]).flat()), " return unwatchFns;", "}");
|
|
2400
2436
|
while (nodeToProcess.size > 0) {
|
|
2401
|
-
const [key,
|
|
2402
|
-
renderFunctions.push(`${key} {`, ...indent(...fn()), "}");
|
|
2437
|
+
const [key, fnData] = nodeToProcess.entries().next().value;
|
|
2438
|
+
if ("args" in fnData) renderFunctions.push(`${key}(${fnData.args.join(", ")}) {`, " let unwatchFns = [];", ...indent(...fnData.fn(...fnData.args)), " return unwatchFns;", "}");
|
|
2439
|
+
else renderFunctions.push(`${key}() {`, " let unwatchFns = [];", ...indent(...fnData.fn()), " return unwatchFns;", "}");
|
|
2403
2440
|
nodeToProcess.delete(key);
|
|
2404
2441
|
}
|
|
2405
2442
|
return renderFunctions.join("\n");
|
|
@@ -2415,17 +2452,20 @@ function processNode(node, nodeName, parentNode, context) {
|
|
|
2415
2452
|
case ASTNodeType.Interpolation: return processTextAndInterpolation(node, getTextIdentifier(parentNode, nodeName), parentNode, context);
|
|
2416
2453
|
case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode, context);
|
|
2417
2454
|
case ASTNodeType.If:
|
|
2418
|
-
const
|
|
2419
|
-
|
|
2420
|
-
return
|
|
2455
|
+
const conditionalBlockData = processIf(node, nodeName, parentNode, context);
|
|
2456
|
+
conditionalBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, { fn: () => fnBody }));
|
|
2457
|
+
return conditionalBlockData.mainBlock;
|
|
2421
2458
|
case ASTNodeType.For:
|
|
2422
|
-
const
|
|
2423
|
-
|
|
2424
|
-
|
|
2459
|
+
const forBlockData = processFor(node, nodeName, parentNode, context);
|
|
2460
|
+
forBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, {
|
|
2461
|
+
fn: () => fnBody.code,
|
|
2462
|
+
args: fnBody.args
|
|
2463
|
+
}));
|
|
2464
|
+
return forBlockData.mainBlock;
|
|
2425
2465
|
case ASTNodeType.Switch:
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
return
|
|
2466
|
+
const switchBlockData = processSwitch(node, nodeName, parentNode, context);
|
|
2467
|
+
switchBlockData.fns.forEach((fnBody, key) => nodeToProcess.set(key, { fn: () => fnBody }));
|
|
2468
|
+
return switchBlockData.mainBlock;
|
|
2429
2469
|
case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode, context);
|
|
2430
2470
|
default: return [];
|
|
2431
2471
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.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.4.
|
|
20
|
-
"@xaendar/types": "0.4.
|
|
19
|
+
"@xaendar/common": "0.4.10",
|
|
20
|
+
"@xaendar/types": "0.4.10",
|
|
21
21
|
"typescript": "^6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|