You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/src/server/server.ts

65 lines
1.9 KiB

import path from 'path'
import { createServer as createViteServer, cachedRead, Plugin } from 'vite'
import { createMarkdownToVueRenderFn } from '../markdown/markdownToVue'
import { VitePressResolver, THEME_PATH, APP_PATH } from './resolver'
const debug = require('debug')('vitepress:serve')
const debugHmr = require('debug')('vitepress:hmr')
const VitePressPlugin: Plugin = ({ app, root, watcher, resolver }) => {
const markdownToVue = createMarkdownToVueRenderFn(root)
// watch theme files if it's outside of project root
if (path.relative(root, THEME_PATH).startsWith('..')) {
debugHmr(`watching theme dir outside of project root: ${THEME_PATH}`)
watcher.add(THEME_PATH)
}
// hot reload .md files as .vue files
watcher.on('change', async (file) => {
if (file.endsWith('.md')) {
debugHmr(`reloading ${file}`)
const content = await cachedRead(null, file)
watcher.handleVueReload(file, Date.now(), markdownToVue(content, file))
}
})
// inject Koa middleware
app.use(async (ctx, next) => {
// handle .md -> vue transforms
if (ctx.path.endsWith('.md')) {
const file = resolver.publicToFile(ctx.path)
await cachedRead(ctx, file)
// let vite know this is supposed to be treated as vue file
ctx.vue = true
ctx.body = markdownToVue(ctx.body, file)
debug(ctx.url)
return next()
}
// detect and serve vitepress @app / @theme files
const file = VitePressResolver.publicToFile(ctx.path, root)
if (file) {
ctx.type = path.extname(file)
await cachedRead(ctx, file)
debug(ctx.url)
return next()
}
await next()
// serve our index.html after vite history fallback
if (ctx.url === '/index.html') {
await cachedRead(ctx, path.join(APP_PATH, 'index-dev.html'))
}
})
}
export function createServer() {
return createViteServer({
plugins: [VitePressPlugin],
resolvers: [VitePressResolver]
})
}