Play liveChoose your opponent
Join
429632f
53 lines · 2.3 KB Raw Permalink History
1// The viewer: the upstream's React UI (its Vite, React and Linaria setup from vite.config.ts) with this folder's entry,
2// as static files with relative paths and no network: one script, one stylesheet, no CDN, no fonts to fetch. The art
3// pack (viewer/art/, built by src/art.py) is plain files beside them, linked from index.html.
4//
5// The look is 无名杀's (viewer/noname/): this folder's own table over the upstream's hooks and action building. When the
6// upstream's own components (its prompts, action bar and hand) import these modules, they get this folder's instead:
7// the image lookups (the art pack), the flying cards and the card face (drawn as 无名杀's; a card you play leaves your
8// hand for the middle of the table), and the style sheet (the same class names, restyled).
9import path from 'node:path';
10import { defineConfig, type Plugin } from 'vite';
11import react from '@vitejs/plugin-react';
12import wyw from '@wyw-in-js/vite';
13
14const NONAME = path.resolve('shoal/viewer/noname');
15const SWAPS: Record<string, string> = {
16 'src/client/assets/imageAssets': 'imageAssets.ts',
17 'src/client/utils/cardMoveAnimation': 'flyCards.ts',
18 'src/client/utils/cardFlyAnimation': 'flyCards.ts',
19 'src/client/components/CardFace': 'CardFace.tsx',
20 'src/client/components/gameViewStyles/index': 'styles.ts',
21};
22
23function swap(): Plugin {
24 return {
25 name: 'shoal-noname-swap',
26 enforce: 'pre',
27 async resolveId(source, importer, opts) {
28 if (!importer || importer.startsWith(NONAME)) return null;
29 const r = await this.resolve(source, importer, { ...opts, skipSelf: true });
30 const id = r?.id.replace(/\.tsx?$/, '');
31 const hit = id && Object.keys(SWAPS).find((k) => id.endsWith(k));
32 return hit ? path.join(NONAME, SWAPS[hit]) : null;
33 },
34 };
35}
36
37export default defineConfig({
38 root: 'shoal/viewer',
39 base: './',
40 publicDir: false,
41 plugins: [
42 swap(),
43 react({ exclude: ['node_modules/**'] }),
44 wyw({ sourceMap: false, displayName: false, exclude: ['node_modules/**'], evaluate: true, babelOptions: { presets: ['@babel/preset-typescript'] } }),
45 ],
46 build: {
47 outDir: '../../dist/shoal-viewer',
48 emptyOutDir: true,
49 target: 'es2022',
50 cssMinify: 'esbuild',
51 rollupOptions: { output: { codeSplitting: false, entryFileNames: 'viewer.js', assetFileNames: 'viewer[extname]' } },
52 },
53});