|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- // src/core/helper/emit-helper.ts?raw
- var emit_helper_default = "export default(emitFn,key,value,...args)=>{emitFn(key,value);return args.length>0?args[0]:value};\n";
-
- // src/core/helper/use-vmodel.ts?raw
- var use_vmodel_default = 'import{getCurrentInstance}from"vue";import{useVModel}from"@vueuse/core";export default(...keys)=>{const props=getCurrentInstance().proxy.$props;const ret={};for(const _k of keys){if(typeof _k==="string"){ret[_k]=useVModel(props,_k,void 0,{eventName:`update:${_k}`,passive:true})}else{const[key,prop=key,eventName=`update:${key}`,options={}]=_k;ret[key]=useVModel(props,prop,void 0,{eventName,passive:true,...options})}}return ret};\n';
-
- // src/core/helper/index.ts
- var helperPrefix = "/vue-macros/define-model";
- var emitHelperId = `${helperPrefix}/emit-helper`;
- var useVmodelHelperId = `${helperPrefix}/use-vmodel`;
-
- // src/core/index.ts
- import { extractIdentifiers, walkAST } from "ast-walker-scope";
- import {
- DEFINE_EMITS,
- DEFINE_MODEL,
- DEFINE_MODEL_DOLLAR,
- DEFINE_OPTIONS,
- DEFINE_PROPS,
- HELPER_PREFIX,
- MagicString,
- REPO_ISSUE_URL,
- WITH_DEFAULTS,
- getTransformResult,
- isCallOf,
- parseSFC,
- resolveObjectKey
- } from "@vue-macros/common";
- function transformDefineModel(code, id, version, unified) {
- let hasDefineProps = false;
- let hasDefineEmits = false;
- let hasDefineModel = false;
- let propsTypeDecl;
- let propsDestructureDecl;
- let emitsTypeDecl;
- let emitsIdentifier;
- let runtimeDefineFn;
- let modelDecl;
- let modelDeclKind;
- let modelTypeDecl;
- let modelIdentifier;
- let modelDestructureDecl;
- const modelIdentifiers = /* @__PURE__ */ new Set();
- const modelVue2 = { prop: "", event: "" };
- let mode;
- function processDefinePropsOrEmits(node, declId) {
- var _a, _b;
- if (isCallOf(node, WITH_DEFAULTS)) {
- node = node.arguments[0];
- }
- let type;
- if (isCallOf(node, DEFINE_PROPS)) {
- type = "props";
- } else if (isCallOf(node, DEFINE_EMITS)) {
- type = "emits";
- } else {
- return false;
- }
- const fnName = type === "props" ? DEFINE_PROPS : DEFINE_EMITS;
- if (node.arguments[0]) {
- runtimeDefineFn = fnName;
- return false;
- }
- if (type === "props")
- hasDefineProps = true;
- else
- hasDefineEmits = true;
- const typeDeclRaw = (_b = (_a = node.typeParameters) == null ? void 0 : _a.params) == null ? void 0 : _b[0];
- if (!typeDeclRaw)
- throw new SyntaxError(
- `${fnName}() expected a type parameter when used with ${DEFINE_MODEL}.`
- );
- const typeDecl = resolveQualifiedType(
- typeDeclRaw,
- (node2) => node2.type === "TSTypeLiteral"
- );
- if (!typeDecl) {
- throw new SyntaxError(
- `type argument passed to ${fnName}() must be a literal type, or a reference to an interface or literal type.`
- );
- }
- if (type === "props")
- propsTypeDecl = typeDecl;
- else
- emitsTypeDecl = typeDecl;
- if (declId) {
- if (type === "props" && declId.type === "ObjectPattern") {
- propsDestructureDecl = declId;
- } else if (type === "emits" && declId.type === "Identifier") {
- emitsIdentifier = declId.name;
- }
- } else if (type === "emits") {
- emitsIdentifier = `_${DEFINE_MODEL}_emit`;
- s.prependRight(setupOffset + node.start, `const ${emitsIdentifier} = `);
- }
- return true;
- }
- function processDefineModel(node, declId, kind) {
- var _a;
- if (isCallOf(node, DEFINE_MODEL))
- mode = "runtime";
- else if (isCallOf(node, DEFINE_MODEL_DOLLAR))
- mode = "reactivity-transform";
- else
- return false;
- if (hasDefineModel) {
- throw new SyntaxError(`duplicate ${DEFINE_MODEL}() call`);
- }
- hasDefineModel = true;
- modelDecl = node;
- const propsTypeDeclRaw = (_a = node.typeParameters) == null ? void 0 : _a.params[0];
- if (!propsTypeDeclRaw) {
- throw new SyntaxError(`expected a type parameter for ${DEFINE_MODEL}.`);
- }
- modelTypeDecl = resolveQualifiedType(
- propsTypeDeclRaw,
- (node2) => node2.type === "TSTypeLiteral"
- );
- if (!modelTypeDecl) {
- throw new SyntaxError(
- `type argument passed to ${DEFINE_MODEL}() must be a literal type, or a reference to an interface or literal type.`
- );
- }
- if (mode === "reactivity-transform" && declId) {
- const ids = extractIdentifiers(declId);
- ids.forEach((id2) => modelIdentifiers.add(id2));
- if (declId.type === "ObjectPattern") {
- modelDestructureDecl = declId;
- for (const property of declId.properties) {
- if (property.type === "RestElement") {
- throw new SyntaxError("rest element is not supported");
- }
- }
- } else {
- modelIdentifier = scriptSetup.loc.source.slice(
- declId.start,
- declId.end
- );
- }
- }
- if (kind)
- modelDeclKind = kind;
- return true;
- }
- function processDefineOptions(node) {
- if (!isCallOf(node, DEFINE_OPTIONS))
- return false;
- const [arg] = node.arguments;
- if (arg)
- processVue2Model(arg);
- return true;
- }
- function processVue2Script() {
- if (!script)
- return;
- const scriptAst = getScriptAst().body;
- if (scriptAst.length === 0)
- return;
- for (const node of scriptAst) {
- if (node.type === "ExportDefaultDeclaration") {
- const { declaration } = node;
- if (declaration.type === "ObjectExpression") {
- processVue2Model(declaration);
- } else if (declaration.type === "CallExpression" && declaration.callee.type === "Identifier" && ["defineComponent", "DO_defineComponent"].includes(
- declaration.callee.name
- )) {
- declaration.arguments.forEach((arg) => {
- if (arg.type === "ObjectExpression") {
- processVue2Model(arg);
- }
- });
- }
- }
- }
- }
- function processVue2Model(node) {
- if (node.type !== "ObjectExpression")
- return false;
- const model = node.properties.find(
- (prop) => prop.type === "ObjectProperty" && prop.key.type === "Identifier" && prop.key.name === "model" && prop.value.type === "ObjectExpression" && prop.value.properties.length === 2
- );
- if (!model)
- return false;
- model.value.properties.forEach((propertyItem) => {
- if (propertyItem.type === "ObjectProperty" && propertyItem.key.type === "Identifier" && propertyItem.value.type === "StringLiteral" && ["prop", "event"].includes(propertyItem.key.name)) {
- const key = propertyItem.key.name;
- modelVue2[key] = propertyItem.value.value;
- }
- });
- return true;
- }
- function resolveQualifiedType(node, qualifier) {
- if (qualifier(node)) {
- return node;
- }
- if (node.type === "TSTypeReference" && node.typeName.type === "Identifier") {
- const refName = node.typeName.name;
- const isQualifiedType = (node2) => {
- if (node2.type === "TSInterfaceDeclaration" && node2.id.name === refName) {
- return node2.body;
- } else if (node2.type === "TSTypeAliasDeclaration" && node2.id.name === refName && qualifier(node2.typeAnnotation)) {
- return node2.typeAnnotation;
- } else if (node2.type === "ExportNamedDeclaration" && node2.declaration) {
- return isQualifiedType(node2.declaration);
- }
- };
- for (const node2 of setupAst) {
- const qualified = isQualifiedType(node2);
- if (qualified) {
- return qualified;
- }
- }
- }
- }
- function extractPropsDefinitions(node) {
- var _a, _b, _c, _d;
- const members = node.type === "TSTypeLiteral" ? node.members : node.body;
- const map2 = {};
- for (const m of members) {
- if ((m.type === "TSPropertySignature" || m.type === "TSMethodSignature") && m.key.type === "Identifier") {
- const type = (_a = m.typeAnnotation) == null ? void 0 : _a.typeAnnotation;
- let typeAnnotation = "";
- let options;
- if (type) {
- typeAnnotation += `${m.optional ? "?" : ""}: `;
- if (type.type === "TSTypeReference" && type.typeName.type === "Identifier" && type.typeName.name === "ModelOptions" && ((_b = type.typeParameters) == null ? void 0 : _b.type) === "TSTypeParameterInstantiation" && type.typeParameters.params[0]) {
- typeAnnotation += setupContent.slice(
- type.typeParameters.params[0].start,
- type.typeParameters.params[0].end
- );
- if (((_c = type.typeParameters.params[1]) == null ? void 0 : _c.type) === "TSTypeLiteral") {
- options = {};
- for (const m2 of type.typeParameters.params[1].members) {
- if ((m2.type === "TSPropertySignature" || m2.type === "TSMethodSignature") && m2.key.type === "Identifier") {
- const type2 = (_d = m2.typeAnnotation) == null ? void 0 : _d.typeAnnotation;
- if (type2)
- options[setupContent.slice(m2.key.start, m2.key.end)] = setupContent.slice(type2.start, type2.end);
- }
- }
- }
- } else
- typeAnnotation += `${setupContent.slice(type.start, type.end)}`;
- }
- map2[m.key.name] = { typeAnnotation, options };
- }
- }
- return map2;
- }
- function getPropKey(key, omitDefault = false) {
- if (unified && version === 2 && key === "modelValue") {
- return "value";
- }
- return !omitDefault ? key : void 0;
- }
- function getEventKey(key, omitDefault = false) {
- if (version === 2) {
- if (modelVue2.prop === key) {
- return modelVue2.event;
- } else if (key === "value" || unified && key === "modelValue") {
- return "input";
- }
- }
- return !omitDefault ? `update:${key}` : void 0;
- }
- function rewriteMacros() {
- rewriteDefines();
- if (mode === "runtime") {
- rewriteRuntime();
- }
- function rewriteDefines() {
- const propsText = Object.entries(map).map(
- ([key, { typeAnnotation }]) => `${getPropKey(key)}${typeAnnotation}`
- ).join("\n");
- const emitsText = Object.entries(map).map(
- ([key, { typeAnnotation }]) => `(evt: '${getEventKey(key)}', value${typeAnnotation}): void`
- ).join("\n");
- if (hasDefineProps) {
- s.appendLeft(setupOffset + propsTypeDecl.start + 1, `${propsText}
- `);
- if (mode === "reactivity-transform" && propsDestructureDecl && modelDestructureDecl)
- for (const property of modelDestructureDecl.properties) {
- const text = code.slice(
- setupOffset + property.start,
- setupOffset + property.end
- );
- s.appendLeft(
- setupOffset + propsDestructureDecl.start + 1,
- `${text}, `
- );
- }
- } else {
- let text = "";
- const kind = modelDeclKind || "let";
- if (mode === "reactivity-transform") {
- if (modelIdentifier) {
- text = modelIdentifier;
- } else if (modelDestructureDecl) {
- text = code.slice(
- setupOffset + modelDestructureDecl.start,
- setupOffset + modelDestructureDecl.end
- );
- }
- }
- s.appendLeft(
- setupOffset,
- `
- ${text ? `${kind} ${text} = ` : ""}defineProps<{
- ${propsText}
- }>();`
- );
- }
- if (hasDefineEmits) {
- s.appendLeft(setupOffset + emitsTypeDecl.start + 1, `${emitsText}
- `);
- } else {
- emitsIdentifier = `${HELPER_PREFIX}emit`;
- s.appendLeft(
- setupOffset,
- `
- ${mode === "reactivity-transform" ? `const ${emitsIdentifier} = ` : ""}defineEmits<{
- ${emitsText}
- }>();`
- );
- }
- }
- function rewriteRuntime() {
- s.prependLeft(
- setupOffset,
- `
- import ${HELPER_PREFIX}useVModel from '${useVmodelHelperId}';`
- );
- const text = `${HELPER_PREFIX}useVModel(${Object.entries(map).map(([name, { options }]) => {
- const prop = getPropKey(name, true);
- const evt = getEventKey(name, true);
- if (!prop && !evt && !options)
- return stringifyValue(name);
- const args = [name, prop, evt].map((arg) => stringifyValue(arg));
- if (options) {
- const str = Object.entries(options).map(([k, v]) => ` ${stringifyValue(k)}: ${v}`).join(",\n");
- args.push(`{
- ${str}
- }`);
- }
- return `[${args.join(", ")}]`;
- }).join(", ")})`;
- s.overwriteNode(modelDecl, text, { offset: setupOffset });
- }
- }
- function processAssignModelVariable() {
- if (!emitsIdentifier)
- throw new Error(
- `Identifier of returning value of ${DEFINE_EMITS} is not found, please report this issue.
- ${REPO_ISSUE_URL}`
- );
- let hasTransformed = false;
- function overwrite(node, id2, value, original = false) {
- hasTransformed = true;
- const eventName = aliasMap[id2.name];
- const content = `${HELPER_PREFIX}emitHelper(${emitsIdentifier}, '${getEventKey(
- String(eventName)
- )}', ${value}${original ? `, ${id2.name}` : ""})`;
- s.overwriteNode(node, content, { offset: setupOffset });
- }
- walkAST(setupAst, {
- leave(node) {
- if (node.type === "AssignmentExpression") {
- if (node.left.type !== "Identifier")
- return;
- const id2 = this.scope[node.left.name];
- if (!modelIdentifiers.has(id2))
- return;
- const left = s.sliceNode(node.left, { offset: setupOffset });
- let right = s.sliceNode(node.right, { offset: setupOffset });
- if (node.operator !== "=") {
- right = `${left} ${node.operator.replace(/=$/, "")} ${right}`;
- }
- overwrite(node, id2, right);
- } else if (node.type === "UpdateExpression") {
- if (node.argument.type !== "Identifier")
- return;
- const id2 = this.scope[node.argument.name];
- if (!modelIdentifiers.has(id2))
- return;
- let value = node.argument.name;
- if (node.operator === "++")
- value += " + 1";
- else
- value += " - 1";
- overwrite(node, id2, value, !node.prefix);
- }
- }
- });
- if (hasTransformed) {
- s.prependLeft(
- setupOffset,
- `
- import ${HELPER_PREFIX}emitHelper from '${emitHelperId}';`
- );
- }
- }
- if (!code.includes(DEFINE_MODEL))
- return;
- const { script, scriptSetup, getSetupAst, getScriptAst } = parseSFC(code, id);
- if (!scriptSetup)
- return;
- const setupOffset = scriptSetup.loc.start.offset;
- const setupContent = scriptSetup.content;
- const setupAst = getSetupAst().body;
- const s = new MagicString(code);
- if (version === 2)
- processVue2Script();
- for (const node of setupAst) {
- if (node.type === "ExpressionStatement") {
- processDefinePropsOrEmits(node.expression);
- if (version === 2) {
- processDefineOptions(node.expression);
- }
- if (processDefineModel(node.expression) && mode === "reactivity-transform")
- s.remove(node.start + setupOffset, node.end + setupOffset);
- } else if (node.type === "VariableDeclaration" && !node.declare) {
- const total = node.declarations.length;
- let left = total;
- for (let i = 0; i < total; i++) {
- const decl = node.declarations[i];
- if (decl.init) {
- processDefinePropsOrEmits(decl.init, decl.id);
- if (processDefineModel(decl.init, decl.id, node.kind) && mode === "reactivity-transform") {
- if (left === 1) {
- s.remove(node.start + setupOffset, node.end + setupOffset);
- } else {
- let start = decl.start + setupOffset;
- let end = decl.end + setupOffset;
- if (i < total - 1) {
- end = node.declarations[i + 1].start + setupOffset;
- } else {
- start = node.declarations[i - 1].end + setupOffset;
- }
- s.remove(start, end);
- left--;
- }
- }
- }
- }
- }
- }
- if (!modelTypeDecl)
- return;
- if (runtimeDefineFn)
- throw new SyntaxError(
- `${runtimeDefineFn}() cannot accept non-type arguments when used with ${DEFINE_MODEL}()`
- );
- if (modelTypeDecl.type !== "TSTypeLiteral") {
- throw new SyntaxError(
- `type argument passed to ${DEFINE_MODEL}() must be a literal type, or a reference to an interface or literal type.`
- );
- }
- const map = extractPropsDefinitions(modelTypeDecl);
- const aliasMap = {};
- if (modelDestructureDecl)
- for (const p of modelDestructureDecl.properties) {
- if (p.type !== "ObjectProperty")
- continue;
- try {
- const key = resolveObjectKey(p.key, p.computed, false);
- if (p.value.type !== "Identifier")
- continue;
- aliasMap[p.value.name] = key;
- } catch {
- }
- }
- rewriteMacros();
- if (mode === "reactivity-transform" && hasDefineModel)
- processAssignModelVariable();
- return getTransformResult(s, id);
- }
- function stringifyValue(value) {
- return value !== void 0 ? JSON.stringify(value) : "undefined";
- }
-
- export {
- emit_helper_default,
- use_vmodel_default,
- helperPrefix,
- emitHelperId,
- useVmodelHelperId,
- transformDefineModel
- };
|