import { defineConfig } from 'vite' import { resolve } from 'node:path' const here = (...p) => resolve(import.meta.dirname, ...p) // Two build targets from one config: // // vite build → dist/ the deliverable: tlig.css + fonts, // no HTML. This is what WordPress // enqueues. // vite build --mode demo → demo-dist/ a static demo page that loads that // stylesheet through a real , // with the site images beside it. // // The second exists because in dev Vite injects CSS through JavaScript, so // anything with a `transition` animates from its unstyled state on first paint. // That is a dev artifact, but it makes the demo misrepresent the stylesheet. // The static build paints once, the way a browser will on the real site. export default defineConfig(({ mode }) => { const isDemo = mode === 'demo' return { root: 'src', // Relative asset URLs — a url() in CSS resolves against the stylesheet's // own location, so the output can be dropped at any path under wp-content // without rebuilding. base: './', // No public directory. It used to point at `site/`, which mirrored the // live asset tree — but `site/` is now a WordPress install, and a demo // build would copy the whole of it into demo-dist/. Every image the // stylesheet needs is a Vite asset under src/images/ instead, which is // also what makes the bundle resolve at whatever path it is dropped. publicDir: false, css: { devSourcemap: true, }, build: { // The build emits straight into the theme, so the theme always runs the // current stylesheet with no copy step and there is no `dist/` to keep in // sync. The theme's `assets/` is a build artifact and is not versioned. outDir: isDemo ? here('demo-dist') : here('site/wp-content/themes/tlig/assets'), emptyOutDir: true, sourcemap: true, cssCodeSplit: false, rollupOptions: { // The demo is built from the page; the deliverable from the entry // module, so no demo markup or demo CSS can reach dist/. input: isDemo ? here('src/index.html') : here('src/main.js'), output: { // Predictable names: WordPress enqueues these paths, so they must not // change on every build. Fonts keep their own names for the same // reason — a preload hint in the theme header has to stay valid. entryFileNames: isDemo ? 'assets/[name]-[hash].js' : 'tlig.js', assetFileNames: (info) => { const name = info.names?.[0] ?? info.name ?? '' if (name.endsWith('.css')) return 'tlig.css' if (/\.(woff2?|ttf|eot)$/.test(name)) return 'fonts/[name][extname]' // Stable, unhashed image paths: the theme preloads the parchment, // so its URL must not change on every build. if (/\.(webp|png|jpe?g|svg|avif)$/.test(name)) return 'images/[name][extname]' return 'assets/[name]-[hash][extname]' }, }, }, }, } })