@esportsplus/template 0.31.2 → 0.31.4

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.
@@ -12,7 +12,8 @@ declare const getNames: () => {
12
12
  event: string;
13
13
  slot: string;
14
14
  };
15
+ declare const initNamespace: () => void;
15
16
  declare const needsArraySlotImport: (sourceFile: ts.SourceFile) => boolean;
16
17
  declare const setTypeChecker: (checker: ts.TypeChecker | undefined) => void;
17
- export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, needsArraySlotImport, setTypeChecker };
18
+ export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, initNamespace, needsArraySlotImport, setTypeChecker };
18
19
  export type { CodegenResult };
@@ -1,9 +1,9 @@
1
- import { addImport, applyReplacementsReverse, uid } from '@esportsplus/typescript/transformer';
1
+ import { applyReplacementsReverse, uid } from '@esportsplus/typescript/transformer';
2
2
  import { analyzeExpression, generateAttributeBinding, generateSpreadBindings } from './type-analyzer.js';
3
3
  import { ts } from '@esportsplus/typescript';
4
4
  import parser from './parser.js';
5
5
  const ARROW_EMPTY_PARAMS = /\(\s*\)\s*=>\s*$/;
6
- let currentChecker, hoistedFactories = new Map(), htmlToTemplateId = new Map(), nameArraySlot = '', nameAttr = '', nameEffectSlot = '', nameEvent = '', nameSlot = '', nameTemplate = '', needsArraySlot = false, needsAttr = false, needsEffectSlot = false, needsEvent = false, needsSlot = false;
6
+ let currentChecker, hoistedFactories = new Map(), htmlToTemplateId = new Map(), ns = '';
7
7
  function collectNestedTemplateReplacements(node, exprStart, sourceFile, replacements) {
8
8
  if (isNestedHtmlTemplate(node)) {
9
9
  replacements.push({
@@ -17,24 +17,7 @@ function collectNestedTemplateReplacements(node, exprStart, sourceFile, replacem
17
17
  }
18
18
  }
19
19
  function generateImports() {
20
- let specifiers = [];
21
- if (needsArraySlot) {
22
- specifiers.push(`ArraySlot as ${nameArraySlot}`);
23
- }
24
- if (needsEffectSlot) {
25
- specifiers.push(`EffectSlot as ${nameEffectSlot}`);
26
- }
27
- if (needsAttr) {
28
- specifiers.push(`attributes as ${nameAttr}`);
29
- }
30
- if (needsEvent) {
31
- specifiers.push(`event as ${nameEvent}`);
32
- }
33
- if (needsSlot) {
34
- specifiers.push(`slot as ${nameSlot}`);
35
- }
36
- specifiers.push(`template as ${nameTemplate}`);
37
- return `import { ${specifiers.join(', ')} } from '@esportsplus/template';`;
20
+ return `import * as ${ns} from '@esportsplus/template';`;
38
21
  }
39
22
  function generateNestedTemplateCode(node, sourceFile) {
40
23
  let expressions = [], exprTexts = [], literals = [], template = node.template;
@@ -54,8 +37,7 @@ function generateNestedTemplateCode(node, sourceFile) {
54
37
  }
55
38
  function generateNodeBinding(anchor, exprText, exprNode, sourceFile) {
56
39
  if (!exprNode) {
57
- needsSlot = true;
58
- return `${nameSlot}(${anchor}, ${exprText});`;
40
+ return `${ns}.slot(${anchor}, ${exprText});`;
59
41
  }
60
42
  if (isNestedHtmlTemplate(exprNode)) {
61
43
  return `${anchor}.parentNode.insertBefore(${generateNestedTemplateCode(exprNode, sourceFile)}, ${anchor});`;
@@ -63,18 +45,15 @@ function generateNodeBinding(anchor, exprText, exprNode, sourceFile) {
63
45
  let slotType = analyzeExpression(exprNode, currentChecker);
64
46
  switch (slotType) {
65
47
  case 'effect':
66
- needsEffectSlot = true;
67
- return `new ${nameEffectSlot}(${anchor}, ${exprText});`;
48
+ return `new ${ns}.EffectSlot(${anchor}, ${exprText});`;
68
49
  case 'array-slot':
69
- needsArraySlot = true;
70
- return `new ${nameArraySlot}(${anchor}, ${exprText});`;
50
+ return `new ${ns}.ArraySlot(${anchor}, ${exprText});`;
71
51
  case 'static':
72
52
  return `${anchor}.textContent = ${exprText};`;
73
53
  case 'document-fragment':
74
54
  return `${anchor}.parentNode.insertBefore(${exprText}, ${anchor});`;
75
55
  default:
76
- needsSlot = true;
77
- return `${nameSlot}(${anchor}, ${exprText});`;
56
+ return `${ns}.slot(${anchor}, ${exprText});`;
78
57
  }
79
58
  }
80
59
  function generateTemplateCode({ html, slots }, exprTexts, exprNodes, sourceFile, isArrowBody) {
@@ -117,14 +96,12 @@ function generateTemplateCode({ html, slots }, exprTexts, exprNodes, sourceFile,
117
96
  if (name === 'spread') {
118
97
  let bindings = generateSpreadBindings(exprNodes[index], exprTexts[index] || 'undefined', elementVar, sourceFile, currentChecker);
119
98
  for (let k = 0, o = bindings.length; k < o; k++) {
120
- trackBindingUsage(bindings[k]);
121
99
  code.push(bindings[k]);
122
100
  }
123
101
  index++;
124
102
  }
125
103
  else {
126
104
  let binding = generateAttributeBinding(elementVar, name, exprTexts[index++] || 'undefined', slot.attributes.statics[name] || '');
127
- trackBindingUsage(binding);
128
105
  code.push(binding);
129
106
  }
130
107
  }
@@ -220,34 +197,13 @@ function rewriteExpression(expr, sourceFile) {
220
197
  collectNestedTemplateReplacements(expr, exprStart, sourceFile, replacements);
221
198
  return applyReplacementsReverse(expr.getText(sourceFile), replacements);
222
199
  }
223
- function trackBindingUsage(binding) {
224
- if (binding.startsWith(nameEvent + '.')) {
225
- needsEvent = true;
226
- }
227
- else if (binding.startsWith(nameAttr + '.')) {
228
- needsAttr = true;
229
- }
230
- }
231
200
  const addArraySlotImport = (code) => {
232
- return addImport(code, '@esportsplus/template', ['ArraySlot']);
201
+ return `import * as ${ns} from '@esportsplus/template';\n\n` + code;
233
202
  };
234
203
  const generateCode = (templates, originalCode, sourceFile) => {
235
204
  if (templates.length === 0) {
236
205
  return { changed: false, code: originalCode };
237
206
  }
238
- hoistedFactories.clear();
239
- htmlToTemplateId.clear();
240
- nameArraySlot = uid('ArraySlot');
241
- nameAttr = uid('attr');
242
- nameEffectSlot = uid('EffectSlot');
243
- nameEvent = uid('event');
244
- nameSlot = uid('slot');
245
- nameTemplate = uid('template');
246
- needsArraySlot = false;
247
- needsAttr = false;
248
- needsEffectSlot = false;
249
- needsEvent = false;
250
- needsSlot = false;
251
207
  let rootTemplates = templates.filter(t => !isNestedTemplate(t, templates));
252
208
  if (rootTemplates.length === 0) {
253
209
  return { changed: false, code: originalCode };
@@ -280,7 +236,7 @@ const generateCode = (templates, originalCode, sourceFile) => {
280
236
  if (changed && hoistedFactories.size > 0) {
281
237
  let factories = [];
282
238
  for (let [id, html] of hoistedFactories) {
283
- factories.push(`const ${id} = ${nameTemplate}(\`${html}\`);`);
239
+ factories.push(`const ${id} = ${ns}.template(\`${html}\`);`);
284
240
  }
285
241
  code = generateImports() + '\n\n' + factories.join('\n') + '\n\n' + code;
286
242
  }
@@ -294,7 +250,7 @@ const generateReactiveInlining = (calls, code, sourceFile) => {
294
250
  for (let i = calls.length - 1; i >= 0; i--) {
295
251
  let call = calls[i];
296
252
  result = result.slice(0, call.start);
297
- result += `new ${nameArraySlot}(
253
+ result += `new ${ns}.ArraySlot(
298
254
  ${printer.printNode(ts.EmitHint.Expression, call.arrayArg, sourceFile)},
299
255
  ${printer.printNode(ts.EmitHint.Expression, call.callbackArg, sourceFile)}
300
256
  )`;
@@ -303,14 +259,19 @@ const generateReactiveInlining = (calls, code, sourceFile) => {
303
259
  return result;
304
260
  };
305
261
  const getNames = () => ({
306
- attr: nameAttr,
307
- event: nameEvent,
308
- slot: nameSlot
262
+ attr: `${ns}.attributes`,
263
+ event: `${ns}.event`,
264
+ slot: `${ns}.slot`
309
265
  });
266
+ const initNamespace = () => {
267
+ hoistedFactories.clear();
268
+ htmlToTemplateId.clear();
269
+ ns = uid('t');
270
+ };
310
271
  const needsArraySlotImport = (sourceFile) => {
311
272
  return hasArraySlotUsage(sourceFile) && !hasArraySlotImport(sourceFile);
312
273
  };
313
274
  const setTypeChecker = (checker) => {
314
275
  currentChecker = checker;
315
276
  };
316
- export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, needsArraySlotImport, setTypeChecker };
277
+ export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, initNamespace, needsArraySlotImport, setTypeChecker };
@@ -1,5 +1,5 @@
1
1
  import { mightNeedTransform } from '@esportsplus/typescript/transformer';
2
- import { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport, setTypeChecker } from './codegen.js';
2
+ import { addArraySlotImport, generateCode, generateReactiveInlining, initNamespace, needsArraySlotImport, setTypeChecker } from './codegen.js';
3
3
  import { findHtmlTemplates, findReactiveCalls } from './ts-parser.js';
4
4
  import { ts } from '@esportsplus/typescript';
5
5
  const PATTERNS = ['html`', 'html.reactive'];
@@ -23,6 +23,7 @@ function createTransformer(program) {
23
23
  }
24
24
  function transformCode(code, sourceFile) {
25
25
  let changed = false, result = code;
26
+ initNamespace();
26
27
  let reactiveCalls = findReactiveCalls(sourceFile);
27
28
  if (reactiveCalls.length > 0) {
28
29
  result = generateReactiveInlining(reactiveCalls, result, sourceFile);
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "type": "module",
42
42
  "types": "./build/index.d.ts",
43
- "version": "0.31.2",
43
+ "version": "0.31.4",
44
44
  "scripts": {
45
45
  "build": "tsc",
46
46
  "build:test": "vite build --config test/vite.config.ts",
@@ -1,4 +1,4 @@
1
- import { addImport, applyReplacementsReverse, uid } from '@esportsplus/typescript/transformer';
1
+ import { applyReplacementsReverse, uid } from '@esportsplus/typescript/transformer';
2
2
  import type { Replacement } from '@esportsplus/typescript/transformer';
3
3
  import type { ReactiveCallInfo, TemplateInfo } from './ts-parser';
4
4
  import { analyzeExpression, generateAttributeBinding, generateSpreadBindings } from './type-analyzer';
@@ -37,17 +37,7 @@ const ARROW_EMPTY_PARAMS = /\(\s*\)\s*=>\s*$/;
37
37
  let currentChecker: ts.TypeChecker | undefined,
38
38
  hoistedFactories = new Map<string, string>(),
39
39
  htmlToTemplateId = new Map<string, string>(),
40
- nameArraySlot = '',
41
- nameAttr = '',
42
- nameEffectSlot = '',
43
- nameEvent = '',
44
- nameSlot = '',
45
- nameTemplate = '',
46
- needsArraySlot = false,
47
- needsAttr = false,
48
- needsEffectSlot = false,
49
- needsEvent = false,
50
- needsSlot = false;
40
+ ns = '';
51
41
 
52
42
 
53
43
  function collectNestedTemplateReplacements(
@@ -69,31 +59,7 @@ function collectNestedTemplateReplacements(
69
59
  }
70
60
 
71
61
  function generateImports(): string {
72
- let specifiers: string[] = [];
73
-
74
- if (needsArraySlot) {
75
- specifiers.push(`ArraySlot as ${nameArraySlot}`);
76
- }
77
-
78
- if (needsEffectSlot) {
79
- specifiers.push(`EffectSlot as ${nameEffectSlot}`);
80
- }
81
-
82
- if (needsAttr) {
83
- specifiers.push(`attributes as ${nameAttr}`);
84
- }
85
-
86
- if (needsEvent) {
87
- specifiers.push(`event as ${nameEvent}`);
88
- }
89
-
90
- if (needsSlot) {
91
- specifiers.push(`slot as ${nameSlot}`);
92
- }
93
-
94
- specifiers.push(`template as ${nameTemplate}`);
95
-
96
- return `import { ${specifiers.join(', ')} } from '@esportsplus/template';`;
62
+ return `import * as ${ns} from '@esportsplus/template';`;
97
63
  }
98
64
 
99
65
  function generateNestedTemplateCode(node: ts.TaggedTemplateExpression, sourceFile: ts.SourceFile): string {
@@ -128,8 +94,7 @@ function generateNestedTemplateCode(node: ts.TaggedTemplateExpression, sourceFil
128
94
 
129
95
  function generateNodeBinding(anchor: string, exprText: string, exprNode: ts.Expression | undefined, sourceFile: ts.SourceFile): string {
130
96
  if (!exprNode) {
131
- needsSlot = true;
132
- return `${nameSlot}(${anchor}, ${exprText});`;
97
+ return `${ns}.slot(${anchor}, ${exprText});`;
133
98
  }
134
99
 
135
100
  if (isNestedHtmlTemplate(exprNode)) {
@@ -140,12 +105,10 @@ function generateNodeBinding(anchor: string, exprText: string, exprNode: ts.Expr
140
105
 
141
106
  switch (slotType) {
142
107
  case 'effect':
143
- needsEffectSlot = true;
144
- return `new ${nameEffectSlot}(${anchor}, ${exprText});`;
108
+ return `new ${ns}.EffectSlot(${anchor}, ${exprText});`;
145
109
 
146
110
  case 'array-slot':
147
- needsArraySlot = true;
148
- return `new ${nameArraySlot}(${anchor}, ${exprText});`;
111
+ return `new ${ns}.ArraySlot(${anchor}, ${exprText});`;
149
112
 
150
113
  case 'static':
151
114
  return `${anchor}.textContent = ${exprText};`;
@@ -154,8 +117,7 @@ function generateNodeBinding(anchor: string, exprText: string, exprNode: ts.Expr
154
117
  return `${anchor}.parentNode.insertBefore(${exprText}, ${anchor});`;
155
118
 
156
119
  default:
157
- needsSlot = true;
158
- return `${nameSlot}(${anchor}, ${exprText});`;
120
+ return `${ns}.slot(${anchor}, ${exprText});`;
159
121
  }
160
122
  }
161
123
 
@@ -237,7 +199,6 @@ function generateTemplateCode(
237
199
  );
238
200
 
239
201
  for (let k = 0, o = bindings.length; k < o; k++) {
240
- trackBindingUsage(bindings[k]);
241
202
  code.push(bindings[k]);
242
203
  }
243
204
 
@@ -251,7 +212,6 @@ function generateTemplateCode(
251
212
  slot.attributes.statics[name] || ''
252
213
  );
253
214
 
254
- trackBindingUsage(binding);
255
215
  code.push(binding);
256
216
  }
257
217
  }
@@ -381,18 +341,10 @@ function rewriteExpression(expr: ts.Expression, sourceFile: ts.SourceFile): stri
381
341
  return applyReplacementsReverse(expr.getText(sourceFile), replacements);
382
342
  }
383
343
 
384
- function trackBindingUsage(binding: string): void {
385
- if (binding.startsWith(nameEvent + '.')) {
386
- needsEvent = true;
387
- }
388
- else if (binding.startsWith(nameAttr + '.')) {
389
- needsAttr = true;
390
- }
391
- }
392
344
 
393
345
 
394
346
  const addArraySlotImport = (code: string): string => {
395
- return addImport(code, '@esportsplus/template', ['ArraySlot']);
347
+ return `import * as ${ns} from '@esportsplus/template';\n\n` + code;
396
348
  };
397
349
 
398
350
  const generateCode = (templates: TemplateInfo[], originalCode: string, sourceFile: ts.SourceFile): CodegenResult => {
@@ -400,20 +352,6 @@ const generateCode = (templates: TemplateInfo[], originalCode: string, sourceFil
400
352
  return { changed: false, code: originalCode };
401
353
  }
402
354
 
403
- hoistedFactories.clear();
404
- htmlToTemplateId.clear();
405
- nameArraySlot = uid('ArraySlot');
406
- nameAttr = uid('attr');
407
- nameEffectSlot = uid('EffectSlot');
408
- nameEvent = uid('event');
409
- nameSlot = uid('slot');
410
- nameTemplate = uid('template');
411
- needsArraySlot = false;
412
- needsAttr = false;
413
- needsEffectSlot = false;
414
- needsEvent = false;
415
- needsSlot = false;
416
-
417
355
  let rootTemplates = templates.filter(t => !isNestedTemplate(t, templates));
418
356
 
419
357
  if (rootTemplates.length === 0) {
@@ -468,7 +406,7 @@ const generateCode = (templates: TemplateInfo[], originalCode: string, sourceFil
468
406
  let factories: string[] = [];
469
407
 
470
408
  for (let [id, html] of hoistedFactories) {
471
- factories.push(`const ${id} = ${nameTemplate}(\`${html}\`);`);
409
+ factories.push(`const ${id} = ${ns}.template(\`${html}\`);`);
472
410
  }
473
411
 
474
412
  code = generateImports() + '\n\n' + factories.join('\n') + '\n\n' + code;
@@ -489,7 +427,7 @@ const generateReactiveInlining = (calls: ReactiveCallInfo[], code: string, sourc
489
427
  let call = calls[i];
490
428
 
491
429
  result = result.slice(0, call.start);
492
- result += `new ${nameArraySlot}(
430
+ result += `new ${ns}.ArraySlot(
493
431
  ${printer.printNode(ts.EmitHint.Expression, call.arrayArg, sourceFile)},
494
432
  ${printer.printNode(ts.EmitHint.Expression, call.callbackArg, sourceFile)}
495
433
  )`;
@@ -500,11 +438,17 @@ const generateReactiveInlining = (calls: ReactiveCallInfo[], code: string, sourc
500
438
  };
501
439
 
502
440
  const getNames = () => ({
503
- attr: nameAttr,
504
- event: nameEvent,
505
- slot: nameSlot
441
+ attr: `${ns}.attributes`,
442
+ event: `${ns}.event`,
443
+ slot: `${ns}.slot`
506
444
  });
507
445
 
446
+ const initNamespace = (): void => {
447
+ hoistedFactories.clear();
448
+ htmlToTemplateId.clear();
449
+ ns = uid('t');
450
+ };
451
+
508
452
  const needsArraySlotImport = (sourceFile: ts.SourceFile): boolean => {
509
453
  return hasArraySlotUsage(sourceFile) && !hasArraySlotImport(sourceFile);
510
454
  };
@@ -514,5 +458,5 @@ const setTypeChecker = (checker: ts.TypeChecker | undefined): void => {
514
458
  };
515
459
 
516
460
 
517
- export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, needsArraySlotImport, setTypeChecker };
461
+ export { addArraySlotImport, generateCode, generateReactiveInlining, getNames, initNamespace, needsArraySlotImport, setTypeChecker };
518
462
  export type { CodegenResult };
@@ -1,5 +1,5 @@
1
1
  import { mightNeedTransform } from '@esportsplus/typescript/transformer';
2
- import { addArraySlotImport, generateCode, generateReactiveInlining, needsArraySlotImport, setTypeChecker } from './codegen';
2
+ import { addArraySlotImport, generateCode, generateReactiveInlining, initNamespace, needsArraySlotImport, setTypeChecker } from './codegen';
3
3
  import { findHtmlTemplates, findReactiveCalls } from './ts-parser';
4
4
  import { ts } from '@esportsplus/typescript';
5
5
 
@@ -47,6 +47,8 @@ function transformCode(code: string, sourceFile: ts.SourceFile): TransformResult
47
47
  let changed = false,
48
48
  result = code;
49
49
 
50
+ initNamespace();
51
+
50
52
  let reactiveCalls = findReactiveCalls(sourceFile);
51
53
 
52
54
  if (reactiveCalls.length > 0) {