@zenithbuild/compiler 1.0.2
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/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/build-analyzer.d.ts +44 -0
- package/dist/build-analyzer.js +87 -0
- package/dist/bundler.d.ts +31 -0
- package/dist/bundler.js +86 -0
- package/dist/core/components/index.d.ts +9 -0
- package/dist/core/components/index.js +13 -0
- package/dist/core/config/index.d.ts +11 -0
- package/dist/core/config/index.js +10 -0
- package/dist/core/config/loader.d.ts +17 -0
- package/dist/core/config/loader.js +60 -0
- package/dist/core/config/types.d.ts +98 -0
- package/dist/core/config/types.js +32 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +6 -0
- package/dist/core/lifecycle/index.d.ts +16 -0
- package/dist/core/lifecycle/index.js +19 -0
- package/dist/core/lifecycle/zen-mount.d.ts +66 -0
- package/dist/core/lifecycle/zen-mount.js +151 -0
- package/dist/core/lifecycle/zen-unmount.d.ts +54 -0
- package/dist/core/lifecycle/zen-unmount.js +76 -0
- package/dist/core/plugins/bridge.d.ts +116 -0
- package/dist/core/plugins/bridge.js +121 -0
- package/dist/core/plugins/index.d.ts +6 -0
- package/dist/core/plugins/index.js +6 -0
- package/dist/core/plugins/registry.d.ts +67 -0
- package/dist/core/plugins/registry.js +113 -0
- package/dist/core/reactivity/index.d.ts +30 -0
- package/dist/core/reactivity/index.js +33 -0
- package/dist/core/reactivity/tracking.d.ts +74 -0
- package/dist/core/reactivity/tracking.js +136 -0
- package/dist/core/reactivity/zen-batch.d.ts +45 -0
- package/dist/core/reactivity/zen-batch.js +54 -0
- package/dist/core/reactivity/zen-effect.d.ts +48 -0
- package/dist/core/reactivity/zen-effect.js +98 -0
- package/dist/core/reactivity/zen-memo.d.ts +43 -0
- package/dist/core/reactivity/zen-memo.js +100 -0
- package/dist/core/reactivity/zen-ref.d.ts +44 -0
- package/dist/core/reactivity/zen-ref.js +34 -0
- package/dist/core/reactivity/zen-signal.d.ts +48 -0
- package/dist/core/reactivity/zen-signal.js +84 -0
- package/dist/core/reactivity/zen-state.d.ts +35 -0
- package/dist/core/reactivity/zen-state.js +147 -0
- package/dist/core/reactivity/zen-untrack.d.ts +38 -0
- package/dist/core/reactivity/zen-untrack.js +41 -0
- package/dist/css/index.d.ts +73 -0
- package/dist/css/index.js +246 -0
- package/dist/discovery/componentDiscovery.d.ts +42 -0
- package/dist/discovery/componentDiscovery.js +56 -0
- package/dist/discovery/layouts.d.ts +13 -0
- package/dist/discovery/layouts.js +41 -0
- package/dist/errors/compilerError.d.ts +31 -0
- package/dist/errors/compilerError.js +51 -0
- package/dist/finalize/finalizeOutput.d.ts +32 -0
- package/dist/finalize/finalizeOutput.js +62 -0
- package/dist/finalize/generateFinalBundle.d.ts +24 -0
- package/dist/finalize/generateFinalBundle.js +68 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +51 -0
- package/dist/ir/types.d.ts +181 -0
- package/dist/ir/types.js +8 -0
- package/dist/output/types.d.ts +30 -0
- package/dist/output/types.js +6 -0
- package/dist/parse/detectMapExpressions.d.ts +45 -0
- package/dist/parse/detectMapExpressions.js +77 -0
- package/dist/parse/parseScript.d.ts +8 -0
- package/dist/parse/parseScript.js +36 -0
- package/dist/parse/parseTemplate.d.ts +11 -0
- package/dist/parse/parseTemplate.js +487 -0
- package/dist/parse/parseZenFile.d.ts +11 -0
- package/dist/parse/parseZenFile.js +50 -0
- package/dist/parse/scriptAnalysis.d.ts +25 -0
- package/dist/parse/scriptAnalysis.js +60 -0
- package/dist/parse/trackLoopContext.d.ts +20 -0
- package/dist/parse/trackLoopContext.js +62 -0
- package/dist/parseZenFile.d.ts +10 -0
- package/dist/parseZenFile.js +55 -0
- package/dist/runtime/analyzeAndEmit.d.ts +20 -0
- package/dist/runtime/analyzeAndEmit.js +70 -0
- package/dist/runtime/build.d.ts +6 -0
- package/dist/runtime/build.js +13 -0
- package/dist/runtime/bundle-generator.d.ts +27 -0
- package/dist/runtime/bundle-generator.js +1263 -0
- package/dist/runtime/client-runtime.d.ts +41 -0
- package/dist/runtime/client-runtime.js +397 -0
- package/dist/runtime/dataExposure.d.ts +52 -0
- package/dist/runtime/dataExposure.js +227 -0
- package/dist/runtime/generateDOM.d.ts +21 -0
- package/dist/runtime/generateDOM.js +194 -0
- package/dist/runtime/generateHydrationBundle.d.ts +15 -0
- package/dist/runtime/generateHydrationBundle.js +399 -0
- package/dist/runtime/hydration.d.ts +53 -0
- package/dist/runtime/hydration.js +271 -0
- package/dist/runtime/navigation.d.ts +58 -0
- package/dist/runtime/navigation.js +372 -0
- package/dist/runtime/serve.d.ts +13 -0
- package/dist/runtime/serve.js +76 -0
- package/dist/runtime/thinRuntime.d.ts +23 -0
- package/dist/runtime/thinRuntime.js +158 -0
- package/dist/runtime/transformIR.d.ts +19 -0
- package/dist/runtime/transformIR.js +285 -0
- package/dist/runtime/wrapExpression.d.ts +24 -0
- package/dist/runtime/wrapExpression.js +76 -0
- package/dist/runtime/wrapExpressionWithLoop.d.ts +17 -0
- package/dist/runtime/wrapExpressionWithLoop.js +75 -0
- package/dist/spa-build.d.ts +26 -0
- package/dist/spa-build.js +866 -0
- package/dist/ssg-build.d.ts +32 -0
- package/dist/ssg-build.js +408 -0
- package/dist/test/analyze-emit.test.d.ts +1 -0
- package/dist/test/analyze-emit.test.js +88 -0
- package/dist/test/bundler-contract.test.d.ts +1 -0
- package/dist/test/bundler-contract.test.js +137 -0
- package/dist/test/compiler-authority.test.d.ts +1 -0
- package/dist/test/compiler-authority.test.js +90 -0
- package/dist/test/component-instance-test.d.ts +1 -0
- package/dist/test/component-instance-test.js +115 -0
- package/dist/test/error-native-bridge.test.d.ts +1 -0
- package/dist/test/error-native-bridge.test.js +51 -0
- package/dist/test/error-serialization.test.d.ts +1 -0
- package/dist/test/error-serialization.test.js +38 -0
- package/dist/test/macro-inlining.test.d.ts +1 -0
- package/dist/test/macro-inlining.test.js +178 -0
- package/dist/test/validate-test.d.ts +6 -0
- package/dist/test/validate-test.js +95 -0
- package/dist/transform/classifyExpression.d.ts +46 -0
- package/dist/transform/classifyExpression.js +354 -0
- package/dist/transform/componentResolver.d.ts +15 -0
- package/dist/transform/componentResolver.js +30 -0
- package/dist/transform/expressionTransformer.d.ts +19 -0
- package/dist/transform/expressionTransformer.js +333 -0
- package/dist/transform/fragmentLowering.d.ts +25 -0
- package/dist/transform/fragmentLowering.js +468 -0
- package/dist/transform/layoutProcessor.d.ts +5 -0
- package/dist/transform/layoutProcessor.js +34 -0
- package/dist/transform/transformTemplate.d.ts +11 -0
- package/dist/transform/transformTemplate.js +33 -0
- package/dist/validate/invariants.d.ts +23 -0
- package/dist/validate/invariants.js +55 -0
- package/native/compiler-native/compiler-native.node +0 -0
- package/native/compiler-native/index.d.ts +113 -0
- package/native/compiler-native/index.js +19 -0
- package/native/compiler-native/package.json +19 -0
- package/package.json +49 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression Classification
|
|
3
|
+
*
|
|
4
|
+
* Analyzes expression code to determine output type for structural lowering.
|
|
5
|
+
*
|
|
6
|
+
* JSX expressions are allowed if — and only if — the compiler can statically
|
|
7
|
+
* enumerate all possible DOM shapes and lower them at compile time.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Check if code contains JSX-like tags
|
|
11
|
+
*/
|
|
12
|
+
function containsJSX(code) {
|
|
13
|
+
// Match opening JSX tags: <Tag or <tag
|
|
14
|
+
return /<[a-zA-Z]/.test(code);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if expression starts with a JSX element
|
|
18
|
+
*/
|
|
19
|
+
function startsWithJSX(code) {
|
|
20
|
+
const trimmed = code.trim();
|
|
21
|
+
return /^<[a-zA-Z]/.test(trimmed) || /^<>/.test(trimmed);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Classify expression output type
|
|
25
|
+
*
|
|
26
|
+
* @param code - The expression code to classify
|
|
27
|
+
* @returns Classification result with metadata
|
|
28
|
+
*/
|
|
29
|
+
export function classifyExpression(code) {
|
|
30
|
+
const trimmed = code.trim();
|
|
31
|
+
// Check for .map() expressions with JSX body
|
|
32
|
+
const mapMatch = parseMapExpression(trimmed);
|
|
33
|
+
if (mapMatch) {
|
|
34
|
+
return {
|
|
35
|
+
type: 'loop',
|
|
36
|
+
loopSource: mapMatch.source,
|
|
37
|
+
loopItemVar: mapMatch.itemVar,
|
|
38
|
+
loopIndexVar: mapMatch.indexVar,
|
|
39
|
+
loopBody: mapMatch.body
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Check for ternary with JSX branches: condition ? <A /> : <B />
|
|
43
|
+
const ternaryMatch = parseTernaryExpression(trimmed);
|
|
44
|
+
if (ternaryMatch && (containsJSX(ternaryMatch.consequent) || containsJSX(ternaryMatch.alternate))) {
|
|
45
|
+
return {
|
|
46
|
+
type: 'conditional',
|
|
47
|
+
condition: ternaryMatch.condition,
|
|
48
|
+
consequent: ternaryMatch.consequent,
|
|
49
|
+
alternate: ternaryMatch.alternate
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Check for logical AND with JSX: condition && <A />
|
|
53
|
+
const logicalAndMatch = parseLogicalAndExpression(trimmed);
|
|
54
|
+
if (logicalAndMatch && containsJSX(logicalAndMatch.fragment)) {
|
|
55
|
+
return {
|
|
56
|
+
type: 'optional',
|
|
57
|
+
optionalCondition: logicalAndMatch.condition,
|
|
58
|
+
optionalFragment: logicalAndMatch.fragment
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// All other expressions (including inline JSX like {<span>text</span>})
|
|
62
|
+
// are treated as primitive and handled by the existing expression transformer
|
|
63
|
+
// which converts JSX to __zenith.h() calls at runtime
|
|
64
|
+
return { type: 'primitive' };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parse .map() expression
|
|
68
|
+
*
|
|
69
|
+
* Matches:
|
|
70
|
+
* - source.map(item => body)
|
|
71
|
+
* - source.map((item, index) => body)
|
|
72
|
+
*/
|
|
73
|
+
function parseMapExpression(code) {
|
|
74
|
+
// Pattern: source.map(item => body)
|
|
75
|
+
// Pattern: source.map((item) => body)
|
|
76
|
+
// Pattern: source.map((item, index) => body)
|
|
77
|
+
// Find .map(
|
|
78
|
+
const mapIndex = code.indexOf('.map(');
|
|
79
|
+
if (mapIndex === -1)
|
|
80
|
+
return null;
|
|
81
|
+
const source = code.slice(0, mapIndex).trim();
|
|
82
|
+
if (!source)
|
|
83
|
+
return null;
|
|
84
|
+
// Find the arrow function parameters
|
|
85
|
+
let afterMap = code.slice(mapIndex + 5); // after ".map("
|
|
86
|
+
// Skip whitespace
|
|
87
|
+
afterMap = afterMap.trimStart();
|
|
88
|
+
// Check for parenthesized params: (item) or (item, index)
|
|
89
|
+
let itemVar;
|
|
90
|
+
let indexVar;
|
|
91
|
+
let bodyStart;
|
|
92
|
+
if (afterMap.startsWith('(')) {
|
|
93
|
+
// Find closing paren
|
|
94
|
+
const closeParenIndex = findBalancedParen(afterMap, 0);
|
|
95
|
+
if (closeParenIndex === -1)
|
|
96
|
+
return null;
|
|
97
|
+
const paramsStr = afterMap.slice(1, closeParenIndex);
|
|
98
|
+
const params = paramsStr.split(',').map(p => p.trim());
|
|
99
|
+
itemVar = params[0] || '';
|
|
100
|
+
indexVar = params[1];
|
|
101
|
+
// Find arrow
|
|
102
|
+
const afterParams = afterMap.slice(closeParenIndex + 1).trimStart();
|
|
103
|
+
if (!afterParams.startsWith('=>'))
|
|
104
|
+
return null;
|
|
105
|
+
bodyStart = mapIndex + 5 + (afterMap.length - afterParams.length) + 2;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Simple param: item => body
|
|
109
|
+
const arrowIndex = afterMap.indexOf('=>');
|
|
110
|
+
if (arrowIndex === -1)
|
|
111
|
+
return null;
|
|
112
|
+
itemVar = afterMap.slice(0, arrowIndex).trim();
|
|
113
|
+
bodyStart = mapIndex + 5 + arrowIndex + 2;
|
|
114
|
+
}
|
|
115
|
+
if (!itemVar)
|
|
116
|
+
return null;
|
|
117
|
+
// Extract body (everything after => until the closing paren of .map())
|
|
118
|
+
let body = code.slice(bodyStart).trim();
|
|
119
|
+
// Remove trailing ) from .map()
|
|
120
|
+
if (body.endsWith(')')) {
|
|
121
|
+
body = body.slice(0, -1).trim();
|
|
122
|
+
}
|
|
123
|
+
// Check if body contains JSX
|
|
124
|
+
if (!containsJSX(body))
|
|
125
|
+
return null;
|
|
126
|
+
return { source, itemVar, indexVar, body };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Find matching closing parenthesis
|
|
130
|
+
*/
|
|
131
|
+
function findBalancedParen(code, startIndex) {
|
|
132
|
+
if (code[startIndex] !== '(')
|
|
133
|
+
return -1;
|
|
134
|
+
let depth = 1;
|
|
135
|
+
let i = startIndex + 1;
|
|
136
|
+
while (i < code.length && depth > 0) {
|
|
137
|
+
if (code[i] === '(')
|
|
138
|
+
depth++;
|
|
139
|
+
else if (code[i] === ')')
|
|
140
|
+
depth--;
|
|
141
|
+
i++;
|
|
142
|
+
}
|
|
143
|
+
return depth === 0 ? i - 1 : -1;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Parse ternary expression
|
|
147
|
+
*
|
|
148
|
+
* Matches: condition ? consequent : alternate
|
|
149
|
+
*/
|
|
150
|
+
function parseTernaryExpression(code) {
|
|
151
|
+
// Find the ? that's not inside JSX or strings
|
|
152
|
+
const questionIndex = findTernaryOperator(code);
|
|
153
|
+
if (questionIndex === -1)
|
|
154
|
+
return null;
|
|
155
|
+
const condition = code.slice(0, questionIndex).trim();
|
|
156
|
+
const afterQuestion = code.slice(questionIndex + 1);
|
|
157
|
+
// Find the : that matches this ternary
|
|
158
|
+
const colonIndex = findTernaryColon(afterQuestion);
|
|
159
|
+
if (colonIndex === -1)
|
|
160
|
+
return null;
|
|
161
|
+
const consequent = afterQuestion.slice(0, colonIndex).trim();
|
|
162
|
+
const alternate = afterQuestion.slice(colonIndex + 1).trim();
|
|
163
|
+
if (!condition || !consequent || !alternate)
|
|
164
|
+
return null;
|
|
165
|
+
return { condition, consequent, alternate };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Find ternary ? operator (not inside JSX or nested ternaries)
|
|
169
|
+
*/
|
|
170
|
+
function findTernaryOperator(code) {
|
|
171
|
+
let depth = 0;
|
|
172
|
+
let inString = false;
|
|
173
|
+
let stringChar = '';
|
|
174
|
+
let inTemplate = false;
|
|
175
|
+
let jsxDepth = 0;
|
|
176
|
+
for (let i = 0; i < code.length; i++) {
|
|
177
|
+
const char = code[i];
|
|
178
|
+
const prevChar = i > 0 ? code[i - 1] : '';
|
|
179
|
+
// Handle escape
|
|
180
|
+
if (prevChar === '\\')
|
|
181
|
+
continue;
|
|
182
|
+
// Handle strings
|
|
183
|
+
if (!inString && !inTemplate && (char === '"' || char === "'")) {
|
|
184
|
+
inString = true;
|
|
185
|
+
stringChar = char;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (inString && char === stringChar) {
|
|
189
|
+
inString = false;
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
// Handle template literals
|
|
193
|
+
if (!inString && !inTemplate && char === '`') {
|
|
194
|
+
inTemplate = true;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (inTemplate && char === '`') {
|
|
198
|
+
inTemplate = false;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (inString || inTemplate)
|
|
202
|
+
continue;
|
|
203
|
+
// Track JSX depth
|
|
204
|
+
if (char === '<' && /[a-zA-Z>]/.test(code[i + 1] || '')) {
|
|
205
|
+
jsxDepth++;
|
|
206
|
+
}
|
|
207
|
+
if (char === '>' && prevChar === '/') {
|
|
208
|
+
jsxDepth = Math.max(0, jsxDepth - 1);
|
|
209
|
+
}
|
|
210
|
+
if (char === '/' && code[i + 1] === '>') {
|
|
211
|
+
// self-closing tag, depth handled when we see >
|
|
212
|
+
}
|
|
213
|
+
if (char === '<' && code[i + 1] === '/') {
|
|
214
|
+
// closing tag coming
|
|
215
|
+
}
|
|
216
|
+
if (char === '>' && jsxDepth > 0 && prevChar !== '/' && code.slice(0, i).includes('</')) {
|
|
217
|
+
jsxDepth = Math.max(0, jsxDepth - 1);
|
|
218
|
+
}
|
|
219
|
+
// Track parens
|
|
220
|
+
if (char === '(' || char === '{' || char === '[')
|
|
221
|
+
depth++;
|
|
222
|
+
if (char === ')' || char === '}' || char === ']')
|
|
223
|
+
depth--;
|
|
224
|
+
// Found ternary operator at top level
|
|
225
|
+
if (char === '?' && depth === 0 && jsxDepth === 0) {
|
|
226
|
+
return i;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return -1;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Find ternary : operator (matching the ?)
|
|
233
|
+
*/
|
|
234
|
+
function findTernaryColon(code) {
|
|
235
|
+
let depth = 0;
|
|
236
|
+
let ternaryDepth = 0;
|
|
237
|
+
let inString = false;
|
|
238
|
+
let stringChar = '';
|
|
239
|
+
let inTemplate = false;
|
|
240
|
+
let jsxDepth = 0;
|
|
241
|
+
for (let i = 0; i < code.length; i++) {
|
|
242
|
+
const char = code[i];
|
|
243
|
+
const prevChar = i > 0 ? code[i - 1] : '';
|
|
244
|
+
// Handle escape
|
|
245
|
+
if (prevChar === '\\')
|
|
246
|
+
continue;
|
|
247
|
+
// Handle strings
|
|
248
|
+
if (!inString && !inTemplate && (char === '"' || char === "'")) {
|
|
249
|
+
inString = true;
|
|
250
|
+
stringChar = char;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (inString && char === stringChar) {
|
|
254
|
+
inString = false;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
// Handle template literals
|
|
258
|
+
if (!inString && !inTemplate && char === '`') {
|
|
259
|
+
inTemplate = true;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (inTemplate && char === '`') {
|
|
263
|
+
inTemplate = false;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (inString || inTemplate)
|
|
267
|
+
continue;
|
|
268
|
+
// Track JSX depth (simplified)
|
|
269
|
+
if (char === '<' && /[a-zA-Z>]/.test(code[i + 1] || '')) {
|
|
270
|
+
jsxDepth++;
|
|
271
|
+
}
|
|
272
|
+
if (char === '>' && (prevChar === '/' || jsxDepth > 0)) {
|
|
273
|
+
jsxDepth = Math.max(0, jsxDepth - 1);
|
|
274
|
+
}
|
|
275
|
+
// Track parens
|
|
276
|
+
if (char === '(' || char === '{' || char === '[')
|
|
277
|
+
depth++;
|
|
278
|
+
if (char === ')' || char === '}' || char === ']')
|
|
279
|
+
depth--;
|
|
280
|
+
// Track nested ternaries
|
|
281
|
+
if (char === '?')
|
|
282
|
+
ternaryDepth++;
|
|
283
|
+
if (char === ':' && ternaryDepth > 0) {
|
|
284
|
+
ternaryDepth--;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
// Found matching colon at top level
|
|
288
|
+
if (char === ':' && depth === 0 && ternaryDepth === 0 && jsxDepth === 0) {
|
|
289
|
+
return i;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return -1;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Parse logical AND expression
|
|
296
|
+
*
|
|
297
|
+
* Matches: condition && fragment
|
|
298
|
+
*/
|
|
299
|
+
function parseLogicalAndExpression(code) {
|
|
300
|
+
// Find && at top level
|
|
301
|
+
let depth = 0;
|
|
302
|
+
let inString = false;
|
|
303
|
+
let stringChar = '';
|
|
304
|
+
let inTemplate = false;
|
|
305
|
+
for (let i = 0; i < code.length - 1; i++) {
|
|
306
|
+
const char = code[i];
|
|
307
|
+
const nextChar = code[i + 1];
|
|
308
|
+
const prevChar = i > 0 ? code[i - 1] : '';
|
|
309
|
+
// Handle escape
|
|
310
|
+
if (prevChar === '\\')
|
|
311
|
+
continue;
|
|
312
|
+
// Handle strings
|
|
313
|
+
if (!inString && !inTemplate && (char === '"' || char === "'")) {
|
|
314
|
+
inString = true;
|
|
315
|
+
stringChar = char;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (inString && char === stringChar) {
|
|
319
|
+
inString = false;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
// Handle template literals
|
|
323
|
+
if (!inString && !inTemplate && char === '`') {
|
|
324
|
+
inTemplate = true;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (inTemplate && char === '`') {
|
|
328
|
+
inTemplate = false;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (inString || inTemplate)
|
|
332
|
+
continue;
|
|
333
|
+
// Track parens
|
|
334
|
+
if (char === '(' || char === '{' || char === '[')
|
|
335
|
+
depth++;
|
|
336
|
+
if (char === ')' || char === '}' || char === ']')
|
|
337
|
+
depth--;
|
|
338
|
+
// Found && at top level
|
|
339
|
+
if (char === '&' && nextChar === '&' && depth === 0) {
|
|
340
|
+
const condition = code.slice(0, i).trim();
|
|
341
|
+
const fragment = code.slice(i + 2).trim();
|
|
342
|
+
if (condition && fragment) {
|
|
343
|
+
return { condition, fragment };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Check if an expression type requires structural lowering
|
|
351
|
+
*/
|
|
352
|
+
export function requiresStructuralLowering(type) {
|
|
353
|
+
return type === 'conditional' || type === 'optional' || type === 'loop' || type === 'fragment';
|
|
354
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ZenIR } from '../ir/types';
|
|
2
|
+
import type { ComponentMetadata } from '../discovery/componentDiscovery';
|
|
3
|
+
/**
|
|
4
|
+
* Inline all components in a ZenIR.
|
|
5
|
+
*
|
|
6
|
+
* This is Stage 2 of the compiler:
|
|
7
|
+
* - Expands <Component /> tags into their templates.
|
|
8
|
+
* - Renames local symbols in component scripts and expressions to avoid collisions.
|
|
9
|
+
* - Merges component scripts directly into the main page script.
|
|
10
|
+
* - Promotes component expressions to the page-level expression registry.
|
|
11
|
+
*
|
|
12
|
+
* NATIVE IMPLEMENTATION:
|
|
13
|
+
* Delegates to the Rust native compiler for performance and correctness.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveComponentsInIR(ir: ZenIR, components: Map<string, ComponentMetadata>): ZenIR;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveComponentsNative } from '../../native/compiler-native';
|
|
2
|
+
/**
|
|
3
|
+
* Inline all components in a ZenIR.
|
|
4
|
+
*
|
|
5
|
+
* This is Stage 2 of the compiler:
|
|
6
|
+
* - Expands <Component /> tags into their templates.
|
|
7
|
+
* - Renames local symbols in component scripts and expressions to avoid collisions.
|
|
8
|
+
* - Merges component scripts directly into the main page script.
|
|
9
|
+
* - Promotes component expressions to the page-level expression registry.
|
|
10
|
+
*
|
|
11
|
+
* NATIVE IMPLEMENTATION:
|
|
12
|
+
* Delegates to the Rust native compiler for performance and correctness.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveComponentsInIR(ir, components) {
|
|
15
|
+
console.error(`[ZenithDebug] resolveComponentsInIR called with ${components.size} components`);
|
|
16
|
+
for (const [name, meta] of components) {
|
|
17
|
+
console.error(`[ZenithDebug] Component '${name}': script=${meta.script ? meta.script.length : 'null'} bytes`);
|
|
18
|
+
}
|
|
19
|
+
const irJson = JSON.stringify(ir);
|
|
20
|
+
// Convert Map to record for JSON serialization
|
|
21
|
+
const componentsRecord = {};
|
|
22
|
+
for (const [key, value] of components) {
|
|
23
|
+
componentsRecord[key] = value;
|
|
24
|
+
}
|
|
25
|
+
const componentsJson = JSON.stringify(componentsRecord);
|
|
26
|
+
console.error(`[ZenithDebug] Calling resolveComponentsNative...`);
|
|
27
|
+
const resolvedJson = resolveComponentsNative(irJson, componentsJson);
|
|
28
|
+
console.error(`[ZenithDebug] resolveComponentsNative returned ${resolvedJson.length} bytes`);
|
|
29
|
+
return JSON.parse(resolvedJson);
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expression JSX Transformer
|
|
3
|
+
*
|
|
4
|
+
* Transforms JSX-like tags inside Zenith expressions into __zenith.h() calls.
|
|
5
|
+
* This allows Zenith to support JSX semantics without a full JSX compiler like Babel.
|
|
6
|
+
*
|
|
7
|
+
* Handles:
|
|
8
|
+
* - Multi-line JSX expressions
|
|
9
|
+
* - Nested elements
|
|
10
|
+
* - Complex event handlers like onclick={() => fn(item)}
|
|
11
|
+
* - Expression attributes {expr}
|
|
12
|
+
* - Text interpolation {item.title}
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Main transformer function
|
|
16
|
+
*
|
|
17
|
+
* Transforms JSX-like tags inside Zenith expressions into __zenith.h() calls.
|
|
18
|
+
*/
|
|
19
|
+
export declare function transformExpressionJSX(code: string): string;
|