From d17e4d11d07c297420dee60c1803020d3dcde7d3 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 16 Jun 2025 21:24:08 +0200 Subject: [PATCH] Fix dev mode for glitch-soc --- config/vite/plugin-glitch-themes.ts | 69 ++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/config/vite/plugin-glitch-themes.ts b/config/vite/plugin-glitch-themes.ts index 1681a0a443..0cbb4a23b6 100644 --- a/config/vite/plugin-glitch-themes.ts +++ b/config/vite/plugin-glitch-themes.ts @@ -13,15 +13,18 @@ interface Flavour { } export function GlitchThemes(): Plugin { + let jsRoot = ''; + const entrypoints: Record = {}; + return { name: 'glitch-themes', async config(userConfig) { - const entrypoints: Record = {}; - if (!userConfig.root || !userConfig.envDir) { throw new Error('Unknown project directory'); } + jsRoot = userConfig.root; + const glitchFlavourFiles = glob.sync( path.resolve(userConfig.root, 'flavours/*/theme.yml'), ); @@ -68,5 +71,67 @@ export function GlitchThemes(): Plugin { }, }; }, + configureServer(server) { + server.middlewares.use((req, res, next) => { + if (!req.url?.startsWith('/packs-dev/skins/')) { + next(); + return; + } + + // Rewrite the URL to the entrypoint if it matches a theme. + const filename = req.url.slice(11).split(/[.?]/)[0] ?? ''; + if (filename in entrypoints) { + req.url = `/packs-dev/${entrypoints[filename]}`; + } + next(); + }); + }, + handleHotUpdate({ modules, server }) { + if (modules.length === 0) { + return; + } + // Unlike upstream, we don't need to look up, we can deduce the theme + // solely from the path name + const baseRoot = path.join(jsRoot, 'skins'); + const themeNames = new Set(); + + const addIfMatches = (file: string | null) => { + if (!file) { + return false; + } + const segments = path.relative(baseRoot, file).split(path.sep); + if ( + segments.length >= 2 && + segments.length < 4 && + segments[0] !== '..' && + segments[1] + ) { + const themeName = `skins/${segments[0]}/${path.basename(segments[1], path.extname(segments[1]))}`; + themeNames.add(themeName); + return true; + } + return false; + }; + + for (const module of modules) { + if (!addIfMatches(module.file)) { + for (const importer of module.importers) { + addIfMatches(importer.file); + } + } + } + + if (themeNames.size > 0) { + server.ws.send({ + type: 'update', + updates: Array.from(themeNames).map((themeName) => ({ + type: 'css-update', + path: themeName, + acceptedPath: themeName, + timestamp: Date.now(), + })), + }); + } + }, }; }