~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
51 lines · 1.8 KB Raw History
import adapter from '@sveltejs/adapter-node';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import { createHash } from 'node:crypto';
import { readFileSync } from 'node:fs';

/** knotless-serve, which `vite dev` hands what it answers itself. */
const serve = process.env.KNOTLESS_SERVE ?? 'http://127.0.0.1:2590';

/** The hash of the script app.html runs before the page is drawn, which lets it run: taken from app.html as it is, so it cannot fall out of step. */
const page = readFileSync(new URL('./src/app.html', import.meta.url), 'utf8');
const inline = page.match(/<script>([\s\S]*?)<\/script>/)?.[1] ?? '';
const flip = `sha256-${createHash('sha256').update(inline).digest('base64')}` as const;

export default defineConfig({
	server: {
		proxy: {
			'^/xrpc/': serve,
			'^/_live/': serve,
			'^/oauth/': serve,
			'^/[^/]+/[^/]+/raw/': serve,
			'^/[^/]+/[^/]+/archive/': serve,
			'^/[^/]+/[^/]+/(commits|tags|releases)\.atom$': serve,
			'^/[^/]+/[^/]+/releases/download/': serve
		}
	},
	plugins: [
		sveltekit({
			compilerOptions: { runes: true },
			adapter: adapter(),
			// One stylesheet, small enough to come with each page.
			inlineStyleThreshold: Infinity,
			csp: {
				mode: 'hash',
				directives: {
					'default-src': ['none'],
					// A picture pasted or picked shows from its blob: URL before it is posted.
					'img-src': ['self', 'https:', 'data:', 'blob:'],
					// Avatars take their hue from a style attribute.
					'style-src': ['unsafe-inline'],
					'script-src': ['self', flip],
					// The login dialog's handles, as they are typed (lib/typeahead.ts).
					'connect-src': ['self', 'https://typeahead.waow.tech'],
					'base-uri': ['none'],
					'form-action': ['self'],
					'frame-ancestors': ['none']
				}
			}
		})
	]
});