@vuecast/astro-module 1.0.4 → 1.0.5
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/dist/index.mjs +161 -14
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -29,14 +29,43 @@ function splitAstroFrontmatter(code) {
|
|
|
29
29
|
function isVueTemplate(template) {
|
|
30
30
|
if (/\{\{\s*[^}]+?\s*\}\}/.test(template))
|
|
31
31
|
return true;
|
|
32
|
-
if (/\sv-(if|else-if|else|for|show|model|bind|on|slot)\b/.test(template))
|
|
32
|
+
if (/\sv-(if|else-if|else|for|show|model|bind|on|slot|html|text)\b/.test(template))
|
|
33
33
|
return true;
|
|
34
34
|
if (/(?:\s|<)[:@][a-zA-Z]/.test(template))
|
|
35
35
|
return true;
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
38
|
function genChildren(children) {
|
|
39
|
-
|
|
39
|
+
let out = "";
|
|
40
|
+
for (let i = 0; i < children.length; i++) {
|
|
41
|
+
const node = children[i];
|
|
42
|
+
if (node.type === NodeTypes.ELEMENT && hasDirective(node, "if")) {
|
|
43
|
+
const chain = [
|
|
44
|
+
{ node, type: "if" }
|
|
45
|
+
];
|
|
46
|
+
let j = i + 1;
|
|
47
|
+
for (; j < children.length; j++) {
|
|
48
|
+
const sib = children[j];
|
|
49
|
+
if (sib.type !== NodeTypes.ELEMENT)
|
|
50
|
+
break;
|
|
51
|
+
if (hasDirective(sib, "else-if")) {
|
|
52
|
+
chain.push({ node: sib, type: "else-if" });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (hasDirective(sib, "else")) {
|
|
56
|
+
chain.push({ node: sib, type: "else" });
|
|
57
|
+
j++;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
out += genIfChain(chain);
|
|
63
|
+
i = j - 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
out += genNode(node);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
40
69
|
}
|
|
41
70
|
function genNode(node) {
|
|
42
71
|
switch (node.type) {
|
|
@@ -54,25 +83,37 @@ function genNode(node) {
|
|
|
54
83
|
}
|
|
55
84
|
function genElement(el) {
|
|
56
85
|
const tag = el.tag;
|
|
57
|
-
const { attrs, vIf, vElseIf, vElse, vFor } = splitDirectives(el.props);
|
|
86
|
+
const { attrs, vIf, vElseIf, vElse, vFor, vShow, vText, vHtml } = splitDirectives(el.props);
|
|
58
87
|
if (vFor) {
|
|
59
88
|
const { source, value, index } = parseVFor(vFor.exp?.content ?? "");
|
|
60
|
-
const inner = genPlainElement(tag, attrs, el.children);
|
|
89
|
+
const inner = genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
61
90
|
const args = index ? `${value}, ${index}` : value;
|
|
62
91
|
return `{${source}.map((${args}) => (${inner}))}`;
|
|
63
92
|
}
|
|
64
93
|
if (vIf) {
|
|
65
94
|
const cond = vIf.exp?.content ?? "false";
|
|
66
|
-
const thenBranch = genPlainElement(tag, attrs, el.children);
|
|
95
|
+
const thenBranch = genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
67
96
|
return `{${cond} ? (${thenBranch}) : null}`;
|
|
68
97
|
}
|
|
69
98
|
if (vElseIf || vElse) {
|
|
70
|
-
return genPlainElement(tag, attrs, el.children);
|
|
99
|
+
return genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
71
100
|
}
|
|
72
|
-
return genPlainElement(tag, attrs, el.children);
|
|
101
|
+
return genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
73
102
|
}
|
|
74
|
-
function genPlainElement(tag, props, children) {
|
|
75
|
-
|
|
103
|
+
function genPlainElement(tag, props, children, extras) {
|
|
104
|
+
let attrs = props;
|
|
105
|
+
if (extras?.vShow)
|
|
106
|
+
attrs = applyVShow(attrs, extras.vShow);
|
|
107
|
+
let attrStr = attrs.map(genAttr).join("");
|
|
108
|
+
if (extras?.vHtml) {
|
|
109
|
+
const expr = extras.vHtml.exp?.content ?? "''";
|
|
110
|
+
attrStr += ` set:html={${expr}}`;
|
|
111
|
+
children = [];
|
|
112
|
+
} else if (extras?.vText) {
|
|
113
|
+
const expr = extras.vText.exp?.content ?? "''";
|
|
114
|
+
attrStr += ` set:text={${expr}}`;
|
|
115
|
+
children = [];
|
|
116
|
+
}
|
|
76
117
|
const inner = genChildren(children);
|
|
77
118
|
return `<${tag}${attrStr}>${inner}</${tag}>`;
|
|
78
119
|
}
|
|
@@ -80,12 +121,20 @@ function genAttr(p) {
|
|
|
80
121
|
if (p.type === NodeTypes.ATTRIBUTE) {
|
|
81
122
|
if (!p.value)
|
|
82
123
|
return ` ${p.name}`;
|
|
83
|
-
|
|
124
|
+
const raw = p.value.content ?? "";
|
|
125
|
+
if (/\$\{[^}]+?\}/.test(raw)) {
|
|
126
|
+
const trimmed = raw.startsWith("`") && raw.endsWith("`") ? raw.slice(1, -1) : raw;
|
|
127
|
+
const safe = trimmed.replace(/`/g, "\\`");
|
|
128
|
+
return ` ${p.name}={\`${safe}\`}`;
|
|
129
|
+
}
|
|
130
|
+
return ` ${p.name}="${escapeAttr(raw)}"`;
|
|
84
131
|
}
|
|
85
132
|
if (p.type === NodeTypes.DIRECTIVE && p.name === "bind") {
|
|
86
133
|
const name = p.arg?.content;
|
|
87
|
-
if (!name)
|
|
88
|
-
|
|
134
|
+
if (!name) {
|
|
135
|
+
const expr2 = p.exp?.content ?? "{}";
|
|
136
|
+
return ` {...${expr2}}`;
|
|
137
|
+
}
|
|
89
138
|
const expr = p.exp?.content ?? "true";
|
|
90
139
|
return ` ${name}={${expr}}`;
|
|
91
140
|
}
|
|
@@ -102,6 +151,9 @@ function splitDirectives(props) {
|
|
|
102
151
|
let vElseIf = null;
|
|
103
152
|
let vElse = null;
|
|
104
153
|
let vFor = null;
|
|
154
|
+
let vShow = null;
|
|
155
|
+
let vText = null;
|
|
156
|
+
let vHtml = null;
|
|
105
157
|
for (const p of props) {
|
|
106
158
|
if (p.type === NodeTypes.DIRECTIVE) {
|
|
107
159
|
if (p.name === "if")
|
|
@@ -112,13 +164,19 @@ function splitDirectives(props) {
|
|
|
112
164
|
vElse = p;
|
|
113
165
|
else if (p.name === "for")
|
|
114
166
|
vFor = p;
|
|
167
|
+
else if (p.name === "show")
|
|
168
|
+
vShow = p;
|
|
169
|
+
else if (p.name === "text")
|
|
170
|
+
vText = p;
|
|
171
|
+
else if (p.name === "html")
|
|
172
|
+
vHtml = p;
|
|
115
173
|
else
|
|
116
174
|
attrs.push(p);
|
|
117
175
|
} else {
|
|
118
176
|
attrs.push(p);
|
|
119
177
|
}
|
|
120
178
|
}
|
|
121
|
-
return { attrs, vIf, vElseIf, vElse, vFor };
|
|
179
|
+
return { attrs, vIf, vElseIf, vElse, vFor, vShow, vText, vHtml };
|
|
122
180
|
}
|
|
123
181
|
function parseVFor(exp) {
|
|
124
182
|
const m = exp.match(/^\s*(.+?)\s+in\s+(.+)\s*$/);
|
|
@@ -139,6 +197,95 @@ function parseVFor(exp) {
|
|
|
139
197
|
function escapeAttr(s) {
|
|
140
198
|
return String(s).replace(/&/g, "&").replace(/"/g, """);
|
|
141
199
|
}
|
|
200
|
+
function hasDirective(node, name) {
|
|
201
|
+
return !!node.props?.some(
|
|
202
|
+
(p) => p.type === NodeTypes.DIRECTIVE && p.name === name
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
function genIfChain(chain) {
|
|
206
|
+
const parts = chain.map((item) => {
|
|
207
|
+
const split = splitDirectives(item.node.props);
|
|
208
|
+
const branch = genElementFromSplit(item.node, split, { ignoreIf: true });
|
|
209
|
+
const cond = item.type === "else" ? null : item.type === "if" ? split.vIf?.exp?.content ?? "false" : split.vElseIf?.exp?.content ?? "false";
|
|
210
|
+
return { cond, branch };
|
|
211
|
+
});
|
|
212
|
+
let expr = "";
|
|
213
|
+
for (let i = 0; i < parts.length; i++) {
|
|
214
|
+
const { cond, branch } = parts[i];
|
|
215
|
+
if (i === 0) {
|
|
216
|
+
expr = `${cond} ? (${branch}) : `;
|
|
217
|
+
} else if (cond) {
|
|
218
|
+
expr += `${cond} ? (${branch}) : `;
|
|
219
|
+
} else {
|
|
220
|
+
expr += `(${branch})`;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (!parts.some((p) => p.cond === null))
|
|
224
|
+
expr += "null";
|
|
225
|
+
return `{${expr}}`;
|
|
226
|
+
}
|
|
227
|
+
function genElementFromSplit(el, split, opts) {
|
|
228
|
+
const tag = el.tag;
|
|
229
|
+
const { attrs, vIf, vElseIf, vElse, vFor, vShow, vText, vHtml } = split;
|
|
230
|
+
if (vFor) {
|
|
231
|
+
const { source, value, index } = parseVFor(vFor.exp?.content ?? "");
|
|
232
|
+
const inner = genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
233
|
+
const args = index ? `${value}, ${index}` : value;
|
|
234
|
+
return `{${source}.map((${args}) => (${inner}))}`;
|
|
235
|
+
}
|
|
236
|
+
if (!opts?.ignoreIf && vIf) {
|
|
237
|
+
const cond = vIf.exp?.content ?? "false";
|
|
238
|
+
const thenBranch = genPlainElement(tag, attrs, el.children, {
|
|
239
|
+
vShow,
|
|
240
|
+
vText,
|
|
241
|
+
vHtml
|
|
242
|
+
});
|
|
243
|
+
return `{${cond} ? (${thenBranch}) : null}`;
|
|
244
|
+
}
|
|
245
|
+
if (!opts?.ignoreIf && (vElseIf || vElse)) {
|
|
246
|
+
return genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
247
|
+
}
|
|
248
|
+
return genPlainElement(tag, attrs, el.children, { vShow, vText, vHtml });
|
|
249
|
+
}
|
|
250
|
+
function applyVShow(attrs, vShow) {
|
|
251
|
+
const showExpr = vShow.exp?.content ?? "false";
|
|
252
|
+
const showStyleExpr = `(${showExpr}) ? '' : 'display: none;'`;
|
|
253
|
+
const next = [...attrs];
|
|
254
|
+
const styleIdx = next.findIndex((p) => {
|
|
255
|
+
if (p.type === NodeTypes.ATTRIBUTE)
|
|
256
|
+
return p.name === "style";
|
|
257
|
+
return p.type === NodeTypes.DIRECTIVE && p.name === "bind" && p.arg?.content === "style";
|
|
258
|
+
});
|
|
259
|
+
if (styleIdx === -1) {
|
|
260
|
+
next.push({
|
|
261
|
+
type: NodeTypes.DIRECTIVE,
|
|
262
|
+
name: "bind",
|
|
263
|
+
arg: { content: "style" },
|
|
264
|
+
exp: { content: showStyleExpr }
|
|
265
|
+
});
|
|
266
|
+
return next;
|
|
267
|
+
}
|
|
268
|
+
const styleProp = next[styleIdx];
|
|
269
|
+
if (styleProp.type === NodeTypes.ATTRIBUTE) {
|
|
270
|
+
const base = styleProp.value?.content ?? "";
|
|
271
|
+
const sep = base && !/;\s*$/.test(base) ? ";" : "";
|
|
272
|
+
const safe = base.replace(/`/g, "\\`");
|
|
273
|
+
const merged = `\`${safe}${sep}\${${showExpr} ? '' : 'display: none;'}\``;
|
|
274
|
+
next[styleIdx] = {
|
|
275
|
+
type: NodeTypes.DIRECTIVE,
|
|
276
|
+
name: "bind",
|
|
277
|
+
arg: { content: "style" },
|
|
278
|
+
exp: { content: merged }
|
|
279
|
+
};
|
|
280
|
+
return next;
|
|
281
|
+
}
|
|
282
|
+
const baseExpr = styleProp.exp?.content ?? "''";
|
|
283
|
+
styleProp.exp = {
|
|
284
|
+
content: `(${baseExpr} ?? '') + (${showStyleExpr})`
|
|
285
|
+
};
|
|
286
|
+
next[styleIdx] = styleProp;
|
|
287
|
+
return next;
|
|
288
|
+
}
|
|
142
289
|
|
|
143
290
|
function vueTemplatePreAstroPlugin() {
|
|
144
291
|
return {
|
|
@@ -166,7 +313,7 @@ function vueTemplatePreAstroPlugin() {
|
|
|
166
313
|
|
|
167
314
|
function VuecastAstro() {
|
|
168
315
|
return {
|
|
169
|
-
name: "@vuecast/astro-
|
|
316
|
+
name: "@vuecast/astro-module",
|
|
170
317
|
hooks: {
|
|
171
318
|
"astro:config:setup": async (params) => {
|
|
172
319
|
const existingPlugins = params.config.vite?.plugins;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuecast/astro-module",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Astro integration for Vue template syntax in .astro pages",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "unbuild",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
21
23
|
"publish-beta": "npm run build && npm run increment-beta-version && npm publish --tag beta",
|
|
22
24
|
"increment-beta-version": "npm version prerelease --preid=beta",
|
|
23
25
|
"publish-patch": "npm run build && npm run increment-version && npm publish",
|
|
@@ -32,6 +34,7 @@
|
|
|
32
34
|
"author": "",
|
|
33
35
|
"license": "MIT",
|
|
34
36
|
"devDependencies": {
|
|
37
|
+
"vitest": "^1.3.1",
|
|
35
38
|
"unbuild": "^2.0.0"
|
|
36
39
|
},
|
|
37
40
|
"dependencies": {
|