Files

142 lines
4.4 KiB
TypeScript

import type { Plugin } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import Vue from '@vitejs/plugin-vue'
import { resolve } from 'pathe'
import { presetAttributify, presetIcons, presetWind3, transformerDirectives } from 'unocss'
import Unocss from 'unocss/vite'
import { defineConfig } from 'vite'
import { resolveApiToken } from '../vitest/src/node/config/apiToken'
export default defineConfig({
base: './',
resolve: {
// TODO: keep manual alias for vite 7 CI
// tsconfigPaths: true,
alias: {
'~/': `${resolve(import.meta.dirname, 'client')}/`,
},
},
plugins: [
Vue(),
Unocss({
presets: [presetWind3(), presetAttributify(), presetIcons()],
content: {
pipeline: {
include: [
// by default .ts is excluded
/\/client\/.*\.(ts|vue)($|\?)/,
],
},
},
shortcuts: {
'bg-base': 'bg-white dark:bg-[#111]',
'bg-overlay': 'bg-[#eee]:50 dark:bg-[#222]:50',
'bg-header': 'bg-gray-500:5',
'bg-active': 'bg-gray-500:8',
'bg-hover': 'bg-gray-500:20',
'border-base': 'border-gray-500:10',
'focus-base': 'border-gray-500 dark:border-gray-400',
'highlight': 'bg-[#eab306] text-[#323238] dark:bg-[#323238] dark:text-[#eab306]',
'tab-button': 'font-light op50 hover:op80 h-full px-4',
'tab-button-active': 'op100 bg-gray-500:10',
},
transformers: [
transformerDirectives(),
],
safelist: 'absolute origin-top mt-[8px]'.split(' '),
}),
process.env.HTML_REPORT_DIR
? devHtmlReportPlugin({ htmlDir: process.env.HTML_REPORT_DIR })
: devUiScriptPlugin(),
{
// workaround `crossorigin` issues on some browsers
// https://github.com/vitejs/vite/issues/6648
name: 'no-crossorigin-for-same-assets',
apply: 'build',
transformIndexHtml(html) {
return html
.replace('crossorigin src="./assets/', 'src="./assets/')
.replace('crossorigin href="./assets/', 'href="./assets/')
},
},
],
build: {
outDir: './dist/client',
},
})
function devUiScriptPlugin(): Plugin {
const BROWSER_SCRIPT_RE = /<script type="module">([\s\S]*?window\.__vitest_browser_runner__\s*=\s*\{[\s\S]*?window\.VITEST_API_TOKEN\s*=[\s\S]*?)<\/script>/
const browserUrl = `http://localhost:${process.env.BROWSER_DEV_PORT || '63315'}/__vitest_test__/`
return {
name: 'dev-ui-script',
apply(_config, env) {
return env.command === 'serve' && env.mode !== 'test'
},
async transformIndexHtml() {
if (process.env.BROWSER_DEV) {
const response = await fetch(browserUrl)
if (!response.ok) {
throw new Error(`Failed to fetch browser runner HTML from ${browserUrl}`)
}
const browserHtml = await response.text()
const browserScript = browserHtml.match(BROWSER_SCRIPT_RE)?.[1]
if (!browserScript) {
throw new Error('Failed to extract browser runner state from the response')
}
return [
{
tag: 'script',
attrs: { type: 'module' },
children: browserScript,
injectTo: 'head-prepend',
},
]
}
const token = resolveApiToken(process.cwd()).token
return [
{
tag: 'script',
children: `window.VITEST_API_TOKEN = ${JSON.stringify(token)}`,
injectTo: 'head-prepend',
},
]
},
}
}
function devHtmlReportPlugin({ htmlDir }: { htmlDir: string }): Plugin {
const REPORT_FILE = 'html.meta.json.gz'
return {
name: 'dev-html-report',
apply(_config, env) {
return !!htmlDir && env.command === 'serve' && env.mode !== 'test'
},
async transformIndexHtml() {
const metadataCode = `window.HTML_REPORT_METADATA=fetch(new URL("./${REPORT_FILE}", window.location.href)).then(async res => new Uint8Array(await res.arrayBuffer()))`
return [
{
tag: 'script',
children: metadataCode,
},
]
},
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
const url = new URL(req.url || '', `http://localhost`)
if (url.pathname === `/${REPORT_FILE}`) {
const data = fs.readFileSync(path.join(htmlDir, 'ui', REPORT_FILE))
res.end(data)
return
}
next()
})
},
}
}