Nuxt/packages/nuxt/src/components/client-fallback-auto-id.ts

54 lines
1.7 KiB
TypeScript

import { createUnplugin } from 'unplugin'
import type { ComponentsOptions } from '@nuxt/schema'
import MagicString from 'magic-string'
import { isAbsolute, relative } from 'pathe'
import { hash } from 'ohash'
import { isVue } from '../core/utils'
interface LoaderOptions {
sourcemap?: boolean
transform?: ComponentsOptions['transform'],
rootDir: string
}
const CLIENT_FALLBACK_RE = /<(NuxtClientFallback|nuxt-client-fallback)( [^>]*)?>/
const CLIENT_FALLBACK_GLOBAL_RE = /<(NuxtClientFallback|nuxt-client-fallback)( [^>]*)?>/g
export const clientFallbackAutoIdPlugin = createUnplugin((options: LoaderOptions) => {
const exclude = options.transform?.exclude || []
const include = options.transform?.include || []
return {
name: 'nuxt:client-fallback-auto-id',
enforce: 'pre',
transformInclude (id) {
if (exclude.some(pattern => pattern.test(id))) {
return false
}
if (include.some(pattern => pattern.test(id))) {
return true
}
return isVue(id)
},
transform (code, id) {
if (!CLIENT_FALLBACK_RE.test(code)) { return }
const s = new MagicString(code)
const relativeID = isAbsolute(id) ? relative(options.rootDir, id) : id
let count = 0
s.replace(CLIENT_FALLBACK_GLOBAL_RE, (full, name, attrs) => {
count++
if (/ :?uid=/g.test(attrs)) { return full }
return `<${name} :uid="'${hash(relativeID)}' + JSON.stringify($props) + '${count}'" ${attrs ?? ''}>`
})
if (s.hasChanged()) {
return {
code: s.toString(),
map: options.sourcemap
? s.generateMap({ hires: true })
: undefined
}
}
}
}
})