@esportsplus/template 0.16.0
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/.editorconfig +9 -0
- package/.gitattributes +2 -0
- package/.github/dependabot.yml +25 -0
- package/.github/workflows/bump.yml +9 -0
- package/.github/workflows/dependabot.yml +12 -0
- package/.github/workflows/publish.yml +16 -0
- package/README.md +385 -0
- package/build/attributes.d.ts +5 -0
- package/build/attributes.js +212 -0
- package/build/compiler/codegen.d.ts +21 -0
- package/build/compiler/codegen.js +303 -0
- package/build/compiler/constants.d.ts +16 -0
- package/build/compiler/constants.js +19 -0
- package/build/compiler/index.d.ts +14 -0
- package/build/compiler/index.js +61 -0
- package/build/compiler/parser.d.ts +19 -0
- package/build/compiler/parser.js +164 -0
- package/build/compiler/plugins/tsc.d.ts +3 -0
- package/build/compiler/plugins/tsc.js +4 -0
- package/build/compiler/plugins/vite.d.ts +13 -0
- package/build/compiler/plugins/vite.js +8 -0
- package/build/compiler/ts-analyzer.d.ts +4 -0
- package/build/compiler/ts-analyzer.js +63 -0
- package/build/compiler/ts-parser.d.ts +24 -0
- package/build/compiler/ts-parser.js +67 -0
- package/build/constants.d.ts +12 -0
- package/build/constants.js +25 -0
- package/build/event/index.d.ts +10 -0
- package/build/event/index.js +90 -0
- package/build/event/onconnect.d.ts +3 -0
- package/build/event/onconnect.js +15 -0
- package/build/event/onresize.d.ts +3 -0
- package/build/event/onresize.js +26 -0
- package/build/event/ontick.d.ts +6 -0
- package/build/event/ontick.js +41 -0
- package/build/html.d.ts +9 -0
- package/build/html.js +7 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +12 -0
- package/build/render.d.ts +3 -0
- package/build/render.js +8 -0
- package/build/slot/array.d.ts +25 -0
- package/build/slot/array.js +189 -0
- package/build/slot/cleanup.d.ts +4 -0
- package/build/slot/cleanup.js +23 -0
- package/build/slot/effect.d.ts +12 -0
- package/build/slot/effect.js +85 -0
- package/build/slot/index.d.ts +7 -0
- package/build/slot/index.js +14 -0
- package/build/slot/render.d.ts +2 -0
- package/build/slot/render.js +44 -0
- package/build/svg.d.ts +5 -0
- package/build/svg.js +14 -0
- package/build/types.d.ts +23 -0
- package/build/types.js +1 -0
- package/build/utilities.d.ts +7 -0
- package/build/utilities.js +31 -0
- package/package.json +43 -0
- package/src/attributes.ts +313 -0
- package/src/compiler/codegen.ts +492 -0
- package/src/compiler/constants.ts +25 -0
- package/src/compiler/index.ts +87 -0
- package/src/compiler/parser.ts +242 -0
- package/src/compiler/plugins/tsc.ts +6 -0
- package/src/compiler/plugins/vite.ts +10 -0
- package/src/compiler/ts-analyzer.ts +89 -0
- package/src/compiler/ts-parser.ts +112 -0
- package/src/constants.ts +44 -0
- package/src/event/index.ts +130 -0
- package/src/event/onconnect.ts +22 -0
- package/src/event/onresize.ts +37 -0
- package/src/event/ontick.ts +59 -0
- package/src/html.ts +18 -0
- package/src/index.ts +19 -0
- package/src/llm.txt +403 -0
- package/src/render.ts +13 -0
- package/src/slot/array.ts +257 -0
- package/src/slot/cleanup.ts +37 -0
- package/src/slot/effect.ts +114 -0
- package/src/slot/index.ts +17 -0
- package/src/slot/render.ts +61 -0
- package/src/svg.ts +27 -0
- package/src/types.ts +40 -0
- package/src/utilities.ts +53 -0
- package/storage/compiler-architecture-2026-01-13.md +420 -0
- package/test/dist/test.js +1912 -0
- package/test/dist/test.js.map +1 -0
- package/test/index.ts +648 -0
- package/test/vite.config.ts +23 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# Compiler Architecture Documentation
|
|
2
|
+
|
|
3
|
+
## Compilation Flow Diagram
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────────────────────────────────────────────┐
|
|
7
|
+
│ BUILD TOOLS │
|
|
8
|
+
│ (Vite / TypeScript) │
|
|
9
|
+
└─────────────────────┬───────────────────────────────┘
|
|
10
|
+
│
|
|
11
|
+
▼
|
|
12
|
+
┌───────────────────────────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ @esportsplus/typescript/compiler │
|
|
14
|
+
│ │
|
|
15
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
16
|
+
│ │ program │───►│ coordinator │───►│ imports │───►│ ast │ │
|
|
17
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
18
|
+
│ │ │ │ │
|
|
19
|
+
│ │ │ Sequential Plugin Execution │ │
|
|
20
|
+
│ ▼ ▼ ▼ │
|
|
21
|
+
│ ┌─────────────┐ ┌──────────────────────────────────────────────────┐ │
|
|
22
|
+
│ │ ts.Program │ │ PLUGIN CHAIN │ │
|
|
23
|
+
│ │ ts.Checker │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐│ │
|
|
24
|
+
│ └─────────────┘ │ │ Plugin 1 │──►│ Plugin 2 │──►│ Plugin N ││ │
|
|
25
|
+
│ │ └────────────┘ └────────────┘ └────────────┘│ │
|
|
26
|
+
│ └──────────────────────────────────────────────────┘ │
|
|
27
|
+
└───────────────────────────────────────────────────────────────────────────────────────────┘
|
|
28
|
+
│
|
|
29
|
+
┌──────────────────────────────┼──────────────────────────────┐
|
|
30
|
+
│ │ │
|
|
31
|
+
▼ ▼ ▼
|
|
32
|
+
┌────────────────────────────────┐ ┌────────────────────────────────┐ ┌────────────────────┐
|
|
33
|
+
│ @esportsplus/reactivity │ │ @esportsplus/frontend │ │ Custom Plugins │
|
|
34
|
+
│ /compiler │ │ /template/compiler │ │ │
|
|
35
|
+
│ │ │ │ │ │
|
|
36
|
+
│ ┌──────────────────────────┐ │ │ ┌──────────────────────────┐ │ │ ┌──────────────┐ │
|
|
37
|
+
│ │ index.ts │ │ │ │ index.ts │ │ │ │ Your │ │
|
|
38
|
+
│ │ (Plugin Definition) │ │ │ │ (Plugin Definition) │ │ │ │ Plugin │ │
|
|
39
|
+
│ └─────────────┬────────────┘ │ │ └─────────────┬────────────┘ │ │ └──────────────┘ │
|
|
40
|
+
│ │ │ │ │ │ │ │
|
|
41
|
+
│ ┌───────┴───────┐ │ │ ┌───────┴───────┐ │ │ │
|
|
42
|
+
│ ▼ ▼ ▼ │ │ ▼ ▼ ▼ │ │ │
|
|
43
|
+
│ ┌────────┬────────┬────────┐ │ │ ┌────────┬────────┬────────┐ │ │ │
|
|
44
|
+
│ │primit- │ array │ object │ │ │ │ parser │codegen │ts- │ │ │ │
|
|
45
|
+
│ │ives.ts │ .ts │ .ts │ │ │ │ .ts │ .ts │parser │ │ │ │
|
|
46
|
+
│ └────────┴────────┴────────┘ │ │ └────────┴────────┴────────┘ │ │ │
|
|
47
|
+
└────────────────────────────────┘ └────────────────────────────────┘ └────────────────────┘
|
|
48
|
+
│ │
|
|
49
|
+
▼ ▼
|
|
50
|
+
┌────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
51
|
+
│ TRANSFORMED CODE │
|
|
52
|
+
│ │
|
|
53
|
+
│ Input: reactive(0) Input: html`<div>${name}</div>` │
|
|
54
|
+
│ Output: _r.signal(0) Output: (() => { let root = _t(); ... })() │
|
|
55
|
+
└────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Package Overview
|
|
61
|
+
|
|
62
|
+
### 1. @esportsplus/typescript/compiler
|
|
63
|
+
|
|
64
|
+
**Purpose**: Core compiler infrastructure providing the plugin system, AST utilities, and build tool integrations.
|
|
65
|
+
|
|
66
|
+
**Location**: `G:/typescript/src/compiler/`
|
|
67
|
+
|
|
68
|
+
**Exports**:
|
|
69
|
+
- `ast` - AST traversal and inspection utilities
|
|
70
|
+
- `code` - Code generation template tag
|
|
71
|
+
- `coordinator` - Sequential plugin execution engine
|
|
72
|
+
- `imports` - Import analysis and manipulation
|
|
73
|
+
- `plugin` - Plugin factory for Vite/TSC
|
|
74
|
+
- `uid` - Unique identifier generator
|
|
75
|
+
|
|
76
|
+
#### Key Components
|
|
77
|
+
|
|
78
|
+
##### coordinator.ts
|
|
79
|
+
The heart of the compilation system. Transforms source code through plugins sequentially:
|
|
80
|
+
|
|
81
|
+
1. **Pattern Matching**: Fast-path skip if source doesn't contain plugin patterns
|
|
82
|
+
2. **Plugin Execution**: Each plugin receives fresh AST with accurate positions
|
|
83
|
+
3. **Intent Application**: Applies replacements, prepends, and import modifications
|
|
84
|
+
4. **Program Rebuild**: Creates updated TypeScript program after each plugin for accurate type checking
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Core transformation flow
|
|
88
|
+
const transform = (plugins, code, file, program, shared) => {
|
|
89
|
+
for (let plugin of plugins) {
|
|
90
|
+
if (plugin.patterns && !hasPattern(code, plugin.patterns)) continue;
|
|
91
|
+
|
|
92
|
+
let { imports, prepend, replacements } = plugin.transform({
|
|
93
|
+
checker: program.getTypeChecker(),
|
|
94
|
+
code, program, shared, sourceFile
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Apply changes and rebuild program
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
##### imports.ts
|
|
103
|
+
Tracks and manipulates import statements:
|
|
104
|
+
- `all(file, pkg)` - Find all imports from a package
|
|
105
|
+
- `includes(checker, node, pkg, symbolName?)` - Check if a symbol originates from a package (handles re-exports)
|
|
106
|
+
- Uses WeakMap caching for performance
|
|
107
|
+
|
|
108
|
+
##### ast.ts
|
|
109
|
+
AST utilities:
|
|
110
|
+
- `expression.name(node)` - Extract identifier or property path
|
|
111
|
+
- `inRange(ranges, start, end)` - Check if position falls within ranges
|
|
112
|
+
- `property.path(node)` - Build dot-separated property path
|
|
113
|
+
- `test(node, fn)` - Recursive predicate testing
|
|
114
|
+
|
|
115
|
+
##### program.ts
|
|
116
|
+
TypeScript program management:
|
|
117
|
+
- Creates and caches `ts.Program` instances per project root
|
|
118
|
+
- Reads `tsconfig.json` for compiler options
|
|
119
|
+
- Provides type checker for semantic analysis
|
|
120
|
+
|
|
121
|
+
##### uid.ts
|
|
122
|
+
Generates collision-free identifiers:
|
|
123
|
+
- Format: `{prefix}_{uuid}{counter}`
|
|
124
|
+
- Used for generated class names, variable names, template IDs
|
|
125
|
+
|
|
126
|
+
#### Plugin Interface
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
type Plugin = {
|
|
130
|
+
patterns?: string[]; // Quick-check strings (e.g., ['reactive(', 'html`'])
|
|
131
|
+
transform: (ctx: TransformContext) => TransformResult;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
type TransformContext = {
|
|
135
|
+
checker: ts.TypeChecker; // Type information
|
|
136
|
+
code: string; // Current source
|
|
137
|
+
program: ts.Program; // Full program
|
|
138
|
+
shared: SharedContext; // Cross-plugin state
|
|
139
|
+
sourceFile: ts.SourceFile;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
type TransformResult = {
|
|
143
|
+
imports?: ImportIntent[]; // Import modifications
|
|
144
|
+
prepend?: string[]; // Code after imports
|
|
145
|
+
replacements?: ReplacementIntent[]; // AST node replacements
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### 2. @esportsplus/reactivity/compiler
|
|
152
|
+
|
|
153
|
+
**Purpose**: Transforms `reactive()` calls into optimized signal/computed/reactive-array code.
|
|
154
|
+
|
|
155
|
+
**Location**: `G:/reactivity/src/compiler/`
|
|
156
|
+
|
|
157
|
+
**Entry Pattern**: `reactive(`, `reactive<`
|
|
158
|
+
|
|
159
|
+
#### Transformation Types
|
|
160
|
+
|
|
161
|
+
| Input | Output | Transform File |
|
|
162
|
+
|-------|--------|----------------|
|
|
163
|
+
| `reactive(value)` | `_r.signal(value)` | primitives.ts |
|
|
164
|
+
| `reactive(() => expr)` | `_r.computed(() => expr)` | primitives.ts |
|
|
165
|
+
| `reactive([...])` | `new _r.ReactiveArray(...)` | array.ts |
|
|
166
|
+
| `reactive({...})` | `new ReactiveObject_xyz(...)` | object.ts |
|
|
167
|
+
|
|
168
|
+
#### primitives.ts
|
|
169
|
+
Handles scalar reactivity transformations:
|
|
170
|
+
|
|
171
|
+
1. **Signal Detection**: `reactive(staticValue)` → `_r.signal(staticValue)`
|
|
172
|
+
2. **Computed Detection**: `reactive(() => expr)` → `_r.computed(() => expr)`
|
|
173
|
+
3. **Read/Write Tracking**: Transforms variable access to `_r.read(x)` and assignments to `_r.write(x, value)`
|
|
174
|
+
4. **Compound Operators**: `x += 1` → `_r.write(x, x.value + 1)`
|
|
175
|
+
5. **Increment/Decrement**: `x++` → `_r.write(x, x.value + 1)`
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Input
|
|
179
|
+
let count = reactive(0);
|
|
180
|
+
count++;
|
|
181
|
+
console.log(count);
|
|
182
|
+
|
|
183
|
+
// Output
|
|
184
|
+
let count = _r.signal(0);
|
|
185
|
+
_r.write(count, count.value + 1);
|
|
186
|
+
console.log(_r.read(count));
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### array.ts
|
|
190
|
+
Transforms reactive arrays:
|
|
191
|
+
|
|
192
|
+
1. **Array Literal Detection**: `reactive([...])` → `new _r.ReactiveArray(...)`
|
|
193
|
+
2. **Type Preservation**: Extracts element type from `as` assertions or variable declarations
|
|
194
|
+
3. **Length Access**: `.length` → `.$length()` (reactive length)
|
|
195
|
+
4. **Index Assignment**: `arr[i] = v` → `arr.$set(i, v)`
|
|
196
|
+
5. **Binding Propagation**: Tracks array bindings through variable assignments
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Input
|
|
200
|
+
let items = reactive([1, 2, 3] as number[]);
|
|
201
|
+
items[0] = 10;
|
|
202
|
+
console.log(items.length);
|
|
203
|
+
|
|
204
|
+
// Output
|
|
205
|
+
let items = new _r.ReactiveArray<number>(...[1, 2, 3]);
|
|
206
|
+
items.$set(0, 10);
|
|
207
|
+
console.log(items.$length());
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### object.ts
|
|
211
|
+
Transforms reactive objects into generated classes:
|
|
212
|
+
|
|
213
|
+
1. **Class Generation**: Creates optimized class with private signals
|
|
214
|
+
2. **Property Analysis**: Determines signal/computed/array type per property
|
|
215
|
+
3. **Static Optimization**: Static values (literals) inline directly
|
|
216
|
+
4. **Type Hints**: `reactive<Type>({...})` preserves type information
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// Input
|
|
220
|
+
let state = reactive({ count: 0, double: () => state.count * 2 });
|
|
221
|
+
|
|
222
|
+
// Output
|
|
223
|
+
class ReactiveObject_abc<T0, T1 extends _r.Computed<ReturnType<T1>>['fn']> extends _r.ReactiveObject<any> {
|
|
224
|
+
#count;
|
|
225
|
+
#double;
|
|
226
|
+
|
|
227
|
+
constructor(_p0: T0, _p1: T1) {
|
|
228
|
+
super(null);
|
|
229
|
+
this.#count = this[_r.SIGNAL](_p0);
|
|
230
|
+
this.#double = this[_r.COMPUTED](_p1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
get count() { return _r.read(this.#count) as T0; }
|
|
234
|
+
set count(_v0) { _r.write(this.#count, _v0); }
|
|
235
|
+
get double() { return _r.read(this.#double); }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let state = new ReactiveObject_abc(0, () => state.count * 2);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### 3. @esportsplus/frontend/template/compiler
|
|
244
|
+
|
|
245
|
+
**Purpose**: Compiles tagged HTML templates into optimized DOM creation code.
|
|
246
|
+
|
|
247
|
+
**Location**: `G:/frontend/src/template/compiler/`
|
|
248
|
+
|
|
249
|
+
**Entry Pattern**: `` html` ``, `html.reactive`
|
|
250
|
+
|
|
251
|
+
#### Transformation Pipeline
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
html`<div>${expr}</div>`
|
|
255
|
+
│
|
|
256
|
+
▼
|
|
257
|
+
┌─────────────────┐
|
|
258
|
+
│ ts-parser.ts │ Extract template literals and expressions
|
|
259
|
+
└────────┬────────┘
|
|
260
|
+
│
|
|
261
|
+
▼
|
|
262
|
+
┌─────────────────┐
|
|
263
|
+
│ parser.ts │ Parse HTML, identify slots, build path tree
|
|
264
|
+
└────────┬────────┘
|
|
265
|
+
│
|
|
266
|
+
▼
|
|
267
|
+
┌─────────────────┐
|
|
268
|
+
│ ts-analyzer.ts │ Analyze expression types (Effect, Static, etc.)
|
|
269
|
+
└────────┬────────┘
|
|
270
|
+
│
|
|
271
|
+
▼
|
|
272
|
+
┌─────────────────┐
|
|
273
|
+
│ codegen.ts │ Generate optimized DOM code
|
|
274
|
+
└─────────────────┘
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### ts-parser.ts
|
|
278
|
+
Extracts template information from AST:
|
|
279
|
+
- `findHtmlTemplates(sourceFile)` - Locate all `html\`...\`` expressions
|
|
280
|
+
- `findReactiveCalls(sourceFile)` - Locate `html.reactive(array, callback)` calls
|
|
281
|
+
- `extractTemplateParts(template)` - Split template into literals and expressions
|
|
282
|
+
|
|
283
|
+
#### parser.ts
|
|
284
|
+
Parses HTML template strings:
|
|
285
|
+
|
|
286
|
+
1. **Slot Detection**: Identifies `{{$}}` markers for dynamic content
|
|
287
|
+
2. **Path Generation**: Creates DOM traversal paths (e.g., `['firstChild', 'nextSibling']`)
|
|
288
|
+
3. **Attribute Parsing**: Extracts dynamic attribute bindings
|
|
289
|
+
4. **HTML Cleanup**: Removes whitespace, events, empty attributes
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// Input: <div class="${cls}">${content}</div>
|
|
293
|
+
// Output:
|
|
294
|
+
{
|
|
295
|
+
html: '<div><!----></div>', // Cleaned HTML with comment slot
|
|
296
|
+
slots: [
|
|
297
|
+
{ type: 'attribute', path: ['firstChild'], attributes: { names: ['class'], static: {} } },
|
|
298
|
+
{ type: 'node', path: ['firstChild', 'firstChild'] }
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### ts-analyzer.ts
|
|
304
|
+
Determines expression types for optimization:
|
|
305
|
+
|
|
306
|
+
| Expression Type | Result | Optimization |
|
|
307
|
+
|-----------------|--------|--------------|
|
|
308
|
+
| Arrow/Function | `Effect` | Creates EffectSlot |
|
|
309
|
+
| `html\`...\`` | `DocumentFragment` | Direct insert |
|
|
310
|
+
| `html.reactive()` | `ArraySlot` | Creates ArraySlot |
|
|
311
|
+
| Literal (string/number/bool/null) | `Static` | Direct textContent |
|
|
312
|
+
| Template expression | `Primitive` | Runtime slot |
|
|
313
|
+
| Conditional | Analyzes branches | Unified handling |
|
|
314
|
+
|
|
315
|
+
#### codegen.ts
|
|
316
|
+
Generates optimized DOM creation code:
|
|
317
|
+
|
|
318
|
+
1. **Template Factory**: Creates reusable template cloners
|
|
319
|
+
2. **Path Variables**: Declares element references via path traversal
|
|
320
|
+
3. **Attribute Bindings**: Generates appropriate setters (property, event, class/style list)
|
|
321
|
+
4. **Node Bindings**: Creates slots, effects, or direct inserts based on type
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// Input
|
|
325
|
+
html`<div class="${cls}" onclick=${handler}>${name}</div>`
|
|
326
|
+
|
|
327
|
+
// Output
|
|
328
|
+
const _t_abc = _template.template(`<div><!----></div>`);
|
|
329
|
+
|
|
330
|
+
(() => {
|
|
331
|
+
let root = _t_abc(),
|
|
332
|
+
el_1 = root.firstChild as _template.Element;
|
|
333
|
+
|
|
334
|
+
_template.setList(el_1, 'class', cls, _attr_1);
|
|
335
|
+
_template.delegate(el_1, 'click', handler);
|
|
336
|
+
_template.slot(el_1.firstChild as _template.Element, name);
|
|
337
|
+
|
|
338
|
+
return root;
|
|
339
|
+
})()
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Event Handling
|
|
343
|
+
Three event binding strategies:
|
|
344
|
+
- **Lifecycle Events** (`oncreate`, `ondestroy`): Direct element callbacks
|
|
345
|
+
- **Direct Attach** (`onfocus`, `onblur`, etc.): `addEventListener` directly
|
|
346
|
+
- **Delegated** (all others): Event delegation via `delegate()`
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Integration Flow
|
|
351
|
+
|
|
352
|
+
### Vite Integration
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// vite.config.ts
|
|
356
|
+
import reactivityCompiler from '@esportsplus/reactivity/compiler/plugins/vite';
|
|
357
|
+
import templateCompiler from '@esportsplus/frontend/template/compiler/plugins/vite';
|
|
358
|
+
|
|
359
|
+
export default {
|
|
360
|
+
plugins: [
|
|
361
|
+
plugin({
|
|
362
|
+
name: '@esportsplus/frontend',
|
|
363
|
+
plugins: [
|
|
364
|
+
reactivityCompiler, // First: transform reactive() calls
|
|
365
|
+
templateCompiler // Second: transform html`` templates
|
|
366
|
+
]
|
|
367
|
+
})({ root: __dirname })
|
|
368
|
+
]
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Execution Order
|
|
373
|
+
|
|
374
|
+
1. **Vite Transform Hook**: File loaded/changed
|
|
375
|
+
2. **Program Resolution**: Get/create TypeScript program
|
|
376
|
+
3. **Coordinator**: Execute plugins sequentially
|
|
377
|
+
- **Reactivity Plugin**: Transform `reactive()` → signals/computed
|
|
378
|
+
- **Template Plugin**: Transform `html\`\`` → DOM code
|
|
379
|
+
4. **Code Generation**: Apply replacements, prepends, imports
|
|
380
|
+
5. **Return**: Transformed code to Vite
|
|
381
|
+
|
|
382
|
+
### Cross-Plugin Communication
|
|
383
|
+
|
|
384
|
+
The `SharedContext` (`Map<string, unknown>`) enables plugins to share state:
|
|
385
|
+
- Cleared on file watch change
|
|
386
|
+
- Scoped per project root
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Key Design Decisions
|
|
391
|
+
|
|
392
|
+
### 1. Sequential Plugin Execution
|
|
393
|
+
Each plugin receives a fresh AST with accurate positions after previous plugins' changes. This ensures:
|
|
394
|
+
- Correct source positions for replacements
|
|
395
|
+
- Valid type checker for semantic analysis
|
|
396
|
+
- No position drift from accumulated changes
|
|
397
|
+
|
|
398
|
+
### 2. Intent-Based Transformations
|
|
399
|
+
Plugins return "intents" rather than modified strings:
|
|
400
|
+
- `ReplacementIntent`: AST node + generator function
|
|
401
|
+
- `ImportIntent`: Package + add/remove specifiers
|
|
402
|
+
- Intents resolved at apply-time with current positions
|
|
403
|
+
|
|
404
|
+
### 3. Pattern-Based Quick Checks
|
|
405
|
+
Plugins declare patterns (e.g., `reactive(`) for fast-path skipping:
|
|
406
|
+
- Avoids AST parsing when unnecessary
|
|
407
|
+
- Simple string indexOf check
|
|
408
|
+
- Patterns checked before type analysis
|
|
409
|
+
|
|
410
|
+
### 4. Type-Aware Transformations
|
|
411
|
+
Full TypeScript program enables:
|
|
412
|
+
- Symbol origin tracking (handles re-exports)
|
|
413
|
+
- Type-based optimization decisions
|
|
414
|
+
- Accurate identifier resolution
|
|
415
|
+
|
|
416
|
+
### 5. Optimized Code Generation
|
|
417
|
+
- **Template Factories**: Clone once, reuse many times
|
|
418
|
+
- **Path-Based Traversal**: Direct DOM navigation, no queries
|
|
419
|
+
- **Event Delegation**: Single listener per event type
|
|
420
|
+
- **Static Inlining**: Literal values inlined directly
|