diff --git a/packages/vue-script-setup-converter/src/lib/__snapshots__/convertSrc.test.ts.snap b/packages/vue-script-setup-converter/src/lib/__snapshots__/convertSrc.test.ts.snap index 6a82991..9acbf06 100644 --- a/packages/vue-script-setup-converter/src/lib/__snapshots__/convertSrc.test.ts.snap +++ b/packages/vue-script-setup-converter/src/lib/__snapshots__/convertSrc.test.ts.snap @@ -2,6 +2,9 @@ exports[`snapshot > defineNuxtComponent 1`] = ` "import { defineNuxtComponent, useNuxtApp } from '#imports'; +definePageMeta({ + name: 'HelloWorld', layout: 'test-layout', middleware: 'test-middleware' +}); const { $client } = useNuxtApp(); diff --git a/packages/vue-script-setup-converter/src/lib/convertSrc.test.ts b/packages/vue-script-setup-converter/src/lib/convertSrc.test.ts index c0a5d64..31b90b0 100644 --- a/packages/vue-script-setup-converter/src/lib/convertSrc.test.ts +++ b/packages/vue-script-setup-converter/src/lib/convertSrc.test.ts @@ -79,6 +79,8 @@ import { defineNuxtComponent, useNuxtApp } from '#imports'; export default defineNuxtComponent({ name: 'HelloWorld', + layout: 'test-layout', + middleware: 'test-middleware', setup(props, ctx) { const { $client } = useNuxtApp(); diff --git a/packages/vue-script-setup-converter/src/lib/convertSrc.ts b/packages/vue-script-setup-converter/src/lib/convertSrc.ts index e096dca..8b9b735 100644 --- a/packages/vue-script-setup-converter/src/lib/convertSrc.ts +++ b/packages/vue-script-setup-converter/src/lib/convertSrc.ts @@ -8,6 +8,7 @@ import { } from "ts-morph"; import { parse } from "@vue/compiler-sfc"; import { getNodeByKind } from "./helper"; +import { convertPageMeta } from "./converter/pageMetaConverter"; import { convertProps } from "./converter/propsConverter"; import { convertSetup } from "./converter/setupConverter"; import { convertEmits } from "./converter/emitsConverter"; @@ -40,6 +41,7 @@ export const convertSrc = (input: string) => { throw new Error("defineComponent is not found."); } + const pageMeta = convertPageMeta(callexpression, lang) ?? ""; const props = convertProps(callexpression, lang) ?? ""; const emits = convertEmits(callexpression, lang) ?? ""; const statement = convertSetup(callexpression) ?? ""; @@ -53,6 +55,10 @@ export const convertSrc = (input: string) => { .map((x) => x.getText()) ); + if (isDefineNuxtComponent(callexpression)) { + statements.addStatements(pageMeta); + } + statements.addStatements(props); statements.addStatements(emits); statements.addStatements(statement); @@ -75,3 +81,10 @@ const isDefineComponent = (node: CallExpression) => { node.getExpression().getText() === "defineNuxtComponent" ); }; + +const isDefineNuxtComponent = (node: CallExpression) => { + if (!Node.isIdentifier(node.getExpression())) { + return false; + } + return node.getExpression().getText() === "defineNuxtComponent"; +}; diff --git a/packages/vue-script-setup-converter/src/lib/converter/index.ts b/packages/vue-script-setup-converter/src/lib/converter/index.ts index 5863e10..6af55d1 100644 --- a/packages/vue-script-setup-converter/src/lib/converter/index.ts +++ b/packages/vue-script-setup-converter/src/lib/converter/index.ts @@ -1,3 +1,4 @@ export * from "./emitsConverter"; +export * from "./pageMetaConverter"; export * from "./propsConverter"; export * from "./setupConverter"; diff --git a/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.test.ts b/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.test.ts new file mode 100644 index 0000000..9cac85b --- /dev/null +++ b/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.test.ts @@ -0,0 +1,85 @@ +import { expect, describe, it } from "vitest"; +import { CallExpression, ScriptTarget, SyntaxKind, Project } from "ts-morph"; +import { parse } from "@vue/compiler-sfc"; +import prettier from "prettier"; +import parserTypeScript from "prettier/parser-typescript"; +import { getNodeByKind } from "../helper"; +import { convertPageMeta } from "./pageMetaConverter"; + +const parseScript = (input: string, lang: "js" | "ts" = "js") => { + const { + descriptor: { script }, + } = parse(input); + + const project = new Project({ + tsConfigFilePath: "tsconfig.json", + compilerOptions: { + target: ScriptTarget.Latest, + }, + }); + + const sourceFile = project.createSourceFile("s.tsx", script?.content ?? ""); + + const callExpression = getNodeByKind(sourceFile, SyntaxKind.CallExpression); + + const pageMeta = convertPageMeta(callExpression as CallExpression, lang); + + const formatedText = prettier.format(pageMeta, { + parser: "typescript", + plugins: [parserTypeScript], + }); + + return formatedText; +}; + +describe("convertPageMeta", () => { + describe("basic", () => { + const source = ``; + + it("returns text including definePageMeta", () => { + const output = parseScript(source); + + const expected = `definePageMeta({ + name: "HelloWorld", + layout: "test-layout", + middleware: "test-middleware", +}); +`; + + expect(output).toBe(expected); + }); + }); + + describe("when middleware is array", () => { + const source = ``; + + it("returns text including definePageMeta", () => { + const output = parseScript(source); + + const expected = `definePageMeta({ + name: "HelloWorld", + layout: "test-layout", + middleware: ["test-middleware-1", "test-middleware-2"], +}); +`; + + expect(output).toBe(expected); + }); + }); +}); diff --git a/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.ts b/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.ts new file mode 100644 index 0000000..70cbf5f --- /dev/null +++ b/packages/vue-script-setup-converter/src/lib/converter/pageMetaConverter.ts @@ -0,0 +1,32 @@ +import { CallExpression, PropertyAssignment } from "ts-morph"; +import { getOptionsNode } from "../helper"; + +export const convertPageMeta = (node: CallExpression, lang: string = "js") => { + const nameNode = getOptionsNode(node, "name"); + const layoutNode = getOptionsNode(node, "layout"); + const middlewareNode = getOptionsNode(node, "middleware"); + + if (!nameNode && !layoutNode && !middlewareNode) return ""; + + return convertToDefinePageMeta({ nameNode, layoutNode, middlewareNode }); +}; + +const convertToDefinePageMeta = ({ + nameNode, + layoutNode, + middlewareNode, +}: { + nameNode: PropertyAssignment | undefined; + layoutNode: PropertyAssignment | undefined; + middlewareNode: PropertyAssignment | undefined; +}) => { + const nameProperty = nameNode ? nameNode.getText() : ""; + const layoutProperty = layoutNode ? layoutNode.getText() : ""; + const middlewareProperty = middlewareNode ? middlewareNode.getText() : ""; + + return `definePageMeta({ + ${[nameProperty, layoutProperty, middlewareProperty] + .filter(Boolean) + .join(",")} + });`; +}; diff --git a/packages/vue-script-setup-converter/src/lib/helper.ts b/packages/vue-script-setup-converter/src/lib/helper.ts index a20b97a..c6057b7 100644 --- a/packages/vue-script-setup-converter/src/lib/helper.ts +++ b/packages/vue-script-setup-converter/src/lib/helper.ts @@ -17,7 +17,7 @@ export const getNodeByKind = ( export const getOptionsNode = ( node: CallExpression, - type: "props" | "emits" + type: "name" | "layout" | "middleware" | "props" | "emits" ) => { const expression = getNodeByKind(node, SyntaxKind.ObjectLiteralExpression);