@akashjs/compiler 0.1.2 → 0.1.3

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/index.cjs CHANGED
@@ -1,1329 +1,39 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- SourceMapBuilder: () => SourceMapBuilder,
24
- analyzeTemplate: () => analyzeTemplate,
25
- compile: () => compile,
26
- createAkashSourceMap: () => createAkashSourceMap,
27
- createLanguageService: () => createLanguageService,
28
- encodeVLQ: () => encodeVLQ,
29
- extractHoistedTemplates: () => extractHoistedTemplates,
30
- generateHoistedDeclarations: () => generateHoistedDeclarations,
31
- generateScopeId: () => generateScopeId,
32
- getHoistedVar: () => getHoistedVar,
33
- getOptimizationStats: () => getOptimizationStats,
34
- isStaticExpression: () => isStaticExpression,
35
- isStaticNode: () => isStaticNode,
36
- parse: () => parse,
37
- parseTemplate: () => parseTemplate,
38
- scopeStyles: () => scopeStyles,
39
- staticNodeToHtml: () => staticNodeToHtml,
40
- transform: () => transform
41
- });
42
- module.exports = __toCommonJS(index_exports);
43
-
44
- // src/parse.ts
45
- function parse(source) {
46
- return {
47
- script: parseBlock(source, "script", (content, attrs, start, end) => ({
48
- content,
49
- lang: extractAttr(attrs, "lang") ?? "ts",
50
- start,
51
- end
52
- })),
53
- template: parseBlock(source, "template", (content, _attrs, start, end) => ({
54
- content,
55
- start,
56
- end
57
- })),
58
- style: parseBlock(source, "style", (content, attrs, start, end) => ({
59
- content,
60
- scoped: attrs.includes("scoped"),
61
- start,
62
- end
63
- }))
64
- };
65
- }
66
- function parseBlock(source, tag, factory) {
67
- const openPattern = new RegExp(`<${tag}(\\b[^>]*)>`, "i");
68
- const closePattern = new RegExp(`</${tag}>`, "i");
69
- const openMatch = openPattern.exec(source);
70
- if (!openMatch) return null;
71
- const attrs = openMatch[1] ?? "";
72
- const contentStart = openMatch.index + openMatch[0].length;
73
- const closeMatch = closePattern.exec(source.slice(contentStart));
74
- if (!closeMatch) return null;
75
- const contentEnd = contentStart + closeMatch.index;
76
- const content = source.slice(contentStart, contentEnd);
77
- return factory(content.trim(), attrs, contentStart, contentEnd);
78
- }
79
- function extractAttr(attrs, name) {
80
- const match = new RegExp(`${name}=["']([^"']+)["']`).exec(attrs);
81
- return match?.[1] ?? null;
82
- }
83
-
84
- // src/template.ts
85
- function parseTemplate(content) {
86
- const nodes = [];
87
- let pos = 0;
88
- while (pos < content.length) {
89
- if (content[pos] === "<") {
90
- if (content[pos + 1] === "/") break;
91
- const element = parseElement(content, pos);
92
- if (element) {
93
- nodes.push(element.node);
94
- pos = element.end;
95
- continue;
96
- }
97
- }
98
- if (content[pos] === "{") {
99
- const expr = parseExpression(content, pos);
100
- if (expr) {
101
- nodes.push(expr.node);
102
- pos = expr.end;
103
- continue;
104
- }
105
- }
106
- const textEnd = findNextBoundary(content, pos);
107
- const text = content.slice(pos, textEnd).trim();
108
- if (text) {
109
- nodes.push({ type: "text", content: text });
110
- }
111
- pos = textEnd;
112
- }
113
- return nodes;
114
- }
115
- function parseElement(content, start) {
116
- const tagMatch = /^<([a-zA-Z][a-zA-Z0-9-]*)/.exec(content.slice(start));
117
- if (!tagMatch) return null;
118
- const tag = tagMatch[1];
119
- let pos = start + tagMatch[0].length;
120
- const attrs = [];
121
- const directives = [];
122
- while (pos < content.length) {
123
- const ws = /^\s+/.exec(content.slice(pos));
124
- if (ws) pos += ws[0].length;
125
- if (content[pos] === ">" || content.slice(pos, pos + 2) === "/>") break;
126
- const attr = parseAttribute(content, pos);
127
- if (attr) {
128
- if (attr.attr.name.startsWith("bind:")) {
129
- directives.push({
130
- name: "bind",
131
- arg: attr.attr.name.slice(5),
132
- // e.g., 'value'
133
- value: attr.attr.value
134
- });
135
- } else if (attr.attr.name.startsWith(":")) {
136
- directives.push({
137
- name: attr.attr.name.slice(1),
138
- // remove ':'
139
- value: attr.attr.value
140
- });
141
- } else {
142
- attrs.push(attr.attr);
143
- }
144
- pos = attr.end;
145
- } else {
146
- pos++;
147
- }
148
- }
149
- const isComponent = tag[0] === tag[0].toUpperCase();
150
- if (content.slice(pos, pos + 2) === "/>") {
151
- return {
152
- node: {
153
- type: isComponent ? "component" : "element",
154
- tag,
155
- attrs,
156
- directives: directives.length > 0 ? directives : void 0,
157
- children: []
158
- },
159
- end: pos + 2
160
- };
161
- }
162
- pos++;
163
- const children = parseTemplate(content.slice(pos));
164
- const childContent = content.slice(pos);
165
- const closeTag = `</${tag}>`;
166
- const closeIdx = findClosingTag(content, pos, tag);
167
- if (closeIdx === -1) {
168
- return {
169
- node: {
170
- type: isComponent ? "component" : "element",
171
- tag,
172
- attrs,
173
- directives: directives.length > 0 ? directives : void 0,
174
- children
175
- },
176
- end: content.length
177
- };
178
- }
179
- const innerContent = content.slice(pos, closeIdx);
180
- const parsedChildren = parseTemplate(innerContent);
181
- return {
182
- node: {
183
- type: isComponent ? "component" : "element",
184
- tag,
185
- attrs,
186
- directives: directives.length > 0 ? directives : void 0,
187
- children: parsedChildren
188
- },
189
- end: closeIdx + closeTag.length
190
- };
191
- }
192
- function parseAttribute(content, start) {
193
- const nameMatch = /^(?:bind:|[:a-zA-Z_])[\w:.-]*/.exec(content.slice(start));
194
- if (!nameMatch) return null;
195
- const name = nameMatch[0];
196
- let pos = start + name.length;
197
- if (content[pos] !== "=") {
198
- return { attr: { name, value: "true", dynamic: false }, end: pos };
199
- }
200
- pos++;
201
- if (content[pos] === "{") {
202
- const expr = extractBraced(content, pos);
203
- if (expr) {
204
- return {
205
- attr: { name, value: expr.content, dynamic: true },
206
- end: expr.end
207
- };
208
- }
209
- }
210
- const quote = content[pos];
211
- if (quote === '"' || quote === "'") {
212
- const endQuote = content.indexOf(quote, pos + 1);
213
- if (endQuote === -1) return null;
214
- return {
215
- attr: { name, value: content.slice(pos + 1, endQuote), dynamic: false },
216
- end: endQuote + 1
217
- };
218
- }
219
- return null;
220
- }
221
- function parseExpression(content, start) {
222
- const result = extractBraced(content, start);
223
- if (!result) return null;
224
- return {
225
- node: { type: "expression", content: result.content },
226
- end: result.end
227
- };
228
- }
229
- function extractBraced(content, start) {
230
- if (content[start] !== "{") return null;
231
- let depth = 1;
232
- let pos = start + 1;
233
- while (pos < content.length && depth > 0) {
234
- const ch = content[pos];
235
- if (ch === '"' || ch === "'" || ch === "`") {
236
- pos = skipString(content, pos) + 1;
237
- continue;
238
- }
239
- if (ch === "{") depth++;
240
- else if (ch === "}") depth--;
241
- pos++;
242
- }
243
- return {
244
- content: content.slice(start + 1, pos - 1).trim(),
245
- end: pos
246
- };
247
- }
248
- function skipString(content, start) {
249
- const quote = content[start];
250
- let pos = start + 1;
251
- while (pos < content.length) {
252
- if (content[pos] === "\\") {
253
- pos += 2;
254
- continue;
255
- }
256
- if (content[pos] === quote) return pos;
257
- pos++;
258
- }
259
- return pos;
260
- }
261
- function findNextBoundary(content, start) {
262
- let pos = start;
263
- while (pos < content.length) {
264
- if (content[pos] === "<" || content[pos] === "{") return pos;
265
- pos++;
266
- }
267
- return pos;
268
- }
269
- function findClosingTag(content, start, tag) {
270
- const closeTag = `</${tag}>`;
271
- let depth = 1;
272
- let pos = start;
273
- while (pos < content.length) {
274
- const openIdx = content.indexOf(`<${tag}`, pos);
275
- const closeIdx = content.indexOf(closeTag, pos);
276
- if (closeIdx === -1) return -1;
277
- if (openIdx !== -1 && openIdx < closeIdx) {
278
- const afterTag = content.indexOf(">", openIdx);
279
- if (afterTag !== -1 && content[afterTag - 1] !== "/") {
280
- depth++;
281
- }
282
- pos = openIdx + 1;
283
- } else {
284
- depth--;
285
- if (depth === 0) return closeIdx;
286
- pos = closeIdx + 1;
287
- }
288
- }
289
- return -1;
290
- }
291
-
292
- // src/style.ts
293
- var import_crypto = require("crypto");
294
- function generateScopeId(filename) {
295
- const hash = (0, import_crypto.createHash)("md5").update(filename).digest("hex").slice(0, 6);
296
- return `data-a-${hash}`;
297
- }
298
- function scopeStyles(css, scopeId) {
299
- return css.replace(
300
- // Match selectors before { blocks
301
- /([^{}@/]+?)(\s*\{)/g,
302
- (match, selector, brace) => {
303
- if (selector.trim().startsWith("@")) {
304
- return match;
305
- }
306
- const scopedSelectors = selector.split(",").map((s) => {
307
- const trimmed = s.trim();
308
- if (!trimmed) return s;
309
- if (trimmed === ":root" || trimmed === ":host" || trimmed.includes(scopeId)) {
310
- return s;
311
- }
312
- return scopeSelector(trimmed, scopeId);
313
- }).join(",");
314
- return scopedSelectors + brace;
315
- }
316
- );
317
- }
318
- function scopeSelector(selector, scopeId) {
319
- const parts = selector.split(/(\s*[>+~]\s*|\s+)/);
320
- for (let i = parts.length - 1; i >= 0; i--) {
321
- const part = parts[i].trim();
322
- if (part && !isCombinator(part)) {
323
- if (part.includes("::")) {
324
- const [before, after] = part.split("::");
325
- parts[i] = parts[i].replace(part, `${before}[${scopeId}]::${after}`);
326
- } else if (part.includes(":")) {
327
- const colonIdx = part.indexOf(":");
328
- const before = part.slice(0, colonIdx);
329
- const after = part.slice(colonIdx);
330
- parts[i] = parts[i].replace(part, `${before}[${scopeId}]${after}`);
331
- } else {
332
- parts[i] = parts[i].replace(part, `${part}[${scopeId}]`);
333
- }
334
- break;
335
- }
336
- }
337
- return parts.join("");
338
- }
339
- function isCombinator(s) {
340
- return s === ">" || s === "+" || s === "~";
341
- }
342
-
343
- // src/transform.ts
344
- function transform(sfc, options = {}) {
345
- const scopeId = options.scopeId ?? (options.filename ? generateScopeId(options.filename) : void 0);
346
- const imports = /* @__PURE__ */ new Set();
347
- const runtimeImports = /* @__PURE__ */ new Set();
348
- runtimeImports.add("defineComponent");
349
- const script = sfc.script?.content ?? "";
350
- detectAutoImports(script, runtimeImports);
351
- const isServer = options.mode === "server";
352
- let templateCode = "";
353
- if (sfc.template) {
354
- const nodes = parseTemplate(sfc.template.content);
355
- if (isServer) {
356
- templateCode = generateServerRenderBody(nodes, runtimeImports, scopeId);
357
- } else {
358
- templateCode = generateRenderBody(nodes, runtimeImports, scopeId);
359
- }
360
- }
361
- let code = "";
362
- if (runtimeImports.size > 0) {
363
- code += `import { ${[...runtimeImports].join(", ")} } from '@akashjs/runtime';
364
- `;
365
- }
366
- const { cleanScript, propsInterface } = extractPropsInterface(script);
367
- const generics = propsInterface ? `<${propsInterface}>` : "";
368
- code += "\n";
369
- code += `export default defineComponent${generics}((ctx) => {
370
- `;
371
- if (script.includes("props")) {
372
- code += ` const props = ctx.props;
373
- `;
374
- }
375
- if (cleanScript.trim()) {
376
- const indented = cleanScript.trim().split("\n").map((line) => ` ${line}`).join("\n");
377
- code += `${indented}
378
- `;
379
- }
380
- code += "\n";
381
- code += ` return () => {
382
- `;
383
- code += templateCode;
384
- code += ` };
385
- `;
386
- code += `});
387
- `;
388
- let css;
389
- if (sfc.style) {
390
- css = sfc.style.scoped && scopeId ? scopeStyles(sfc.style.content, scopeId) : sfc.style.content;
391
- }
392
- return { code, css };
393
- }
394
- function detectAutoImports(script, imports) {
395
- const apis = [
396
- "signal",
397
- "computed",
398
- "effect",
399
- "batch",
400
- "untrack",
401
- "onMount",
402
- "onUnmount",
403
- "onError",
404
- "ref",
405
- "createContext",
406
- "provide",
407
- "inject",
408
- "Show",
409
- "For"
410
- ];
411
- for (const api of apis) {
412
- const usagePattern = new RegExp(`\\b${api}\\b`);
413
- const importPattern = new RegExp(`import\\s+.*\\b${api}\\b.*from`);
414
- if (usagePattern.test(script) && !importPattern.test(script)) {
415
- imports.add(api);
416
- }
417
- }
418
- }
419
- function extractPropsInterface(script) {
420
- const match = /interface\s+Props\s*\{([^}]*)\}/s.exec(script);
421
- if (!match) {
422
- return { cleanScript: script, propsInterface: null };
423
- }
424
- const cleanScript = script.replace(match[0], "").trim();
425
- const propsInterface = `{${match[1].trim()}}`;
426
- return { cleanScript, propsInterface };
427
- }
428
- function generateRenderBody(nodes, imports, scopeId) {
429
- if (nodes.length === 0) {
430
- return ` return null;
431
- `;
432
- }
433
- if (nodes.length === 1) {
434
- const lines2 = [];
435
- generateNode(nodes[0], lines2, imports, 4, "root", scopeId);
436
- lines2.push(` return root;`);
437
- return lines2.join("\n") + "\n";
438
- }
439
- imports.add("createElement");
440
- const lines = [];
441
- lines.push(` const __fragment = document.createDocumentFragment();`);
442
- for (let i = 0; i < nodes.length; i++) {
443
- const varName = `__n${i}`;
444
- generateNode(nodes[i], lines, imports, 4, varName, scopeId);
445
- lines.push(` __fragment.appendChild(${varName});`);
446
- }
447
- lines.push(` return __fragment;`);
448
- return lines.join("\n") + "\n";
449
- }
450
- function generateNode(node, lines, imports, indent, varName, scopeId) {
451
- const pad = " ".repeat(indent);
452
- switch (node.type) {
453
- case "element":
454
- generateElement(node, lines, imports, indent, varName, scopeId);
455
- break;
456
- case "component":
457
- generateComponentCall(node, lines, imports, indent, varName);
458
- break;
459
- case "text":
460
- lines.push(`${pad}const ${varName} = document.createTextNode(${JSON.stringify(node.content ?? "")});`);
461
- break;
462
- case "expression":
463
- imports.add("effect");
464
- lines.push(`${pad}const ${varName} = document.createTextNode('');`);
465
- lines.push(`${pad}effect(() => { ${varName}.textContent = String(${node.content}); }, { render: true });`);
466
- break;
467
- }
468
- }
469
- function generateElement(node, lines, imports, indent, varName, scopeId) {
470
- const pad = " ".repeat(indent);
471
- const tag = node.tag;
472
- const ifDirective = node.directives?.find((d) => d.name === "if");
473
- if (ifDirective) {
474
- imports.add("renderConditional");
475
- lines.push(`${pad}const ${varName}_anchor = document.createComment('if');`);
476
- lines.push(`${pad}const ${varName} = document.createDocumentFragment();`);
477
- lines.push(`${pad}${varName}.appendChild(${varName}_anchor);`);
478
- lines.push(`${pad}renderConditional(${varName}, ${varName}_anchor, () => ${ifDirective.value}, () => {`);
479
- const innerLines = [];
480
- const innerNode = { ...node, directives: node.directives?.filter((d) => d.name !== "if") };
481
- generateElement(innerNode, innerLines, imports, indent + 2, "__el", scopeId);
482
- innerLines.push(`${pad} return __el;`);
483
- lines.push(...innerLines);
484
- lines.push(`${pad}});`);
485
- return;
486
- }
487
- const forDirective = node.directives?.find((d) => d.name === "for");
488
- if (forDirective) {
489
- imports.add("renderList");
490
- const keyDirective = node.directives?.find((d) => d.name === "key");
491
- const forMatch = /^(?:\(([^)]+)\)|(\w+))\s+of\s+(.+)$/.exec(forDirective.value);
492
- if (forMatch) {
493
- const itemVar = forMatch[1] ?? forMatch[2];
494
- const listExpr = forMatch[3];
495
- const keyExpr = keyDirective?.value ?? `${itemVar}`;
496
- lines.push(`${pad}const ${varName}_anchor = document.createComment('for');`);
497
- lines.push(`${pad}const ${varName} = document.createDocumentFragment();`);
498
- lines.push(`${pad}${varName}.appendChild(${varName}_anchor);`);
499
- lines.push(`${pad}renderList(${varName}, ${varName}_anchor, () => ${listExpr}, (${itemVar}) => ${keyExpr}, (${itemVar}) => {`);
500
- const innerLines = [];
501
- const innerNode = { ...node, directives: node.directives?.filter((d) => d.name !== "for" && d.name !== "key") };
502
- generateElement(innerNode, innerLines, imports, indent + 2, "__el", scopeId);
503
- innerLines.push(`${pad} return __el;`);
504
- lines.push(...innerLines);
505
- lines.push(`${pad}});`);
506
- }
507
- return;
508
- }
509
- const bindDirectives = node.directives?.filter((d) => d.name === "bind") ?? [];
510
- if (bindDirectives.length > 0 && node.directives) {
511
- node.directives = node.directives.filter((d) => d.name !== "bind");
512
- }
513
- lines.push(`${pad}const ${varName} = document.createElement('${tag}');`);
514
- if (scopeId) {
515
- lines.push(`${pad}${varName}.setAttribute('${scopeId}', '');`);
516
- }
517
- if (node.attrs) {
518
- for (const attr of node.attrs) {
519
- if (attr.dynamic) {
520
- imports.add("effect");
521
- if (attr.name.startsWith("on")) {
522
- lines.push(`${pad}${varName}.addEventListener('${attr.name.slice(2).toLowerCase()}', ${attr.value});`);
523
- } else {
524
- lines.push(`${pad}effect(() => {`);
525
- if (attr.name === "class" || attr.name === "className") {
526
- lines.push(`${pad} ${varName}.className = ${attr.value};`);
527
- } else {
528
- lines.push(`${pad} ${varName}.setAttribute('${attr.name}', String(${attr.value}));`);
529
- }
530
- lines.push(`${pad}}, { render: true });`);
531
- }
532
- } else {
533
- if (attr.name === "class" || attr.name === "className") {
534
- lines.push(`${pad}${varName}.className = ${JSON.stringify(attr.value)};`);
535
- } else if (attr.name.startsWith("on")) {
536
- lines.push(`${pad}${varName}.setAttribute('${attr.name}', ${JSON.stringify(attr.value)});`);
537
- } else {
538
- lines.push(`${pad}${varName}.setAttribute('${attr.name}', ${JSON.stringify(attr.value)});`);
539
- }
540
- }
541
- }
542
- }
543
- for (const bindDir of bindDirectives) {
544
- const prop = bindDir.arg ?? "value";
545
- const signalExpr = bindDir.value;
546
- imports.add("effect");
547
- lines.push(`${pad}effect(() => { ${varName}.${prop} = ${signalExpr}(); }, { render: true });`);
548
- const eventName = prop === "value" || prop === "checked" ? "input" : "change";
549
- const valuePath = prop === "checked" ? "checked" : "value";
550
- lines.push(`${pad}${varName}.addEventListener('${eventName}', (e) => { ${signalExpr}.set(e.target.${valuePath}); });`);
551
- }
552
- if (node.children && node.children.length > 0) {
553
- for (let i = 0; i < node.children.length; i++) {
554
- const childVar = `${varName}_c${i}`;
555
- generateNode(node.children[i], lines, imports, indent, childVar, scopeId);
556
- lines.push(`${pad}${varName}.appendChild(${childVar});`);
557
- }
558
- }
559
- }
560
- function generateComponentCall(node, lines, imports, indent, varName) {
561
- const pad = " ".repeat(indent);
562
- const tag = node.tag;
563
- const propParts = [];
564
- if (node.attrs) {
565
- for (const attr of node.attrs) {
566
- if (attr.dynamic) {
567
- propParts.push(`${attr.name}: ${attr.value}`);
568
- } else {
569
- propParts.push(`${attr.name}: ${JSON.stringify(attr.value)}`);
570
- }
571
- }
572
- }
573
- if (node.children && node.children.length > 0) {
574
- const childLines = [];
575
- for (let i = 0; i < node.children.length; i++) {
576
- generateNode(node.children[i], childLines, imports, indent + 2, `__cc${i}`);
577
- }
578
- propParts.push(`children: () => null`);
579
- }
580
- const propsStr = propParts.length > 0 ? `{ ${propParts.join(", ")} }` : "{}";
581
- lines.push(`${pad}const ${varName} = ${tag}(${propsStr});`);
582
- }
583
- function generateServerRenderBody(nodes, imports, scopeId) {
584
- if (nodes.length === 0) {
585
- return ` return '';
586
- `;
587
- }
588
- const lines = [];
589
- lines.push(` let __html = '';`);
590
- for (const node of nodes) {
591
- generateServerNode(node, lines, imports, 4, scopeId);
592
- }
593
- lines.push(` return __html;`);
594
- return lines.join("\n") + "\n";
595
- }
596
- function generateServerNode(node, lines, imports, indent, scopeId) {
597
- const pad = " ".repeat(indent);
598
- switch (node.type) {
599
- case "text":
600
- lines.push(`${pad}__html += ${JSON.stringify(node.content ?? "")};`);
601
- break;
602
- case "expression":
603
- imports.add("escapeHtml");
604
- lines.push(`${pad}__html += escapeHtml(String(${node.content}));`);
605
- break;
606
- case "element":
607
- generateServerElement(node, lines, imports, indent, scopeId);
608
- break;
609
- case "component":
610
- lines.push(`${pad}// TODO: SSR component rendering for ${node.tag}`);
611
- lines.push(`${pad}__html += '';`);
612
- break;
613
- }
614
- }
615
- var SERVER_VOID_ELEMENTS = /* @__PURE__ */ new Set([
616
- "area",
617
- "base",
618
- "br",
619
- "col",
620
- "embed",
621
- "hr",
622
- "img",
623
- "input",
624
- "link",
625
- "meta",
626
- "param",
627
- "source",
628
- "track",
629
- "wbr"
630
- ]);
631
- function generateServerElement(node, lines, imports, indent, scopeId) {
632
- const pad = " ".repeat(indent);
633
- const tag = node.tag;
634
- const ifDirective = node.directives?.find((d) => d.name === "if");
635
- if (ifDirective) {
636
- lines.push(`${pad}if (${ifDirective.value}) {`);
637
- const innerNode = { ...node, directives: node.directives?.filter((d) => d.name !== "if") };
638
- generateServerElement(innerNode, lines, imports, indent + 2, scopeId);
639
- lines.push(`${pad}}`);
640
- return;
641
- }
642
- const forDirective = node.directives?.find((d) => d.name === "for");
643
- if (forDirective) {
644
- const forMatch = /^(?:\(([^)]+)\)|(\w+))\s+of\s+(.+)$/.exec(forDirective.value);
645
- if (forMatch) {
646
- const itemVar = forMatch[1] ?? forMatch[2];
647
- const listExpr = forMatch[3];
648
- lines.push(`${pad}for (const ${itemVar} of ${listExpr}) {`);
649
- const innerNode = { ...node, directives: node.directives?.filter((d) => d.name !== "for" && d.name !== "key") };
650
- generateServerElement(innerNode, lines, imports, indent + 2, scopeId);
651
- lines.push(`${pad}}`);
652
- }
653
- return;
654
- }
655
- let openTag = `'<${tag}`;
656
- if (scopeId) {
657
- openTag += ` ${scopeId}`;
658
- }
659
- if (node.attrs) {
660
- for (const attr of node.attrs) {
661
- if (attr.name.startsWith("on")) continue;
662
- if (attr.dynamic) {
663
- lines.push(`${pad}__html += ${openTag}';`);
664
- openTag = "'";
665
- imports.add("escapeHtml");
666
- if (attr.name === "class" || attr.name === "className") {
667
- lines.push(`${pad}__html += ' class="' + escapeHtml(String(${attr.value})) + '"';`);
668
- } else {
669
- lines.push(`${pad}__html += ' ${attr.name}="' + escapeHtml(String(${attr.value})) + '"';`);
670
- }
671
- } else {
672
- if (attr.name === "class" || attr.name === "className") {
673
- openTag += ` class="${attr.value}"`;
674
- } else {
675
- openTag += ` ${attr.name}="${attr.value}"`;
676
- }
677
- }
678
- }
679
- }
680
- if (SERVER_VOID_ELEMENTS.has(tag)) {
681
- lines.push(`${pad}__html += ${openTag} />';`);
682
- return;
683
- }
684
- lines.push(`${pad}__html += ${openTag}>';`);
685
- if (node.children) {
686
- for (const child of node.children) {
687
- generateServerNode(child, lines, imports, indent, scopeId);
688
- }
689
- }
690
- lines.push(`${pad}__html += '</${tag}>';`);
691
- }
692
-
693
- // src/analyze.ts
694
- function analyzeTemplate(nodes) {
695
- const result = {
696
- signalReads: [],
697
- eventHandlers: [],
698
- hasDynamicContent: false,
699
- staticSubtrees: [],
700
- reactiveExpressions: [],
701
- componentRefs: []
702
- };
703
- for (const node of nodes) {
704
- analyzeNode(node, result);
705
- }
706
- return result;
707
- }
708
- function analyzeNode(node, result) {
709
- switch (node.type) {
710
- case "expression":
711
- result.hasDynamicContent = true;
712
- if (node.content) {
713
- result.reactiveExpressions.push({
714
- expression: node.content,
715
- kind: "text"
716
- });
717
- extractSignalReads(node.content, "text", result);
718
- }
719
- break;
720
- case "element":
721
- analyzeElement(node, result);
722
- break;
723
- case "component":
724
- if (node.tag) {
725
- result.componentRefs.push(node.tag);
726
- }
727
- result.hasDynamicContent = true;
728
- analyzeAttributes(node, result);
729
- if (node.children) {
730
- for (const child of node.children) {
731
- analyzeNode(child, result);
732
- }
733
- }
734
- break;
735
- case "text":
736
- break;
737
- }
738
- }
739
- function analyzeElement(node, result) {
740
- const isDynamic = hasDynamicContent(node);
741
- if (node.directives) {
742
- for (const dir of node.directives) {
743
- result.hasDynamicContent = true;
744
- analyzeDirective(dir, node, result);
745
- }
746
- }
747
- analyzeAttributes(node, result);
748
- if (!isDynamic && !node.directives?.length) {
749
- result.staticSubtrees.push(node);
750
- }
751
- if (node.children) {
752
- for (const child of node.children) {
753
- analyzeNode(child, result);
754
- }
755
- }
756
- }
757
- function analyzeAttributes(node, result) {
758
- if (!node.attrs) return;
759
- for (const attr of node.attrs) {
760
- if (attr.dynamic) {
761
- result.hasDynamicContent = true;
762
- if (attr.name.startsWith("on")) {
763
- const event = attr.name.slice(2).toLowerCase();
764
- result.eventHandlers.push({
765
- event,
766
- handler: attr.value,
767
- tag: node.tag ?? "unknown"
768
- });
769
- } else {
770
- result.reactiveExpressions.push({
771
- expression: attr.value,
772
- kind: "attribute",
773
- attributeName: attr.name
774
- });
775
- extractSignalReads(attr.value, "attribute", result);
776
- }
777
- }
778
- }
779
- }
780
- function analyzeDirective(dir, node, result) {
781
- switch (dir.name) {
782
- case "if":
783
- case "else-if":
784
- case "show":
785
- result.reactiveExpressions.push({
786
- expression: dir.value,
787
- kind: "conditional"
788
- });
789
- extractSignalReads(dir.value, "directive", result);
790
- break;
791
- case "for": {
792
- const match = /\bof\s+(.+)$/.exec(dir.value);
793
- if (match) {
794
- result.reactiveExpressions.push({
795
- expression: match[1],
796
- kind: "list"
797
- });
798
- extractSignalReads(match[1], "directive", result);
799
- }
800
- break;
801
- }
802
- case "bind": {
803
- result.reactiveExpressions.push({
804
- expression: dir.value,
805
- kind: "attribute",
806
- attributeName: dir.value
807
- });
808
- extractSignalReads(dir.value, "directive", result);
809
- break;
810
- }
811
- }
812
- }
813
- function extractSignalReads(expression, context, result) {
814
- const KNOWN_NON_SIGNALS = /* @__PURE__ */ new Set([
815
- "console",
816
- "Math",
817
- "JSON",
818
- "Object",
819
- "Array",
820
- "String",
821
- "Number",
822
- "Boolean",
823
- "Date",
824
- "RegExp",
825
- "Error",
826
- "Promise",
827
- "parseInt",
828
- "parseFloat",
829
- "setTimeout",
830
- "setInterval",
831
- "clearTimeout",
832
- "clearInterval",
833
- "document",
834
- "window",
835
- "navigator",
836
- "fetch"
837
- ]);
838
- const callPattern = /\b([a-zA-Z_$][\w$]*)\s*\(\s*\)/g;
839
- let match;
840
- while ((match = callPattern.exec(expression)) !== null) {
841
- const name = match[1];
842
- if (!KNOWN_NON_SIGNALS.has(name)) {
843
- result.signalReads.push({
844
- expression: `${name}()`,
845
- context
846
- });
847
- }
848
- }
849
- }
850
- function hasDynamicContent(node) {
851
- if (node.attrs?.some((a) => a.dynamic)) return true;
852
- if (node.directives?.length) return true;
853
- if (node.children?.some((c) => c.type === "expression" || c.type === "component")) return true;
854
- if (node.children?.some((c) => hasDynamicContent(c))) return true;
855
- return false;
856
- }
857
- function isStaticExpression(expr) {
858
- const trimmed = expr.trim();
859
- if (/^['"`].*['"`]$/.test(trimmed)) return true;
860
- if (/^-?\d+(\.\d+)?$/.test(trimmed)) return true;
861
- if (trimmed === "true" || trimmed === "false") return true;
862
- if (trimmed === "null" || trimmed === "undefined") return true;
863
- return false;
864
- }
865
-
866
- // src/sourcemap.ts
867
- var VLQ_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
868
- function encodeVLQ(value) {
869
- let result = "";
870
- let vlq = value < 0 ? -value << 1 | 1 : value << 1;
871
- do {
872
- let digit = vlq & 31;
873
- vlq >>>= 5;
874
- if (vlq > 0) digit |= 32;
875
- result += VLQ_CHARS[digit];
876
- } while (vlq > 0);
877
- return result;
878
- }
879
- var SourceMapBuilder = class {
880
- mappings = [];
881
- sources = [];
882
- sourcesContent = [];
883
- /**
884
- * Add a source file.
885
- * @returns The source index.
886
- */
887
- addSource(filename, content) {
888
- const idx = this.sources.length;
889
- this.sources.push(filename);
890
- this.sourcesContent.push(content ?? null);
891
- return idx;
892
- }
893
- /**
894
- * Add a mapping from generated position to original position.
895
- */
896
- addMapping(mapping) {
897
- this.mappings.push(mapping);
898
- }
899
- /**
900
- * Add a 1:1 mapping for a range of lines.
901
- * Useful for script blocks that are mostly copied verbatim.
902
- */
903
- addLineRange(generatedStart, originalStart, lineCount, sourceIndex = 0) {
904
- for (let i = 0; i < lineCount; i++) {
905
- this.addMapping({
906
- generatedLine: generatedStart + i,
907
- generatedColumn: 0,
908
- originalLine: originalStart + i,
909
- originalColumn: 0,
910
- source: sourceIndex
911
- });
912
- }
913
- }
914
- /**
915
- * Generate the V3 source map JSON.
916
- */
917
- build(outputFilename) {
918
- const sorted = [...this.mappings].sort(
919
- (a, b) => a.generatedLine - b.generatedLine || a.generatedColumn - b.generatedColumn
920
- );
921
- return {
922
- version: 3,
923
- file: outputFilename,
924
- sources: this.sources,
925
- sourcesContent: this.sourcesContent,
926
- names: [],
927
- mappings: encodeMappings(sorted)
928
- };
929
- }
930
- /**
931
- * Generate the source map as a JSON string.
932
- */
933
- toJSON(outputFilename) {
934
- return JSON.stringify(this.build(outputFilename));
935
- }
936
- /**
937
- * Generate a data URL for inline source maps.
938
- */
939
- toDataUrl(outputFilename) {
940
- const json = this.toJSON(outputFilename);
941
- const base64 = typeof btoa === "function" ? btoa(json) : Buffer.from(json).toString("base64");
942
- return `data:application/json;charset=utf-8;base64,${base64}`;
943
- }
944
- };
945
- function encodeMappings(mappings) {
946
- const lines = [];
947
- let prevGeneratedLine = 0;
948
- let prevGeneratedColumn = 0;
949
- let prevOriginalLine = 0;
950
- let prevOriginalColumn = 0;
951
- let prevSource = 0;
952
- for (const mapping of mappings) {
953
- while (lines.length <= mapping.generatedLine) {
954
- lines.push([]);
955
- }
956
- if (mapping.generatedLine !== prevGeneratedLine) {
957
- prevGeneratedColumn = 0;
958
- prevGeneratedLine = mapping.generatedLine;
959
- }
960
- let segment = "";
961
- segment += encodeVLQ(mapping.generatedColumn - prevGeneratedColumn);
962
- prevGeneratedColumn = mapping.generatedColumn;
963
- const source = mapping.source ?? 0;
964
- segment += encodeVLQ(source - prevSource);
965
- prevSource = source;
966
- segment += encodeVLQ(mapping.originalLine - prevOriginalLine);
967
- prevOriginalLine = mapping.originalLine;
968
- segment += encodeVLQ(mapping.originalColumn - prevOriginalColumn);
969
- prevOriginalColumn = mapping.originalColumn;
970
- lines[mapping.generatedLine].push(segment);
971
- }
972
- return lines.map((segments) => segments.join(",")).join(";");
973
- }
974
- function createAkashSourceMap(filename, originalSource, scriptStartLine, scriptLineCount, generatedScriptStartLine) {
975
- const builder = new SourceMapBuilder();
976
- builder.addSource(filename, originalSource);
977
- builder.addLineRange(
978
- generatedScriptStartLine,
979
- scriptStartLine,
980
- scriptLineCount,
981
- 0
982
- );
983
- return builder;
984
- }
985
-
986
- // src/optimize.ts
987
- function isStaticNode(node) {
988
- if (node.type === "expression") return false;
989
- if (node.type === "component") return false;
990
- if (node.type === "text") return true;
991
- if (node.directives && node.directives.length > 0) return false;
992
- if (node.attrs?.some((a) => a.dynamic)) return false;
993
- if (node.children?.some((c) => !isStaticNode(c))) return false;
994
- return true;
995
- }
996
- function staticNodeToHtml(node) {
997
- switch (node.type) {
998
- case "text":
999
- return node.content ?? "";
1000
- case "element": {
1001
- let html = `<${node.tag}`;
1002
- if (node.attrs) {
1003
- for (const attr of node.attrs) {
1004
- if (attr.name === "class" || attr.name === "className") {
1005
- html += ` class="${attr.value}"`;
1006
- } else {
1007
- html += ` ${attr.name}="${attr.value}"`;
1008
- }
1009
- }
1010
- }
1011
- html += ">";
1012
- if (node.children) {
1013
- for (const child of node.children) {
1014
- html += staticNodeToHtml(child);
1015
- }
1016
- }
1017
- html += `</${node.tag}>`;
1018
- return html;
1019
- }
1020
- default:
1021
- return "";
1022
- }
1023
- }
1024
- function extractHoistedTemplates(nodes) {
1025
- const templates = [];
1026
- let counter = 0;
1027
- function visit(node) {
1028
- if (node.type !== "element") return;
1029
- if (isStaticNode(node) && node.children && node.children.length > 0) {
1030
- const varName = `__hoisted_${counter++}`;
1031
- templates.push({
1032
- varName,
1033
- html: staticNodeToHtml(node)
1034
- });
1035
- node._hoisted = varName;
1036
- return;
1037
- }
1038
- if (node.children) {
1039
- for (const child of node.children) {
1040
- visit(child);
1041
- }
1042
- }
1043
- }
1044
- for (const node of nodes) {
1045
- visit(node);
1046
- }
1047
- return templates;
1048
- }
1049
- function generateHoistedDeclarations(templates) {
1050
- if (templates.length === 0) return "";
1051
- let code = "// Hoisted static templates (created once, cloned per instance)\n";
1052
- for (const t of templates) {
1053
- code += `const ${t.varName} = /*#__PURE__*/ (() => {
1054
- `;
1055
- code += ` const _t = document.createElement('template');
1056
- `;
1057
- code += ` _t.innerHTML = ${JSON.stringify(t.html)};
1058
- `;
1059
- code += ` return _t;
1060
- `;
1061
- code += `})();
1062
- `;
1063
- }
1064
- return code;
1065
- }
1066
- function getHoistedVar(node) {
1067
- return node._hoisted ?? null;
1068
- }
1069
- function getOptimizationStats(nodes) {
1070
- let totalNodes = 0;
1071
- let staticNodes = 0;
1072
- function count(node) {
1073
- totalNodes++;
1074
- if (isStaticNode(node)) staticNodes++;
1075
- if (node.children) {
1076
- for (const child of node.children) {
1077
- count(child);
1078
- }
1079
- }
1080
- }
1081
- for (const node of nodes) {
1082
- count(node);
1083
- }
1084
- const hoisted = extractHoistedTemplates(
1085
- JSON.parse(JSON.stringify(nodes))
1086
- // clone to avoid mutation
1087
- );
1088
- return {
1089
- totalNodes,
1090
- staticNodes,
1091
- hoistedTemplates: hoisted.length,
1092
- staticRatio: totalNodes > 0 ? staticNodes / totalNodes : 0
1093
- };
1094
- }
1095
-
1096
- // src/language-service.ts
1097
- var RUNTIME_APIS = [
1098
- { label: "signal", kind: "property", detail: "signal<T>(initial: T): Signal<T>", documentation: "Create a reactive signal" },
1099
- { label: "computed", kind: "property", detail: "computed<T>(fn: () => T): ReadonlySignal<T>", documentation: "Create a derived reactive value" },
1100
- { label: "effect", kind: "property", detail: "effect(fn: () => void): () => void", documentation: "Run a side-effect when dependencies change" },
1101
- { label: "batch", kind: "property", detail: "batch(fn: () => void): void", documentation: "Batch signal updates" },
1102
- { label: "untrack", kind: "property", detail: "untrack<T>(fn: () => T): T", documentation: "Read signals without tracking" },
1103
- { label: "onMount", kind: "property", detail: "onMount(fn: () => void | (() => void)): void", documentation: "Run after component mounts" },
1104
- { label: "onUnmount", kind: "property", detail: "onUnmount(fn: () => void): void", documentation: "Run before component unmounts" },
1105
- { label: "provide", kind: "property", detail: "provide<T>(key: InjectionKey<T>, value: T): void", documentation: "Provide a value to descendants" },
1106
- { label: "inject", kind: "property", detail: "inject<T>(key: InjectionKey<T>): T", documentation: "Inject a value from ancestors" },
1107
- { label: "defineStore", kind: "property", detail: "defineStore(id, config): () => Store", documentation: "Define a global store" },
1108
- { label: "useHead", kind: "property", detail: "useHead(config: HeadConfig): void", documentation: "Manage document head tags" },
1109
- { label: "cx", kind: "property", detail: "cx(...inputs): string", documentation: "Merge CSS class names" },
1110
- { label: "pipe", kind: "property", detail: "pipe(value, transform, ...args): any", documentation: "Apply a pipe transform" }
1111
- ];
1112
- var BUILT_IN_COMPONENTS = [
1113
- { label: "Show", kind: "component", detail: "<Show when={condition}>{value => ...}</Show>", documentation: "Conditional rendering with type narrowing" },
1114
- { label: "For", kind: "component", detail: "<For each={items} key={fn}>{item => ...}</For>", documentation: "List rendering with keyed reconciliation" },
1115
- { label: "Switch", kind: "component", detail: "<Switch on={value} cases={...} />", documentation: "Switch/case rendering" },
1116
- { label: "Portal", kind: "component", detail: '<Portal target="selector">...</Portal>', documentation: "Render into different DOM node" },
1117
- { label: "Transition", kind: "component", detail: '<Transition name="fade" when={show}>...</Transition>', documentation: "CSS enter/exit transitions" },
1118
- { label: "ErrorBoundary", kind: "component", detail: "<ErrorBoundary fallback={fn}>...</ErrorBoundary>", documentation: "Catch errors from children" },
1119
- { label: "Suspense", kind: "component", detail: "<Suspense fallback={fn}>...</Suspense>", documentation: "Show fallback during async loading" },
1120
- { label: "VirtualFor", kind: "component", detail: "<VirtualFor each={items} itemHeight={40}>...</VirtualFor>", documentation: "Virtual scrolling for large lists" },
1121
- { label: "Image", kind: "component", detail: '<Image src="..." alt="..." />', documentation: "Optimized image with lazy loading" }
1122
- ];
1123
- var DIRECTIVES = [
1124
- { label: ":if", kind: "directive", detail: ":if={condition}", documentation: "Conditional rendering" },
1125
- { label: ":for", kind: "directive", detail: ":for={item of items()}", documentation: "List rendering" },
1126
- { label: ":show", kind: "directive", detail: ":show={condition}", documentation: "Toggle visibility (display)" },
1127
- { label: ":key", kind: "directive", detail: ":key={uniqueId}", documentation: "Reconciliation key for lists" },
1128
- { label: "bind:value", kind: "directive", detail: "bind:value={signal}", documentation: "Two-way binding" },
1129
- { label: "bind:checked", kind: "directive", detail: "bind:checked={signal}", documentation: "Two-way checkbox binding" }
1130
- ];
1131
- var HTML_EVENTS = [
1132
- "onClick",
1133
- "onInput",
1134
- "onChange",
1135
- "onSubmit",
1136
- "onKeyDown",
1137
- "onKeyUp",
1138
- "onFocus",
1139
- "onBlur",
1140
- "onMouseEnter",
1141
- "onMouseLeave",
1142
- "onScroll",
1143
- "onLoad",
1144
- "onError",
1145
- "onResize",
1146
- "onPointerDown",
1147
- "onPointerUp"
1148
- ].map((name) => ({
1149
- label: name,
1150
- kind: "event",
1151
- detail: `${name}={(e) => { ... }}`,
1152
- documentation: `${name.slice(2)} event handler`
1153
- }));
1154
- function createLanguageService() {
1155
- return {
1156
- /**
1157
- * Get diagnostics for an .akash file.
1158
- */
1159
- getDiagnostics(source, filename) {
1160
- const diagnostics = [];
1161
- try {
1162
- const sfc = parse(source);
1163
- if (!sfc.template) {
1164
- diagnostics.push({
1165
- range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
1166
- message: "Missing <template> block",
1167
- severity: "warning"
1168
- });
1169
- }
1170
- if (sfc.template) {
1171
- const nodes = parseTemplate(sfc.template.content);
1172
- validateNodes(nodes, diagnostics, sfc.template.start);
1173
- }
1174
- } catch (err) {
1175
- diagnostics.push({
1176
- range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
1177
- message: `Parse error: ${err instanceof Error ? err.message : String(err)}`,
1178
- severity: "error"
1179
- });
1180
- }
1181
- return diagnostics;
1182
- },
1183
- /**
1184
- * Get completion items at a position.
1185
- */
1186
- getCompletions(source, position) {
1187
- const line = source.split("\n")[position.line] ?? "";
1188
- const before = line.slice(0, position.character);
1189
- if (isInScript(source, position)) {
1190
- return [...RUNTIME_APIS];
1191
- }
1192
- if (isInTemplate(source, position)) {
1193
- if (before.endsWith("<") || /^<[A-Z]/.test(before.trimStart())) {
1194
- return [...BUILT_IN_COMPONENTS];
1195
- }
1196
- if (before.endsWith(":") || before.includes(":")) {
1197
- return [...DIRECTIVES];
1198
- }
1199
- if (isInsideTag(before)) {
1200
- return [...DIRECTIVES, ...HTML_EVENTS];
1201
- }
1202
- return [...BUILT_IN_COMPONENTS, ...DIRECTIVES];
1203
- }
1204
- return [];
1205
- },
1206
- /**
1207
- * Get hover information at a position.
1208
- */
1209
- getHoverInfo(source, position) {
1210
- const line = source.split("\n")[position.line] ?? "";
1211
- const word = getWordAt(line, position.character);
1212
- const api = RUNTIME_APIS.find((a) => a.label === word);
1213
- if (api) {
1214
- return { contents: `**${api.label}**
1215
-
1216
- ${api.detail}
1217
-
1218
- ${api.documentation}` };
1219
- }
1220
- const comp = BUILT_IN_COMPONENTS.find((c) => c.label === word);
1221
- if (comp) {
1222
- return { contents: `**${comp.label}**
1223
-
1224
- ${comp.detail}
1225
-
1226
- ${comp.documentation}` };
1227
- }
1228
- return null;
1229
- },
1230
- /**
1231
- * Get all available completions (for external tooling).
1232
- */
1233
- getAllCompletions() {
1234
- return {
1235
- apis: RUNTIME_APIS,
1236
- components: BUILT_IN_COMPONENTS,
1237
- directives: DIRECTIVES,
1238
- events: HTML_EVENTS
1239
- };
1240
- }
1241
- };
1242
- }
1243
- function validateNodes(nodes, diagnostics, baseOffset) {
1244
- for (const node of nodes) {
1245
- if (node.type === "element" && node.tag === "img") {
1246
- const hasAlt = node.attrs?.some((a) => a.name === "alt");
1247
- if (!hasAlt) {
1248
- diagnostics.push({
1249
- range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
1250
- message: "<img> element should have an alt attribute for accessibility",
1251
- severity: "warning",
1252
- code: "a11y-img-alt"
1253
- });
1254
- }
1255
- }
1256
- if (node.type === "element" && node.tag === "button") {
1257
- const hasType = node.attrs?.some((a) => a.name === "type");
1258
- if (!hasType) {
1259
- diagnostics.push({
1260
- range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
1261
- message: '<button> should have an explicit type attribute (type="button" or type="submit")',
1262
- severity: "hint",
1263
- code: "a11y-button-type"
1264
- });
1265
- }
1266
- }
1267
- if (node.children) {
1268
- validateNodes(node.children, diagnostics, baseOffset);
1269
- }
1270
- }
1271
- }
1272
- function isInScript(source, pos) {
1273
- const lines = source.split("\n");
1274
- let inScript = false;
1275
- for (let i = 0; i <= pos.line && i < lines.length; i++) {
1276
- if (lines[i].includes("<script")) inScript = true;
1277
- if (lines[i].includes("</script>")) inScript = false;
1278
- }
1279
- return inScript;
1280
- }
1281
- function isInTemplate(source, pos) {
1282
- const lines = source.split("\n");
1283
- let inTemplate = false;
1284
- for (let i = 0; i <= pos.line && i < lines.length; i++) {
1285
- if (lines[i].includes("<template>")) inTemplate = true;
1286
- if (lines[i].includes("</template>")) inTemplate = false;
1287
- }
1288
- return inTemplate;
1289
- }
1290
- function isInsideTag(before) {
1291
- const lastOpen = before.lastIndexOf("<");
1292
- const lastClose = before.lastIndexOf(">");
1293
- return lastOpen > lastClose;
1294
- }
1295
- function getWordAt(line, col) {
1296
- let start = col;
1297
- let end = col;
1298
- while (start > 0 && /\w/.test(line[start - 1])) start--;
1299
- while (end < line.length && /\w/.test(line[end])) end++;
1300
- return line.slice(start, end);
1301
- }
1302
-
1303
- // src/index.ts
1304
- function compile(source, options = {}) {
1305
- const sfc = parse(source);
1306
- return transform(sfc, options);
1307
- }
1308
- // Annotate the CommonJS export names for ESM import in node:
1309
- 0 && (module.exports = {
1310
- SourceMapBuilder,
1311
- analyzeTemplate,
1312
- compile,
1313
- createAkashSourceMap,
1314
- createLanguageService,
1315
- encodeVLQ,
1316
- extractHoistedTemplates,
1317
- generateHoistedDeclarations,
1318
- generateScopeId,
1319
- getHoistedVar,
1320
- getOptimizationStats,
1321
- isStaticExpression,
1322
- isStaticNode,
1323
- parse,
1324
- parseTemplate,
1325
- scopeStyles,
1326
- staticNodeToHtml,
1327
- transform
1328
- });
1
+ 'use strict';var crypto=require('crypto');function b(e){return {script:_(e,"script",(t,n,r,i)=>({content:t,lang:J(n,"lang")??"ts",start:r,end:i})),template:_(e,"template",(t,n,r,i)=>({content:t,start:r,end:i})),style:_(e,"style",(t,n,r,i)=>({content:t,scoped:n.includes("scoped"),start:r,end:i}))}}function _(e,t,n){let r=new RegExp(`<${t}(\\b[^>]*)>`,"i"),i=new RegExp(`</${t}>`,"i"),s=r.exec(e);if(!s)return null;let o=s[1]??"",a=s.index+s[0].length,u=i.exec(e.slice(a));if(!u)return null;let p=a+u.index,l=e.slice(a,p);return n(l.trim(),o,a,p)}function J(e,t){return new RegExp(`${t}=["']([^"']+)["']`).exec(e)?.[1]??null}function h(e){let t=[],n=0;for(;n<e.length;){if(e[n]==="<"){if(e[n+1]==="/")break;let s=W(e,n);if(s){t.push(s.node),n=s.end;continue}}if(e[n]==="{"){let s=K(e,n);if(s){t.push(s.node),n=s.end;continue}}let r=q(e,n),i=e.slice(n,r).trim();i&&t.push({type:"text",content:i}),n=r;}return t}function W(e,t){let n=/^<([a-zA-Z][a-zA-Z0-9-]*)/.exec(e.slice(t));if(!n)return null;let r=n[1],i=t+n[0].length,s=[],o=[];for(;i<e.length;){let g=/^\s+/.exec(e.slice(i));if(g&&(i+=g[0].length),e[i]===">"||e.slice(i,i+2)==="/>")break;let f=U(e,i);f?(f.attr.name.startsWith("bind:")?o.push({name:"bind",arg:f.attr.name.slice(5),value:f.attr.value}):f.attr.name.startsWith(":")?o.push({name:f.attr.name.slice(1),value:f.attr.value}):s.push(f.attr),i=f.end):i++;}let a=r[0]===r[0].toUpperCase();if(e.slice(i,i+2)==="/>")return {node:{type:a?"component":"element",tag:r,attrs:s,directives:o.length>0?o:void 0,children:[]},end:i+2};i++;let u=h(e.slice(i));e.slice(i);let l=`</${r}>`,c=Q(e,i,r);if(c===-1)return {node:{type:a?"component":"element",tag:r,attrs:s,directives:o.length>0?o:void 0,children:u},end:e.length};let d=e.slice(i,c),m=h(d);return {node:{type:a?"component":"element",tag:r,attrs:s,directives:o.length>0?o:void 0,children:m},end:c+l.length}}function U(e,t){let n=/^(?:bind:|[:a-zA-Z_])[\w:.-]*/.exec(e.slice(t));if(!n)return null;let r=n[0],i=t+r.length;if(e[i]!=="=")return {attr:{name:r,value:"true",dynamic:false},end:i};if(i++,e[i]==="{"){let o=A(e,i);if(o)return {attr:{name:r,value:o.content,dynamic:true},end:o.end}}let s=e[i];if(s==='"'||s==="'"){let o=e.indexOf(s,i+1);return o===-1?null:{attr:{name:r,value:e.slice(i+1,o),dynamic:false},end:o+1}}return null}function K(e,t){let n=A(e,t);return n?{node:{type:"expression",content:n.content},end:n.end}:null}function A(e,t){if(e[t]!=="{")return null;let n=1,r=t+1;for(;r<e.length&&n>0;){let i=e[r];if(i==='"'||i==="'"||i==="`"){r=Z(e,r)+1;continue}i==="{"?n++:i==="}"&&n--,r++;}return {content:e.slice(t+1,r-1).trim(),end:r}}function Z(e,t){let n=e[t],r=t+1;for(;r<e.length;){if(e[r]==="\\"){r+=2;continue}if(e[r]===n)return r;r++;}return r}function q(e,t){let n=t;for(;n<e.length;){if(e[n]==="<"||e[n]==="{")return n;n++;}return n}function Q(e,t,n){let r=`</${n}>`,i=1,s=t;for(;s<e.length;){let o=e.indexOf(`<${n}`,s),a=e.indexOf(r,s);if(a===-1)return -1;if(o!==-1&&o<a){let u=e.indexOf(">",o);u!==-1&&e[u-1]!=="/"&&i++,s=o+1;}else {if(i--,i===0)return a;s=a+1;}}return -1}function w(e){return `data-a-${crypto.createHash("md5").update(e).digest("hex").slice(0,6)}`}function N(e,t){return e.replace(/([^{}@/]+?)(\s*\{)/g,(n,r,i)=>r.trim().startsWith("@")?n:r.split(",").map(o=>{let a=o.trim();return !a||a===":root"||a===":host"||a.includes(t)?o:X(a,t)}).join(",")+i)}function X(e,t){let n=e.split(/(\s*[>+~]\s*|\s+)/);for(let r=n.length-1;r>=0;r--){let i=n[r].trim();if(i&&!Y(i)){if(i.includes("::")){let[s,o]=i.split("::");n[r]=n[r].replace(i,`${s}[${t}]::${o}`);}else if(i.includes(":")){let s=i.indexOf(":"),o=i.slice(0,s),a=i.slice(s);n[r]=n[r].replace(i,`${o}[${t}]${a}`);}else n[r]=n[r].replace(i,`${i}[${t}]`);break}}return n.join("")}function Y(e){return e===">"||e==="+"||e==="~"}function D(e,t={}){let n=t.scopeId??(t.filename?w(t.filename):void 0),i=new Set;i.add("defineComponent");let s=e.script?.content??"";ee(s,i);let o=t.mode==="server",a="";if(e.template){let m=h(e.template.content);o?a=re(m,i,n):a=ne(m,i,n);}let u="";i.size>0&&(u+=`import { ${[...i].join(", ")} } from '@akashjs/runtime';
2
+ `);let{cleanScript:p,propsInterface:l}=te(s),c=l?`<${l}>`:"";if(u+=`
3
+ `,u+=`export default defineComponent${c}((ctx) => {
4
+ `,s.includes("props")&&(u+=` const props = ctx.props;
5
+ `),p.trim()){let m=p.trim().split(`
6
+ `).map(g=>` ${g}`).join(`
7
+ `);u+=`${m}
8
+ `;}u+=`
9
+ `,u+=` return () => {
10
+ `,u+=a,u+=` };
11
+ `,u+=`});
12
+ `;let d;return e.style&&(d=e.style.scoped&&n?N(e.style.content,n):e.style.content),{code:u,css:d}}function ee(e,t){let n=["signal","computed","effect","batch","untrack","onMount","onUnmount","onError","ref","createContext","provide","inject","Show","For"];for(let r of n){let i=new RegExp(`\\b${r}\\b`),s=new RegExp(`import\\s+.*\\b${r}\\b.*from`);i.test(e)&&!s.test(e)&&t.add(r);}}function te(e){let t=/interface\s+Props\s*\{([^}]*)\}/s.exec(e);if(!t)return {cleanScript:e,propsInterface:null};let n=e.replace(t[0],"").trim(),r=`{${t[1].trim()}}`;return {cleanScript:n,propsInterface:r}}function ne(e,t,n){if(e.length===0)return ` return null;
13
+ `;if(e.length===1){let i=[];return y(e[0],i,t,4,"root",n),i.push(" return root;"),i.join(`
14
+ `)+`
15
+ `}t.add("createElement");let r=[];r.push(" const __fragment = document.createDocumentFragment();");for(let i=0;i<e.length;i++){let s=`__n${i}`;y(e[i],r,t,4,s,n),r.push(` __fragment.appendChild(${s});`);}return r.push(" return __fragment;"),r.join(`
16
+ `)+`
17
+ `}function y(e,t,n,r,i,s){let o=" ".repeat(r);switch(e.type){case "element":R(e,t,n,r,i,s);break;case "component":ie(e,t,n,r,i);break;case "text":t.push(`${o}const ${i} = document.createTextNode(${JSON.stringify(e.content??"")});`);break;case "expression":n.add("effect"),t.push(`${o}const ${i} = document.createTextNode('');`),t.push(`${o}effect(() => { ${i}.textContent = String(${e.content}); }, { render: true });`);break}}function R(e,t,n,r,i,s){let o=" ".repeat(r),a=e.tag,u=e.directives?.find(c=>c.name==="if");if(u){n.add("renderConditional"),t.push(`${o}const ${i}_anchor = document.createComment('if');`),t.push(`${o}const ${i} = document.createDocumentFragment();`),t.push(`${o}${i}.appendChild(${i}_anchor);`),t.push(`${o}renderConditional(${i}, ${i}_anchor, () => ${u.value}, () => {`);let c=[],d={...e,directives:e.directives?.filter(m=>m.name!=="if")};R(d,c,n,r+2,"__el",s),c.push(`${o} return __el;`),t.push(...c),t.push(`${o}});`);return}let p=e.directives?.find(c=>c.name==="for");if(p){n.add("renderList");let c=e.directives?.find(m=>m.name==="key"),d=/^(?:\(([^)]+)\)|(\w+))\s+of\s+(.+)$/.exec(p.value);if(d){let m=d[1]??d[2],g=d[3],f=c?.value??`${m}`;t.push(`${o}const ${i}_anchor = document.createComment('for');`),t.push(`${o}const ${i} = document.createDocumentFragment();`),t.push(`${o}${i}.appendChild(${i}_anchor);`),t.push(`${o}renderList(${i}, ${i}_anchor, () => ${g}, (${m}) => ${f}, (${m}) => {`);let C=[],V={...e,directives:e.directives?.filter(H=>H.name!=="for"&&H.name!=="key")};R(V,C,n,r+2,"__el",s),C.push(`${o} return __el;`),t.push(...C),t.push(`${o}});`);}return}let l=e.directives?.filter(c=>c.name==="bind")??[];if(l.length>0&&e.directives&&(e.directives=e.directives.filter(c=>c.name!=="bind")),t.push(`${o}const ${i} = document.createElement('${a}');`),s&&t.push(`${o}${i}.setAttribute('${s}', '');`),e.attrs)for(let c of e.attrs)c.dynamic?(n.add("effect"),c.name.startsWith("on")?t.push(`${o}${i}.addEventListener('${c.name.slice(2).toLowerCase()}', ${c.value});`):(t.push(`${o}effect(() => {`),c.name==="class"||c.name==="className"?t.push(`${o} ${i}.className = ${c.value};`):t.push(`${o} ${i}.setAttribute('${c.name}', String(${c.value}));`),t.push(`${o}}, { render: true });`))):c.name==="class"||c.name==="className"?t.push(`${o}${i}.className = ${JSON.stringify(c.value)};`):c.name.startsWith("on")?t.push(`${o}${i}.setAttribute('${c.name}', ${JSON.stringify(c.value)});`):t.push(`${o}${i}.setAttribute('${c.name}', ${JSON.stringify(c.value)});`);for(let c of l){let d=c.arg??"value",m=c.value;n.add("effect"),t.push(`${o}effect(() => { ${i}.${d} = ${m}(); }, { render: true });`);let g=d==="value"||d==="checked"?"input":"change",f=d==="checked"?"checked":"value";t.push(`${o}${i}.addEventListener('${g}', (e) => { ${m}.set(e.target.${f}); });`);}if(e.children&&e.children.length>0)for(let c=0;c<e.children.length;c++){let d=`${i}_c${c}`;y(e.children[c],t,n,r,d,s),t.push(`${o}${i}.appendChild(${d});`);}}function ie(e,t,n,r,i){let s=" ".repeat(r),o=e.tag,a=[];if(e.attrs)for(let p of e.attrs)p.dynamic?a.push(`${p.name}: ${p.value}`):a.push(`${p.name}: ${JSON.stringify(p.value)}`);if(e.children&&e.children.length>0){let p=[];for(let l=0;l<e.children.length;l++)y(e.children[l],p,n,r+2,`__cc${l}`);a.push("children: () => null");}let u=a.length>0?`{ ${a.join(", ")} }`:"{}";t.push(`${s}const ${i} = ${o}(${u});`);}function re(e,t,n){if(e.length===0)return ` return '';
18
+ `;let r=[];r.push(" let __html = '';");for(let i of e)M(i,r,t,4,n);return r.push(" return __html;"),r.join(`
19
+ `)+`
20
+ `}function M(e,t,n,r,i){let s=" ".repeat(r);switch(e.type){case "text":t.push(`${s}__html += ${JSON.stringify(e.content??"")};`);break;case "expression":n.add("escapeHtml"),t.push(`${s}__html += escapeHtml(String(${e.content}));`);break;case "element":E(e,t,n,r,i);break;case "component":t.push(`${s}// TODO: SSR component rendering for ${e.tag}`),t.push(`${s}__html += '';`);break}}var se=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);function E(e,t,n,r,i){let s=" ".repeat(r),o=e.tag,a=e.directives?.find(l=>l.name==="if");if(a){t.push(`${s}if (${a.value}) {`);let l={...e,directives:e.directives?.filter(c=>c.name!=="if")};E(l,t,n,r+2,i),t.push(`${s}}`);return}let u=e.directives?.find(l=>l.name==="for");if(u){let l=/^(?:\(([^)]+)\)|(\w+))\s+of\s+(.+)$/.exec(u.value);if(l){let c=l[1]??l[2],d=l[3];t.push(`${s}for (const ${c} of ${d}) {`);let m={...e,directives:e.directives?.filter(g=>g.name!=="for"&&g.name!=="key")};E(m,t,n,r+2,i),t.push(`${s}}`);}return}let p=`'<${o}`;if(i&&(p+=` ${i}`),e.attrs)for(let l of e.attrs)l.name.startsWith("on")||(l.dynamic?(t.push(`${s}__html += ${p}';`),p="'",n.add("escapeHtml"),l.name==="class"||l.name==="className"?t.push(`${s}__html += ' class="' + escapeHtml(String(${l.value})) + '"';`):t.push(`${s}__html += ' ${l.name}="' + escapeHtml(String(${l.value})) + '"';`)):l.name==="class"||l.name==="className"?p+=` class="${l.value}"`:p+=` ${l.name}="${l.value}"`);if(se.has(o)){t.push(`${s}__html += ${p} />';`);return}if(t.push(`${s}__html += ${p}>';`),e.children)for(let l of e.children)M(l,t,n,r,i);t.push(`${s}__html += '</${o}>';`);}function oe(e){let t={signalReads:[],eventHandlers:[],hasDynamicContent:false,staticSubtrees:[],reactiveExpressions:[],componentRefs:[]};for(let n of e)O(n,t);return t}function O(e,t){switch(e.type){case "expression":t.hasDynamicContent=true,e.content&&(t.reactiveExpressions.push({expression:e.content,kind:"text"}),v(e.content,"text",t));break;case "element":ae(e,t);break;case "component":if(e.tag&&t.componentRefs.push(e.tag),t.hasDynamicContent=true,P(e,t),e.children)for(let n of e.children)O(n,t);break;}}function ae(e,t){let n=j(e);if(e.directives)for(let r of e.directives)t.hasDynamicContent=true,ce(r,e,t);if(P(e,t),!n&&!e.directives?.length&&t.staticSubtrees.push(e),e.children)for(let r of e.children)O(r,t);}function P(e,t){if(e.attrs){for(let n of e.attrs)if(n.dynamic)if(t.hasDynamicContent=true,n.name.startsWith("on")){let r=n.name.slice(2).toLowerCase();t.eventHandlers.push({event:r,handler:n.value,tag:e.tag??"unknown"});}else t.reactiveExpressions.push({expression:n.value,kind:"attribute",attributeName:n.name}),v(n.value,"attribute",t);}}function ce(e,t,n){switch(e.name){case "if":case "else-if":case "show":n.reactiveExpressions.push({expression:e.value,kind:"conditional"}),v(e.value,"directive",n);break;case "for":{let r=/\bof\s+(.+)$/.exec(e.value);r&&(n.reactiveExpressions.push({expression:r[1],kind:"list"}),v(r[1],"directive",n));break}case "bind":{n.reactiveExpressions.push({expression:e.value,kind:"attribute",attributeName:e.value}),v(e.value,"directive",n);break}}}function v(e,t,n){let r=new Set(["console","Math","JSON","Object","Array","String","Number","Boolean","Date","RegExp","Error","Promise","parseInt","parseFloat","setTimeout","setInterval","clearTimeout","clearInterval","document","window","navigator","fetch"]),i=/\b([a-zA-Z_$][\w$]*)\s*\(\s*\)/g,s;for(;(s=i.exec(e))!==null;){let o=s[1];r.has(o)||n.signalReads.push({expression:`${o}()`,context:t});}}function j(e){return !!(e.attrs?.some(t=>t.dynamic)||e.directives?.length||e.children?.some(t=>t.type==="expression"||t.type==="component")||e.children?.some(t=>j(t)))}function le(e){let t=e.trim();return !!(/^['"`].*['"`]$/.test(t)||/^-?\d+(\.\d+)?$/.test(t)||t==="true"||t==="false"||t==="null"||t==="undefined")}var ue="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function $(e){let t="",n=e<0?-e<<1|1:e<<1;do{let r=n&31;n>>>=5,n>0&&(r|=32),t+=ue[r];}while(n>0);return t}var x=class{mappings=[];sources=[];sourcesContent=[];addSource(t,n){let r=this.sources.length;return this.sources.push(t),this.sourcesContent.push(n??null),r}addMapping(t){this.mappings.push(t);}addLineRange(t,n,r,i=0){for(let s=0;s<r;s++)this.addMapping({generatedLine:t+s,generatedColumn:0,originalLine:n+s,originalColumn:0,source:i});}build(t){let n=[...this.mappings].sort((r,i)=>r.generatedLine-i.generatedLine||r.generatedColumn-i.generatedColumn);return {version:3,file:t,sources:this.sources,sourcesContent:this.sourcesContent,names:[],mappings:pe(n)}}toJSON(t){return JSON.stringify(this.build(t))}toDataUrl(t){let n=this.toJSON(t);return `data:application/json;charset=utf-8;base64,${typeof btoa=="function"?btoa(n):Buffer.from(n).toString("base64")}`}};function pe(e){let t=[],n=0,r=0,i=0,s=0,o=0;for(let a of e){for(;t.length<=a.generatedLine;)t.push([]);a.generatedLine!==n&&(r=0,n=a.generatedLine);let u="";u+=$(a.generatedColumn-r),r=a.generatedColumn;let p=a.source??0;u+=$(p-o),o=p,u+=$(a.originalLine-i),i=a.originalLine,u+=$(a.originalColumn-s),s=a.originalColumn,t[a.generatedLine].push(u);}return t.map(a=>a.join(",")).join(";")}function de(e,t,n,r,i){let s=new x;return s.addSource(e,t),s.addLineRange(i,n,r,0),s}function S(e){return e.type==="expression"||e.type==="component"?false:e.type==="text"?true:!(e.directives&&e.directives.length>0||e.attrs?.some(t=>t.dynamic)||e.children?.some(t=>!S(t)))}function I(e){switch(e.type){case "text":return e.content??"";case "element":{let t=`<${e.tag}`;if(e.attrs)for(let n of e.attrs)n.name==="class"||n.name==="className"?t+=` class="${n.value}"`:t+=` ${n.name}="${n.value}"`;if(t+=">",e.children)for(let n of e.children)t+=I(n);return t+=`</${e.tag}>`,t}default:return ""}}function z(e){let t=[],n=0;function r(i){if(i.type==="element"){if(S(i)&&i.children&&i.children.length>0){let s=`__hoisted_${n++}`;t.push({varName:s,html:I(i)}),i._hoisted=s;return}if(i.children)for(let s of i.children)r(s);}}for(let i of e)r(i);return t}function me(e){if(e.length===0)return "";let t=`// Hoisted static templates (created once, cloned per instance)
21
+ `;for(let n of e)t+=`const ${n.varName} = /*#__PURE__*/ (() => {
22
+ `,t+=` const _t = document.createElement('template');
23
+ `,t+=` _t.innerHTML = ${JSON.stringify(n.html)};
24
+ `,t+=` return _t;
25
+ `,t+=`})();
26
+ `;return t}function fe(e){return e._hoisted??null}function ge(e){let t=0,n=0;function r(s){if(t++,S(s)&&n++,s.children)for(let o of s.children)r(o);}for(let s of e)r(s);let i=z(JSON.parse(JSON.stringify(e)));return {totalNodes:t,staticNodes:n,hoistedTemplates:i.length,staticRatio:t>0?n/t:0}}var L=[{label:"signal",kind:"property",detail:"signal<T>(initial: T): Signal<T>",documentation:"Create a reactive signal"},{label:"computed",kind:"property",detail:"computed<T>(fn: () => T): ReadonlySignal<T>",documentation:"Create a derived reactive value"},{label:"effect",kind:"property",detail:"effect(fn: () => void): () => void",documentation:"Run a side-effect when dependencies change"},{label:"batch",kind:"property",detail:"batch(fn: () => void): void",documentation:"Batch signal updates"},{label:"untrack",kind:"property",detail:"untrack<T>(fn: () => T): T",documentation:"Read signals without tracking"},{label:"onMount",kind:"property",detail:"onMount(fn: () => void | (() => void)): void",documentation:"Run after component mounts"},{label:"onUnmount",kind:"property",detail:"onUnmount(fn: () => void): void",documentation:"Run before component unmounts"},{label:"provide",kind:"property",detail:"provide<T>(key: InjectionKey<T>, value: T): void",documentation:"Provide a value to descendants"},{label:"inject",kind:"property",detail:"inject<T>(key: InjectionKey<T>): T",documentation:"Inject a value from ancestors"},{label:"defineStore",kind:"property",detail:"defineStore(id, config): () => Store",documentation:"Define a global store"},{label:"useHead",kind:"property",detail:"useHead(config: HeadConfig): void",documentation:"Manage document head tags"},{label:"cx",kind:"property",detail:"cx(...inputs): string",documentation:"Merge CSS class names"},{label:"pipe",kind:"property",detail:"pipe(value, transform, ...args): any",documentation:"Apply a pipe transform"}],T=[{label:"Show",kind:"component",detail:"<Show when={condition}>{value => ...}</Show>",documentation:"Conditional rendering with type narrowing"},{label:"For",kind:"component",detail:"<For each={items} key={fn}>{item => ...}</For>",documentation:"List rendering with keyed reconciliation"},{label:"Switch",kind:"component",detail:"<Switch on={value} cases={...} />",documentation:"Switch/case rendering"},{label:"Portal",kind:"component",detail:'<Portal target="selector">...</Portal>',documentation:"Render into different DOM node"},{label:"Transition",kind:"component",detail:'<Transition name="fade" when={show}>...</Transition>',documentation:"CSS enter/exit transitions"},{label:"ErrorBoundary",kind:"component",detail:"<ErrorBoundary fallback={fn}>...</ErrorBoundary>",documentation:"Catch errors from children"},{label:"Suspense",kind:"component",detail:"<Suspense fallback={fn}>...</Suspense>",documentation:"Show fallback during async loading"},{label:"VirtualFor",kind:"component",detail:"<VirtualFor each={items} itemHeight={40}>...</VirtualFor>",documentation:"Virtual scrolling for large lists"},{label:"Image",kind:"component",detail:'<Image src="..." alt="..." />',documentation:"Optimized image with lazy loading"}],k=[{label:":if",kind:"directive",detail:":if={condition}",documentation:"Conditional rendering"},{label:":for",kind:"directive",detail:":for={item of items()}",documentation:"List rendering"},{label:":show",kind:"directive",detail:":show={condition}",documentation:"Toggle visibility (display)"},{label:":key",kind:"directive",detail:":key={uniqueId}",documentation:"Reconciliation key for lists"},{label:"bind:value",kind:"directive",detail:"bind:value={signal}",documentation:"Two-way binding"},{label:"bind:checked",kind:"directive",detail:"bind:checked={signal}",documentation:"Two-way checkbox binding"}],B=["onClick","onInput","onChange","onSubmit","onKeyDown","onKeyUp","onFocus","onBlur","onMouseEnter","onMouseLeave","onScroll","onLoad","onError","onResize","onPointerDown","onPointerUp"].map(e=>({label:e,kind:"event",detail:`${e}={(e) => { ... }}`,documentation:`${e.slice(2)} event handler`}));function he(){return {getDiagnostics(e,t){let n=[];try{let r=b(e);if(r.template||n.push({range:{start:{line:0,character:0},end:{line:0,character:0}},message:"Missing <template> block",severity:"warning"}),r.template){let i=h(r.template.content);F(i,n,r.template.start);}}catch(r){n.push({range:{start:{line:0,character:0},end:{line:0,character:0}},message:`Parse error: ${r instanceof Error?r.message:String(r)}`,severity:"error"});}return n},getCompletions(e,t){let r=(e.split(`
27
+ `)[t.line]??"").slice(0,t.character);return be(e,t)?[...L]:ve(e,t)?r.endsWith("<")||/^<[A-Z]/.test(r.trimStart())?[...T]:r.endsWith(":")||r.includes(":")?[...k]:$e(r)?[...k,...B]:[...T,...k]:[]},getHoverInfo(e,t){let n=e.split(`
28
+ `)[t.line]??"",r=ye(n,t.character),i=L.find(o=>o.label===r);if(i)return {contents:`**${i.label}**
29
+
30
+ ${i.detail}
31
+
32
+ ${i.documentation}`};let s=T.find(o=>o.label===r);return s?{contents:`**${s.label}**
33
+
34
+ ${s.detail}
35
+
36
+ ${s.documentation}`}:null},getAllCompletions(){return {apis:L,components:T,directives:k,events:B}}}}function F(e,t,n){for(let r of e)r.type==="element"&&r.tag==="img"&&(r.attrs?.some(s=>s.name==="alt")||t.push({range:{start:{line:0,character:0},end:{line:0,character:0}},message:"<img> element should have an alt attribute for accessibility",severity:"warning",code:"a11y-img-alt"})),r.type==="element"&&r.tag==="button"&&(r.attrs?.some(s=>s.name==="type")||t.push({range:{start:{line:0,character:0},end:{line:0,character:0}},message:'<button> should have an explicit type attribute (type="button" or type="submit")',severity:"hint",code:"a11y-button-type"})),r.children&&F(r.children,t);}function be(e,t){let n=e.split(`
37
+ `),r=false;for(let i=0;i<=t.line&&i<n.length;i++)n[i].includes("<script")&&(r=true),n[i].includes("</script>")&&(r=false);return r}function ve(e,t){let n=e.split(`
38
+ `),r=false;for(let i=0;i<=t.line&&i<n.length;i++)n[i].includes("<template>")&&(r=true),n[i].includes("</template>")&&(r=false);return r}function $e(e){let t=e.lastIndexOf("<"),n=e.lastIndexOf(">");return t>n}function ye(e,t){let n=t,r=t;for(;n>0&&/\w/.test(e[n-1]);)n--;for(;r<e.length&&/\w/.test(e[r]);)r++;return e.slice(n,r)}function Ae(e,t={}){let n=b(e);return D(n,t)}exports.SourceMapBuilder=x;exports.analyzeTemplate=oe;exports.compile=Ae;exports.createAkashSourceMap=de;exports.createLanguageService=he;exports.encodeVLQ=$;exports.extractHoistedTemplates=z;exports.generateHoistedDeclarations=me;exports.generateScopeId=w;exports.getHoistedVar=fe;exports.getOptimizationStats=ge;exports.isStaticExpression=le;exports.isStaticNode=S;exports.parse=b;exports.parseTemplate=h;exports.scopeStyles=N;exports.staticNodeToHtml=I;exports.transform=D;//# sourceMappingURL=index.cjs.map
1329
39
  //# sourceMappingURL=index.cjs.map