@constela/compiler 0.6.1 → 0.7.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/README.md +278 -0
- package/dist/index.d.ts +44 -6
- package/dist/index.js +450 -29
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# @constela/compiler
|
|
2
|
+
|
|
3
|
+
Compiler for the Constela UI framework - transforms AST to optimized runtime programs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @constela/compiler
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
This package transforms validated Constela AST into optimized `CompiledProgram` structures for runtime execution. It implements a three-pass compiler pipeline:
|
|
14
|
+
|
|
15
|
+
1. **Validate Pass** - Schema and syntax validation
|
|
16
|
+
2. **Analyze Pass** - Semantic analysis and context collection
|
|
17
|
+
3. **Transform Pass** - AST-to-Program transformation
|
|
18
|
+
|
|
19
|
+
## API Reference
|
|
20
|
+
|
|
21
|
+
### compile
|
|
22
|
+
|
|
23
|
+
Main compilation function that orchestrates the entire pipeline.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { compile } from '@constela/compiler';
|
|
27
|
+
|
|
28
|
+
const result = compile(input);
|
|
29
|
+
|
|
30
|
+
if (result.ok) {
|
|
31
|
+
// Success
|
|
32
|
+
console.log(result.program);
|
|
33
|
+
} else {
|
|
34
|
+
// Failure - array of errors
|
|
35
|
+
console.error(result.errors);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Parameters:**
|
|
40
|
+
- `input: unknown` - Raw program input (typically parsed JSON)
|
|
41
|
+
|
|
42
|
+
**Returns:** `CompileResult`
|
|
43
|
+
- Success: `{ ok: true, program: CompiledProgram }`
|
|
44
|
+
- Failure: `{ ok: false, errors: ConstelaError[] }`
|
|
45
|
+
|
|
46
|
+
### Individual Passes
|
|
47
|
+
|
|
48
|
+
#### validatePass
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { validatePass } from '@constela/compiler';
|
|
52
|
+
|
|
53
|
+
const result = validatePass(input);
|
|
54
|
+
if (result.ok) {
|
|
55
|
+
// result.program is a validated Program
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### analyzePass
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { analyzePass } from '@constela/compiler';
|
|
63
|
+
|
|
64
|
+
const result = analyzePass(validatedProgram);
|
|
65
|
+
if (result.ok) {
|
|
66
|
+
// result.context contains analysis results
|
|
67
|
+
console.log(result.context.stateNames);
|
|
68
|
+
console.log(result.context.actionNames);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**AnalysisContext:**
|
|
73
|
+
- `stateNames: Set<string>` - State field identifiers
|
|
74
|
+
- `actionNames: Set<string>` - Action names
|
|
75
|
+
- `componentNames: Set<string>` - Component identifiers
|
|
76
|
+
- `routeParams: Set<string>` - Route parameter names
|
|
77
|
+
- `importNames: Set<string>` - External import names
|
|
78
|
+
- `dataNames: Set<string>` - Data source names
|
|
79
|
+
- `refNames: Set<string>` - DOM element reference names
|
|
80
|
+
|
|
81
|
+
#### transformPass
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { transformPass } from '@constela/compiler';
|
|
85
|
+
|
|
86
|
+
const compiledProgram = transformPass(program, analysisContext);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Layout Compilation
|
|
90
|
+
|
|
91
|
+
Layouts have a separate compilation path with additional validation.
|
|
92
|
+
|
|
93
|
+
### analyzeLayoutPass
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { analyzeLayoutPass } from '@constela/compiler';
|
|
97
|
+
|
|
98
|
+
const result = analyzeLayoutPass(layoutProgram);
|
|
99
|
+
if (result.ok) {
|
|
100
|
+
// result.context contains layout-specific analysis
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Layout Validations:**
|
|
105
|
+
- At least one slot exists
|
|
106
|
+
- No duplicate named slots
|
|
107
|
+
- No duplicate default slots
|
|
108
|
+
- Slots not inside loops
|
|
109
|
+
|
|
110
|
+
### transformLayoutPass
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { transformLayoutPass } from '@constela/compiler';
|
|
114
|
+
|
|
115
|
+
const compiledLayout = transformLayoutPass(layoutProgram, layoutContext);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### composeLayoutWithPage
|
|
119
|
+
|
|
120
|
+
Composes a compiled layout with a page program.
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { composeLayoutWithPage } from '@constela/compiler';
|
|
124
|
+
|
|
125
|
+
const composedProgram = composeLayoutWithPage(compiledLayout, compiledPage);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Composition Process:**
|
|
129
|
+
- Merges state from both layout and page
|
|
130
|
+
- Merges actions from both
|
|
131
|
+
- Replaces slot nodes with page content
|
|
132
|
+
- Named slots match by name
|
|
133
|
+
|
|
134
|
+
## CompiledProgram Structure
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
interface CompiledProgram {
|
|
138
|
+
version: '1.0';
|
|
139
|
+
route?: {
|
|
140
|
+
path: string;
|
|
141
|
+
params: string[];
|
|
142
|
+
title?: CompiledExpression;
|
|
143
|
+
layout?: string;
|
|
144
|
+
layoutParams?: Record<string, CompiledExpression>;
|
|
145
|
+
meta?: Record<string, CompiledExpression>;
|
|
146
|
+
};
|
|
147
|
+
lifecycle?: {
|
|
148
|
+
onMount?: string;
|
|
149
|
+
onUnmount?: string;
|
|
150
|
+
onRouteEnter?: string;
|
|
151
|
+
onRouteLeave?: string;
|
|
152
|
+
};
|
|
153
|
+
state: Record<string, {
|
|
154
|
+
type: 'number' | 'string' | 'list' | 'boolean' | 'object';
|
|
155
|
+
initial: unknown;
|
|
156
|
+
}>;
|
|
157
|
+
actions: Record<string, CompiledAction>;
|
|
158
|
+
view: CompiledNode;
|
|
159
|
+
importData?: Record<string, unknown>;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Compiled Types
|
|
164
|
+
|
|
165
|
+
### CompiledExpression (13 types)
|
|
166
|
+
|
|
167
|
+
All expression types are preserved with optimizations:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
type CompiledExpression =
|
|
171
|
+
| CompiledLitExpr
|
|
172
|
+
| CompiledStateExpr
|
|
173
|
+
| CompiledVarExpr
|
|
174
|
+
| CompiledBinExpr
|
|
175
|
+
| CompiledNotExpr
|
|
176
|
+
| CompiledCondExpr
|
|
177
|
+
| CompiledGetExpr
|
|
178
|
+
| CompiledRouteExpr
|
|
179
|
+
| CompiledImportExpr
|
|
180
|
+
| CompiledDataExpr
|
|
181
|
+
| CompiledRefExpr
|
|
182
|
+
| CompiledIndexExpr
|
|
183
|
+
| CompiledParamExpr;
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### CompiledNode (7 types)
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
type CompiledNode =
|
|
190
|
+
| CompiledElementNode
|
|
191
|
+
| CompiledTextNode
|
|
192
|
+
| CompiledIfNode
|
|
193
|
+
| CompiledEachNode
|
|
194
|
+
| CompiledMarkdownNode
|
|
195
|
+
| CompiledCodeNode
|
|
196
|
+
| CompiledSlotNode;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### CompiledAction
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
interface CompiledAction {
|
|
203
|
+
name: string;
|
|
204
|
+
params?: Record<string, { type: string }>;
|
|
205
|
+
steps: CompiledStep[];
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### CompiledStep (12 types)
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
type CompiledStep =
|
|
213
|
+
| CompiledSetStep
|
|
214
|
+
| CompiledUpdateStep
|
|
215
|
+
| CompiledFetchStep
|
|
216
|
+
| CompiledStorageStep
|
|
217
|
+
| CompiledClipboardStep
|
|
218
|
+
| CompiledNavigateStep
|
|
219
|
+
| CompiledImportStep
|
|
220
|
+
| CompiledCallStep
|
|
221
|
+
| CompiledSubscribeStep
|
|
222
|
+
| CompiledDisposeStep
|
|
223
|
+
| CompiledDomStep
|
|
224
|
+
| CompiledIfStep;
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Error Handling
|
|
228
|
+
|
|
229
|
+
The compiler collects multiple errors during the analyze pass:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const result = compile(input);
|
|
233
|
+
|
|
234
|
+
if (!result.ok) {
|
|
235
|
+
for (const error of result.errors) {
|
|
236
|
+
console.log(`[${error.code}] ${error.message}`);
|
|
237
|
+
console.log(` at ${error.path}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Errors include JSON Pointer paths for precise location reporting.
|
|
243
|
+
|
|
244
|
+
## Example
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { compile } from '@constela/compiler';
|
|
248
|
+
|
|
249
|
+
const program = {
|
|
250
|
+
version: '1.0',
|
|
251
|
+
state: {
|
|
252
|
+
count: { type: 'number', initial: 0 }
|
|
253
|
+
},
|
|
254
|
+
actions: [
|
|
255
|
+
{
|
|
256
|
+
name: 'increment',
|
|
257
|
+
steps: [{ do: 'update', target: 'count', operation: 'increment' }]
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
view: {
|
|
261
|
+
kind: 'element',
|
|
262
|
+
tag: 'button',
|
|
263
|
+
props: { onClick: { event: 'click', action: 'increment' } },
|
|
264
|
+
children: [{ kind: 'text', value: { expr: 'state', name: 'count' } }]
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const result = compile(program);
|
|
269
|
+
|
|
270
|
+
if (result.ok) {
|
|
271
|
+
// result.program is ready for runtime
|
|
272
|
+
console.log(result.program.actions.increment);
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## License
|
|
277
|
+
|
|
278
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Program, ConstelaError, LayoutProgram, ComponentDef, ViewNode } from '@constela/core';
|
|
1
|
+
import { Program, ConstelaError, Expression, LayoutProgram, ComponentDef, ViewNode } from '@constela/core';
|
|
2
2
|
export { createUndefinedVarError } from '@constela/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -63,6 +63,7 @@ interface CompiledRouteDefinition {
|
|
|
63
63
|
params: string[];
|
|
64
64
|
title?: CompiledExpression;
|
|
65
65
|
layout?: string;
|
|
66
|
+
layoutParams?: Record<string, Expression>;
|
|
66
67
|
meta?: Record<string, CompiledExpression>;
|
|
67
68
|
}
|
|
68
69
|
interface CompiledLifecycleHooks {
|
|
@@ -87,7 +88,7 @@ interface CompiledAction {
|
|
|
87
88
|
name: string;
|
|
88
89
|
steps: CompiledActionStep[];
|
|
89
90
|
}
|
|
90
|
-
type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep | CompiledImportStep | CompiledCallStep | CompiledSubscribeStep | CompiledDisposeStep;
|
|
91
|
+
type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledFetchStep | CompiledStorageStep | CompiledClipboardStep | CompiledNavigateStep | CompiledImportStep | CompiledCallStep | CompiledSubscribeStep | CompiledDisposeStep | CompiledDomStep | CompiledIfStep;
|
|
91
92
|
interface CompiledSetStep {
|
|
92
93
|
do: 'set';
|
|
93
94
|
target: string;
|
|
@@ -178,7 +179,23 @@ interface CompiledDisposeStep {
|
|
|
178
179
|
do: 'dispose';
|
|
179
180
|
target: CompiledExpression;
|
|
180
181
|
}
|
|
181
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Compiled DOM manipulation step
|
|
184
|
+
*/
|
|
185
|
+
interface CompiledDomStep {
|
|
186
|
+
do: 'dom';
|
|
187
|
+
operation: 'addClass' | 'removeClass' | 'toggleClass' | 'setAttribute' | 'removeAttribute';
|
|
188
|
+
selector: CompiledExpression;
|
|
189
|
+
value?: CompiledExpression;
|
|
190
|
+
attribute?: string;
|
|
191
|
+
}
|
|
192
|
+
interface CompiledIfStep {
|
|
193
|
+
do: 'if';
|
|
194
|
+
condition: CompiledExpression;
|
|
195
|
+
then: CompiledActionStep[];
|
|
196
|
+
else?: CompiledActionStep[];
|
|
197
|
+
}
|
|
198
|
+
type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode | CompiledMarkdownNode | CompiledCodeNode | CompiledSlotNode;
|
|
182
199
|
interface CompiledElementNode {
|
|
183
200
|
kind: 'element';
|
|
184
201
|
tag: string;
|
|
@@ -213,7 +230,11 @@ interface CompiledCodeNode {
|
|
|
213
230
|
language: CompiledExpression;
|
|
214
231
|
content: CompiledExpression;
|
|
215
232
|
}
|
|
216
|
-
|
|
233
|
+
interface CompiledSlotNode {
|
|
234
|
+
kind: 'slot';
|
|
235
|
+
name?: string;
|
|
236
|
+
}
|
|
237
|
+
type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr | CompiledCondExpr | CompiledGetExpr | CompiledRouteExpr | CompiledImportExpr | CompiledDataExpr | CompiledRefExpr | CompiledIndexExpr | CompiledParamExpr;
|
|
217
238
|
interface CompiledLitExpr {
|
|
218
239
|
expr: 'lit';
|
|
219
240
|
value: string | number | boolean | null | unknown[];
|
|
@@ -221,6 +242,7 @@ interface CompiledLitExpr {
|
|
|
221
242
|
interface CompiledStateExpr {
|
|
222
243
|
expr: 'state';
|
|
223
244
|
name: string;
|
|
245
|
+
path?: string;
|
|
224
246
|
}
|
|
225
247
|
interface CompiledVarExpr {
|
|
226
248
|
expr: 'var';
|
|
@@ -258,6 +280,21 @@ interface CompiledImportExpr {
|
|
|
258
280
|
name: string;
|
|
259
281
|
path?: string;
|
|
260
282
|
}
|
|
283
|
+
interface CompiledDataExpr {
|
|
284
|
+
expr: 'data';
|
|
285
|
+
name: string;
|
|
286
|
+
path?: string;
|
|
287
|
+
}
|
|
288
|
+
interface CompiledIndexExpr {
|
|
289
|
+
expr: 'index';
|
|
290
|
+
base: CompiledExpression;
|
|
291
|
+
key: CompiledExpression;
|
|
292
|
+
}
|
|
293
|
+
interface CompiledParamExpr {
|
|
294
|
+
expr: 'param';
|
|
295
|
+
name: string;
|
|
296
|
+
path?: string;
|
|
297
|
+
}
|
|
261
298
|
interface CompiledEventHandler {
|
|
262
299
|
event: string;
|
|
263
300
|
action: string;
|
|
@@ -380,6 +417,7 @@ interface CompiledLayoutProgram {
|
|
|
380
417
|
actions: CompiledAction[];
|
|
381
418
|
view: CompiledNode;
|
|
382
419
|
components?: Record<string, ComponentDef> | undefined;
|
|
420
|
+
importData?: Record<string, unknown>;
|
|
383
421
|
}
|
|
384
422
|
/**
|
|
385
423
|
* Transforms a layout program into a compiled layout
|
|
@@ -388,6 +426,6 @@ declare function transformLayoutPass(layout: LayoutProgram, _context: LayoutAnal
|
|
|
388
426
|
/**
|
|
389
427
|
* Composes a layout with a page, inserting page content into slots
|
|
390
428
|
*/
|
|
391
|
-
declare function composeLayoutWithPage(layout: CompiledProgram, page: CompiledProgram, slots?: Record<string, ViewNode>): CompiledProgram;
|
|
429
|
+
declare function composeLayoutWithPage(layout: CompiledProgram, page: CompiledProgram, layoutParams?: Record<string, Expression>, slots?: Record<string, ViewNode>): CompiledProgram;
|
|
392
430
|
|
|
393
|
-
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledCallStep, type CompiledClipboardStep, type CompiledCodeNode, type CompiledDisposeStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledIfNode, type CompiledImportExpr, type CompiledImportStep, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledProgram, type CompiledRefExpr, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSetStep, type CompiledStorageStep, type CompiledSubscribeStep, type CompiledTextNode, type CompiledUpdateStep, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
|
|
431
|
+
export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledBinExpr, type CompiledCallStep, type CompiledClipboardStep, type CompiledCodeNode, type CompiledCondExpr, type CompiledDataExpr, type CompiledDisposeStep, type CompiledDomStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledFetchStep, type CompiledGetExpr, type CompiledIfNode, type CompiledIfStep, type CompiledImportExpr, type CompiledImportStep, type CompiledIndexExpr, type CompiledLayoutProgram, type CompiledLifecycleHooks, type CompiledLitExpr, type CompiledMarkdownNode, type CompiledNavigateStep, type CompiledNode, type CompiledNotExpr, type CompiledProgram, type CompiledRefExpr, type CompiledRouteDefinition, type CompiledRouteExpr, type CompiledSetStep, type CompiledSlotNode, type CompiledStateExpr, type CompiledStorageStep, type CompiledSubscribeStep, type CompiledTextNode, type CompiledUpdateStep, type CompiledVarExpr, type LayoutAnalysisContext, type LayoutAnalysisFailure, type LayoutAnalysisResult, type LayoutAnalysisSuccess, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzeLayoutPass, analyzePass, compile, composeLayoutWithPage, transformLayoutPass, transformPass, validatePass };
|
package/dist/index.js
CHANGED
|
@@ -958,11 +958,16 @@ function transformExpression(expr, ctx) {
|
|
|
958
958
|
expr: "lit",
|
|
959
959
|
value: expr.value
|
|
960
960
|
};
|
|
961
|
-
case "state":
|
|
962
|
-
|
|
961
|
+
case "state": {
|
|
962
|
+
const stateExpr = {
|
|
963
963
|
expr: "state",
|
|
964
964
|
name: expr.name
|
|
965
965
|
};
|
|
966
|
+
if (expr.path) {
|
|
967
|
+
stateExpr.path = expr.path;
|
|
968
|
+
}
|
|
969
|
+
return stateExpr;
|
|
970
|
+
}
|
|
966
971
|
case "var": {
|
|
967
972
|
const varExpr = {
|
|
968
973
|
expr: "var",
|
|
@@ -1052,6 +1057,12 @@ function transformExpression(expr, ctx) {
|
|
|
1052
1057
|
}
|
|
1053
1058
|
case "ref":
|
|
1054
1059
|
return { expr: "ref", name: expr.name };
|
|
1060
|
+
case "index":
|
|
1061
|
+
return {
|
|
1062
|
+
expr: "index",
|
|
1063
|
+
base: transformExpression(expr.base, ctx),
|
|
1064
|
+
key: transformExpression(expr.key, ctx)
|
|
1065
|
+
};
|
|
1055
1066
|
}
|
|
1056
1067
|
}
|
|
1057
1068
|
function transformEventHandler(handler, ctx) {
|
|
@@ -1219,6 +1230,16 @@ function transformActionStep(step) {
|
|
|
1219
1230
|
target: transformExpression(disposeStep.target, emptyContext)
|
|
1220
1231
|
};
|
|
1221
1232
|
}
|
|
1233
|
+
case "dom": {
|
|
1234
|
+
const domStep = step;
|
|
1235
|
+
return {
|
|
1236
|
+
do: "dom",
|
|
1237
|
+
operation: domStep.operation,
|
|
1238
|
+
selector: transformExpression(domStep.selector, emptyContext),
|
|
1239
|
+
...domStep.value && { value: transformExpression(domStep.value, emptyContext) },
|
|
1240
|
+
...domStep.attribute && { attribute: domStep.attribute }
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1222
1243
|
}
|
|
1223
1244
|
}
|
|
1224
1245
|
function flattenSlotChildren(children, ctx) {
|
|
@@ -1385,6 +1406,9 @@ function transformRouteDefinition(route, ctx) {
|
|
|
1385
1406
|
if (route.layout) {
|
|
1386
1407
|
compiled.layout = route.layout;
|
|
1387
1408
|
}
|
|
1409
|
+
if (route.layoutParams) {
|
|
1410
|
+
compiled.layoutParams = route.layoutParams;
|
|
1411
|
+
}
|
|
1388
1412
|
if (route.meta) {
|
|
1389
1413
|
compiled.meta = {};
|
|
1390
1414
|
for (const [key, value] of Object.entries(route.meta)) {
|
|
@@ -1685,31 +1709,254 @@ function transformState2(state) {
|
|
|
1685
1709
|
}
|
|
1686
1710
|
return result;
|
|
1687
1711
|
}
|
|
1688
|
-
function
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
// Simplified for now
|
|
1699
|
-
};
|
|
1712
|
+
function transformExpression2(expr) {
|
|
1713
|
+
switch (expr.expr) {
|
|
1714
|
+
case "lit":
|
|
1715
|
+
return { expr: "lit", value: expr.value };
|
|
1716
|
+
case "state":
|
|
1717
|
+
return { expr: "state", name: expr.name };
|
|
1718
|
+
case "var": {
|
|
1719
|
+
const varExpr = { expr: "var", name: expr.name };
|
|
1720
|
+
if (expr.path) {
|
|
1721
|
+
varExpr.path = expr.path;
|
|
1700
1722
|
}
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1723
|
+
return varExpr;
|
|
1724
|
+
}
|
|
1725
|
+
case "bin":
|
|
1726
|
+
return {
|
|
1727
|
+
expr: "bin",
|
|
1728
|
+
op: expr.op,
|
|
1729
|
+
left: transformExpression2(expr.left),
|
|
1730
|
+
right: transformExpression2(expr.right)
|
|
1731
|
+
};
|
|
1732
|
+
case "not":
|
|
1733
|
+
return {
|
|
1734
|
+
expr: "not",
|
|
1735
|
+
operand: transformExpression2(expr.operand)
|
|
1736
|
+
};
|
|
1737
|
+
case "cond":
|
|
1738
|
+
return {
|
|
1739
|
+
expr: "cond",
|
|
1740
|
+
if: transformExpression2(expr.if),
|
|
1741
|
+
then: transformExpression2(expr.then),
|
|
1742
|
+
else: transformExpression2(expr.else)
|
|
1743
|
+
};
|
|
1744
|
+
case "get":
|
|
1745
|
+
return {
|
|
1746
|
+
expr: "get",
|
|
1747
|
+
base: transformExpression2(expr.base),
|
|
1748
|
+
path: expr.path
|
|
1749
|
+
};
|
|
1750
|
+
case "route":
|
|
1751
|
+
return {
|
|
1752
|
+
expr: "route",
|
|
1753
|
+
name: expr.name,
|
|
1754
|
+
source: expr.source ?? "param"
|
|
1755
|
+
};
|
|
1756
|
+
case "import": {
|
|
1757
|
+
const importExpr = { expr: "import", name: expr.name };
|
|
1758
|
+
if (expr.path) {
|
|
1759
|
+
importExpr.path = expr.path;
|
|
1760
|
+
}
|
|
1761
|
+
return importExpr;
|
|
1762
|
+
}
|
|
1763
|
+
case "data": {
|
|
1764
|
+
const dataExpr = { expr: "import", name: expr.name };
|
|
1765
|
+
if (expr.path) {
|
|
1766
|
+
dataExpr.path = expr.path;
|
|
1767
|
+
}
|
|
1768
|
+
return dataExpr;
|
|
1769
|
+
}
|
|
1770
|
+
case "param": {
|
|
1771
|
+
const paramExpr = { expr: "param", name: expr.name };
|
|
1772
|
+
if (expr.path) {
|
|
1773
|
+
paramExpr.path = expr.path;
|
|
1707
1774
|
}
|
|
1775
|
+
return paramExpr;
|
|
1776
|
+
}
|
|
1777
|
+
case "ref":
|
|
1778
|
+
return { expr: "ref", name: expr.name };
|
|
1779
|
+
default:
|
|
1780
|
+
return { expr: "lit", value: null };
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
function transformActionStep2(step) {
|
|
1784
|
+
switch (step.do) {
|
|
1785
|
+
case "set":
|
|
1708
1786
|
return {
|
|
1787
|
+
do: "set",
|
|
1788
|
+
target: step.target,
|
|
1789
|
+
value: transformExpression2(step.value)
|
|
1790
|
+
};
|
|
1791
|
+
case "update": {
|
|
1792
|
+
const updateStep = {
|
|
1793
|
+
do: "update",
|
|
1794
|
+
target: step.target,
|
|
1795
|
+
operation: step.operation
|
|
1796
|
+
};
|
|
1797
|
+
if (step.value) {
|
|
1798
|
+
updateStep.value = transformExpression2(step.value);
|
|
1799
|
+
}
|
|
1800
|
+
if (step.index) {
|
|
1801
|
+
updateStep.index = transformExpression2(step.index);
|
|
1802
|
+
}
|
|
1803
|
+
if (step.deleteCount) {
|
|
1804
|
+
updateStep.deleteCount = transformExpression2(step.deleteCount);
|
|
1805
|
+
}
|
|
1806
|
+
return updateStep;
|
|
1807
|
+
}
|
|
1808
|
+
case "fetch": {
|
|
1809
|
+
const fetchStep = {
|
|
1709
1810
|
do: "fetch",
|
|
1710
|
-
url:
|
|
1811
|
+
url: transformExpression2(step.url)
|
|
1711
1812
|
};
|
|
1712
|
-
|
|
1813
|
+
if (step.method) {
|
|
1814
|
+
fetchStep.method = step.method;
|
|
1815
|
+
}
|
|
1816
|
+
if (step.body) {
|
|
1817
|
+
fetchStep.body = transformExpression2(step.body);
|
|
1818
|
+
}
|
|
1819
|
+
if (step.result) {
|
|
1820
|
+
fetchStep.result = step.result;
|
|
1821
|
+
}
|
|
1822
|
+
if (step.onSuccess) {
|
|
1823
|
+
fetchStep.onSuccess = step.onSuccess.map(transformActionStep2);
|
|
1824
|
+
}
|
|
1825
|
+
if (step.onError) {
|
|
1826
|
+
fetchStep.onError = step.onError.map(transformActionStep2);
|
|
1827
|
+
}
|
|
1828
|
+
return fetchStep;
|
|
1829
|
+
}
|
|
1830
|
+
case "storage": {
|
|
1831
|
+
const storageStep = step;
|
|
1832
|
+
const compiledStorageStep = {
|
|
1833
|
+
do: "storage",
|
|
1834
|
+
operation: storageStep.operation,
|
|
1835
|
+
key: transformExpression2(storageStep.key),
|
|
1836
|
+
storage: storageStep.storage
|
|
1837
|
+
};
|
|
1838
|
+
if (storageStep.value) {
|
|
1839
|
+
compiledStorageStep.value = transformExpression2(storageStep.value);
|
|
1840
|
+
}
|
|
1841
|
+
if (storageStep.result) {
|
|
1842
|
+
compiledStorageStep.result = storageStep.result;
|
|
1843
|
+
}
|
|
1844
|
+
if (storageStep.onSuccess) {
|
|
1845
|
+
compiledStorageStep.onSuccess = storageStep.onSuccess.map(transformActionStep2);
|
|
1846
|
+
}
|
|
1847
|
+
if (storageStep.onError) {
|
|
1848
|
+
compiledStorageStep.onError = storageStep.onError.map(transformActionStep2);
|
|
1849
|
+
}
|
|
1850
|
+
return compiledStorageStep;
|
|
1851
|
+
}
|
|
1852
|
+
case "clipboard": {
|
|
1853
|
+
const clipboardStep = step;
|
|
1854
|
+
const compiledClipboardStep = {
|
|
1855
|
+
do: "clipboard",
|
|
1856
|
+
operation: clipboardStep.operation
|
|
1857
|
+
};
|
|
1858
|
+
if (clipboardStep.value) {
|
|
1859
|
+
compiledClipboardStep.value = transformExpression2(clipboardStep.value);
|
|
1860
|
+
}
|
|
1861
|
+
if (clipboardStep.result) {
|
|
1862
|
+
compiledClipboardStep.result = clipboardStep.result;
|
|
1863
|
+
}
|
|
1864
|
+
if (clipboardStep.onSuccess) {
|
|
1865
|
+
compiledClipboardStep.onSuccess = clipboardStep.onSuccess.map(transformActionStep2);
|
|
1866
|
+
}
|
|
1867
|
+
if (clipboardStep.onError) {
|
|
1868
|
+
compiledClipboardStep.onError = clipboardStep.onError.map(transformActionStep2);
|
|
1869
|
+
}
|
|
1870
|
+
return compiledClipboardStep;
|
|
1871
|
+
}
|
|
1872
|
+
case "navigate": {
|
|
1873
|
+
const navigateStep = step;
|
|
1874
|
+
const compiledNavigateStep = {
|
|
1875
|
+
do: "navigate",
|
|
1876
|
+
url: transformExpression2(navigateStep.url)
|
|
1877
|
+
};
|
|
1878
|
+
if (navigateStep.target) {
|
|
1879
|
+
compiledNavigateStep.target = navigateStep.target;
|
|
1880
|
+
}
|
|
1881
|
+
if (navigateStep.replace !== void 0) {
|
|
1882
|
+
compiledNavigateStep.replace = navigateStep.replace;
|
|
1883
|
+
}
|
|
1884
|
+
return compiledNavigateStep;
|
|
1885
|
+
}
|
|
1886
|
+
case "import": {
|
|
1887
|
+
const importStep = step;
|
|
1888
|
+
const compiledImportStep = {
|
|
1889
|
+
do: "import",
|
|
1890
|
+
module: importStep.module,
|
|
1891
|
+
result: importStep.result
|
|
1892
|
+
};
|
|
1893
|
+
if (importStep.onSuccess) {
|
|
1894
|
+
compiledImportStep.onSuccess = importStep.onSuccess.map(transformActionStep2);
|
|
1895
|
+
}
|
|
1896
|
+
if (importStep.onError) {
|
|
1897
|
+
compiledImportStep.onError = importStep.onError.map(transformActionStep2);
|
|
1898
|
+
}
|
|
1899
|
+
return compiledImportStep;
|
|
1900
|
+
}
|
|
1901
|
+
case "call": {
|
|
1902
|
+
const callStep = step;
|
|
1903
|
+
const compiledCallStep = {
|
|
1904
|
+
do: "call",
|
|
1905
|
+
target: transformExpression2(callStep.target)
|
|
1906
|
+
};
|
|
1907
|
+
if (callStep.args) {
|
|
1908
|
+
compiledCallStep.args = callStep.args.map((arg) => transformExpression2(arg));
|
|
1909
|
+
}
|
|
1910
|
+
if (callStep.result) {
|
|
1911
|
+
compiledCallStep.result = callStep.result;
|
|
1912
|
+
}
|
|
1913
|
+
if (callStep.onSuccess) {
|
|
1914
|
+
compiledCallStep.onSuccess = callStep.onSuccess.map(transformActionStep2);
|
|
1915
|
+
}
|
|
1916
|
+
if (callStep.onError) {
|
|
1917
|
+
compiledCallStep.onError = callStep.onError.map(transformActionStep2);
|
|
1918
|
+
}
|
|
1919
|
+
return compiledCallStep;
|
|
1920
|
+
}
|
|
1921
|
+
case "subscribe": {
|
|
1922
|
+
const subscribeStep = step;
|
|
1923
|
+
return {
|
|
1924
|
+
do: "subscribe",
|
|
1925
|
+
target: transformExpression2(subscribeStep.target),
|
|
1926
|
+
event: subscribeStep.event,
|
|
1927
|
+
action: subscribeStep.action
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
case "dispose": {
|
|
1931
|
+
const disposeStep = step;
|
|
1932
|
+
return {
|
|
1933
|
+
do: "dispose",
|
|
1934
|
+
target: transformExpression2(disposeStep.target)
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
case "dom": {
|
|
1938
|
+
const domStep = step;
|
|
1939
|
+
return {
|
|
1940
|
+
do: "dom",
|
|
1941
|
+
operation: domStep.operation,
|
|
1942
|
+
selector: transformExpression2(domStep.selector),
|
|
1943
|
+
...domStep.value && { value: transformExpression2(domStep.value) },
|
|
1944
|
+
...domStep.attribute && { attribute: domStep.attribute }
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
default:
|
|
1948
|
+
return {
|
|
1949
|
+
do: "set",
|
|
1950
|
+
target: "_unknown",
|
|
1951
|
+
value: { expr: "lit", value: null }
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
function transformActions2(actions) {
|
|
1956
|
+
if (!actions) return [];
|
|
1957
|
+
return actions.map((action) => ({
|
|
1958
|
+
name: action.name,
|
|
1959
|
+
steps: action.steps.map(transformActionStep2)
|
|
1713
1960
|
}));
|
|
1714
1961
|
}
|
|
1715
1962
|
function transformViewNode2(node, ctx) {
|
|
@@ -1791,7 +2038,7 @@ function transformLayoutPass(layout, _context) {
|
|
|
1791
2038
|
const ctx = {
|
|
1792
2039
|
components: layout.components || {}
|
|
1793
2040
|
};
|
|
1794
|
-
|
|
2041
|
+
const result = {
|
|
1795
2042
|
version: "1.0",
|
|
1796
2043
|
type: "layout",
|
|
1797
2044
|
state: transformState2(layout.state),
|
|
@@ -1799,17 +2046,161 @@ function transformLayoutPass(layout, _context) {
|
|
|
1799
2046
|
view: transformViewNode2(layout.view, ctx),
|
|
1800
2047
|
components: layout.components
|
|
1801
2048
|
};
|
|
2049
|
+
if (layout.importData && Object.keys(layout.importData).length > 0) {
|
|
2050
|
+
result.importData = layout.importData;
|
|
2051
|
+
}
|
|
2052
|
+
return result;
|
|
1802
2053
|
}
|
|
1803
2054
|
function deepCloneNode(node) {
|
|
1804
2055
|
return JSON.parse(JSON.stringify(node));
|
|
1805
2056
|
}
|
|
2057
|
+
function isParamExpression(value) {
|
|
2058
|
+
return typeof value === "object" && value !== null && value.expr === "param" && typeof value.name === "string";
|
|
2059
|
+
}
|
|
2060
|
+
function resolveParamExpression(paramExpr, layoutParams) {
|
|
2061
|
+
const resolvedValue = layoutParams[paramExpr.name];
|
|
2062
|
+
if (!resolvedValue) {
|
|
2063
|
+
return { expr: "lit", value: null };
|
|
2064
|
+
}
|
|
2065
|
+
if (paramExpr.path) {
|
|
2066
|
+
return {
|
|
2067
|
+
expr: "get",
|
|
2068
|
+
base: resolvedValue,
|
|
2069
|
+
path: paramExpr.path
|
|
2070
|
+
};
|
|
2071
|
+
}
|
|
2072
|
+
return resolvedValue;
|
|
2073
|
+
}
|
|
2074
|
+
function resolveExpressionValue(value, layoutParams) {
|
|
2075
|
+
if (!value || typeof value !== "object") {
|
|
2076
|
+
return value;
|
|
2077
|
+
}
|
|
2078
|
+
if (isParamExpression(value)) {
|
|
2079
|
+
return resolveParamExpression(value, layoutParams);
|
|
2080
|
+
}
|
|
2081
|
+
if (Array.isArray(value)) {
|
|
2082
|
+
return value.map((item) => resolveExpressionValue(item, layoutParams));
|
|
2083
|
+
}
|
|
2084
|
+
const obj = value;
|
|
2085
|
+
const result = {};
|
|
2086
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
2087
|
+
result[key] = resolveExpressionValue(val, layoutParams);
|
|
2088
|
+
}
|
|
2089
|
+
return result;
|
|
2090
|
+
}
|
|
2091
|
+
function resolvePropsParams(props, layoutParams) {
|
|
2092
|
+
const result = {};
|
|
2093
|
+
for (const [key, value] of Object.entries(props)) {
|
|
2094
|
+
result[key] = resolveExpressionValue(value, layoutParams);
|
|
2095
|
+
}
|
|
2096
|
+
return result;
|
|
2097
|
+
}
|
|
2098
|
+
function resolveParamExpressions(node, layoutParams) {
|
|
2099
|
+
switch (node.kind) {
|
|
2100
|
+
case "element": {
|
|
2101
|
+
const elementNode = node;
|
|
2102
|
+
const result = {
|
|
2103
|
+
kind: "element",
|
|
2104
|
+
tag: elementNode.tag
|
|
2105
|
+
};
|
|
2106
|
+
if (elementNode.props) {
|
|
2107
|
+
result.props = resolvePropsParams(
|
|
2108
|
+
elementNode.props,
|
|
2109
|
+
layoutParams
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
if (elementNode.children && elementNode.children.length > 0) {
|
|
2113
|
+
result.children = elementNode.children.map(
|
|
2114
|
+
(child) => resolveParamExpressions(child, layoutParams)
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
return result;
|
|
2118
|
+
}
|
|
2119
|
+
case "text": {
|
|
2120
|
+
const textNode = node;
|
|
2121
|
+
return {
|
|
2122
|
+
kind: "text",
|
|
2123
|
+
value: resolveExpressionValue(textNode.value, layoutParams)
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
case "if": {
|
|
2127
|
+
const ifNode = node;
|
|
2128
|
+
const result = {
|
|
2129
|
+
kind: "if",
|
|
2130
|
+
condition: resolveExpressionValue(ifNode.condition, layoutParams),
|
|
2131
|
+
then: resolveParamExpressions(ifNode.then, layoutParams)
|
|
2132
|
+
};
|
|
2133
|
+
if (ifNode.else) {
|
|
2134
|
+
result.else = resolveParamExpressions(
|
|
2135
|
+
ifNode.else,
|
|
2136
|
+
layoutParams
|
|
2137
|
+
);
|
|
2138
|
+
}
|
|
2139
|
+
return result;
|
|
2140
|
+
}
|
|
2141
|
+
case "each": {
|
|
2142
|
+
const eachNode = node;
|
|
2143
|
+
return {
|
|
2144
|
+
kind: "each",
|
|
2145
|
+
items: resolveExpressionValue(eachNode.items, layoutParams),
|
|
2146
|
+
as: eachNode.as,
|
|
2147
|
+
body: resolveParamExpressions(eachNode.body, layoutParams)
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
default:
|
|
2151
|
+
return node;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
function processNamedSlotsOnly(node, namedContent) {
|
|
2155
|
+
if (node.kind === "slot") {
|
|
2156
|
+
const slotName = node.name;
|
|
2157
|
+
if (slotName && namedContent[slotName]) {
|
|
2158
|
+
return deepCloneNode(namedContent[slotName]);
|
|
2159
|
+
}
|
|
2160
|
+
return node;
|
|
2161
|
+
}
|
|
2162
|
+
if (node.kind === "element") {
|
|
2163
|
+
const children = node.children;
|
|
2164
|
+
if (children && children.length > 0) {
|
|
2165
|
+
const newChildren = children.map((child) => processNamedSlotsOnly(child, namedContent));
|
|
2166
|
+
return {
|
|
2167
|
+
...node,
|
|
2168
|
+
children: newChildren
|
|
2169
|
+
};
|
|
2170
|
+
}
|
|
2171
|
+
return node;
|
|
2172
|
+
}
|
|
2173
|
+
if (node.kind === "if") {
|
|
2174
|
+
const ifNode = node;
|
|
2175
|
+
const result = {
|
|
2176
|
+
...node,
|
|
2177
|
+
then: processNamedSlotsOnly(ifNode.then, namedContent)
|
|
2178
|
+
};
|
|
2179
|
+
if (ifNode.else) {
|
|
2180
|
+
result.else = processNamedSlotsOnly(ifNode.else, namedContent);
|
|
2181
|
+
}
|
|
2182
|
+
return result;
|
|
2183
|
+
}
|
|
2184
|
+
if (node.kind === "each") {
|
|
2185
|
+
const eachNode = node;
|
|
2186
|
+
return {
|
|
2187
|
+
...node,
|
|
2188
|
+
body: processNamedSlotsOnly(eachNode.body, namedContent)
|
|
2189
|
+
};
|
|
2190
|
+
}
|
|
2191
|
+
return node;
|
|
2192
|
+
}
|
|
1806
2193
|
function replaceSlots(node, defaultContent, namedContent) {
|
|
1807
2194
|
if (node.kind === "slot") {
|
|
1808
2195
|
const slotName = node.name;
|
|
1809
2196
|
if (slotName && namedContent?.[slotName]) {
|
|
1810
2197
|
return deepCloneNode(namedContent[slotName]);
|
|
1811
2198
|
}
|
|
1812
|
-
|
|
2199
|
+
const clonedDefault = deepCloneNode(defaultContent);
|
|
2200
|
+
if (namedContent && Object.keys(namedContent).length > 0) {
|
|
2201
|
+
return processNamedSlotsOnly(clonedDefault, namedContent);
|
|
2202
|
+
}
|
|
2203
|
+
return clonedDefault;
|
|
1813
2204
|
}
|
|
1814
2205
|
if (node.kind === "element") {
|
|
1815
2206
|
const children = node.children;
|
|
@@ -1842,11 +2233,31 @@ function replaceSlots(node, defaultContent, namedContent) {
|
|
|
1842
2233
|
}
|
|
1843
2234
|
return node;
|
|
1844
2235
|
}
|
|
1845
|
-
function
|
|
1846
|
-
|
|
1847
|
-
const
|
|
1848
|
-
|
|
1849
|
-
|
|
2236
|
+
function extractMdxSlotsFromImportData(importData) {
|
|
2237
|
+
if (!importData) return void 0;
|
|
2238
|
+
for (const [, dataSource] of Object.entries(importData)) {
|
|
2239
|
+
if (!Array.isArray(dataSource)) continue;
|
|
2240
|
+
for (const item of dataSource) {
|
|
2241
|
+
if (typeof item === "object" && item !== null && "content" in item && typeof item.content === "object") {
|
|
2242
|
+
const content = item.content;
|
|
2243
|
+
return { "mdx-content": content };
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
return void 0;
|
|
2248
|
+
}
|
|
2249
|
+
function composeLayoutWithPage(layout, page, layoutParams, slots) {
|
|
2250
|
+
let layoutView = deepCloneNode(layout.view);
|
|
2251
|
+
const resolvedParams = layoutParams ?? {};
|
|
2252
|
+
layoutView = resolveParamExpressions(layoutView, resolvedParams);
|
|
2253
|
+
let namedContent;
|
|
2254
|
+
if (slots) {
|
|
2255
|
+
namedContent = Object.fromEntries(
|
|
2256
|
+
Object.entries(slots).map(([name, node]) => [name, node])
|
|
2257
|
+
);
|
|
2258
|
+
} else {
|
|
2259
|
+
namedContent = extractMdxSlotsFromImportData(page.importData);
|
|
2260
|
+
}
|
|
1850
2261
|
const composedView = replaceSlots(layoutView, page.view, namedContent);
|
|
1851
2262
|
const mergedState = {};
|
|
1852
2263
|
for (const [name, field] of Object.entries(page.state)) {
|
|
@@ -1897,6 +2308,16 @@ function composeLayoutWithPage(layout, page, slots) {
|
|
|
1897
2308
|
if (Object.keys(mergedComponents).length > 0) {
|
|
1898
2309
|
result.components = mergedComponents;
|
|
1899
2310
|
}
|
|
2311
|
+
const mergedImportData = {
|
|
2312
|
+
...layout.importData || {},
|
|
2313
|
+
...page.importData || {}
|
|
2314
|
+
};
|
|
2315
|
+
if (Object.keys(mergedImportData).length > 0) {
|
|
2316
|
+
result.importData = mergedImportData;
|
|
2317
|
+
}
|
|
2318
|
+
if (page.lifecycle) {
|
|
2319
|
+
result.lifecycle = page.lifecycle;
|
|
2320
|
+
}
|
|
1900
2321
|
return result;
|
|
1901
2322
|
}
|
|
1902
2323
|
export {
|