import { Plugin , ViteDevServer , loadConfigFromFile , normalizePath } from 'vite' ; import { dirname , relative } from 'path' ; import { isMatch } from 'micromatch' ; const loaderMatch = /\.data\.(j|t)s$/ ; let server ; interface LoaderModule { watch : string [ ] | string | undefined ; load : ( ) => any ; } interface CachedLoaderModule { base : string ; pattern : string [ ] | undefined ; loader : ( ) => any ; } const idToLoaderModulesMap = Object . create ( null ) ; let idToPendingPromiseMap = Object . create ( null ) ; let isBuild = false ; export const staticDataPlugin = { name : 'vitepress:data' , configResolved ( config ) { isBuild = config . command === 'build' ; } , configureServer ( _server ) { server = _server ; } , async load ( id ) { if ( loaderMatch . test ( id ) ) { let _resolve ; if ( isBuild ) { if ( idToPendingPromiseMap [ id ] ) { return idToPendingPromiseMap [ id ] ; } idToPendingPromiseMap [ id ] = new Promise ( ( r ) => { _resolve = r ; } ) ; } const base = dirname ( id ) ; let pattern ; let loader ; const existing = idToLoaderModulesMap [ id ] ; if ( existing ) { ; ( { pattern , loader } = existing ) ; } else { const loaderModule = ( await loadConfigFromFile ( { } as any , id ) ) ?. config as LoaderModule ; pattern = typeof loaderModule . watch === 'string' ? [ loaderModule . watch ] : loaderModule . watch ; if ( pattern ) { pattern = pattern . map ( ( p ) => { return p . startsWith ( './' ) ? p . slice ( 2 ) : p ; } ) ; } loader = loaderModule . load ; } const data = await loader ( ) ; if ( server ) { idToLoaderModulesMap [ id ] = { base , pattern , loader } ; } const result = `export const data = JSON.parse(${ JSON . stringify ( JSON . stringify ( data ) ) })` ; if ( _resolve ) _resolve ( result ) ; return result ; } } , transform ( _code , id ) { if ( server && loaderMatch . test ( id ) ) { const { base , pattern } = idToLoaderModulesMap [ id ] ! ; ( server as any ) . _globImporters [ id ] = { module : server . moduleGraph . getModuleById ( id ) , importGlobs : pattern ?. map ( ( pattern ) => ( { base , pattern } ) ) } ; } return null ; } , handleHotUpdate ( ctx ) { for ( const id in idToLoaderModulesMap ) { const { base , pattern } = idToLoaderModulesMap [ id ] ! ; const isLoaderFile = normalizePath ( ctx . file ) === id ; if ( isLoaderFile ) { delete idToLoaderModulesMap [ id ] ; } if ( isLoaderFile || ( pattern && isMatch ( relative ( base , ctx . file ) , pattern ) ) ) { ctx . modules . push ( server . moduleGraph . getModuleById ( id ) ! ) ; } } } } ;