@esportsplus/template 0.37.0 → 0.38.1
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/build/compiler/codegen.d.ts +7 -6
- package/build/compiler/codegen.js +140 -105
- package/build/compiler/index.d.ts +3 -10
- package/build/compiler/index.js +54 -73
- package/build/compiler/plugins/tsc.d.ts +2 -3
- package/build/compiler/plugins/tsc.js +2 -3
- package/build/compiler/plugins/vite.js +2 -3
- package/build/constants.d.ts +2 -1
- package/build/constants.js +3 -1
- package/package.json +3 -3
- package/src/compiler/codegen.ts +201 -150
- package/src/compiler/index.ts +65 -107
- package/src/compiler/plugins/tsc.ts +2 -3
- package/src/compiler/plugins/vite.ts +3 -4
- package/src/constants.ts +6 -1
- package/test/integration/combined.ts +90 -0
- package/test/integration/tsconfig.json +17 -0
package/src/compiler/codegen.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
|
|
1
2
|
import { ts } from '@esportsplus/typescript';
|
|
2
|
-
import { ast,
|
|
3
|
-
import { COMPILER_ENTRYPOINT, COMPILER_TYPES, DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS
|
|
4
|
-
import type {
|
|
3
|
+
import { ast, uid } from '@esportsplus/typescript/compiler';
|
|
4
|
+
import { COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REACTIVITY, COMPILER_NAMESPACE, COMPILER_TYPES, DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS } from '~/constants';
|
|
5
|
+
import type { TemplateInfo } from './ts-parser';
|
|
5
6
|
import { analyze } from './analyzer';
|
|
6
7
|
import parser from './parser';
|
|
7
8
|
|
|
@@ -17,15 +18,15 @@ type Attribute = {
|
|
|
17
18
|
|
|
18
19
|
type CodegenContext = {
|
|
19
20
|
checker?: ts.TypeChecker;
|
|
20
|
-
imports: Map<string, string>;
|
|
21
21
|
printer: ts.Printer;
|
|
22
22
|
sourceFile: ts.SourceFile;
|
|
23
23
|
templates: Map<string, string>;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
type CodegenResult = {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
prepend: string[];
|
|
28
|
+
replacements: ReplacementIntent[];
|
|
29
|
+
templates: Map<string, string>;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
type Node = {
|
|
@@ -38,6 +39,12 @@ type ParseResult = {
|
|
|
38
39
|
slots: (Attribute | Node)[] | null;
|
|
39
40
|
};
|
|
40
41
|
|
|
42
|
+
type Replacement = {
|
|
43
|
+
end: number;
|
|
44
|
+
newText: string;
|
|
45
|
+
start: number;
|
|
46
|
+
};
|
|
47
|
+
|
|
41
48
|
|
|
42
49
|
const ARROW_EMPTY_PARAMS = /\(\s*\)\s*=>\s*$/;
|
|
43
50
|
|
|
@@ -45,60 +52,56 @@ const ARROW_EMPTY_PARAMS = /\(\s*\)\s*=>\s*$/;
|
|
|
45
52
|
let printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
46
53
|
|
|
47
54
|
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
function collectNestedReplacements(
|
|
56
|
+
ctx: CodegenContext,
|
|
57
|
+
node: ts.Node,
|
|
58
|
+
exprStart: number,
|
|
59
|
+
replacements: Replacement[]
|
|
60
|
+
): void {
|
|
61
|
+
if (isNestedHtmlTemplate(node as ts.Expression)) {
|
|
62
|
+
replacements.push({
|
|
63
|
+
end: node.end - exprStart,
|
|
64
|
+
newText: generateNestedTemplateCode(ctx, node as ts.TaggedTemplateExpression),
|
|
65
|
+
start: node.getStart(ctx.sourceFile) - exprStart
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else if (isReactiveCall(node as ts.Expression)) {
|
|
69
|
+
replacements.push({
|
|
70
|
+
end: node.end - exprStart,
|
|
71
|
+
newText: rewriteReactiveCall(ctx, node as ts.CallExpression),
|
|
72
|
+
start: node.getStart(ctx.sourceFile) - exprStart
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
ts.forEachChild(node, child => collectNestedReplacements(ctx, child, exprStart, replacements));
|
|
54
77
|
}
|
|
55
|
-
|
|
56
|
-
return alias;
|
|
57
78
|
}
|
|
58
79
|
|
|
59
|
-
function generateAttributeBinding(
|
|
80
|
+
function generateAttributeBinding(element: string, name: string, expr: string, staticValue: string): string {
|
|
60
81
|
if (name.startsWith('on') && name.length > 2) {
|
|
61
82
|
let event = name.slice(2).toLowerCase(),
|
|
62
83
|
key = name.toLowerCase();
|
|
63
84
|
|
|
64
85
|
if (LIFECYCLE_EVENTS.has(key)) {
|
|
65
|
-
return `${
|
|
86
|
+
return `${COMPILER_NAMESPACE}.${key}(${element}, ${expr});`;
|
|
66
87
|
}
|
|
67
88
|
|
|
68
89
|
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
69
|
-
return `${
|
|
90
|
+
return `${COMPILER_NAMESPACE}.on(${element}, '${event}', ${expr});`;
|
|
70
91
|
}
|
|
71
92
|
|
|
72
|
-
return `${
|
|
93
|
+
return `${COMPILER_NAMESPACE}.delegate(${element}, '${event}', ${expr});`;
|
|
73
94
|
}
|
|
74
95
|
|
|
75
96
|
if (name === 'class') {
|
|
76
|
-
return `${
|
|
97
|
+
return `${COMPILER_NAMESPACE}.setClass(${element}, '${staticValue}', ${expr});`;
|
|
77
98
|
}
|
|
78
99
|
|
|
79
100
|
if (name === 'style') {
|
|
80
|
-
return `${
|
|
101
|
+
return `${COMPILER_NAMESPACE}.setStyle(${element}, '${staticValue}', ${expr});`;
|
|
81
102
|
}
|
|
82
103
|
|
|
83
|
-
return `${
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function collectNestedTemplateReplacements(
|
|
87
|
-
ctx: CodegenContext,
|
|
88
|
-
node: ts.Node,
|
|
89
|
-
exprStart: number,
|
|
90
|
-
replacements: Replacement[]
|
|
91
|
-
): void {
|
|
92
|
-
if (isNestedHtmlTemplate(node as ts.Expression)) {
|
|
93
|
-
replacements.push({
|
|
94
|
-
end: node.end - exprStart,
|
|
95
|
-
newText: generateNestedTemplateCode(ctx, node as ts.TaggedTemplateExpression),
|
|
96
|
-
start: node.getStart() - exprStart
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
ts.forEachChild(node, child => collectNestedTemplateReplacements(ctx, child, exprStart, replacements));
|
|
101
|
-
}
|
|
104
|
+
return `${COMPILER_NAMESPACE}.setProperty(${element}, '${name}', ${expr});`;
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
function generateNestedTemplateCode(ctx: CodegenContext, node: ts.TaggedTemplateExpression): string {
|
|
@@ -133,30 +136,30 @@ function generateNestedTemplateCode(ctx: CodegenContext, node: ts.TaggedTemplate
|
|
|
133
136
|
|
|
134
137
|
function generateNodeBinding(ctx: CodegenContext, anchor: string, exprText: string, exprNode: ts.Expression | undefined): string {
|
|
135
138
|
if (!exprNode) {
|
|
136
|
-
return `${
|
|
139
|
+
return `${COMPILER_NAMESPACE}.slot(${anchor}, ${exprText});`;
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
if (isNestedHtmlTemplate(exprNode)) {
|
|
140
|
-
return `${anchor}.parentNode
|
|
143
|
+
return `${anchor}.parentNode!.insertBefore(${generateNestedTemplateCode(ctx, exprNode)}, ${anchor});`;
|
|
141
144
|
}
|
|
142
145
|
|
|
143
146
|
let slotType = analyze(exprNode, ctx.checker);
|
|
144
147
|
|
|
145
148
|
switch (slotType) {
|
|
146
|
-
case COMPILER_TYPES.Effect:
|
|
147
|
-
return `new ${addImport(ctx, 'EffectSlot')}(${anchor}, ${exprText});`;
|
|
148
|
-
|
|
149
149
|
case COMPILER_TYPES.ArraySlot:
|
|
150
|
-
return
|
|
150
|
+
return `${anchor}.parentNode!.insertBefore(new ${COMPILER_NAMESPACE}.ArraySlot(${exprText}).fragment, ${anchor});`;
|
|
151
|
+
|
|
152
|
+
case COMPILER_TYPES.DocumentFragment:
|
|
153
|
+
return `${anchor}.parentNode!.insertBefore(${exprText}, ${anchor});`;
|
|
154
|
+
|
|
155
|
+
case COMPILER_TYPES.Effect:
|
|
156
|
+
return `new ${COMPILER_NAMESPACE}.EffectSlot(${anchor}, ${exprText});`;
|
|
151
157
|
|
|
152
158
|
case COMPILER_TYPES.Static:
|
|
153
159
|
return `${anchor}.textContent = ${exprText};`;
|
|
154
160
|
|
|
155
|
-
case COMPILER_TYPES.DocumentFragment:
|
|
156
|
-
return `${anchor}.parentNode.insertBefore(${exprText}, ${anchor});`;
|
|
157
|
-
|
|
158
161
|
default:
|
|
159
|
-
return `${
|
|
162
|
+
return `${COMPILER_NAMESPACE}.slot(${anchor}, ${exprText});`;
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
|
|
@@ -206,17 +209,15 @@ function generateTemplateCode(
|
|
|
206
209
|
}
|
|
207
210
|
}
|
|
208
211
|
|
|
209
|
-
let
|
|
210
|
-
name = uid('element'),
|
|
212
|
+
let name = uid('element'),
|
|
211
213
|
segments = path.slice(start),
|
|
212
214
|
value = `${ancestor}.${segments.join('!.')}`;
|
|
213
215
|
|
|
214
|
-
// Cast root.firstChild to Element since DocumentFragment.firstChild returns ChildNode
|
|
215
216
|
if (ancestor === root && segments[0] === 'firstChild') {
|
|
216
|
-
value = value.replace(`${ancestor}.firstChild!`, `(${ancestor}.firstChild! as ${
|
|
217
|
+
value = value.replace(`${ancestor}.firstChild!`, `(${ancestor}.firstChild! as ${COMPILER_NAMESPACE}.Element)`);
|
|
217
218
|
}
|
|
218
219
|
|
|
219
|
-
declarations.push(`${name} = ${value} as ${
|
|
220
|
+
declarations.push(`${name} = ${value} as ${COMPILER_NAMESPACE}.Element`);
|
|
220
221
|
nodes.set(key, name);
|
|
221
222
|
}
|
|
222
223
|
|
|
@@ -239,14 +240,13 @@ function generateTemplateCode(
|
|
|
239
240
|
|
|
240
241
|
if (name === COMPILER_TYPES.Attributes) {
|
|
241
242
|
code.push(
|
|
242
|
-
`${
|
|
243
|
+
`${COMPILER_NAMESPACE}.setProperties(${element}, ${exprTexts[index] || 'undefined'});`
|
|
243
244
|
);
|
|
244
245
|
index++;
|
|
245
246
|
}
|
|
246
247
|
else {
|
|
247
248
|
code.push(
|
|
248
249
|
generateAttributeBinding(
|
|
249
|
-
ctx,
|
|
250
250
|
element,
|
|
251
251
|
name,
|
|
252
252
|
exprTexts[index++] || 'undefined',
|
|
@@ -285,143 +285,194 @@ function isNestedHtmlTemplate(expr: ts.Expression): expr is ts.TaggedTemplateExp
|
|
|
285
285
|
return ts.isTaggedTemplateExpression(expr) && ts.isIdentifier(expr.tag) && expr.tag.text === COMPILER_ENTRYPOINT;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
function isReactiveCall(expr: ts.Expression): expr is ts.CallExpression {
|
|
289
|
+
return (
|
|
290
|
+
ts.isCallExpression(expr) &&
|
|
291
|
+
ts.isPropertyAccessExpression(expr.expression) &&
|
|
292
|
+
ts.isIdentifier(expr.expression.expression) &&
|
|
293
|
+
expr.expression.expression.text === COMPILER_ENTRYPOINT &&
|
|
294
|
+
expr.expression.name.text === COMPILER_ENTRYPOINT_REACTIVITY
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function replaceReverse(text: string, replacements: Replacement[]): string {
|
|
299
|
+
let sorted = replacements.slice().sort((a, b) => b.start - a.start);
|
|
300
|
+
|
|
301
|
+
for (let i = 0, n = sorted.length; i < n; i++) {
|
|
302
|
+
let r = sorted[i];
|
|
303
|
+
|
|
304
|
+
text = text.slice(0, r.start) + r.newText + text.slice(r.end);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return text;
|
|
308
|
+
}
|
|
309
|
+
|
|
288
310
|
function rewriteExpression(ctx: CodegenContext, expr: ts.Expression): string {
|
|
289
311
|
if (isNestedHtmlTemplate(expr)) {
|
|
290
312
|
return generateNestedTemplateCode(ctx, expr);
|
|
291
313
|
}
|
|
292
314
|
|
|
293
|
-
if (
|
|
315
|
+
if (isReactiveCall(expr)) {
|
|
316
|
+
return rewriteReactiveCall(ctx, expr);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!ast.hasMatch(expr, n => isNestedHtmlTemplate(n as ts.Expression) || isReactiveCall(n as ts.Expression))) {
|
|
294
320
|
return ctx.printer.printNode(ts.EmitHint.Expression, expr, ctx.sourceFile);
|
|
295
321
|
}
|
|
296
322
|
|
|
297
323
|
let replacements: Replacement[] = [];
|
|
298
324
|
|
|
299
|
-
|
|
325
|
+
collectNestedReplacements(ctx, expr, expr.getStart(ctx.sourceFile), replacements);
|
|
300
326
|
|
|
301
|
-
return
|
|
327
|
+
return replaceReverse(expr.getText(ctx.sourceFile), replacements);
|
|
302
328
|
}
|
|
303
329
|
|
|
330
|
+
function rewriteReactiveCall(ctx: CodegenContext, node: ts.CallExpression): string {
|
|
331
|
+
let arrayArg = node.arguments[0],
|
|
332
|
+
arrayText = ctx.printer.printNode(ts.EmitHint.Expression, arrayArg, ctx.sourceFile),
|
|
333
|
+
callbackArg = node.arguments[1],
|
|
334
|
+
callbackText = rewriteExpression(ctx, callbackArg as ts.Expression);
|
|
304
335
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return { changed: false, code: originalCode };
|
|
308
|
-
}
|
|
336
|
+
return `${arrayText}, ${callbackText}`;
|
|
337
|
+
}
|
|
309
338
|
|
|
310
|
-
|
|
311
|
-
|
|
339
|
+
// Eager discovery - walk all expressions to find templates before prepend generation
|
|
340
|
+
function discoverTemplatesInExpression(ctx: CodegenContext, node: ts.Node): void {
|
|
341
|
+
if (isNestedHtmlTemplate(node as ts.Expression)) {
|
|
342
|
+
let template = node as ts.TaggedTemplateExpression,
|
|
343
|
+
expressions: ts.Expression[] = [],
|
|
344
|
+
literals: string[] = [],
|
|
345
|
+
tpl = template.template;
|
|
312
346
|
|
|
313
|
-
|
|
314
|
-
|
|
347
|
+
if (ts.isNoSubstitutionTemplateLiteral(tpl)) {
|
|
348
|
+
literals.push(tpl.text);
|
|
349
|
+
}
|
|
350
|
+
else if (ts.isTemplateExpression(tpl)) {
|
|
351
|
+
literals.push(tpl.head.text);
|
|
315
352
|
|
|
316
|
-
|
|
317
|
-
|
|
353
|
+
for (let i = 0, n = tpl.templateSpans.length; i < n; i++) {
|
|
354
|
+
expressions.push(tpl.templateSpans[i].expression);
|
|
355
|
+
literals.push(tpl.templateSpans[i].literal.text);
|
|
356
|
+
}
|
|
318
357
|
}
|
|
319
|
-
}
|
|
320
358
|
|
|
321
|
-
|
|
359
|
+
let parsed = parser.parse(literals) as ParseResult;
|
|
322
360
|
|
|
323
|
-
|
|
324
|
-
|
|
361
|
+
getOrCreateTemplateId(ctx, parsed.html);
|
|
362
|
+
|
|
363
|
+
for (let i = 0, n = expressions.length; i < n; i++) {
|
|
364
|
+
discoverTemplatesInExpression(ctx, expressions[i]);
|
|
365
|
+
}
|
|
325
366
|
}
|
|
367
|
+
else if (isReactiveCall(node as ts.Expression)) {
|
|
368
|
+
let call = node as ts.CallExpression;
|
|
326
369
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
templateAlias = addImport(ctx, 'template');
|
|
370
|
+
if (call.arguments.length >= 2) {
|
|
371
|
+
discoverTemplatesInExpression(ctx, call.arguments[1]);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
ts.forEachChild(node, child => discoverTemplatesInExpression(ctx, child));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
336
378
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
379
|
+
function discoverAllTemplates(ctx: CodegenContext, templates: TemplateInfo[]): void {
|
|
380
|
+
for (let i = 0, n = templates.length; i < n; i++) {
|
|
381
|
+
let parsed = parser.parse(templates[i].literals) as ParseResult;
|
|
340
382
|
|
|
341
|
-
|
|
342
|
-
exprTexts.push(rewriteExpression(ctx, template.expressions[j]));
|
|
343
|
-
}
|
|
383
|
+
getOrCreateTemplateId(ctx, parsed.html);
|
|
344
384
|
|
|
345
|
-
let
|
|
346
|
-
|
|
347
|
-
parsed = parser.parse(template.literals) as ParseResult;
|
|
348
|
-
|
|
349
|
-
// Optimize: when template has no slots and is `() => template`, use template directly
|
|
350
|
-
if (isArrowBody && (!parsed.slots || parsed.slots.length === 0)) {
|
|
351
|
-
let arrowMatch = codeBefore.match(ARROW_EMPTY_PARAMS);
|
|
352
|
-
|
|
353
|
-
if (arrowMatch) {
|
|
354
|
-
replacements.push({
|
|
355
|
-
end: template.end,
|
|
356
|
-
newText: getOrCreateTemplateId(ctx, parsed.html),
|
|
357
|
-
start: template.start - arrowMatch[0].length
|
|
358
|
-
});
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
385
|
+
for (let j = 0, m = templates[i].expressions.length; j < m; j++) {
|
|
386
|
+
discoverTemplatesInExpression(ctx, templates[i].expressions[j]);
|
|
361
387
|
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
362
390
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
});
|
|
391
|
+
|
|
392
|
+
const generateCode = (templates: TemplateInfo[], sourceFile: ts.SourceFile, checker?: ts.TypeChecker): CodegenResult => {
|
|
393
|
+
let result: CodegenResult = {
|
|
394
|
+
prepend: [],
|
|
395
|
+
replacements: [],
|
|
396
|
+
templates: new Map()
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
if (templates.length === 0) {
|
|
400
|
+
return result;
|
|
374
401
|
}
|
|
375
402
|
|
|
376
|
-
let
|
|
377
|
-
code = c.replaceReverse(originalCode, replacements);
|
|
403
|
+
let ranges: { end: number; start: number }[] = [];
|
|
378
404
|
|
|
379
|
-
|
|
380
|
-
let
|
|
381
|
-
factories: string[] = [],
|
|
382
|
-
updatedSourceFile = ts.createSourceFile(sourceFile.fileName, code, sourceFile.languageVersion, true);
|
|
405
|
+
for (let i = 0, n = templates.length; i < n; i++) {
|
|
406
|
+
let exprs = templates[i].expressions;
|
|
383
407
|
|
|
384
|
-
for (let
|
|
385
|
-
|
|
408
|
+
for (let j = 0, m = exprs.length; j < m; j++) {
|
|
409
|
+
ranges.push({ end: exprs[j].end, start: exprs[j].getStart(sourceFile) });
|
|
386
410
|
}
|
|
411
|
+
}
|
|
387
412
|
|
|
388
|
-
|
|
389
|
-
factories.push(`const ${id} = ${templateAlias}(\`${html}\`);`);
|
|
390
|
-
}
|
|
413
|
+
let rootTemplates = templates.filter(t => !ast.inRange(ranges, t.node.getStart(sourceFile), t.node.end));
|
|
391
414
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
add: new Set(aliasedImports),
|
|
395
|
-
remove: [COMPILER_ENTRYPOINT]
|
|
396
|
-
});
|
|
397
|
-
code = factories.join('\n') + '\n\n' + code;
|
|
415
|
+
if (rootTemplates.length === 0) {
|
|
416
|
+
return result;
|
|
398
417
|
}
|
|
399
418
|
|
|
400
|
-
|
|
401
|
-
|
|
419
|
+
let ctx: CodegenContext = {
|
|
420
|
+
checker,
|
|
421
|
+
printer,
|
|
422
|
+
sourceFile,
|
|
423
|
+
templates: result.templates
|
|
424
|
+
};
|
|
402
425
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
426
|
+
for (let i = 0, n = rootTemplates.length; i < n; i++) {
|
|
427
|
+
let template = rootTemplates[i];
|
|
428
|
+
|
|
429
|
+
result.replacements.push({
|
|
430
|
+
generate: (sf) => {
|
|
431
|
+
let codeBefore = sf.getFullText().slice(0, template.node.getStart(sf)),
|
|
432
|
+
exprTexts: string[] = [],
|
|
433
|
+
isArrowBody = codeBefore.trimEnd().endsWith('=>'),
|
|
434
|
+
localCtx: CodegenContext = {
|
|
435
|
+
checker,
|
|
436
|
+
printer,
|
|
437
|
+
sourceFile: sf,
|
|
438
|
+
templates: ctx.templates
|
|
439
|
+
},
|
|
440
|
+
parsed = parser.parse(template.literals) as ParseResult;
|
|
441
|
+
|
|
442
|
+
for (let j = 0, m = template.expressions.length; j < m; j++) {
|
|
443
|
+
exprTexts.push(rewriteExpression(localCtx, template.expressions[j]));
|
|
444
|
+
}
|
|
407
445
|
|
|
408
|
-
|
|
446
|
+
if (isArrowBody && (!parsed.slots || parsed.slots.length === 0)) {
|
|
447
|
+
let arrowMatch = codeBefore.match(ARROW_EMPTY_PARAMS);
|
|
409
448
|
|
|
410
|
-
|
|
411
|
-
|
|
449
|
+
if (arrowMatch) {
|
|
450
|
+
return getOrCreateTemplateId(localCtx, parsed.html);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
412
453
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
454
|
+
return generateTemplateCode(
|
|
455
|
+
localCtx,
|
|
456
|
+
parsed,
|
|
457
|
+
exprTexts,
|
|
458
|
+
template.expressions,
|
|
459
|
+
isArrowBody
|
|
460
|
+
);
|
|
461
|
+
},
|
|
462
|
+
node: template.node
|
|
420
463
|
});
|
|
421
464
|
}
|
|
422
465
|
|
|
423
|
-
|
|
466
|
+
// Eager discovery: find all templates before prepend generation
|
|
467
|
+
discoverAllTemplates(ctx, templates);
|
|
468
|
+
|
|
469
|
+
for (let [html, id] of ctx.templates) {
|
|
470
|
+
result.prepend.push(`const ${id} = ${COMPILER_NAMESPACE}.template(\`${html}\`);`);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return result;
|
|
424
474
|
};
|
|
425
475
|
|
|
426
|
-
|
|
476
|
+
|
|
477
|
+
export { generateCode };
|
|
427
478
|
export type { CodegenResult };
|