@zenithbuild/core 0.4.6 → 0.5.0-beta.2.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.
Files changed (109) hide show
  1. package/CORE_CONTRACT.md +143 -0
  2. package/README.md +11 -31
  3. package/bin/zenith.js +68 -0
  4. package/package.json +40 -52
  5. package/src/config.js +134 -0
  6. package/src/core-template.js +30 -0
  7. package/src/errors.js +54 -0
  8. package/src/guards.js +61 -0
  9. package/src/hash.js +52 -0
  10. package/src/index.js +26 -0
  11. package/src/ir/index.js +1 -0
  12. package/src/order.js +69 -0
  13. package/src/path.js +131 -0
  14. package/src/schema.js +28 -0
  15. package/src/version.js +67 -0
  16. package/bin/zen-build.ts +0 -2
  17. package/bin/zen-dev.ts +0 -2
  18. package/bin/zen-preview.ts +0 -2
  19. package/bin/zenith.ts +0 -2
  20. package/cli/commands/add.ts +0 -37
  21. package/cli/commands/build.ts +0 -37
  22. package/cli/commands/create.ts +0 -702
  23. package/cli/commands/dev.ts +0 -335
  24. package/cli/commands/index.ts +0 -112
  25. package/cli/commands/preview.ts +0 -62
  26. package/cli/commands/remove.ts +0 -33
  27. package/cli/index.ts +0 -10
  28. package/cli/main.ts +0 -101
  29. package/cli/utils/branding.ts +0 -178
  30. package/cli/utils/content.ts +0 -112
  31. package/cli/utils/logger.ts +0 -46
  32. package/cli/utils/plugin-manager.ts +0 -114
  33. package/cli/utils/project.ts +0 -77
  34. package/compiler/README.md +0 -380
  35. package/compiler/build-analyzer.ts +0 -122
  36. package/compiler/css/index.ts +0 -317
  37. package/compiler/discovery/componentDiscovery.ts +0 -174
  38. package/compiler/discovery/layouts.ts +0 -61
  39. package/compiler/errors/compilerError.ts +0 -56
  40. package/compiler/finalize/finalizeOutput.ts +0 -192
  41. package/compiler/finalize/generateFinalBundle.ts +0 -82
  42. package/compiler/index.ts +0 -81
  43. package/compiler/ir/types.ts +0 -150
  44. package/compiler/output/types.ts +0 -34
  45. package/compiler/parse/detectMapExpressions.ts +0 -102
  46. package/compiler/parse/parseScript.ts +0 -46
  47. package/compiler/parse/parseTemplate.ts +0 -591
  48. package/compiler/parse/parseZenFile.ts +0 -66
  49. package/compiler/parse/scriptAnalysis.ts +0 -83
  50. package/compiler/parse/trackLoopContext.ts +0 -82
  51. package/compiler/runtime/dataExposure.ts +0 -317
  52. package/compiler/runtime/generateDOM.ts +0 -246
  53. package/compiler/runtime/generateHydrationBundle.ts +0 -407
  54. package/compiler/runtime/hydration.ts +0 -309
  55. package/compiler/runtime/navigation.ts +0 -432
  56. package/compiler/runtime/thinRuntime.ts +0 -160
  57. package/compiler/runtime/transformIR.ts +0 -343
  58. package/compiler/runtime/wrapExpression.ts +0 -95
  59. package/compiler/runtime/wrapExpressionWithLoop.ts +0 -83
  60. package/compiler/spa-build.ts +0 -917
  61. package/compiler/ssg-build.ts +0 -422
  62. package/compiler/test/validate-test.ts +0 -104
  63. package/compiler/transform/classifyExpression.ts +0 -444
  64. package/compiler/transform/componentResolver.ts +0 -289
  65. package/compiler/transform/expressionTransformer.ts +0 -385
  66. package/compiler/transform/fragmentLowering.ts +0 -634
  67. package/compiler/transform/generateBindings.ts +0 -47
  68. package/compiler/transform/generateHTML.ts +0 -28
  69. package/compiler/transform/layoutProcessor.ts +0 -132
  70. package/compiler/transform/slotResolver.ts +0 -292
  71. package/compiler/transform/transformNode.ts +0 -126
  72. package/compiler/transform/transformTemplate.ts +0 -38
  73. package/compiler/validate/invariants.ts +0 -292
  74. package/compiler/validate/validateExpressions.ts +0 -168
  75. package/core/config/index.ts +0 -16
  76. package/core/config/loader.ts +0 -69
  77. package/core/config/types.ts +0 -89
  78. package/core/index.ts +0 -135
  79. package/core/lifecycle/index.ts +0 -49
  80. package/core/lifecycle/zen-mount.ts +0 -182
  81. package/core/lifecycle/zen-unmount.ts +0 -88
  82. package/core/plugins/index.ts +0 -7
  83. package/core/plugins/registry.ts +0 -81
  84. package/core/reactivity/index.ts +0 -54
  85. package/core/reactivity/tracking.ts +0 -167
  86. package/core/reactivity/zen-batch.ts +0 -57
  87. package/core/reactivity/zen-effect.ts +0 -139
  88. package/core/reactivity/zen-memo.ts +0 -146
  89. package/core/reactivity/zen-ref.ts +0 -52
  90. package/core/reactivity/zen-signal.ts +0 -121
  91. package/core/reactivity/zen-state.ts +0 -180
  92. package/core/reactivity/zen-untrack.ts +0 -44
  93. package/dist/cli.js +0 -11653
  94. package/dist/zen-build.js +0 -15388
  95. package/dist/zen-dev.js +0 -15388
  96. package/dist/zen-preview.js +0 -15388
  97. package/dist/zenith.js +0 -15388
  98. package/router/index.ts +0 -76
  99. package/router/manifest.ts +0 -314
  100. package/router/navigation/ZenLink.zen +0 -231
  101. package/router/navigation/index.ts +0 -78
  102. package/router/navigation/zen-link.ts +0 -584
  103. package/router/runtime.ts +0 -458
  104. package/router/types.ts +0 -168
  105. package/runtime/build.ts +0 -17
  106. package/runtime/bundle-generator.ts +0 -800
  107. package/runtime/client-runtime.ts +0 -549
  108. package/runtime/serve.ts +0 -93
  109. package/tsconfig.json +0 -28
@@ -1,343 +0,0 @@
1
- /**
2
- * Transform IR to Runtime Code
3
- *
4
- * Phase 4: Transform ZenIR into runtime-ready JavaScript code with full reactivity
5
- */
6
-
7
- import type { ZenIR } from '../ir/types'
8
- import { generateExpressionWrappers } from './wrapExpression'
9
- import { generateDOMFunction } from './generateDOM'
10
- import { generateHydrationRuntime, generateExpressionRegistry } from './generateHydrationBundle'
11
- import { analyzeAllExpressions } from './dataExposure'
12
- import { generateNavigationRuntime } from './navigation'
13
- import { extractStateDeclarations, extractProps, transformStateDeclarations } from '../parse/scriptAnalysis'
14
-
15
- export interface RuntimeCode {
16
- expressions: string // Expression wrapper functions
17
- render: string // renderDynamicPage function (legacy, for reference)
18
- hydration: string // Phase 5 hydration runtime code
19
- styles: string // Style injection code
20
- script: string // Transformed script code
21
- stateInit: string // State initialization code
22
- bundle: string // Complete runtime bundle (expressions + hydration + helpers)
23
- }
24
-
25
- /**
26
- * Transform ZenIR into runtime JavaScript code
27
- */
28
- export function transformIR(ir: ZenIR): RuntimeCode {
29
- // Phase 6: Analyze expression dependencies for explicit data exposure
30
- const expressionDependencies = analyzeAllExpressions(
31
- ir.template.expressions,
32
- ir.filePath,
33
- [], // declaredLoaderProps
34
- ir.script?.attributes['props'] ? ir.script.attributes['props'].split(',') : [], // declaredProps
35
- [] // declaredStores
36
- )
37
-
38
- // Generate expression wrappers with dependencies
39
- const expressions = generateExpressionWrappers(ir.template.expressions, expressionDependencies)
40
-
41
- // Generate DOM creation code
42
- const renderFunction = generateDOMFunction(
43
- ir.template.nodes,
44
- ir.template.expressions,
45
- 'renderDynamicPage'
46
- )
47
-
48
- // Generate hydrate function (legacy, for reference)
49
- const hydrateFunction = generateHydrateFunction()
50
-
51
- // Generate Phase 5 hydration runtime
52
- const hydrationRuntime = generateHydrationRuntime()
53
-
54
- // Generate Phase 7 navigation runtime
55
- const navigationRuntime = generateNavigationRuntime()
56
-
57
- // Generate expression registry initialization
58
- const expressionRegistry = generateExpressionRegistry(ir.template.expressions)
59
-
60
- // Generate style injection code
61
- const stylesCode = generateStyleInjection(ir.styles)
62
-
63
- // Extract state and prop declarations
64
- const scriptContent = ir.script?.raw || ''
65
- const stateDeclarations = extractStateDeclarations(scriptContent)
66
- const propKeys = Object.keys(ir.script?.attributes || {}).filter(k => k !== 'setup' && k !== 'lang')
67
- const propDeclarations = extractProps(scriptContent)
68
- const stateInitCode = generateStateInitialization(stateDeclarations, [...propDeclarations, ...propKeys])
69
-
70
- // Transform script (remove state and prop declarations, they're handled by runtime)
71
- const scriptCode = transformStateDeclarations(scriptContent)
72
-
73
- // Generate complete runtime bundle
74
- const bundle = generateRuntimeBundle({
75
- expressions,
76
- expressionRegistry,
77
- hydrationRuntime,
78
- navigationRuntime,
79
- stylesCode,
80
- scriptCode,
81
- stateInitCode
82
- })
83
-
84
- return {
85
- expressions,
86
- render: renderFunction,
87
- hydration: hydrationRuntime,
88
- styles: stylesCode,
89
- script: scriptCode,
90
- stateInit: stateInitCode,
91
- bundle
92
- }
93
- }
94
-
95
- /**
96
- * Generate complete runtime bundle
97
- */
98
- function generateRuntimeBundle(parts: {
99
- expressions: string
100
- expressionRegistry: string
101
- hydrationRuntime: string
102
- navigationRuntime: string
103
- stylesCode: string
104
- scriptCode: string
105
- stateInitCode: string
106
- }): string {
107
- // Extract function declarations from script code to register on window
108
- const functionRegistrations = extractFunctionRegistrations(parts.scriptCode)
109
-
110
- return `// Zenith Runtime Bundle (Phase 5)
111
- // Generated at compile time - no .zen parsing in browser
112
-
113
- ${parts.expressions}
114
-
115
- ${parts.expressionRegistry}
116
-
117
- ${parts.hydrationRuntime}
118
-
119
- ${parts.navigationRuntime}
120
-
121
- ${parts.stylesCode ? `// Style injection
122
- ${parts.stylesCode}` : ''}
123
-
124
- // User script code - executed first to define variables needed by state initialization
125
- ${parts.scriptCode ? parts.scriptCode : ''}
126
-
127
- ${functionRegistrations}
128
-
129
- ${parts.stateInitCode ? `// State initialization
130
- ${parts.stateInitCode}` : ''}
131
-
132
- // Export hydration functions
133
- if (typeof window !== 'undefined') {
134
- window.zenithHydrate = window.__zenith_hydrate || function(state, container) {
135
- console.warn('[Zenith] Hydration runtime not loaded');
136
- };
137
- window.zenithUpdate = window.__zenith_update || function(state) {
138
- console.warn('[Zenith] Update runtime not loaded');
139
- };
140
- window.zenithBindEvents = window.__zenith_bindEvents || function(container) {
141
- console.warn('[Zenith] Event binding runtime not loaded');
142
- };
143
- window.zenithCleanup = window.__zenith_cleanup || function(container) {
144
- console.warn('[Zenith] Cleanup runtime not loaded');
145
- };
146
- }
147
-
148
- // Auto-hydrate on page mount
149
- (function() {
150
- 'use strict';
151
-
152
- function autoHydrate() {
153
- // Initialize state object
154
- const state = window.__ZENITH_STATE__ || {};
155
-
156
- // Run state initialization if defined
157
- if (typeof initializeState === 'function') {
158
- initializeState(state);
159
- }
160
-
161
- // Store state globally
162
- window.__ZENITH_STATE__ = state;
163
-
164
- // Expose state variables on window with reactive getters/setters
165
- // This allows user functions (like increment) to access state variables directly
166
- for (const key in state) {
167
- if (state.hasOwnProperty(key) && !window.hasOwnProperty(key)) {
168
- Object.defineProperty(window, key, {
169
- get: function() { return window.__ZENITH_STATE__[key]; },
170
- set: function(value) {
171
- window.__ZENITH_STATE__[key] = value;
172
- // Trigger reactive update
173
- if (window.__zenith_update) {
174
- window.__zenith_update(window.__ZENITH_STATE__);
175
- }
176
- },
177
- configurable: true
178
- });
179
- }
180
- }
181
-
182
- // Inject styles if defined
183
- if (typeof injectStyles === 'function') {
184
- injectStyles();
185
- }
186
-
187
- // Get the router outlet or body
188
- const container = document.querySelector('#app') || document.body;
189
-
190
- // Hydrate with state
191
- if (window.__zenith_hydrate) {
192
- window.__zenith_hydrate(state, {}, {}, {}, container);
193
- }
194
- }
195
-
196
- // Run on DOM ready
197
- if (document.readyState === 'loading') {
198
- document.addEventListener('DOMContentLoaded', autoHydrate);
199
- } else {
200
- // DOM already loaded, hydrate immediately
201
- autoHydrate();
202
- }
203
- })();
204
- `
205
- }
206
-
207
- /**
208
- * Extract function declarations and generate window registration code
209
- */
210
- function extractFunctionRegistrations(scriptCode: string): string {
211
- if (!scriptCode) return ''
212
-
213
- // Match function declarations: function name(...) { ... }
214
- const functionPattern = /function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g
215
- const functionNames: string[] = []
216
- let match
217
-
218
- while ((match = functionPattern.exec(scriptCode)) !== null) {
219
- if (match[1]) {
220
- functionNames.push(match[1])
221
- }
222
- }
223
-
224
- if (functionNames.length === 0) {
225
- return ''
226
- }
227
-
228
- // Generate window registration for each function
229
- const registrations = functionNames.map(name =>
230
- ` if (typeof ${name} === 'function') window.${name} = ${name};`
231
- ).join('\n')
232
-
233
- return `// Register functions on window for event handlers\n${registrations}`
234
- }
235
-
236
- /**
237
- * Generate hydrate function that mounts the DOM with reactivity
238
- */
239
- function generateHydrateFunction(): string {
240
- return `function hydrate(root, state) {
241
- if (!root) {
242
- // SSR fallback - return initial HTML string
243
- console.warn('[Zenith] hydrate called without root element - SSR mode');
244
- return '';
245
- }
246
-
247
- // Clear root
248
- root.innerHTML = '';
249
-
250
- // Render template
251
- const dom = renderDynamicPage(state);
252
-
253
- // Append to root
254
- if (dom instanceof DocumentFragment) {
255
- root.appendChild(dom);
256
- } else if (dom instanceof Node) {
257
- root.appendChild(dom);
258
- }
259
-
260
- // Bind event handlers
261
- bindEventHandlers(root, state);
262
-
263
- // Set up reactive updates (if state is reactive)
264
- setupReactiveUpdates(root, state);
265
-
266
- return root;
267
- }
268
-
269
- function bindEventHandlers(root, state) {
270
- // Find all elements with data-zen-* event attributes
271
- const eventTypes = ['click', 'change', 'input', 'submit', 'focus', 'blur'];
272
-
273
- for (const eventType of eventTypes) {
274
- const elements = root.querySelectorAll(\`[data-zen-\${eventType}]\`);
275
- for (const el of elements) {
276
- const handlerName = el.getAttribute(\`data-zen-\${eventType}\`);
277
- if (handlerName && typeof window[handlerName] === 'function') {
278
- el.addEventListener(eventType, (e) => {
279
- window[handlerName](e, el);
280
- });
281
- }
282
- }
283
- }
284
- }
285
-
286
- function setupReactiveUpdates(root, state) {
287
- // For now, reactive updates are handled by the existing binding system
288
- // This is a placeholder for future reactive DOM updates
289
- // The existing runtime handles reactivity via state property setters
290
- }`
291
- }
292
-
293
- /**
294
- * Generate style injection code
295
- */
296
- function generateStyleInjection(styles: Array<{ raw: string }>): string {
297
- if (styles.length === 0) {
298
- return ''
299
- }
300
-
301
- const styleBlocks = styles.map((style, index) => {
302
- const escapedStyle = style.raw.replace(/`/g, '\\`').replace(/\$/g, '\\$')
303
- return `
304
- const style${index} = document.createElement('style');
305
- style${index}.textContent = \`${escapedStyle}\`;
306
- document.head.appendChild(style${index});`
307
- }).join('')
308
-
309
- return `function injectStyles() {${styleBlocks}
310
- }`
311
- }
312
-
313
- /**
314
- * Generate state initialization code
315
- * In Phase 9: Also handles props passing
316
- */
317
- function generateStateInitialization(stateDeclarations: Map<string, string>, propDeclarations: string[]): string {
318
- const stateInit = Array.from(stateDeclarations.entries()).map(([name, value]) => {
319
- return `
320
- // Initialize state: ${name}
321
- if (typeof state.${name} === 'undefined') {
322
- state.${name} = ${value};
323
- }`
324
- }).join('')
325
-
326
- const legacyPropInit = propDeclarations.includes('props') ? `
327
- // Initialize props object (legacy)
328
- if (typeof window.__ZEN_PROPS__ !== 'undefined') {
329
- state.props = window.__ZEN_PROPS__;
330
- }` : ''
331
-
332
- const individualPropInit = propDeclarations.filter(p => p !== 'props').map(prop => `
333
- // Initialize prop: ${prop}
334
- if (typeof state.${prop} === 'undefined' && typeof window.__ZEN_PROPS__ !== 'undefined' && typeof window.__ZEN_PROPS__.${prop} !== 'undefined') {
335
- state.${prop} = window.__ZEN_PROPS__.${prop};
336
- }`).join('')
337
-
338
- return `function initializeState(state) {${stateInit}${legacyPropInit}${individualPropInit}
339
- }`
340
- }
341
-
342
- // Note: transformScript is now handled by transformStateDeclarations in legacy/parse.ts
343
-
@@ -1,95 +0,0 @@
1
- /**
2
- * Expression Wrapper
3
- *
4
- * Wraps extracted expressions into runtime functions with explicit data arguments
5
- *
6
- * Phase 6: Expressions now accept explicit loaderData, props, stores arguments
7
- * instead of relying on implicit globals
8
- */
9
-
10
- import type { ExpressionIR, LoopContext } from '../ir/types'
11
- import type { ExpressionDataDependencies } from './dataExposure'
12
- import { generateExplicitExpressionWrapper } from './dataExposure'
13
- import { wrapExpressionWithLoopContext } from './wrapExpressionWithLoop'
14
-
15
- import { transformExpressionJSX } from '../transform/expressionTransformer'
16
-
17
- /**
18
- * Wrap an expression into a runtime function with explicit data arguments
19
- *
20
- * Phase 6: Supports explicit loaderData, props, stores arguments
21
- * Phase 7: Supports loop context for expressions inside map iterations
22
- */
23
- export function wrapExpression(
24
- expr: ExpressionIR,
25
- dependencies?: ExpressionDataDependencies,
26
- loopContext?: LoopContext // Phase 7: Loop context for map expressions
27
- ): string {
28
- const { id, code } = expr
29
-
30
- // Phase 7: If loop context is provided, use loop-aware wrapper
31
- if (loopContext && loopContext.variables.length > 0) {
32
- return wrapExpressionWithLoopContext(expr, loopContext, dependencies)
33
- }
34
-
35
- // If dependencies are provided, use explicit wrapper (Phase 6)
36
- if (dependencies) {
37
- return generateExplicitExpressionWrapper(expr, dependencies)
38
- }
39
-
40
- // Fallback to legacy wrapper (backwards compatibility)
41
- // Transform JSX-like tags inside expression code
42
- const transformedCode = transformExpressionJSX(code)
43
- // Escape the code for use in a single-line comment (replace newlines with spaces)
44
- const commentCode = code.replace(/[\r\n]+/g, ' ').replace(/\s+/g, ' ').substring(0, 100)
45
- const jsonEscapedCode = JSON.stringify(code)
46
-
47
- return `
48
- // Expression: ${commentCode}${code.length > 100 ? '...' : ''}
49
- const ${id} = (state) => {
50
- try {
51
- // Expose zenith helpers for JSX and content
52
- const __zenith = window.__zenith || {};
53
- const zenCollection = __zenith.zenCollection || ((name) => ({ get: () => [] }));
54
-
55
- with (state) {
56
- return ${transformedCode};
57
- }
58
- } catch (e) {
59
- console.warn('[Zenith] Expression evaluation error:', ${jsonEscapedCode}, e);
60
- return undefined;
61
- }
62
- };`
63
- }
64
-
65
- /**
66
- * Generate all expression wrappers for a set of expressions
67
- *
68
- * Phase 6: Accepts dependencies array for explicit data exposure
69
- * Phase 7: Accepts loop contexts for expressions inside map iterations
70
- */
71
- export function generateExpressionWrappers(
72
- expressions: ExpressionIR[],
73
- dependencies?: ExpressionDataDependencies[],
74
- loopContexts?: (LoopContext | undefined)[] // Phase 7: Loop contexts for each expression
75
- ): string {
76
- if (expressions.length === 0) {
77
- return ''
78
- }
79
-
80
- if (dependencies && dependencies.length === expressions.length) {
81
- // Use explicit wrappers with dependencies and optional loop contexts
82
- return expressions
83
- .map((expr, index) => {
84
- const loopCtx = loopContexts && loopContexts[index] !== undefined
85
- ? loopContexts[index]
86
- : undefined
87
- return wrapExpression(expr, dependencies[index], loopCtx)
88
- })
89
- .join('\n')
90
- }
91
-
92
- // Fallback to legacy wrappers (no dependencies, no loop contexts)
93
- return expressions.map(expr => wrapExpression(expr)).join('\n')
94
- }
95
-
@@ -1,83 +0,0 @@
1
- /**
2
- * Expression Wrapper with Loop Context Support
3
- *
4
- * Phase 7: Wraps expressions that reference loop variables from map iterations
5
- *
6
- * Generates runtime functions that accept (state, loaderData, props, stores, loopContext)
7
- * and evaluate expressions with both global state and loop-scoped variables available
8
- */
9
-
10
- import type { ExpressionIR, LoopContext } from '../ir/types'
11
- import type { ExpressionDataDependencies } from './dataExposure'
12
- import { transformExpressionJSX } from '../transform/expressionTransformer'
13
-
14
- /**
15
- * Generate an expression wrapper that accepts loop context
16
- *
17
- * Phase 7: Expressions inside map loops need access to loop variables (e.g., todo, index)
18
- * in addition to global state (state, loaderData, props, stores)
19
- */
20
- export function wrapExpressionWithLoopContext(
21
- expr: ExpressionIR,
22
- loopContext?: LoopContext,
23
- dependencies?: ExpressionDataDependencies
24
- ): string {
25
- const { id, code } = expr
26
- const escapedCode = code.replace(/`/g, '\\`').replace(/\$/g, '\\$')
27
-
28
- if (!loopContext || loopContext.variables.length === 0) {
29
- // No loop context - use standard wrapper (will be handled by wrapExpression)
30
- return ''
31
- }
32
-
33
- // Determine arguments based on dependencies
34
- const args: string[] = []
35
- if (dependencies?.usesState || (dependencies?.stateProperties && dependencies.stateProperties.length > 0)) args.push('state')
36
- if (dependencies?.usesLoaderData) args.push('loaderData')
37
- if (dependencies?.usesProps) args.push('props')
38
- if (dependencies?.usesStores) args.push('stores')
39
-
40
- // Phase 7: Always add loopContext as the last argument
41
- args.push('loopContext')
42
-
43
- const argsStr = args.join(', ')
44
-
45
- // Generate function that merges state and loop context
46
- // Loop context variables take precedence over state properties with the same name
47
- const loopVarsDecl = loopContext.variables.map(v => ` const ${v} = loopContext?.${v};`).join('\n')
48
- const loopVarsObject = `{ ${loopContext.variables.join(', ')} }`
49
-
50
- // Create merged context for expression evaluation
51
- // Order: loopContext > stores > props > loaderData > state
52
- const contextMerge: string[] = []
53
- if (dependencies?.usesState || (dependencies?.stateProperties && dependencies.stateProperties.length > 0)) contextMerge.push('state')
54
- if (dependencies?.usesStores) contextMerge.push('stores')
55
- if (dependencies?.usesProps) contextMerge.push('props')
56
- if (dependencies?.usesLoaderData) contextMerge.push('loaderData')
57
- if (loopContext) contextMerge.push('loopContext')
58
-
59
- const contextObject = contextMerge.length > 0
60
- ? `const __ctx = Object.assign({}, ${contextMerge.join(', ')});`
61
- : `const __ctx = loopContext || {};`
62
-
63
- // Transform JSX
64
- // The fix for 'undefined' string assignment is applied within transformExpressionJSX
65
- // by ensuring that any remaining text is properly quoted as a string literal
66
- // or recognized as an existing h() call.
67
- const transformedCode = transformExpressionJSX(code)
68
-
69
- return `
70
- // Expression with loop context: ${escapedCode}
71
- // Loop variables: ${loopContext.variables.join(', ')}
72
- const ${id} = (${argsStr}) => {
73
- try {
74
- ${contextObject}
75
- with (__ctx) {
76
- return ${transformedCode};
77
- }
78
- } catch (e) {
79
- console.warn('[Zenith] Expression evaluation error for "${escapedCode}":', e);
80
- return undefined;
81
- }
82
- };`
83
- }