diff --git a/playground/src/pages/custom-definePage.vue b/playground/src/pages/custom-definePage.vue new file mode 100644 index 000000000..3995b29e0 --- /dev/null +++ b/playground/src/pages/custom-definePage.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typed-router.d.ts b/playground/typed-router.d.ts index 6ae02d906..e48a14151 100644 --- a/playground/typed-router.d.ts +++ b/playground/typed-router.d.ts @@ -43,6 +43,7 @@ declare module 'vue-router/auto/routes' { '/articles/': RouteRecordInfo<'/articles/', '/articles', Record, Record>, '/articles/[id]': RouteRecordInfo<'/articles/[id]', '/articles/:id', { id: ParamValue }, { id: ParamValue }>, '/articles/[id]+': RouteRecordInfo<'/articles/[id]+', '/articles/:id+', { id: ParamValueOneOrMore }, { id: ParamValueOneOrMore }>, + '/custom-definePage': RouteRecordInfo<'/custom-definePage', '/custom-definePage', Record, Record>, 'a rebel': RouteRecordInfo<'a rebel', '/custom-name', Record, Record>, '/deep/nesting/works/[[files]]+': RouteRecordInfo<'/deep/nesting/works/[[files]]+', '/deep/nesting/works/:files*', { files?: ParamValueZeroOrMore }, { files?: ParamValueZeroOrMore }>, 'deep the most rebel': RouteRecordInfo<'deep the most rebel', '/deep-most-rebel', Record, Record>, diff --git a/src/core/__snapshots__/definePage.spec.ts.snap b/src/core/__snapshots__/definePage.spec.ts.snap new file mode 100644 index 000000000..8ac4cb269 --- /dev/null +++ b/src/core/__snapshots__/definePage.spec.ts.snap @@ -0,0 +1,15 @@ +// Vitest Snapshot v1 + +exports[`definePage > removes definePage 1`] = ` +" + + + + " +`; diff --git a/src/core/definePage.spec.ts b/src/core/definePage.spec.ts index 8b17fa039..577fee800 100644 --- a/src/core/definePage.spec.ts +++ b/src/core/definePage.spec.ts @@ -1,10 +1,8 @@ +import { TransformResult } from 'vite' import { expect, describe, it } from 'vitest' import { definePageTransform, extractDefinePageNameAndPath } from './definePage' -describe('definePage', () => { - it('removes definePage', async () => { - const result = await definePageTransform({ - code: ` +const sampleCode = ` - `, - id: 'src/pages/basic.vue', - }) - const code = typeof result === 'string' ? result : result?.code + + ` - expect(code).toMatchInlineSnapshot(` - " - - " - `) + expect(result).toHaveProperty('code') + expect(result?.code).toMatchSnapshot() }) it('extracts name and path', async () => { expect( - await extractDefinePageNameAndPath( - ` - - `, - 'src/pages/basic.vue' - ) + await extractDefinePageNameAndPath(sampleCode, 'src/pages/basic.vue') ).toEqual({ name: 'custom', path: '/custom', @@ -59,9 +45,39 @@ const b = 1 const a = 1 const b = 1 + + `, 'src/pages/basic.vue' ) - ).toEqual(undefined) + ).toBeFalsy() + }) + + it('works with comments', async () => { + const code = ` + + + + ` + // no need to transform + let result = (await definePageTransform({ + code, + id: 'src/pages/basic.vue', + })) as Exclude + expect(result).toBeFalsy() + + // should give an empty object + result = (await definePageTransform({ + code, + id: 'src/pages/basic.vue?definePage&vue', + })) as Exclude + + expect(result).toBe('export default {}') }) }) diff --git a/src/core/definePage.ts b/src/core/definePage.ts index 1be5dd7d4..ea5cd6afa 100644 --- a/src/core/definePage.ts +++ b/src/core/definePage.ts @@ -32,12 +32,14 @@ export function definePageTransform({ if (!code.includes(MACRO_DEFINE_PAGE)) return const sfc = parseSFC(code, id) - if (!sfc.scriptSetup) return + // are we extracting only the definePage object + const isExtractingDefinePage = id.includes(MACRO_DEFINE_PAGE) + const { script, scriptSetup, scriptCompiled } = sfc - const definePageNodes = (scriptCompiled.scriptSetupAst as Node[]) + const definePageNodes = (scriptCompiled?.scriptSetupAst || ([] as Node[])) .map((node) => { if (node.type === 'ExpressionStatement') node = node.expression return isCallOf(node, MACRO_DEFINE_PAGE) ? node : null @@ -45,7 +47,11 @@ export function definePageTransform({ .filter((node): node is CallExpression => !!node) if (!definePageNodes.length) { - return + return isExtractingDefinePage + ? // e.g. index.vue?definePage that contains a commented `definePage() + 'export default {}' + : // e.g. index.vue that contains a commented `definePage() + null } else if (definePageNodes.length > 1) { throw new SyntaxError(`duplicate definePage() call`) } @@ -54,7 +60,7 @@ export function definePageTransform({ const setupOffset = scriptSetup.loc.start.offset // we only want the page info - if (id.includes(MACRO_DEFINE_PAGE)) { + if (isExtractingDefinePage) { const s = new MagicString(code) // remove everything except the page info @@ -107,7 +113,7 @@ export function extractDefinePageNameAndPath( const { script, scriptSetup, scriptCompiled } = sfc - const definePageNodes = (scriptCompiled.scriptSetupAst as Node[]) + const definePageNodes = (scriptCompiled?.scriptSetupAst ?? ([] as Node[])) .map((node) => { if (node.type === 'ExpressionStatement') node = node.expression return isCallOf(node, MACRO_DEFINE_PAGE) ? node : null