react-vfor
Version:
`ReactVFor` is a Vite/React plugin that allows you to use Vue-like `v-for` syntax in React components.
60 lines (59 loc) • 2.27 kB
JavaScript
import * as e from "@babel/types";
import E from "@babel/traverse";
import { parse as g } from "@babel/parser";
import b from "@babel/generator";
function S(o) {
const [t, l] = o.split(" in ").map((a) => a.trim());
let u = t, i = null;
return t.includes(",") && ([u, i] = t.split(",").map((a) => a.trim())), { items: l, item: u, index: i };
}
function C() {
return {
name: "vite-plugin-vfor-react",
enforce: "pre",
transform(o, t) {
if (!t.endsWith(".jsx") && !t.endsWith(".tsx")) return null;
const l = g(o, { sourceType: "module", plugins: ["jsx", "typescript"] });
return E(l, {
JSXElement(i) {
const n = i.node.openingElement.attributes.find(
(s) => e.isJSXAttribute(s) && e.isJSXIdentifier(s.name, { name: "v-for" })
);
if (!n || !n.value) return;
let m = null;
if (e.isStringLiteral(n.value) ? m = n.value.value : e.isJSXExpressionContainer(n.value) && e.isStringLiteral(n.value.expression) && (m = n.value.expression.value), !m) return;
const { items: p, item: c, index: f } = S(m);
try {
const s = e.objectExpression(
i.node.openingElement.attributes.filter((r) => !(e.isJSXAttribute(r) && e.isJSXIdentifier(r.name, { name: "v-for" }))).map((r) => e.objectProperty(
e.identifier(r.name.name),
e.isJSXExpressionContainer(r.value) ? r.value.expression : e.stringLiteral(r.value.value)
))
), d = e.callExpression(
e.memberExpression(e.identifier("React"), e.identifier("createElement")),
[
e.identifier(i.node.openingElement.name.name),
s,
...i.node.children
]
), x = e.arrowFunctionExpression(
[e.identifier(c), e.identifier(f || "index")],
d
), v = e.jsxExpressionContainer(
e.callExpression(
e.memberExpression(e.identifier(p), e.identifier("map")),
[x]
)
);
i.replaceWith(v);
} catch {
return;
}
}
}), { code: b(l, {}, o).code, map: null };
}
};
}
export {
C as default
};