import {addVitePlugin, defineNuxtModule, getLayerDirectories} from '@nuxt/kit' import {getLayerFiles, getLayerContent} from '../utils/content-files' import {getRoutes, getExpandedRoutes, getRouteShortcuts, getConfig} from '../utils/content-routes' import {join, relative, dirname, basename, extname} from 'path' import {existsSync} from 'fs' /* Rationale: 1) Every project file containing useInjectedContent() is transformed and virtual modules are imported 2) Upon request the virtual modules are compiled from ts/yaml files 3) If any of the files that back a virtual module change the module is invalidated */ export default defineNuxtModule({ setup() { addVitePlugin(() => ({ name: 'content-import-injector', resolveId(id) { if (id.startsWith('virtual:content/')) { return '\0' + id // convention, hide from further processing } }, async load(id) { if (id.startsWith('\0' + 'virtual:content/')) { const slug = id.slice(17) if (slug === 'shortcuts') { const routes = await getRoutes() const shortcuts = getRouteShortcuts(routes) return `export default ${JSON.stringify(shortcuts)}` } else if (slug === 'content.config') { const file = getLayerDirectories().map(d => join(d.root, 'content.config.ts')).find(f => existsSync(f)) if (file) { this.addWatchFile(file) return `export {default} from '${file}'` } } else { const files = getLayerFiles(slug) const content = await getLayerContent(files) files.filter(f => existsSync(f)).forEach(f => this.addWatchFile(f)) return `export const content = ${JSON.stringify(content)}` } } }, hotUpdate({file, server}) { const root = getLayerDirectories().map(d => d.root).find(r => file.startsWith(r)) if (root !== undefined) { const path = relative(root, file) const slug = join(dirname(path), basename(path, extname(path))) const module = server.moduleGraph.getModuleById('\0' + `virtual:content/${slug}`) if (module) { server.moduleGraph.invalidateModule(module) this.environment.hot.send({ type: 'full-reload' }) } } return [] }, transform(code, id) { let slug: string | undefined = undefined for (const root of getLayerDirectories().map(d => d.root)) { if (id.startsWith(root) && !id.includes('/node_modules/')) { const path = relative(root, id).split('?')[0]! slug = join(dirname(path), basename(path, extname(path))) break } } if (slug === undefined) { return null } const expression = /\buseContentInjected\s*\(\s*\)/g if (!expression.test(code)) return null const transformed = code.replace(expression, `useContentInjected('${slug}', a23631da455de90c5a945da16897d0bd, d61397115e513f2bb1d8e872b7e7788f)`) return ` import {content as a23631da455de90c5a945da16897d0bd} from 'virtual:content/content.global'; import {content as d61397115e513f2bb1d8e872b7e7788f} from 'virtual:content/${slug}'; ${transformed} ` } })) } })