438bdbf62b8726cd811ba603b5914f5940c863091c39e061b878e38856ca7e77ab1ef64088ceabd11b262c3a5e676292543894e4281b22dfad20fb3eaf5ca6 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // src/index.ts
  2. import { parseExpression } from "@babel/parser";
  3. import {
  4. extractRuntimeEmits,
  5. extractRuntimeProps
  6. } from "@vue/compiler-sfc";
  7. import { codeFrameColumns } from "@babel/code-frame";
  8. import { addNamed } from "@babel/helper-module-imports";
  9. import { declare } from "@babel/helper-plugin-utils";
  10. var index_default = declare(({ types: t }, options) => {
  11. let ctx;
  12. let helpers;
  13. return {
  14. name: "babel-plugin-resolve-type",
  15. pre(file) {
  16. const filename = file.opts.filename || "unknown.js";
  17. helpers = /* @__PURE__ */ new Set();
  18. ctx = {
  19. filename,
  20. source: file.code,
  21. options,
  22. ast: file.ast.program.body,
  23. isCE: false,
  24. error(msg, node) {
  25. throw new Error(
  26. `[@vue/babel-plugin-resolve-type] ${msg}
  27. ${filename}
  28. ${codeFrameColumns(
  29. file.code,
  30. {
  31. start: {
  32. line: node.loc.start.line,
  33. column: node.loc.start.column + 1
  34. },
  35. end: {
  36. line: node.loc.end.line,
  37. column: node.loc.end.column + 1
  38. }
  39. }
  40. )}`
  41. );
  42. },
  43. helper(key) {
  44. helpers.add(key);
  45. return `_${key}`;
  46. },
  47. getString(node) {
  48. return file.code.slice(node.start, node.end);
  49. },
  50. propsTypeDecl: void 0,
  51. propsRuntimeDefaults: void 0,
  52. propsDestructuredBindings: {},
  53. emitsTypeDecl: void 0
  54. };
  55. },
  56. visitor: {
  57. CallExpression(path) {
  58. if (!ctx) {
  59. throw new Error(
  60. "[@vue/babel-plugin-resolve-type] context is not loaded."
  61. );
  62. }
  63. const { node } = path;
  64. if (!t.isIdentifier(node.callee, { name: "defineComponent" })) return;
  65. if (!checkDefineComponent(path)) return;
  66. const comp = node.arguments[0];
  67. if (!comp || !t.isFunction(comp)) return;
  68. let options2 = node.arguments[1];
  69. if (!options2) {
  70. options2 = t.objectExpression([]);
  71. node.arguments.push(options2);
  72. }
  73. node.arguments[1] = processProps(comp, options2) || options2;
  74. node.arguments[1] = processEmits(comp, node.arguments[1]) || options2;
  75. },
  76. VariableDeclarator(path) {
  77. inferComponentName(path);
  78. }
  79. },
  80. post(file) {
  81. for (const helper of helpers) {
  82. addNamed(file.path, `_${helper}`, "vue");
  83. }
  84. }
  85. };
  86. function inferComponentName(path) {
  87. var _a;
  88. const id = path.get("id");
  89. const init = path.get("init");
  90. if (!id || !id.isIdentifier() || !init || !init.isCallExpression()) return;
  91. if (!((_a = init.get("callee")) == null ? void 0 : _a.isIdentifier({ name: "defineComponent" }))) return;
  92. if (!checkDefineComponent(init)) return;
  93. const nameProperty = t.objectProperty(
  94. t.identifier("name"),
  95. t.stringLiteral(id.node.name)
  96. );
  97. const { arguments: args } = init.node;
  98. if (args.length === 0) return;
  99. if (args.length === 1) {
  100. init.node.arguments.push(t.objectExpression([]));
  101. }
  102. args[1] = addProperty(t, args[1], nameProperty);
  103. }
  104. function processProps(comp, options2) {
  105. const props = comp.params[0];
  106. if (!props) return;
  107. if (props.type === "AssignmentPattern") {
  108. ctx.propsTypeDecl = getTypeAnnotation(props.left);
  109. ctx.propsRuntimeDefaults = props.right;
  110. } else {
  111. ctx.propsTypeDecl = getTypeAnnotation(props);
  112. }
  113. if (!ctx.propsTypeDecl) return;
  114. const runtimeProps = extractRuntimeProps(ctx);
  115. if (!runtimeProps) {
  116. return;
  117. }
  118. const ast = parseExpression(runtimeProps);
  119. return addProperty(
  120. t,
  121. options2,
  122. t.objectProperty(t.identifier("props"), ast)
  123. );
  124. }
  125. function processEmits(comp, options2) {
  126. var _a;
  127. const setupCtx = comp.params[1] && getTypeAnnotation(comp.params[1]);
  128. if (!setupCtx || !t.isTSTypeReference(setupCtx) || !t.isIdentifier(setupCtx.typeName, { name: "SetupContext" }))
  129. return;
  130. const emitType = (_a = setupCtx.typeParameters) == null ? void 0 : _a.params[0];
  131. if (!emitType) return;
  132. ctx.emitsTypeDecl = emitType;
  133. const runtimeEmits = extractRuntimeEmits(ctx);
  134. const ast = t.arrayExpression(
  135. Array.from(runtimeEmits).map((e) => t.stringLiteral(e))
  136. );
  137. return addProperty(
  138. t,
  139. options2,
  140. t.objectProperty(t.identifier("emits"), ast)
  141. );
  142. }
  143. });
  144. function getTypeAnnotation(node) {
  145. if ("typeAnnotation" in node && node.typeAnnotation && node.typeAnnotation.type === "TSTypeAnnotation") {
  146. return node.typeAnnotation.typeAnnotation;
  147. }
  148. }
  149. function checkDefineComponent(path) {
  150. var _a;
  151. const defineCompImport = (_a = path.scope.getBinding("defineComponent")) == null ? void 0 : _a.path.parent;
  152. if (!defineCompImport) return true;
  153. return defineCompImport.type === "ImportDeclaration" && /^@?vue(\/|$)/.test(defineCompImport.source.value);
  154. }
  155. function addProperty(t, object, property) {
  156. if (t.isObjectExpression(object)) {
  157. object.properties.unshift(property);
  158. } else if (t.isExpression(object)) {
  159. return t.objectExpression([property, t.spreadElement(object)]);
  160. }
  161. return object;
  162. }
  163. export {
  164. index_default as default
  165. };