@esportsplus/template 0.34.1 → 0.35.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/attributes.d.ts +3 -3
- package/build/attributes.js +4 -1
- package/build/compiler/codegen.d.ts +3 -5
- package/build/compiler/codegen.js +48 -61
- package/build/compiler/index.d.ts +0 -6
- package/build/compiler/index.js +16 -17
- package/build/compiler/ts-parser.d.ts +2 -2
- package/build/compiler/ts-parser.js +38 -12
- package/build/compiler/type-analyzer.d.ts +2 -2
- package/build/compiler/type-analyzer.js +17 -105
- package/build/constants.d.ts +1 -3
- package/build/constants.js +1 -4
- package/build/index.d.ts +6 -1
- package/build/index.js +11 -1
- package/build/utilities.js +1 -1
- package/package.json +7 -13
- package/src/attributes.ts +9 -6
- package/src/compiler/codegen.ts +65 -88
- package/src/compiler/index.ts +21 -19
- package/src/compiler/parser.ts +1 -1
- package/src/compiler/ts-parser.ts +53 -12
- package/src/compiler/type-analyzer.ts +24 -142
- package/src/constants.ts +3 -12
- package/src/index.ts +16 -1
- package/src/utilities.ts +2 -2
- package/test/vite.config.ts +1 -1
- package/build/runtime.d.ts +0 -1
- package/build/runtime.js +0 -5
- package/src/runtime.ts +0 -8
|
@@ -4,68 +4,10 @@ import {
|
|
|
4
4
|
COMPILER_TYPES,
|
|
5
5
|
DIRECT_ATTACH_EVENTS,
|
|
6
6
|
LIFECYCLE_EVENTS
|
|
7
|
-
} from '
|
|
7
|
+
} from '~/constants';
|
|
8
8
|
import { ts } from '@esportsplus/typescript';
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
type SpreadAnalysis = {
|
|
12
|
-
canUnpack: boolean;
|
|
13
|
-
keys: string[];
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function analyzeSpread(expr: ts.Expression, checker?: ts.TypeChecker): SpreadAnalysis {
|
|
18
|
-
while (ts.isParenthesizedExpression(expr)) {
|
|
19
|
-
expr = expr.expression;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (ts.isObjectLiteralExpression(expr)) {
|
|
23
|
-
let keys: string[] = [];
|
|
24
|
-
|
|
25
|
-
for (let i = 0, n = expr.properties.length; i < n; i++) {
|
|
26
|
-
let prop = expr.properties[i];
|
|
27
|
-
|
|
28
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
29
|
-
if (ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name)) {
|
|
30
|
-
keys.push(prop.name.text);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else if (ts.isShorthandPropertyAssignment(prop)) {
|
|
34
|
-
keys.push(prop.name.text);
|
|
35
|
-
}
|
|
36
|
-
else if (ts.isSpreadAssignment(prop)) {
|
|
37
|
-
return { canUnpack: false, keys: [] };
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return { canUnpack: true, keys };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (checker && (ts.isIdentifier(expr) || ts.isPropertyAccessExpression(expr))) {
|
|
45
|
-
try {
|
|
46
|
-
let keys: string[] = [],
|
|
47
|
-
props = checker.getTypeAtLocation(expr).getProperties();
|
|
48
|
-
|
|
49
|
-
for (let i = 0, n = props.length; i < n; i++) {
|
|
50
|
-
let name = props[i].getName();
|
|
51
|
-
|
|
52
|
-
if (name.startsWith('__') || name.startsWith('[')) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
keys.push(name);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (keys.length > 0) {
|
|
60
|
-
return { canUnpack: true, keys };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch { }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { canUnpack: false, keys: [] };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
11
|
function inferCOMPILER_TYPES(expr: ts.Expression, checker?: ts.TypeChecker): COMPILER_TYPES {
|
|
70
12
|
while (ts.isParenthesizedExpression(expr)) {
|
|
71
13
|
expr = expr.expression;
|
|
@@ -75,6 +17,7 @@ function inferCOMPILER_TYPES(expr: ts.Expression, checker?: ts.TypeChecker): COM
|
|
|
75
17
|
return COMPILER_TYPES.Effect;
|
|
76
18
|
}
|
|
77
19
|
|
|
20
|
+
// Only html.reactive() calls become ArraySlot - handled by generateReactiveInlining
|
|
78
21
|
if (
|
|
79
22
|
ts.isCallExpression(expr) &&
|
|
80
23
|
ts.isPropertyAccessExpression(expr.expression) &&
|
|
@@ -89,10 +32,6 @@ function inferCOMPILER_TYPES(expr: ts.Expression, checker?: ts.TypeChecker): COM
|
|
|
89
32
|
return COMPILER_TYPES.DocumentFragment;
|
|
90
33
|
}
|
|
91
34
|
|
|
92
|
-
if (ts.isArrayLiteralExpression(expr)) {
|
|
93
|
-
return COMPILER_TYPES.ArraySlot;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
35
|
if (
|
|
97
36
|
ts.isNumericLiteral(expr) ||
|
|
98
37
|
ts.isStringLiteral(expr) ||
|
|
@@ -131,10 +70,6 @@ function inferCOMPILER_TYPES(expr: ts.Expression, checker?: ts.TypeChecker): COM
|
|
|
131
70
|
if (isTypeFunction(type, checker)) {
|
|
132
71
|
return COMPILER_TYPES.Effect;
|
|
133
72
|
}
|
|
134
|
-
|
|
135
|
-
if (isTypeArray(type, checker)) {
|
|
136
|
-
return COMPILER_TYPES.ArraySlot;
|
|
137
|
-
}
|
|
138
73
|
}
|
|
139
74
|
catch {
|
|
140
75
|
}
|
|
@@ -143,28 +78,26 @@ function inferCOMPILER_TYPES(expr: ts.Expression, checker?: ts.TypeChecker): COM
|
|
|
143
78
|
return COMPILER_TYPES.Unknown;
|
|
144
79
|
}
|
|
145
80
|
|
|
146
|
-
function isTypeArray(type: ts.Type, checker: ts.TypeChecker): boolean {
|
|
147
|
-
if (checker.isArrayType(type)) {
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return type.getSymbol()?.getName() === 'ReactiveArray';
|
|
152
|
-
}
|
|
153
|
-
|
|
154
81
|
function isTypeFunction(type: ts.Type, checker: ts.TypeChecker): boolean {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
82
|
+
// Union types that mix functions with non-functions (e.g., Renderable)
|
|
83
|
+
// should fall through to runtime slot dispatch
|
|
159
84
|
if (type.isUnion()) {
|
|
85
|
+
let allFunctions = true,
|
|
86
|
+
hasFunction = false;
|
|
87
|
+
|
|
160
88
|
for (let i = 0, n = type.types.length; i < n; i++) {
|
|
161
89
|
if (isTypeFunction(type.types[i], checker)) {
|
|
162
|
-
|
|
90
|
+
hasFunction = true;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
allFunctions = false;
|
|
163
94
|
}
|
|
164
95
|
}
|
|
96
|
+
|
|
97
|
+
return hasFunction && allFunctions;
|
|
165
98
|
}
|
|
166
99
|
|
|
167
|
-
return
|
|
100
|
+
return type.getCallSignatures().length > 0;
|
|
168
101
|
}
|
|
169
102
|
|
|
170
103
|
|
|
@@ -172,94 +105,43 @@ const analyzeExpression = (expr: ts.Expression, checker?: ts.TypeChecker): COMPI
|
|
|
172
105
|
return inferCOMPILER_TYPES(expr, checker);
|
|
173
106
|
};
|
|
174
107
|
|
|
175
|
-
const generateAttributeBinding = (elementVar: string, name: string, expr: string, staticValue: string,
|
|
108
|
+
const generateAttributeBinding = (elementVar: string, name: string, expr: string, staticValue: string, addImport: (name: string) => string): string => {
|
|
176
109
|
if (name.startsWith('on') && name.length > 2) {
|
|
177
110
|
let event = name.slice(2).toLowerCase(),
|
|
178
111
|
key = name.toLowerCase();
|
|
179
112
|
|
|
180
113
|
if (LIFECYCLE_EVENTS.has(key)) {
|
|
181
|
-
return `${
|
|
114
|
+
return `${addImport(key)}(${elementVar}, ${expr});`;
|
|
182
115
|
}
|
|
183
116
|
|
|
184
117
|
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
185
|
-
return `${
|
|
118
|
+
return `${addImport('on')}(${elementVar}, '${event}', ${expr});`;
|
|
186
119
|
}
|
|
187
120
|
|
|
188
|
-
return `${
|
|
121
|
+
return `${addImport('delegate')}(${elementVar}, '${event}', ${expr});`;
|
|
189
122
|
}
|
|
190
123
|
|
|
191
124
|
if (name === 'class') {
|
|
192
|
-
return `${
|
|
125
|
+
return `${addImport('setClass')}(${elementVar}, '${staticValue}', ${expr});`;
|
|
193
126
|
}
|
|
194
127
|
|
|
195
128
|
if (name === COMPILER_TYPES.Attributes) {
|
|
196
|
-
return `${
|
|
129
|
+
return `${addImport('setProperties')}(${elementVar}, ${expr});`;
|
|
197
130
|
}
|
|
198
131
|
|
|
199
132
|
if (name === 'style') {
|
|
200
|
-
return `${
|
|
133
|
+
return `${addImport('setStyle')}(${elementVar}, '${staticValue}', ${expr});`;
|
|
201
134
|
}
|
|
202
135
|
|
|
203
|
-
return `${
|
|
136
|
+
return `${addImport('setProperty')}(${elementVar}, '${name}', ${expr});`;
|
|
204
137
|
};
|
|
205
138
|
|
|
206
139
|
const generateSpreadBindings = (
|
|
207
|
-
expr: ts.Expression,
|
|
208
140
|
exprCode: string,
|
|
209
141
|
elementVar: string,
|
|
210
|
-
|
|
211
|
-
ns: string
|
|
142
|
+
addImport: (name: string) => string
|
|
212
143
|
): string[] => {
|
|
213
|
-
|
|
214
|
-
expr = expr.expression;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
let analysis = analyzeSpread(expr, checker);
|
|
218
|
-
|
|
219
|
-
if (!analysis.canUnpack) {
|
|
220
|
-
return [`${ns}.setProperties(${elementVar}, ${exprCode});`];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
let lines: string[] = [];
|
|
224
|
-
|
|
225
|
-
if (ts.isObjectLiteralExpression(expr)) {
|
|
226
|
-
for (let i = 0, n = analysis.keys.length; i < n; i++) {
|
|
227
|
-
let key = analysis.keys[i],
|
|
228
|
-
value: string | null = null;
|
|
229
|
-
|
|
230
|
-
for (let j = 0, m = expr.properties.length; j < m; j++) {
|
|
231
|
-
let prop = expr.properties[j];
|
|
232
|
-
|
|
233
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
234
|
-
let text = ts.isIdentifier(prop.name)
|
|
235
|
-
? prop.name.text
|
|
236
|
-
: ts.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
237
|
-
|
|
238
|
-
if (text === key) {
|
|
239
|
-
value = prop.initializer.getText();
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else if (ts.isShorthandPropertyAssignment(prop) && prop.name.text === key) {
|
|
244
|
-
value = prop.name.text;
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (value !== null) {
|
|
250
|
-
lines.push(generateAttributeBinding(elementVar, key, value, '', ns));
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
for (let i = 0, n = analysis.keys.length; i < n; i++) {
|
|
256
|
-
let key = analysis.keys[i];
|
|
257
|
-
|
|
258
|
-
lines.push(generateAttributeBinding(elementVar, key, `${exprCode}.${key}`, '', ns));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return lines;
|
|
144
|
+
return [`${addImport('setProperties')}(${elementVar}, ${exprCode});`];
|
|
263
145
|
};
|
|
264
146
|
|
|
265
147
|
|
package/src/constants.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { uid } from '@esportsplus/typescript/compiler';
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
const ARRAY_SLOT = Symbol('template.array.slot');
|
|
5
2
|
|
|
6
3
|
const CLEANUP = Symbol('template.cleanup');
|
|
7
4
|
|
|
8
|
-
|
|
9
5
|
const COMPILER_ENTRYPOINT = 'html';
|
|
10
6
|
|
|
11
7
|
const COMPILER_ENTRYPOINT_REACTIVITY = 'reactive';
|
|
12
8
|
|
|
13
|
-
const COMPILER_NAMESPACE = uid('template');
|
|
14
|
-
|
|
15
9
|
const enum COMPILER_TYPES {
|
|
16
10
|
ArraySlot = 'array-slot',
|
|
17
11
|
Attributes = 'attributes',
|
|
@@ -40,9 +34,6 @@ const LIFECYCLE_EVENTS = new Set<string>([
|
|
|
40
34
|
|
|
41
35
|
const PACKAGE = '@esportsplus/template';
|
|
42
36
|
|
|
43
|
-
const PACKAGE_COMPILER = '@esportsplus/template/compiler';
|
|
44
|
-
|
|
45
|
-
|
|
46
37
|
const SLOT_HTML = '<!--$-->';
|
|
47
38
|
|
|
48
39
|
const STATE_HYDRATING = 0;
|
|
@@ -57,9 +48,9 @@ const STORE = Symbol('template.store');
|
|
|
57
48
|
export {
|
|
58
49
|
ARRAY_SLOT,
|
|
59
50
|
CLEANUP,
|
|
60
|
-
COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REACTIVITY,
|
|
51
|
+
COMPILER_ENTRYPOINT, COMPILER_ENTRYPOINT_REACTIVITY, COMPILER_TYPES,
|
|
61
52
|
DIRECT_ATTACH_EVENTS,
|
|
62
53
|
LIFECYCLE_EVENTS,
|
|
63
|
-
PACKAGE,
|
|
54
|
+
PACKAGE,
|
|
64
55
|
SLOT_HTML, STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE,
|
|
65
|
-
};
|
|
56
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import { CLEANUP, STORE } from './constants';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// Pre-allocate on Node prototype to optimize property access
|
|
5
|
+
if (typeof Node !== 'undefined') {
|
|
6
|
+
(Node.prototype as any)[CLEANUP] = null;
|
|
7
|
+
(Node.prototype as any)[STORE] = null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
2
11
|
export { default as html } from './html';
|
|
3
12
|
export { default as render } from './render';
|
|
4
13
|
export { default as svg } from './svg';
|
|
14
|
+
export * from './attributes';
|
|
15
|
+
export * from './event';
|
|
16
|
+
export { ArraySlot } from './slot/array';
|
|
17
|
+
export { EffectSlot } from './slot/effect';
|
|
18
|
+
export { default as slot } from './slot';
|
|
5
19
|
export type { Attributes, Element, Renderable } from './types';
|
|
20
|
+
export * from './utilities';
|
package/src/utilities.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SLOT_HTML } from './constants';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
let tmpl = document
|
|
5
|
-
txt = document
|
|
4
|
+
let tmpl = document.createElement('template'),
|
|
5
|
+
txt = document.createTextNode('');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
// Firefox's importNode outperforms cloneNode in certain scenarios
|
package/test/vite.config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
3
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
4
|
-
import templatePlugin from '../src/compiler/vite';
|
|
4
|
+
import templatePlugin from '../src/compiler/plugins/vite';
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
export default defineConfig({
|
package/build/runtime.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/build/runtime.js
DELETED
package/src/runtime.ts
DELETED