@vue-macros/export-props
Version:
exportProps feature from Vue Macros.
47 lines (45 loc) • 2.26 kB
JavaScript
import { DEFINE_PROPS, MagicStringAST, WITH_DEFAULTS, generateTransform, isCallOf, parseSFC } from "@vue-macros/common";
//#region src/core/index.ts
function transformExportProps(code, id) {
const { scriptSetup, getSetupAst } = parseSFC(code, id);
if (!scriptSetup) return;
const offset = scriptSetup.loc.start.offset;
const s = new MagicStringAST(code);
const props = Object.create(null);
let hasDefineProps = false;
const setupAst = getSetupAst();
for (const stmt of setupAst.body) if (stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "VariableDeclaration") {
for (const decl of stmt.declaration.declarations) walkVariableDeclarator(decl, stmt.declaration.kind);
s.removeNode(stmt, { offset });
} else if (isCallOf(stmt, DEFINE_PROPS) || isCallOf(stmt, WITH_DEFAULTS)) hasDefineProps = true;
if (Object.keys(props).length === 0) return;
else if (hasDefineProps) throw new Error("Don't support export props mixed with defineProps");
let propsCodegen = "";
let destructureString = "";
let modelCodegen = "";
for (const [name, { isModel, type, defaultValue }] of Object.entries(props)) if (isModel) modelCodegen += `\nlet ${name} = $(defineModel("${name}"${defaultValue ? `, { default: () => (${defaultValue}) }` : ""}))`;
else {
propsCodegen += ` ${name}${defaultValue ? "?" : ""}${type},\n`;
destructureString += ` ${name}${defaultValue ? ` = ${defaultValue}` : ""},`;
}
if (propsCodegen) propsCodegen = `const {${destructureString} } = defineProps<{\n${propsCodegen}}>()`;
s.prependLeft(offset, `\n${propsCodegen}${modelCodegen}`);
return generateTransform(s, id);
function walkVariableDeclarator(decl, kind) {
if (decl.id.type !== "Identifier") throw new Error("Only support identifier in export props");
else if (decl.init && (isCallOf(decl.init, DEFINE_PROPS) || isCallOf(decl.init, WITH_DEFAULTS))) {
hasDefineProps = true;
return;
}
const name = decl.id.name;
const type = decl.id.typeAnnotation ? s.sliceNode(decl.id.typeAnnotation, { offset }) : ": any";
const defaultValue = decl.init ? s.sliceNode(decl.init, { offset }) : void 0;
props[name] = {
type,
defaultValue,
isModel: kind === "let" || kind === "var"
};
}
}
//#endregion
export { transformExportProps };