mikuru 1.0.19 → 1.0.21
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/CHANGELOG.md +92 -0
- package/README.md +23 -13
- package/dist/compiler/analyzeTemplate.js +116 -12
- package/dist/compiler/analyzeTemplate.js.map +1 -1
- package/dist/compiler/compile.js +2 -2
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/compileHydration.d.ts +2 -0
- package/dist/compiler/compileHydration.js +27 -0
- package/dist/compiler/compileHydration.js.map +1 -0
- package/dist/compiler/compileSsr.d.ts +2 -0
- package/dist/compiler/compileSsr.js +21 -0
- package/dist/compiler/compileSsr.js.map +1 -0
- package/dist/compiler/generate.d.ts +6 -1
- package/dist/compiler/generate.js +1399 -93
- package/dist/compiler/generate.js.map +1 -1
- package/dist/compiler/generateHydration.d.ts +6 -0
- package/dist/compiler/generateHydration.js +1553 -0
- package/dist/compiler/generateHydration.js.map +1 -0
- package/dist/compiler/generateSsr.d.ts +2 -0
- package/dist/compiler/generateSsr.js +915 -0
- package/dist/compiler/generateSsr.js.map +1 -0
- package/dist/compiler/index.d.ts +3 -1
- package/dist/compiler/index.js +2 -0
- package/dist/compiler/index.js.map +1 -1
- package/dist/compiler/parseTemplate.js +16 -1
- package/dist/compiler/parseTemplate.js.map +1 -1
- package/dist/compiler/sourceMap.d.ts +2 -2
- package/dist/compiler/sourceMap.js +110 -6
- package/dist/compiler/sourceMap.js.map +1 -1
- package/dist/compiler/types.d.ts +8 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/router/index.d.ts +8 -0
- package/dist/router/index.js +133 -3
- package/dist/router/index.js.map +1 -1
- package/dist/runtime/asyncComponent.d.ts +22 -2
- package/dist/runtime/asyncComponent.js +84 -2
- package/dist/runtime/asyncComponent.js.map +1 -1
- package/dist/runtime/devtools.d.ts +51 -0
- package/dist/runtime/devtools.js +113 -0
- package/dist/runtime/devtools.js.map +1 -0
- package/dist/runtime/dom.d.ts +5 -1
- package/dist/runtime/dom.js +100 -3
- package/dist/runtime/dom.js.map +1 -1
- package/dist/runtime/index.d.ts +7 -5
- package/dist/runtime/index.js +3 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/lifecycle.d.ts +6 -0
- package/dist/runtime/lifecycle.js +66 -10
- package/dist/runtime/lifecycle.js.map +1 -1
- package/dist/runtime/reactivity.d.ts +33 -1
- package/dist/runtime/reactivity.js +254 -13
- package/dist/runtime/reactivity.js.map +1 -1
- package/dist/server.d.ts +33 -0
- package/dist/server.js +285 -0
- package/dist/server.js.map +1 -0
- package/dist/vite.d.ts +1 -0
- package/dist/vite.js +39 -18
- package/dist/vite.js.map +1 -1
- package/package.json +110 -100
- package/types/env.d.ts +58 -29
|
@@ -0,0 +1,915 @@
|
|
|
1
|
+
import { createCompileError } from "./errors.js";
|
|
2
|
+
import { compileTemplateExpression, parseForExpression } from "./parseExpression.js";
|
|
3
|
+
const voidElements = new Set([
|
|
4
|
+
"area",
|
|
5
|
+
"base",
|
|
6
|
+
"br",
|
|
7
|
+
"col",
|
|
8
|
+
"embed",
|
|
9
|
+
"hr",
|
|
10
|
+
"img",
|
|
11
|
+
"input",
|
|
12
|
+
"link",
|
|
13
|
+
"meta",
|
|
14
|
+
"param",
|
|
15
|
+
"source",
|
|
16
|
+
"track",
|
|
17
|
+
"wbr"
|
|
18
|
+
]);
|
|
19
|
+
export function generateSsr(descriptor, root) {
|
|
20
|
+
const context = {
|
|
21
|
+
lines: [],
|
|
22
|
+
index: 0,
|
|
23
|
+
teleportIndex: 0,
|
|
24
|
+
source: descriptor.source,
|
|
25
|
+
filename: descriptor.filename,
|
|
26
|
+
scopeAttr: descriptor.styleScoped ? createScopeAttr(descriptor) : undefined
|
|
27
|
+
};
|
|
28
|
+
const script = splitScript(descriptor.script ?? "");
|
|
29
|
+
for (const importLine of script.imports) {
|
|
30
|
+
emit(context, 0, importLine);
|
|
31
|
+
}
|
|
32
|
+
emit(context, 0, "import { escapeHtml as __mikuru_escape, renderAttr as __mikuru_renderAttr, renderAttrs as __mikuru_renderAttrs, renderComponentToString as __mikuru_renderComponent } from \"mikuru/server\";");
|
|
33
|
+
emit(context, 0, "import { unwrap as __mikuru_unwrap } from \"mikuru/runtime\";");
|
|
34
|
+
emit(context, 0, "");
|
|
35
|
+
emit(context, 0, "export async function renderToString(props = {}) {");
|
|
36
|
+
emit(context, 1, "let __mikuru_html = \"\";");
|
|
37
|
+
emit(context, 1, "const __mikuru_teleports = props.__mikuru_teleports ?? {};");
|
|
38
|
+
emit(context, 1, `const __mikuru_componentInfo = { component: ${quote(descriptor.filename ?? "anonymous.mikuru")}, filename: ${quote(descriptor.filename ?? "anonymous.mikuru")} };`);
|
|
39
|
+
emit(context, 1, "const __mikuru_context = { parent: props.__mikuru_context, provides: new Map(), ...__mikuru_componentInfo };");
|
|
40
|
+
emit(context, 1, "const __mikuru_ssrRegistrar = {");
|
|
41
|
+
emit(context, 2, "provide: (key, value) => __mikuru_context.provides.set(key, value),");
|
|
42
|
+
emit(context, 2, "inject: (key) => {");
|
|
43
|
+
emit(context, 3, "for (let context = __mikuru_context; context; context = context.parent) {");
|
|
44
|
+
emit(context, 4, "if (context.provides?.has(key)) return { found: true, value: context.provides.get(key) };");
|
|
45
|
+
emit(context, 3, "}");
|
|
46
|
+
emit(context, 3, "return { found: false };");
|
|
47
|
+
emit(context, 2, "}");
|
|
48
|
+
emit(context, 1, "};");
|
|
49
|
+
emit(context, 1, "const __mikuru_previousRegistrar = globalThis.__mikuru_currentRegistrar;");
|
|
50
|
+
emit(context, 1, "globalThis.__mikuru_currentRegistrar = __mikuru_ssrRegistrar;");
|
|
51
|
+
emit(context, 1, "try {");
|
|
52
|
+
if (script.body.trim()) {
|
|
53
|
+
emitRaw(context, script.body.trim());
|
|
54
|
+
emit(context, 2, "");
|
|
55
|
+
}
|
|
56
|
+
emitNode(context, root, 2);
|
|
57
|
+
emit(context, 2, "return __mikuru_html;");
|
|
58
|
+
emit(context, 1, "} finally {");
|
|
59
|
+
emit(context, 2, "globalThis.__mikuru_currentRegistrar = __mikuru_previousRegistrar;");
|
|
60
|
+
emit(context, 1, "}");
|
|
61
|
+
emit(context, 0, "}");
|
|
62
|
+
return `${context.lines.join("\n")}\n`;
|
|
63
|
+
}
|
|
64
|
+
function emitNode(context, node, indent) {
|
|
65
|
+
if (node.type === "text") {
|
|
66
|
+
emitText(context, node, indent);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
emitElement(context, node, indent);
|
|
70
|
+
}
|
|
71
|
+
function emitChildren(context, children, indent) {
|
|
72
|
+
for (let index = 0; index < children.length; index += 1) {
|
|
73
|
+
const child = children[index];
|
|
74
|
+
if (child.type === "element" && getAttr(child, "v-if")) {
|
|
75
|
+
const branches = [{ node: child, condition: getAttrValue(child, "v-if"), directive: "v-if" }];
|
|
76
|
+
let cursor = index + 1;
|
|
77
|
+
while (cursor < children.length && children[cursor]?.type === "element") {
|
|
78
|
+
const branchNode = children[cursor];
|
|
79
|
+
if (getAttr(branchNode, "v-else-if")) {
|
|
80
|
+
branches.push({ node: branchNode, condition: getAttrValue(branchNode, "v-else-if"), directive: "v-else-if" });
|
|
81
|
+
cursor += 1;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (getAttr(branchNode, "v-else")) {
|
|
85
|
+
branches.push({ node: branchNode, directive: "v-else" });
|
|
86
|
+
cursor += 1;
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
emitIfBranches(context, branches, indent);
|
|
91
|
+
index = cursor - 1;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (child.type === "element" && (getAttr(child, "v-else-if") || getAttr(child, "v-else"))) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
emitNode(context, child, indent);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function emitIfBranches(context, branches, indent) {
|
|
101
|
+
branches.forEach((branch, index) => {
|
|
102
|
+
const expression = branch.condition ? compileSsrExpression(context, branch.condition, branch.directive) : undefined;
|
|
103
|
+
if (index === 0) {
|
|
104
|
+
emit(context, indent, `if (__mikuru_unwrap(${expression})) {`);
|
|
105
|
+
}
|
|
106
|
+
else if (branch.directive === "v-else-if") {
|
|
107
|
+
emit(context, indent, `else if (__mikuru_unwrap(${expression})) {`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
emit(context, indent, "else {");
|
|
111
|
+
}
|
|
112
|
+
emitElement(context, branch.node, indent + 1, new Set(["v-if", "v-else-if", "v-else"]));
|
|
113
|
+
emit(context, indent, "}");
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function emitElement(context, node, indent, skippedAttrs = new Set()) {
|
|
117
|
+
if (getAttr(node, "v-pre") && !skippedAttrs.has("v-pre")) {
|
|
118
|
+
emitPreElement(context, node, indent);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const forAttr = getAttr(node, "v-for");
|
|
122
|
+
if (forAttr && !skippedAttrs.has("v-for")) {
|
|
123
|
+
const forExpression = parseForExpression(String(forAttr.value), expressionContext(context, forAttr, "v-for"));
|
|
124
|
+
const source = compileSsrExpression(context, forExpression.source, "v-for source");
|
|
125
|
+
const listVar = nextName(context, "list");
|
|
126
|
+
const entryVar = nextName(context, "entry");
|
|
127
|
+
emit(context, indent, `const ${listVar} = Array.from(__mikuru_unwrap(${source}) ?? []);`);
|
|
128
|
+
emit(context, indent, `for (const [__mikuru_index, ${entryVar}] of ${listVar}.entries()) {`);
|
|
129
|
+
emit(context, indent + 1, `const ${forExpression.item} = ${entryVar};`);
|
|
130
|
+
if (forExpression.index) {
|
|
131
|
+
emit(context, indent + 1, `const ${forExpression.index} = __mikuru_index;`);
|
|
132
|
+
}
|
|
133
|
+
emitElement(context, node, indent + 1, new Set([...skippedAttrs, "v-for"]));
|
|
134
|
+
emit(context, indent, "}");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (node.tag === "template") {
|
|
138
|
+
emitChildren(context, node.children, indent);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (node.tag === "slot") {
|
|
142
|
+
emitSlot(context, node, indent);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (node.tag === "component") {
|
|
146
|
+
emitDynamicComponent(context, node, indent);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (node.tag === "KeepAlive") {
|
|
150
|
+
emitKeepAlive(context, node, indent);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (node.tag === "AsyncBoundary") {
|
|
154
|
+
emitAsyncBoundary(context, node, indent);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (node.tag === "ErrorBoundary") {
|
|
158
|
+
emitErrorBoundary(context, node, indent);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (node.tag === "TransitionGroup") {
|
|
162
|
+
emitTransitionGroup(context, node, indent);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (node.tag === "Transition") {
|
|
166
|
+
emitTransition(context, node, indent);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (node.tag === "Teleport") {
|
|
170
|
+
emitTeleport(context, node, indent);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (isComponentTag(node.tag)) {
|
|
174
|
+
emitComponent(context, node, indent);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
emit(context, indent, `__mikuru_html += ${quote(`<${node.tag}`)};`);
|
|
178
|
+
emitAttrs(context, node, indent);
|
|
179
|
+
if (voidElements.has(node.tag.toLowerCase())) {
|
|
180
|
+
emit(context, indent, "__mikuru_html += \">\";");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
emit(context, indent, "__mikuru_html += \">\";");
|
|
184
|
+
const contentDirective = getContentDirectiveAttr(node);
|
|
185
|
+
if (contentDirective) {
|
|
186
|
+
emitContentDirective(context, contentDirective, indent);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
emitChildren(context, node.children, indent);
|
|
190
|
+
}
|
|
191
|
+
emit(context, indent, `__mikuru_html += ${quote(`</${node.tag}>`)};`);
|
|
192
|
+
}
|
|
193
|
+
function emitPreElement(context, node, indent) {
|
|
194
|
+
emit(context, indent, `__mikuru_html += ${quote(`<${node.tag}`)};`);
|
|
195
|
+
for (const attr of node.attrs) {
|
|
196
|
+
if (attr.name === "v-pre") {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${quote(attr.name)}, ${attr.value === true ? "true" : quote(attr.value)});`);
|
|
200
|
+
}
|
|
201
|
+
if (context.scopeAttr) {
|
|
202
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${quote(context.scopeAttr)}, true);`);
|
|
203
|
+
}
|
|
204
|
+
if (voidElements.has(node.tag.toLowerCase())) {
|
|
205
|
+
emit(context, indent, "__mikuru_html += \">\";");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
emit(context, indent, "__mikuru_html += \">\";");
|
|
209
|
+
for (const child of node.children) {
|
|
210
|
+
emitPreNode(context, child, indent);
|
|
211
|
+
}
|
|
212
|
+
emit(context, indent, `__mikuru_html += ${quote(`</${node.tag}>`)};`);
|
|
213
|
+
}
|
|
214
|
+
function emitPreNode(context, node, indent) {
|
|
215
|
+
if (node.type === "text") {
|
|
216
|
+
for (const part of node.parts) {
|
|
217
|
+
emit(context, indent, `__mikuru_html += __mikuru_escape(${quote(part.value)});`);
|
|
218
|
+
}
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
emitPreElement(context, node, indent);
|
|
222
|
+
}
|
|
223
|
+
function emitContentDirective(context, attr, indent) {
|
|
224
|
+
const expression = compileSsrExpression(context, requireAttrValue(attr), attr.name);
|
|
225
|
+
if (attr.name === "v-html") {
|
|
226
|
+
emit(context, indent, `__mikuru_html += String(__mikuru_unwrap(${expression}) ?? "");`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
emit(context, indent, `__mikuru_html += __mikuru_escape(__mikuru_unwrap(${expression}) ?? "");`);
|
|
230
|
+
}
|
|
231
|
+
function emitComponent(context, node, indent) {
|
|
232
|
+
const propsVar = nextName(context, "props");
|
|
233
|
+
emit(context, indent, `const ${propsVar} = {};`);
|
|
234
|
+
emitComponentProps(context, node, propsVar, indent);
|
|
235
|
+
emit(context, indent, `${propsVar}.__mikuru_context = __mikuru_context;`);
|
|
236
|
+
emitRouterViewRouteSlot(context, node, propsVar, indent);
|
|
237
|
+
if (node.children.length > 0) {
|
|
238
|
+
emitComponentSlots(context, node, propsVar, indent);
|
|
239
|
+
}
|
|
240
|
+
emit(context, indent, `__mikuru_html += await __mikuru_renderComponent(${node.tag}, ${propsVar});`);
|
|
241
|
+
}
|
|
242
|
+
function emitRouterViewRouteSlot(context, node, propsVar, indent) {
|
|
243
|
+
if (node.tag !== "RouterView")
|
|
244
|
+
return;
|
|
245
|
+
emit(context, indent, `if (typeof props.children === "function") { ${propsVar}.children = props.children; ${propsVar}.slots = { ...(${propsVar}.slots ?? {}), default: props.children }; }`);
|
|
246
|
+
}
|
|
247
|
+
function emitDynamicComponent(context, node, indent) {
|
|
248
|
+
const isAttr = node.attrs.find((attr) => parseBindDirective(attr.name)?.name === "is");
|
|
249
|
+
if (!isAttr) {
|
|
250
|
+
throw createCompileError("Dynamic component requires :is to resolve to a component object", contextSource(node), node.loc?.offset ?? 0);
|
|
251
|
+
}
|
|
252
|
+
const componentExpression = compileSsrExpression(context, requireAttrValue(isAttr), isAttr.name);
|
|
253
|
+
const dynamicNode = withoutDynamicComponentIs(node);
|
|
254
|
+
const componentVar = nextName(context, "dynamicComponent");
|
|
255
|
+
const propsVar = nextName(context, "props");
|
|
256
|
+
emit(context, indent, `const ${componentVar} = __mikuru_unwrap(${componentExpression});`);
|
|
257
|
+
emit(context, indent, `if (${componentVar}) {`);
|
|
258
|
+
emit(context, indent + 1, `if ((typeof ${componentVar} !== "object" && typeof ${componentVar} !== "function") || (typeof ${componentVar} === "object" && typeof ${componentVar}.renderToString !== "function") && typeof ${componentVar} !== "function") {`);
|
|
259
|
+
emit(context, indent + 2, `throw new Error("Dynamic component :is must resolve to a component object with renderToString()");`);
|
|
260
|
+
emit(context, indent + 1, "}");
|
|
261
|
+
emit(context, indent + 1, `const ${propsVar} = {};`);
|
|
262
|
+
emitComponentProps(context, dynamicNode, propsVar, indent + 1);
|
|
263
|
+
emit(context, indent + 1, `${propsVar}.__mikuru_context = __mikuru_context;`);
|
|
264
|
+
emitRouterViewRouteSlot(context, dynamicNode, propsVar, indent + 1);
|
|
265
|
+
if (dynamicNode.children.length > 0) {
|
|
266
|
+
emitComponentSlots(context, dynamicNode, propsVar, indent + 1);
|
|
267
|
+
}
|
|
268
|
+
emit(context, indent + 1, `__mikuru_html += await __mikuru_renderComponent(${componentVar}, ${propsVar});`);
|
|
269
|
+
emit(context, indent, "}");
|
|
270
|
+
}
|
|
271
|
+
function emitKeepAlive(context, node, indent) {
|
|
272
|
+
validateKeepAliveAttributes(node);
|
|
273
|
+
const child = getSingleElementChild(node, "<KeepAlive>");
|
|
274
|
+
if (child.tag !== "component") {
|
|
275
|
+
throw createCompileError("<KeepAlive> requires a single <component :is=\"...\" /> child in v1", contextSource(child), child.loc?.offset ?? 0);
|
|
276
|
+
}
|
|
277
|
+
if (!getDynamicComponentIsAttr(child)) {
|
|
278
|
+
throw createCompileError("<KeepAlive> dynamic child requires :is to resolve to a component object", contextSource(child), child.loc?.offset ?? 0);
|
|
279
|
+
}
|
|
280
|
+
emitDynamicComponent(context, child, indent);
|
|
281
|
+
}
|
|
282
|
+
function emitAsyncBoundary(context, node, indent) {
|
|
283
|
+
validateAsyncBoundaryAttributes(node);
|
|
284
|
+
emitChildren(context, getAsyncBoundaryChildren(node), indent);
|
|
285
|
+
}
|
|
286
|
+
function emitErrorBoundary(context, node, indent) {
|
|
287
|
+
validateErrorBoundaryAttributes(node);
|
|
288
|
+
getErrorBoundaryFallbackAttr(node);
|
|
289
|
+
emitElement(context, getSingleElementChild(node, "<ErrorBoundary>"), indent);
|
|
290
|
+
}
|
|
291
|
+
function emitTransition(context, node, indent) {
|
|
292
|
+
validateTransitionAttributes(node);
|
|
293
|
+
const children = getTransitionChildren(node);
|
|
294
|
+
if (getAttr(children[0], "v-if")) {
|
|
295
|
+
emitIfBranches(context, getTransitionBranches(children), indent);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
emitElement(context, children[0], indent);
|
|
299
|
+
}
|
|
300
|
+
function emitTransitionGroup(context, node, indent) {
|
|
301
|
+
validateTransitionGroupAttributes(node);
|
|
302
|
+
const child = getTransitionGroupChild(node);
|
|
303
|
+
const tagVar = nextName(context, "transitionGroupTag");
|
|
304
|
+
emit(context, indent, `const ${tagVar} = String(__mikuru_unwrap(${getTransitionGroupTagExpression(context, node)}) ?? "span");`);
|
|
305
|
+
emit(context, indent, `__mikuru_html += "<" + ${tagVar} + ">";`);
|
|
306
|
+
emitElement(context, withoutAttrs(child, [":key", "v-bind:key"]), indent);
|
|
307
|
+
emit(context, indent, `__mikuru_html += "</" + ${tagVar} + ">";`);
|
|
308
|
+
}
|
|
309
|
+
function emitTeleport(context, node, indent) {
|
|
310
|
+
const id = `t${context.teleportIndex}`;
|
|
311
|
+
context.teleportIndex += 1;
|
|
312
|
+
const toExpression = getTeleportToExpression(context, node);
|
|
313
|
+
const disabledExpression = getTeleportDisabledExpression(context, node);
|
|
314
|
+
const disabledVar = nextName(context, "teleportDisabled");
|
|
315
|
+
const targetVar = nextName(context, "teleportTarget");
|
|
316
|
+
const previousHtmlVar = nextName(context, "previousHtml");
|
|
317
|
+
const contentVar = nextName(context, "teleportContent");
|
|
318
|
+
emit(context, indent, `__mikuru_html += ${quote(`<!--teleport:${id}-->`)};`);
|
|
319
|
+
emit(context, indent, `const ${disabledVar} = Boolean(__mikuru_unwrap(${disabledExpression}));`);
|
|
320
|
+
emit(context, indent, `if (${disabledVar}) {`);
|
|
321
|
+
emitChildren(context, node.children, indent + 1);
|
|
322
|
+
emit(context, indent, "} else {");
|
|
323
|
+
emit(context, indent + 1, `const ${targetVar} = __mikuru_unwrap(${toExpression});`);
|
|
324
|
+
emit(context, indent + 1, `if (typeof ${targetVar} !== "string") { throw new Error("SSR Teleport target must be a string selector."); }`);
|
|
325
|
+
emit(context, indent + 1, `const ${previousHtmlVar} = __mikuru_html;`);
|
|
326
|
+
emit(context, indent + 1, "__mikuru_html = \"\";");
|
|
327
|
+
emitChildren(context, node.children, indent + 1);
|
|
328
|
+
emit(context, indent + 1, `const ${contentVar} = __mikuru_html;`);
|
|
329
|
+
emit(context, indent + 1, `__mikuru_html = ${previousHtmlVar};`);
|
|
330
|
+
emit(context, indent + 1, `__mikuru_teleports[${targetVar}] = (__mikuru_teleports[${targetVar}] ?? "") + ${quote(`<!--teleport content:${id}-->`)} + ${contentVar} + ${quote(`<!--/teleport content:${id}-->`)};`);
|
|
331
|
+
emit(context, indent, "}");
|
|
332
|
+
emit(context, indent, `__mikuru_html += ${quote(`<!--/teleport:${id}-->`)};`);
|
|
333
|
+
}
|
|
334
|
+
function emitComponentSlots(context, node, propsVar, indent) {
|
|
335
|
+
const defaultChildren = [];
|
|
336
|
+
const namedSlots = [];
|
|
337
|
+
for (const child of node.children) {
|
|
338
|
+
if (child.type === "element" && child.tag === "template") {
|
|
339
|
+
const slot = getSlotTemplate(child);
|
|
340
|
+
if (slot) {
|
|
341
|
+
namedSlots.push({ ...slot, children: child.children });
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
defaultChildren.push(child);
|
|
346
|
+
}
|
|
347
|
+
const slotEntries = [];
|
|
348
|
+
if (defaultChildren.length > 0) {
|
|
349
|
+
const slotVar = emitSlotFunction(context, defaultChildren, indent, undefined);
|
|
350
|
+
emit(context, indent, `${propsVar}.children = ${slotVar};`);
|
|
351
|
+
slotEntries.push(`default: ${slotVar}`);
|
|
352
|
+
}
|
|
353
|
+
for (const slot of namedSlots) {
|
|
354
|
+
const slotVar = emitSlotFunction(context, slot.children, indent, slot.scope);
|
|
355
|
+
slotEntries.push(`${quote(slot.name)}: ${slotVar}`);
|
|
356
|
+
}
|
|
357
|
+
if (slotEntries.length > 0) {
|
|
358
|
+
emit(context, indent, `${propsVar}.slots = { ${slotEntries.join(", ")} };`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function emitSlotFunction(context, children, indent, scope) {
|
|
362
|
+
const slotVar = nextName(context, "slot");
|
|
363
|
+
const propsVar = nextName(context, "slotProps");
|
|
364
|
+
emit(context, indent, `const ${slotVar} = async (${propsVar} = {}) => {`);
|
|
365
|
+
emit(context, indent + 1, "const __mikuru_previousSlotRegistrar = globalThis.__mikuru_currentRegistrar;");
|
|
366
|
+
emit(context, indent + 1, "globalThis.__mikuru_currentRegistrar = __mikuru_ssrRegistrar;");
|
|
367
|
+
emit(context, indent + 1, "try {");
|
|
368
|
+
if (scope) {
|
|
369
|
+
emit(context, indent + 2, `const ${scope} = ${propsVar};`);
|
|
370
|
+
}
|
|
371
|
+
emit(context, indent + 2, "let __mikuru_html = \"\";");
|
|
372
|
+
emitChildren(context, children, indent + 2);
|
|
373
|
+
emit(context, indent + 2, "return __mikuru_html;");
|
|
374
|
+
emit(context, indent + 1, "} finally {");
|
|
375
|
+
emit(context, indent + 2, "globalThis.__mikuru_currentRegistrar = __mikuru_previousSlotRegistrar;");
|
|
376
|
+
emit(context, indent + 1, "}");
|
|
377
|
+
emit(context, indent, "};");
|
|
378
|
+
return slotVar;
|
|
379
|
+
}
|
|
380
|
+
function emitComponentProps(context, node, propsVar, indent) {
|
|
381
|
+
for (const attr of node.attrs) {
|
|
382
|
+
if (shouldSkipAttr(attr)) {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
const objectBindDirective = parseObjectBindDirective(attr.name);
|
|
386
|
+
if (objectBindDirective) {
|
|
387
|
+
validateObjectBindModifiers(objectBindDirective, attr, "component");
|
|
388
|
+
emit(context, indent, `Object.assign(${propsVar}, __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)}) ?? {});`);
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
const bindDirective = parseBindDirective(attr.name);
|
|
392
|
+
const dynamicArgument = bindDirective?.nameExpression ? bindDirective : undefined;
|
|
393
|
+
if (dynamicArgument) {
|
|
394
|
+
validateBindModifiers(dynamicArgument, attr, "component");
|
|
395
|
+
emit(context, indent, `${propsVar}[${bindNameExpression(`String(__mikuru_unwrap(${compileSsrExpression(context, dynamicArgument.nameExpression ?? "", attr.name)}) ?? "")`, dynamicArgument)}] = __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)});`);
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
const dynamicName = bindDirective?.name;
|
|
399
|
+
if (dynamicName) {
|
|
400
|
+
validateBindModifiers(bindDirective, attr, "component");
|
|
401
|
+
emit(context, indent, `${propsVar}[${quote(dynamicName)}] = __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)});`);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
emit(context, indent, `${propsVar}[${quote(attr.name)}] = ${attr.value === true ? "true" : quote(attr.value)};`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function emitSlot(context, node, indent) {
|
|
408
|
+
const slotVar = nextName(context, "slotValue");
|
|
409
|
+
const slotName = getSlotName(context, node);
|
|
410
|
+
const slotPropsVar = nextName(context, "slotProps");
|
|
411
|
+
emit(context, indent, `const ${slotVar} = props.slots?.[${slotName}] ?? ${slotName === "\"default\"" ? "props.children" : "undefined"};`);
|
|
412
|
+
emit(context, indent, `const ${slotPropsVar} = {};`);
|
|
413
|
+
emit(context, indent, `${slotPropsVar}.__mikuru_context = __mikuru_context;`);
|
|
414
|
+
emitSlotProps(context, node, slotPropsVar, indent);
|
|
415
|
+
emit(context, indent, `if (typeof ${slotVar} === "function") {`);
|
|
416
|
+
emit(context, indent + 1, `__mikuru_html += await ${slotVar}(${slotPropsVar});`);
|
|
417
|
+
emit(context, indent, `} else if (${slotVar} !== undefined && ${slotVar} !== null) {`);
|
|
418
|
+
emit(context, indent + 1, `__mikuru_html += __mikuru_escape(${slotVar});`);
|
|
419
|
+
if (node.children.length > 0) {
|
|
420
|
+
emit(context, indent, "} else {");
|
|
421
|
+
emitChildren(context, node.children, indent + 1);
|
|
422
|
+
}
|
|
423
|
+
emit(context, indent, "}");
|
|
424
|
+
}
|
|
425
|
+
function emitSlotProps(context, node, propsVar, indent) {
|
|
426
|
+
for (const attr of node.attrs) {
|
|
427
|
+
if (attr.name === "name" || attr.name === ":name" || attr.name === "v-bind:name" || shouldSkipAttr(attr)) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const objectBindDirective = parseObjectBindDirective(attr.name);
|
|
431
|
+
if (objectBindDirective) {
|
|
432
|
+
validateObjectBindModifiers(objectBindDirective, attr, "component");
|
|
433
|
+
emit(context, indent, `Object.assign(${propsVar}, __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)}) ?? {});`);
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
const bindDirective = parseBindDirective(attr.name);
|
|
437
|
+
const dynamicArgument = bindDirective?.nameExpression ? bindDirective : undefined;
|
|
438
|
+
if (dynamicArgument) {
|
|
439
|
+
validateBindModifiers(dynamicArgument, attr, "component");
|
|
440
|
+
emit(context, indent, `${propsVar}[${bindNameExpression(`String(__mikuru_unwrap(${compileSsrExpression(context, dynamicArgument.nameExpression ?? "", attr.name)}) ?? "")`, dynamicArgument)}] = __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)});`);
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const dynamicName = bindDirective?.name;
|
|
444
|
+
if (dynamicName) {
|
|
445
|
+
validateBindModifiers(bindDirective, attr, "component");
|
|
446
|
+
emit(context, indent, `${propsVar}[${quote(dynamicName)}] = __mikuru_unwrap(${compileSsrExpression(context, String(attr.value), attr.name)});`);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
emit(context, indent, `${propsVar}[${quote(attr.name)}] = ${attr.value === true ? "true" : quote(attr.value)};`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function emitAttrs(context, node, indent) {
|
|
453
|
+
const staticClass = getStaticAttrValue(node, "class");
|
|
454
|
+
const staticStyle = getStaticAttrValue(node, "style");
|
|
455
|
+
const hasObjectBind = node.attrs.some((attr) => Boolean(parseObjectBindDirective(attr.name)));
|
|
456
|
+
const hasDynamicClass = node.attrs.some((attr) => getDynamicAttrName(attr.name) === "class");
|
|
457
|
+
const hasDynamicStyle = node.attrs.some((attr) => getDynamicAttrName(attr.name) === "style");
|
|
458
|
+
for (const attr of node.attrs) {
|
|
459
|
+
if (attr.name === "v-cloak") {
|
|
460
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr("v-cloak", "");`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (shouldSkipAttr(attr)) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
const objectBindDirective = parseObjectBindDirective(attr.name);
|
|
467
|
+
if (objectBindDirective) {
|
|
468
|
+
validateObjectBindModifiers(objectBindDirective, attr, "element");
|
|
469
|
+
if (objectBindDirective.modifiers.includes("prop")) {
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
const value = String(attr.value);
|
|
473
|
+
const attrsVar = nextName(context, "attrs");
|
|
474
|
+
const renderedAttrsVar = objectBindDirective.modifiers.includes("camel") ? nextName(context, "attrs") : attrsVar;
|
|
475
|
+
emit(context, indent, "{");
|
|
476
|
+
emit(context, indent + 1, `const ${attrsVar} = __mikuru_unwrap(${compileSsrExpression(context, value, "v-bind")}) ?? {};`);
|
|
477
|
+
if (objectBindDirective.modifiers.includes("camel")) {
|
|
478
|
+
emit(context, indent + 1, `const ${renderedAttrsVar} = Object.fromEntries(Object.entries(${attrsVar}).map(([key, value]) => [String(key).replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase()), value]));`);
|
|
479
|
+
}
|
|
480
|
+
emit(context, indent + 1, `__mikuru_html += __mikuru_renderAttrs({ ...${renderedAttrsVar}${staticClass ? `, class: [${quote(staticClass)}, ${renderedAttrsVar}.class]` : ""}${staticStyle ? `, style: [${quote(staticStyle)}, ${renderedAttrsVar}.style]` : ""} });`);
|
|
481
|
+
emit(context, indent, "}");
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
const bindDirective = parseBindDirective(attr.name);
|
|
485
|
+
const dynamicArgument = bindDirective?.nameExpression ? bindDirective : undefined;
|
|
486
|
+
if (dynamicArgument) {
|
|
487
|
+
validateBindModifiers(dynamicArgument, attr, "element");
|
|
488
|
+
if (dynamicArgument.modifiers.includes("prop")) {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
const value = String(attr.value);
|
|
492
|
+
const nameExpression = compileSsrExpression(context, dynamicArgument.nameExpression ?? "", attr.name);
|
|
493
|
+
const valueExpression = compileSsrExpression(context, value, attr.name);
|
|
494
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${bindNameExpression(`String(__mikuru_unwrap(${nameExpression}) ?? "")`, dynamicArgument)}, __mikuru_unwrap(${valueExpression}));`);
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
const dynamicName = bindDirective?.name;
|
|
498
|
+
if (dynamicName) {
|
|
499
|
+
validateBindModifiers(bindDirective, attr, "element");
|
|
500
|
+
if (bindDirective.modifiers.includes("prop")) {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
const value = String(attr.value);
|
|
504
|
+
const expression = compileSsrExpression(context, value, attr.name);
|
|
505
|
+
const valueExpression = dynamicName === "class" && staticClass
|
|
506
|
+
? `[${quote(staticClass)}, __mikuru_unwrap(${expression})]`
|
|
507
|
+
: dynamicName === "style" && staticStyle
|
|
508
|
+
? `[${quote(staticStyle)}, __mikuru_unwrap(${expression})]`
|
|
509
|
+
: `__mikuru_unwrap(${expression})`;
|
|
510
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${quote(dynamicName)}, ${valueExpression});`);
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
if ((attr.name === "class" && (hasDynamicClass || hasObjectBind)) || (attr.name === "style" && (hasDynamicStyle || hasObjectBind))) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${quote(attr.name)}, ${attr.value === true ? "true" : quote(attr.value)});`);
|
|
517
|
+
}
|
|
518
|
+
if (context.scopeAttr) {
|
|
519
|
+
emit(context, indent, `__mikuru_html += __mikuru_renderAttr(${quote(context.scopeAttr)}, true);`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function emitText(context, node, indent) {
|
|
523
|
+
for (const part of node.parts) {
|
|
524
|
+
if (part.type === "static") {
|
|
525
|
+
emit(context, indent, `__mikuru_html += __mikuru_escape(${quote(part.value)});`);
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
emit(context, indent, `__mikuru_html += __mikuru_escape(__mikuru_unwrap(${compileSsrExpression(context, part.value, "interpolation")}));`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function shouldSkipAttr(attr) {
|
|
532
|
+
return attr.name === "v-if"
|
|
533
|
+
|| attr.name === "v-else-if"
|
|
534
|
+
|| attr.name === "v-else"
|
|
535
|
+
|| attr.name === "v-for"
|
|
536
|
+
|| attr.name === "v-show"
|
|
537
|
+
|| attr.name === "v-html"
|
|
538
|
+
|| attr.name === "v-text"
|
|
539
|
+
|| attr.name === "v-pre"
|
|
540
|
+
|| attr.name === "v-cloak"
|
|
541
|
+
|| attr.name === "v-model"
|
|
542
|
+
|| attr.name === "ref"
|
|
543
|
+
|| attr.name === "key"
|
|
544
|
+
|| attr.name.startsWith("@")
|
|
545
|
+
|| attr.name.startsWith("v-on:")
|
|
546
|
+
|| attr.name.startsWith("#")
|
|
547
|
+
|| attr.name.startsWith("v-slot");
|
|
548
|
+
}
|
|
549
|
+
function getDynamicAttrName(name) {
|
|
550
|
+
const binding = parseBindDirective(name);
|
|
551
|
+
return binding?.nameExpression ? undefined : binding?.name;
|
|
552
|
+
}
|
|
553
|
+
function getDynamicAttrArgument(name) {
|
|
554
|
+
const binding = parseBindDirective(name);
|
|
555
|
+
return binding?.nameExpression ? { expression: binding.nameExpression } : undefined;
|
|
556
|
+
}
|
|
557
|
+
function parseBindDirective(name) {
|
|
558
|
+
const dynamic = parseDynamicArgument(name, [":", "v-bind:"]);
|
|
559
|
+
if (dynamic) {
|
|
560
|
+
return { nameExpression: dynamic.expression, modifiers: dynamic.modifiers };
|
|
561
|
+
}
|
|
562
|
+
const rawName = name.startsWith(":")
|
|
563
|
+
? name.slice(1)
|
|
564
|
+
: name.startsWith("v-bind:")
|
|
565
|
+
? name.slice("v-bind:".length)
|
|
566
|
+
: undefined;
|
|
567
|
+
if (!rawName) {
|
|
568
|
+
return undefined;
|
|
569
|
+
}
|
|
570
|
+
const [bindingName, ...modifiers] = rawName.split(".");
|
|
571
|
+
if (!bindingName) {
|
|
572
|
+
return undefined;
|
|
573
|
+
}
|
|
574
|
+
return { name: modifiers.includes("camel") ? camelize(bindingName) : bindingName, modifiers };
|
|
575
|
+
}
|
|
576
|
+
function validateBindModifiers(binding, attr, target) {
|
|
577
|
+
const allowed = new Set(["camel", "prop", "attr"]);
|
|
578
|
+
for (const modifier of binding.modifiers) {
|
|
579
|
+
if (!allowed.has(modifier)) {
|
|
580
|
+
throw new Error(`Unsupported v-bind modifier ".${modifier}" on ${attr.name}. Use .camel, .prop, or .attr.`);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (binding.modifiers.includes("prop") && binding.modifiers.includes("attr")) {
|
|
584
|
+
throw new Error(`v-bind modifiers .prop and .attr cannot be used together on ${attr.name}`);
|
|
585
|
+
}
|
|
586
|
+
if (target === "component" && (binding.modifiers.includes("prop") || binding.modifiers.includes("attr"))) {
|
|
587
|
+
throw new Error(`v-bind .prop and .attr modifiers are only supported on native elements: ${attr.name}`);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
function validateObjectBindModifiers(binding, attr, target) {
|
|
591
|
+
const allowed = new Set(["camel", "prop", "attr"]);
|
|
592
|
+
for (const modifier of binding.modifiers) {
|
|
593
|
+
if (!allowed.has(modifier)) {
|
|
594
|
+
throw new Error(`Unsupported object v-bind modifier ".${modifier}" on ${attr.name}. Use .camel, .prop, or .attr.`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (binding.modifiers.includes("prop") && binding.modifiers.includes("attr")) {
|
|
598
|
+
throw new Error(`Object v-bind modifiers .prop and .attr cannot be used together on ${attr.name}`);
|
|
599
|
+
}
|
|
600
|
+
if (target === "component" && binding.modifiers.length > 0) {
|
|
601
|
+
throw new Error(`Object v-bind modifiers are only supported on native elements: ${attr.name}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function bindNameExpression(expression, binding) {
|
|
605
|
+
return binding.modifiers.includes("camel") ? `(${expression}).replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase())` : expression;
|
|
606
|
+
}
|
|
607
|
+
function camelize(value) {
|
|
608
|
+
return value.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
609
|
+
}
|
|
610
|
+
function parseObjectBindDirective(name) {
|
|
611
|
+
if (name === "v-bind") {
|
|
612
|
+
return { modifiers: [] };
|
|
613
|
+
}
|
|
614
|
+
if (!name.startsWith("v-bind.")) {
|
|
615
|
+
return undefined;
|
|
616
|
+
}
|
|
617
|
+
return { modifiers: name.slice("v-bind.".length).split(".").filter(Boolean) };
|
|
618
|
+
}
|
|
619
|
+
function parseDynamicArgument(name, prefixes) {
|
|
620
|
+
for (const prefix of prefixes) {
|
|
621
|
+
if (!name.startsWith(`${prefix}[`)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const argumentStart = prefix.length + 1;
|
|
625
|
+
const argumentEnd = name.indexOf("]", argumentStart);
|
|
626
|
+
if (argumentEnd === -1) {
|
|
627
|
+
return undefined;
|
|
628
|
+
}
|
|
629
|
+
const expression = name.slice(argumentStart, argumentEnd).trim();
|
|
630
|
+
if (!expression) {
|
|
631
|
+
return undefined;
|
|
632
|
+
}
|
|
633
|
+
const rest = name.slice(argumentEnd + 1);
|
|
634
|
+
const modifiers = rest.startsWith(".") ? rest.slice(1).split(".").filter(Boolean) : [];
|
|
635
|
+
return { expression, modifiers };
|
|
636
|
+
}
|
|
637
|
+
return undefined;
|
|
638
|
+
}
|
|
639
|
+
function getSlotTemplate(node) {
|
|
640
|
+
for (const attr of node.attrs) {
|
|
641
|
+
if (attr.name === "v-slot") {
|
|
642
|
+
return { name: "default", scope: attr.value === true ? undefined : String(attr.value) };
|
|
643
|
+
}
|
|
644
|
+
if (attr.name.startsWith("#") && !attr.name.startsWith("#[")) {
|
|
645
|
+
return { name: attr.name.slice(1) || "default", scope: attr.value === true ? undefined : String(attr.value) };
|
|
646
|
+
}
|
|
647
|
+
if (attr.name.startsWith("v-slot:")) {
|
|
648
|
+
return { name: attr.name.slice("v-slot:".length) || "default", scope: attr.value === true ? undefined : String(attr.value) };
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return undefined;
|
|
652
|
+
}
|
|
653
|
+
function getSlotName(context, node) {
|
|
654
|
+
const dynamicName = getAttr(node, ":name") ?? getAttr(node, "v-bind:name");
|
|
655
|
+
if (dynamicName && dynamicName.value !== true) {
|
|
656
|
+
return `String(__mikuru_unwrap(${compileSsrExpression(context, String(dynamicName.value), "slot name")}) ?? "default")`;
|
|
657
|
+
}
|
|
658
|
+
const staticName = getAttr(node, "name");
|
|
659
|
+
if (staticName && staticName.value !== true) {
|
|
660
|
+
return quote(staticName.value);
|
|
661
|
+
}
|
|
662
|
+
return quote("default");
|
|
663
|
+
}
|
|
664
|
+
function getTeleportToExpression(context, node) {
|
|
665
|
+
const dynamicTarget = getAttr(node, ":to") ?? getAttr(node, "v-bind:to");
|
|
666
|
+
if (dynamicTarget && dynamicTarget.value !== true) {
|
|
667
|
+
return compileSsrExpression(context, String(dynamicTarget.value), "Teleport to");
|
|
668
|
+
}
|
|
669
|
+
const staticTarget = getAttr(node, "to");
|
|
670
|
+
if (staticTarget && staticTarget.value !== true) {
|
|
671
|
+
return quote(staticTarget.value);
|
|
672
|
+
}
|
|
673
|
+
throw createCompileError("<Teleport> requires a to target", contextSource(node), node.loc?.offset ?? 0);
|
|
674
|
+
}
|
|
675
|
+
function getTeleportDisabledExpression(context, node) {
|
|
676
|
+
const dynamicDisabled = getAttr(node, ":disabled") ?? getAttr(node, "v-bind:disabled");
|
|
677
|
+
if (dynamicDisabled && dynamicDisabled.value !== true) {
|
|
678
|
+
return compileSsrExpression(context, String(dynamicDisabled.value), "Teleport disabled");
|
|
679
|
+
}
|
|
680
|
+
return getAttr(node, "disabled") ? "true" : "false";
|
|
681
|
+
}
|
|
682
|
+
function validateKeepAliveAttributes(node) {
|
|
683
|
+
for (const attr of node.attrs) {
|
|
684
|
+
const name = parseBindDirective(attr.name)?.name ?? attr.name;
|
|
685
|
+
if (name === "include" || name === "exclude" || name === "max") {
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
throw createCompileError(`Unsupported attribute "${attr.name}" on <KeepAlive>. Supported attributes: include, exclude, and max.`, contextSource(node), attr.loc?.offset ?? node.loc?.offset ?? 0);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
function validateAsyncBoundaryAttributes(node) {
|
|
692
|
+
for (const attr of node.attrs) {
|
|
693
|
+
const name = parseBindDirective(attr.name)?.name ?? attr.name;
|
|
694
|
+
if (name === "loading" || name === "fallback" || name === "delay" || name === "timeout") {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
throw createCompileError(`Unsupported attribute "${attr.name}" on <AsyncBoundary>. Supported attributes: loading, fallback, delay, and timeout.`, contextSource(node), attr.loc?.offset ?? node.loc?.offset ?? 0);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
function validateErrorBoundaryAttributes(node) {
|
|
701
|
+
for (const attr of node.attrs) {
|
|
702
|
+
const name = parseBindDirective(attr.name)?.name ?? attr.name;
|
|
703
|
+
if (name === "fallback" || name === "reset-key") {
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
throw createCompileError(`Unsupported attribute "${attr.name}" on <ErrorBoundary>. Supported attributes: fallback and reset-key.`, contextSource(node), attr.loc?.offset ?? node.loc?.offset ?? 0);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
function getErrorBoundaryFallbackAttr(node) {
|
|
710
|
+
const attr = node.attrs.find((candidate) => parseBindDirective(candidate.name)?.name === "fallback");
|
|
711
|
+
if (!attr) {
|
|
712
|
+
throw createCompileError("<ErrorBoundary> requires :fallback to resolve to a component object", contextSource(node), node.loc?.offset ?? 0);
|
|
713
|
+
}
|
|
714
|
+
return attr;
|
|
715
|
+
}
|
|
716
|
+
function validateTransitionAttributes(node) {
|
|
717
|
+
const supported = new Set([
|
|
718
|
+
"name",
|
|
719
|
+
"appear",
|
|
720
|
+
"mode",
|
|
721
|
+
"enter-from-class",
|
|
722
|
+
"enter-active-class",
|
|
723
|
+
"enter-to-class",
|
|
724
|
+
"leave-from-class",
|
|
725
|
+
"leave-active-class",
|
|
726
|
+
"leave-to-class"
|
|
727
|
+
]);
|
|
728
|
+
for (const attr of node.attrs) {
|
|
729
|
+
const name = parseBindDirective(attr.name)?.name ?? attr.name;
|
|
730
|
+
if (supported.has(name)) {
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
throw createCompileError(`Unsupported attribute "${attr.name}" on <Transition>. Supported attributes: name, appear, mode, and CSS class override attributes.`, contextSource(node), attr.loc?.offset ?? node.loc?.offset ?? 0);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
function validateTransitionGroupAttributes(node) {
|
|
737
|
+
const supported = new Set([
|
|
738
|
+
"name",
|
|
739
|
+
"tag",
|
|
740
|
+
"enter-from-class",
|
|
741
|
+
"enter-active-class",
|
|
742
|
+
"enter-to-class",
|
|
743
|
+
"leave-from-class",
|
|
744
|
+
"leave-active-class",
|
|
745
|
+
"leave-to-class",
|
|
746
|
+
"move-class"
|
|
747
|
+
]);
|
|
748
|
+
for (const attr of node.attrs) {
|
|
749
|
+
const name = parseBindDirective(attr.name)?.name ?? attr.name;
|
|
750
|
+
if (supported.has(name)) {
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
throw createCompileError(`Unsupported attribute "${attr.name}" on <TransitionGroup>. Supported attributes: name, tag, and CSS class override attributes.`, contextSource(node), attr.loc?.offset ?? node.loc?.offset ?? 0);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function getAsyncBoundaryChildren(node) {
|
|
757
|
+
const meaningful = node.children.filter((child) => child.type === "element" || child.parts.some((part) => part.value.trim()));
|
|
758
|
+
if (meaningful.length === 0) {
|
|
759
|
+
throw createCompileError("<AsyncBoundary> requires at least one child", contextSource(node), node.loc?.offset ?? 0);
|
|
760
|
+
}
|
|
761
|
+
return node.children;
|
|
762
|
+
}
|
|
763
|
+
function getTransitionChildren(node) {
|
|
764
|
+
const meaningful = node.children.filter((child) => child.type === "element" || child.parts.some((part) => part.value.trim()));
|
|
765
|
+
if (meaningful.length === 0 || meaningful.some((child) => child.type !== "element")) {
|
|
766
|
+
throw createCompileError("<Transition> requires exactly one element/component child or one v-if chain", contextSource(node), node.loc?.offset ?? 0);
|
|
767
|
+
}
|
|
768
|
+
const children = meaningful;
|
|
769
|
+
if (children.length === 1) {
|
|
770
|
+
return children;
|
|
771
|
+
}
|
|
772
|
+
if (!getAttr(children[0], "v-if")) {
|
|
773
|
+
throw createCompileError("<Transition> requires exactly one element/component child or one v-if chain", contextSource(node), node.loc?.offset ?? 0);
|
|
774
|
+
}
|
|
775
|
+
for (const child of children.slice(1)) {
|
|
776
|
+
if (!getAttr(child, "v-else-if") && !getAttr(child, "v-else")) {
|
|
777
|
+
throw createCompileError("<Transition> only accepts multiple children when they form a v-if chain", contextSource(child), child.loc?.offset ?? node.loc?.offset ?? 0);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
return children;
|
|
781
|
+
}
|
|
782
|
+
function getTransitionBranches(children) {
|
|
783
|
+
return children.map((child, index) => {
|
|
784
|
+
if (index === 0) {
|
|
785
|
+
return { node: child, condition: getAttrValue(child, "v-if"), directive: "v-if" };
|
|
786
|
+
}
|
|
787
|
+
if (getAttr(child, "v-else-if")) {
|
|
788
|
+
return { node: child, condition: getAttrValue(child, "v-else-if"), directive: "v-else-if" };
|
|
789
|
+
}
|
|
790
|
+
return { node: child, directive: "v-else" };
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
function getTransitionGroupChild(node) {
|
|
794
|
+
const child = getSingleElementChild(node, "<TransitionGroup>");
|
|
795
|
+
if (!getAttr(child, "v-for") || !getKeyExpression(child)) {
|
|
796
|
+
throw createCompileError("<TransitionGroup> requires a single keyed v-for child in v1", contextSource(child), child.loc?.offset ?? node.loc?.offset ?? 0);
|
|
797
|
+
}
|
|
798
|
+
return child;
|
|
799
|
+
}
|
|
800
|
+
function getTransitionGroupTagExpression(context, node) {
|
|
801
|
+
const dynamicTag = node.attrs.find((attr) => parseBindDirective(attr.name)?.name === "tag");
|
|
802
|
+
if (dynamicTag) {
|
|
803
|
+
return compileSsrExpression(context, requireAttrValue(dynamicTag), dynamicTag.name);
|
|
804
|
+
}
|
|
805
|
+
return quote(getStaticAttrValue(node, "tag") ?? "span");
|
|
806
|
+
}
|
|
807
|
+
function getKeyExpression(node) {
|
|
808
|
+
return getStaticAttrValue(node, ":key") ?? getStaticAttrValue(node, "v-bind:key");
|
|
809
|
+
}
|
|
810
|
+
function withoutAttrs(node, names) {
|
|
811
|
+
return {
|
|
812
|
+
...node,
|
|
813
|
+
attrs: node.attrs.filter((attr) => !names.includes(attr.name))
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function getSingleElementChild(node, label) {
|
|
817
|
+
const meaningful = node.children.filter((child) => child.type === "element" || child.parts.some((part) => part.value.trim()));
|
|
818
|
+
if (meaningful.length !== 1 || meaningful[0]?.type !== "element") {
|
|
819
|
+
throw createCompileError(`${label} requires exactly one element or component child`, contextSource(node), node.loc?.offset ?? 0);
|
|
820
|
+
}
|
|
821
|
+
return meaningful[0];
|
|
822
|
+
}
|
|
823
|
+
function getDynamicComponentIsAttr(node) {
|
|
824
|
+
return node.attrs.find((attr) => parseBindDirective(attr.name)?.name === "is");
|
|
825
|
+
}
|
|
826
|
+
function withoutDynamicComponentIs(node) {
|
|
827
|
+
return {
|
|
828
|
+
...node,
|
|
829
|
+
attrs: node.attrs.filter((attr) => parseBindDirective(attr.name)?.name !== "is")
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function isComponentTag(tag) {
|
|
833
|
+
return /^[A-Z]/.test(tag);
|
|
834
|
+
}
|
|
835
|
+
function getAttr(node, name) {
|
|
836
|
+
return node.attrs.find((attr) => attr.name === name);
|
|
837
|
+
}
|
|
838
|
+
function getAttrValue(node, name) {
|
|
839
|
+
const attr = getAttr(node, name);
|
|
840
|
+
if (!attr || attr.value === true) {
|
|
841
|
+
throw createCompileError(`${name} requires an expression`, contextSource(node), node.loc?.offset ?? 0);
|
|
842
|
+
}
|
|
843
|
+
return attr.value;
|
|
844
|
+
}
|
|
845
|
+
function getStaticAttrValue(node, name) {
|
|
846
|
+
const attr = getAttr(node, name);
|
|
847
|
+
return attr && attr.value !== true ? String(attr.value) : undefined;
|
|
848
|
+
}
|
|
849
|
+
function getContentDirectiveAttr(node) {
|
|
850
|
+
return getAttr(node, "v-html") ?? getAttr(node, "v-text");
|
|
851
|
+
}
|
|
852
|
+
function requireAttrValue(attr) {
|
|
853
|
+
if (attr.value === true) {
|
|
854
|
+
throw new Error(`Attribute ${attr.name} requires a value`);
|
|
855
|
+
}
|
|
856
|
+
return attr.value;
|
|
857
|
+
}
|
|
858
|
+
function compileSsrExpression(context, expression, usage) {
|
|
859
|
+
return compileTemplateExpression(expression, usage, {
|
|
860
|
+
source: context.source ?? expression,
|
|
861
|
+
offset: 0,
|
|
862
|
+
filename: context.filename
|
|
863
|
+
}).replace(/\bunwrap\(/g, "__mikuru_unwrap(");
|
|
864
|
+
}
|
|
865
|
+
function expressionContext(context, attr, usage) {
|
|
866
|
+
return {
|
|
867
|
+
source: context.source ?? String(attr.value),
|
|
868
|
+
offset: attr.valueLoc?.offset ?? attr.loc?.offset ?? 0,
|
|
869
|
+
filename: context.filename
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
function splitScript(script) {
|
|
873
|
+
const imports = [];
|
|
874
|
+
const body = [];
|
|
875
|
+
for (const line of script.split(/\r?\n/)) {
|
|
876
|
+
if (/^\s*import\s/.test(line)) {
|
|
877
|
+
imports.push(line.trim());
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
body.push(line);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return {
|
|
884
|
+
imports,
|
|
885
|
+
body: body.join("\n")
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
function createScopeAttr(descriptor) {
|
|
889
|
+
const seed = descriptor.filename ?? descriptor.template;
|
|
890
|
+
let hash = 0;
|
|
891
|
+
for (let index = 0; index < seed.length; index += 1) {
|
|
892
|
+
hash = ((hash << 5) - hash + seed.charCodeAt(index)) | 0;
|
|
893
|
+
}
|
|
894
|
+
return `data-mikuru-${Math.abs(hash).toString(36)}`;
|
|
895
|
+
}
|
|
896
|
+
function contextSource(node) {
|
|
897
|
+
return node.tag;
|
|
898
|
+
}
|
|
899
|
+
function emit(context, indent, line) {
|
|
900
|
+
context.lines.push(`${" ".repeat(indent)}${line}`);
|
|
901
|
+
}
|
|
902
|
+
function nextName(context, prefix) {
|
|
903
|
+
const name = `__mikuru_${prefix}_${context.index}`;
|
|
904
|
+
context.index += 1;
|
|
905
|
+
return name;
|
|
906
|
+
}
|
|
907
|
+
function emitRaw(context, source, indent = 0) {
|
|
908
|
+
for (const line of source.split(/\r?\n/)) {
|
|
909
|
+
context.lines.push(`${" ".repeat(indent)}${line}`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function quote(value) {
|
|
913
|
+
return JSON.stringify(String(value));
|
|
914
|
+
}
|
|
915
|
+
//# sourceMappingURL=generateSsr.js.map
|