2022-07-07 16:26:04 +00:00
|
|
|
import { pathToFileURL } from 'node:url'
|
|
|
|
import { createUnplugin } from 'unplugin'
|
|
|
|
import { isAbsolute, relative } from 'pathe'
|
|
|
|
import { walk } from 'estree-walker'
|
|
|
|
import MagicString from 'magic-string'
|
|
|
|
import { hash } from 'ohash'
|
|
|
|
import type { CallExpression } from 'estree'
|
|
|
|
import { parseURL } from 'ufo'
|
|
|
|
|
|
|
|
export interface ComposableKeysOptions {
|
2022-08-15 13:40:06 +00:00
|
|
|
sourcemap: boolean
|
|
|
|
rootDir: string
|
2022-07-07 16:26:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const keyedFunctions = [
|
|
|
|
'useState', 'useFetch', 'useAsyncData', 'useLazyAsyncData', 'useLazyFetch'
|
|
|
|
]
|
|
|
|
const KEYED_FUNCTIONS_RE = new RegExp(`(${keyedFunctions.join('|')})`)
|
|
|
|
|
2022-08-15 13:40:06 +00:00
|
|
|
export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptions) => {
|
2022-07-07 16:26:04 +00:00
|
|
|
return {
|
|
|
|
name: 'nuxt:composable-keys',
|
|
|
|
enforce: 'post',
|
|
|
|
transform (code, id) {
|
|
|
|
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href))
|
|
|
|
if (!pathname.match(/\.(m?[jt]sx?|vue)/)) { return }
|
|
|
|
if (!KEYED_FUNCTIONS_RE.test(code)) { return }
|
|
|
|
const { 0: script = code, index: codeIndex = 0 } = code.match(/(?<=<script[^>]*>)[\S\s.]*?(?=<\/script>)/) || []
|
|
|
|
const s = new MagicString(code)
|
|
|
|
// https://github.com/unjs/unplugin/issues/90
|
2022-07-29 09:40:04 +00:00
|
|
|
let count = 0
|
2022-07-07 16:26:04 +00:00
|
|
|
const relativeID = isAbsolute(id) ? relative(options.rootDir, id) : id
|
|
|
|
walk(this.parse(script, {
|
|
|
|
sourceType: 'module',
|
|
|
|
ecmaVersion: 'latest'
|
|
|
|
}), {
|
2022-08-15 13:40:06 +00:00
|
|
|
enter (_node) {
|
|
|
|
if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return }
|
|
|
|
const node: CallExpression = _node as CallExpression
|
|
|
|
if (keyedFunctions.includes((node.callee as any).name) && node.arguments.length < 4) {
|
2022-07-07 16:26:04 +00:00
|
|
|
const end = (node as any).end
|
|
|
|
s.appendLeft(
|
|
|
|
codeIndex + end - 1,
|
2022-07-29 09:40:04 +00:00
|
|
|
(node.arguments.length ? ', ' : '') + "'$" + hash(`${relativeID}-${++count}`) + "'"
|
2022-07-07 16:26:04 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
if (s.hasChanged()) {
|
|
|
|
return {
|
|
|
|
code: s.toString(),
|
2022-08-15 13:40:06 +00:00
|
|
|
map: options.sourcemap
|
|
|
|
? s.generateMap({ source: id, includeContent: true })
|
|
|
|
: undefined
|
2022-07-07 16:26:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|