123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
import react, { reactCompilerPreset } from "@vitejs/plugin-react"
|
|
import babel from "@rolldown/plugin-babel"
|
|
import tailwindcss from "@tailwindcss/vite"
|
|
import { icones } from "@icones/vite"
|
|
import { readFile } from "node:fs/promises"
|
|
import expressiveCode from "satteri-expressive-code"
|
|
import { fileURLToPath } from "node:url"
|
|
import { defineConfig, type Plugin } from "vite"
|
|
import { satteri } from "vite-plugin-satteri"
|
|
import { parse } from "yaml"
|
|
|
|
const packagesDirectory = fileURLToPath(new URL("../packages", import.meta.url))
|
|
|
|
/**
|
|
* Vite 默认监听 docs 根目录。现有的外部文档与元数据会作为模块被监听,但新建
|
|
* package、meta.yaml 或 MDX 文件在首次进入模块图之前不会触发 glob 重新计算。
|
|
*/
|
|
function watchPackageDocs(): Plugin {
|
|
return {
|
|
name: "watch-package-docs",
|
|
configureServer(server) {
|
|
server.watcher.add(packagesDirectory)
|
|
},
|
|
}
|
|
}
|
|
|
|
function loadYamlModules(): Plugin {
|
|
return {
|
|
name: "load-yaml-modules",
|
|
enforce: "pre",
|
|
transform(source, id) {
|
|
if (!/\.ya?ml(?:\?|$)/.test(id)) return
|
|
|
|
try {
|
|
return {
|
|
code: `export default ${JSON.stringify(parse(source))}`,
|
|
map: null,
|
|
}
|
|
} catch (error) {
|
|
this.error(
|
|
`Unable to parse ${id}: ${error instanceof Error ? error.message : String(error)}`
|
|
)
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
function loadDocSearchSources(): Plugin {
|
|
const suffix = "?docs-search-raw"
|
|
const virtualPrefix = "\0docs-search-raw:"
|
|
|
|
return {
|
|
name: "load-doc-search-sources",
|
|
enforce: "pre",
|
|
async resolveId(id, importer) {
|
|
if (!id.endsWith(suffix)) return
|
|
|
|
const sourceId = id.slice(0, -suffix.length)
|
|
const resolved = await this.resolve(sourceId, importer, {
|
|
skipSelf: true,
|
|
})
|
|
const filename = resolved?.id ?? sourceId
|
|
return `${virtualPrefix}${encodeURIComponent(filename)}.js`
|
|
},
|
|
async load(id) {
|
|
if (!id.startsWith(virtualPrefix)) return
|
|
|
|
const sourceId = decodeURIComponent(
|
|
id.slice(virtualPrefix.length, -".js".length)
|
|
)
|
|
const filename = sourceId.startsWith("/@fs/")
|
|
? sourceId.slice("/@fs".length)
|
|
: sourceId
|
|
this.addWatchFile(filename)
|
|
const source = await readFile(filename, "utf8")
|
|
return `export default ${JSON.stringify(source)}`
|
|
},
|
|
}
|
|
}
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig({
|
|
plugins: [
|
|
watchPackageDocs(),
|
|
loadYamlModules(),
|
|
loadDocSearchSources(),
|
|
satteri({
|
|
features: {
|
|
frontmatter: true,
|
|
gfm: true,
|
|
headingAttributes: true,
|
|
},
|
|
mdx: {
|
|
jsxImportSource: "react",
|
|
},
|
|
hastPlugins: [
|
|
expressiveCode({
|
|
frames: false,
|
|
textMarkers: false,
|
|
themes: ["github-light", "github-dark"],
|
|
useDarkModeMediaQuery: false,
|
|
themeCssSelector: (theme) =>
|
|
theme.type === "dark" ? ".dark" : ":root:not(.dark)",
|
|
styleOverrides: {
|
|
borderRadius: "0.75rem",
|
|
borderWidth: "1px",
|
|
codeFontSize: "0.875rem",
|
|
codeLineHeight: "1.5rem",
|
|
codePaddingInline: "1rem",
|
|
},
|
|
}),
|
|
],
|
|
}),
|
|
tailwindcss(),
|
|
icones({
|
|
mode: "symbol",
|
|
emitData: false,
|
|
}),
|
|
react(),
|
|
babel({ presets: [reactCompilerPreset()] }),
|
|
],
|
|
})
|