mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 00:52:01 +00:00
fix(nuxt): extract route rules/page meta in 2+ script blocks (#28625)
This commit is contained in:
parent
81774f3a5a
commit
eed8730688
@ -18,10 +18,12 @@ export async function extractRouteRules (code: string): Promise<NitroRouteConfig
|
|||||||
}
|
}
|
||||||
if (!ROUTE_RULE_RE.test(code)) { return null }
|
if (!ROUTE_RULE_RE.test(code)) { return null }
|
||||||
|
|
||||||
const script = extractScriptContent(code)
|
|
||||||
code = script?.code || code
|
|
||||||
|
|
||||||
let rule: NitroRouteConfig | null = null
|
let rule: NitroRouteConfig | null = null
|
||||||
|
const contents = extractScriptContent(code)
|
||||||
|
for (const script of contents) {
|
||||||
|
if (rule) { break }
|
||||||
|
|
||||||
|
code = script?.code || code
|
||||||
|
|
||||||
const js = await transform(code, { loader: script?.loader || 'ts' })
|
const js = await transform(code, { loader: script?.loader || 'ts' })
|
||||||
walk(parse(js.code, {
|
walk(parse(js.code, {
|
||||||
@ -42,6 +44,7 @@ export async function extractRouteRules (code: string): Promise<NitroRouteConfig
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ruleCache[code] = rule
|
ruleCache[code] = rule
|
||||||
return rule
|
return rule
|
||||||
|
@ -168,21 +168,23 @@ export async function augmentPages (routes: NuxtPage[], vfs: Record<string, stri
|
|||||||
return augmentedPages
|
return augmentedPages
|
||||||
}
|
}
|
||||||
|
|
||||||
const SFC_SCRIPT_RE = /<script(?<attrs>[^>]*)>(?<content>[\s\S]*?)<\/script[^>]*>/i
|
const SFC_SCRIPT_RE = /<script(?<attrs>[^>]*)>(?<content>[\s\S]*?)<\/script[^>]*>/gi
|
||||||
export function extractScriptContent (html: string) {
|
export function extractScriptContent (html: string) {
|
||||||
const groups = html.match(SFC_SCRIPT_RE)?.groups || {}
|
const contents: Array<{ loader: 'tsx' | 'ts', code: string }> = []
|
||||||
|
for (const match of html.matchAll(SFC_SCRIPT_RE)) {
|
||||||
if (groups.content) {
|
if (match?.groups?.content) {
|
||||||
return {
|
contents.push({
|
||||||
loader: groups.attrs.includes('tsx') ? 'tsx' : 'ts',
|
loader: match.groups.attrs.includes('tsx') ? 'tsx' : 'ts',
|
||||||
code: groups.content.trim(),
|
code: match.groups.content.trim(),
|
||||||
} as const
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return contents
|
||||||
}
|
}
|
||||||
|
|
||||||
const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/
|
const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/
|
||||||
|
const extractionKeys = ['name', 'path', 'alias', 'redirect'] as const
|
||||||
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
||||||
|
|
||||||
const pageContentsCache: Record<string, string> = {}
|
const pageContentsCache: Record<string, string> = {}
|
||||||
@ -197,15 +199,17 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
if (absolutePath in metaCache) { return metaCache[absolutePath] }
|
if (absolutePath in metaCache) { return metaCache[absolutePath] }
|
||||||
|
|
||||||
const loader = getLoader(absolutePath)
|
const loader = getLoader(absolutePath)
|
||||||
const script = !loader ? null : loader === 'vue' ? extractScriptContent(contents) : { code: contents, loader }
|
const scriptBlocks = !loader ? null : loader === 'vue' ? extractScriptContent(contents) : [{ code: contents, loader }]
|
||||||
if (!script) {
|
if (!scriptBlocks) {
|
||||||
metaCache[absolutePath] = {}
|
metaCache[absolutePath] = {}
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const extractedMeta = {} as Partial<Record<keyof NuxtPage, any>>
|
||||||
|
|
||||||
|
for (const script of scriptBlocks) {
|
||||||
if (!PAGE_META_RE.test(script.code)) {
|
if (!PAGE_META_RE.test(script.code)) {
|
||||||
metaCache[absolutePath] = {}
|
continue
|
||||||
return {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const js = await transform(script.code, { loader: script.loader })
|
const js = await transform(script.code, { loader: script.loader })
|
||||||
@ -215,8 +219,6 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
ranges: true,
|
ranges: true,
|
||||||
}) as unknown as Program
|
}) as unknown as Program
|
||||||
|
|
||||||
const extractedMeta = {} as Partial<Record<keyof NuxtPage, any>>
|
|
||||||
const extractionKeys = ['name', 'path', 'alias', 'redirect'] as const
|
|
||||||
const dynamicProperties = new Set<keyof NuxtPage>()
|
const dynamicProperties = new Set<keyof NuxtPage>()
|
||||||
|
|
||||||
let foundMeta = false
|
let foundMeta = false
|
||||||
@ -291,6 +293,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
metaCache[absolutePath] = extractedMeta
|
metaCache[absolutePath] = extractedMeta
|
||||||
return extractedMeta
|
return extractedMeta
|
||||||
|
@ -61,6 +61,41 @@ describe('page metadata', () => {
|
|||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should extract serialisable metadata from files with multiple blocks', async () => {
|
||||||
|
const meta = await getRouteMeta(`
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'thing'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
name: 'some-custom-name',
|
||||||
|
path: '/some-custom-path',
|
||||||
|
validate: () => true,
|
||||||
|
middleware: [
|
||||||
|
function () {},
|
||||||
|
],
|
||||||
|
otherValue: {
|
||||||
|
foo: 'bar',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
`, filePath)
|
||||||
|
|
||||||
|
expect(meta).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"__nuxt_dynamic_meta_key": Set {
|
||||||
|
"meta",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"name": "some-custom-name",
|
||||||
|
"path": "/some-custom-path",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
it('should extract serialisable metadata in options api', async () => {
|
it('should extract serialisable metadata in options api', async () => {
|
||||||
const meta = await getRouteMeta(`
|
const meta = await getRouteMeta(`
|
||||||
<script>
|
<script>
|
||||||
|
Loading…
Reference in New Issue
Block a user