Skip to content

Commit

Permalink
feat(vue-script-setup-converter): Convert page meta into definePageMe…
Browse files Browse the repository at this point in the history
…ta (#50)

* feat: Convert to definePageMeta

* feat: Convert page meta in convertSrt
  • Loading branch information
inouetakuya authored May 5, 2024
1 parent 6a92d55 commit e65a483
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 13 additions & 0 deletions packages/vue-script-setup-converter/src/lib/convertSrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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) ?? "";
Expand All @@ -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);
Expand All @@ -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";
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./emitsConverter";
export * from "./pageMetaConverter";
export * from "./propsConverter";
export * from "./setupConverter";
Original file line number Diff line number Diff line change
@@ -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 = `<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'HelloWorld',
layout: 'test-layout',
middleware: 'test-middleware',
})
</script>`;

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 = `<script>
import { defineComponent } from 'vue';
export default defineComponent({
name: 'HelloWorld',
layout: 'test-layout',
middleware: ['test-middleware-1', 'test-middleware-2'],
})
</script>`;

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);
});
});
});
Original file line number Diff line number Diff line change
@@ -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(",")}
});`;
};
2 changes: 1 addition & 1 deletion packages/vue-script-setup-converter/src/lib/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit e65a483

Please sign in to comment.