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

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
88 lines · 3.9 KB Raw History
import type { Handle, HandleFetch } from '@sveltejs/kit/hooks';
import { KNOTLESS_SERVE } from '$app/env/private';
import {
	NIGHT,
	NIGHT_PALETTE,
	PALETTE,
	THEME,
	customOf,
	halvesStyle,
	paletteOf,
	styleOf,
	themeOf
} from '#lib/theme.ts';

/** What `<html>` says of the theme the cookies name: a theme of the viewer's own only with its palette, which is only ever colours as #rrggbb. */
function drawn(theme: string | null, said: string | undefined): string {
	const palette = theme?.startsWith('custom-') ? paletteOf(said) : null;
	if (palette) return ` data-theme="${customOf(palette)}" style="${styleOf(palette)}"`;
	return theme && !theme.startsWith('custom-') ? ` data-theme="${theme}"` : '';
}

/** A half of a pair, as the cookies name it: its theme, and its palette for one of the viewer's own. */
function half(theme: string | null, said: string | undefined) {
	const palette = theme?.startsWith('custom-') ? paletteOf(said) : null;
	return theme && (palette || !theme.startsWith('custom-')) ? { id: theme, palette } : null;
}

/** What `<html>` says of a pair, by day and at night, and the <style> its palettes are drawn from: app.html's script shows the half the system says. */
function pair(day: ReturnType<typeof half>, night: ReturnType<typeof half>) {
	if (!day || !night) return null;
	const own = halvesStyle(day.palette, night.palette);
	return {
		html: ` data-day="${day.id}" data-night="${night.id}" data-theme="${day.id}" data-half="day"`,
		head: own ? `<style id="theme-own">${own}</style>` : ''
	};
}

export const handle: Handle = async ({ event, resolve }) => {
	// A page is drawn in the theme its cookie names, from the first paint;
	// or in a pair's, as the system is light or dark.
	const both = pair(
		half(themeOf(event.cookies.get(THEME)), event.cookies.get(PALETTE)),
		half(themeOf(event.cookies.get(NIGHT)), event.cookies.get(NIGHT_PALETTE))
	);
	const theme = both?.html ?? drawn(themeOf(event.cookies.get(THEME)), event.cookies.get(PALETTE));
	const res = await resolve(event, {
		filterSerializedResponseHeaders: (name) => name === 'cache-control',
		transformPageChunk: theme
			? ({ html }) =>
					html
						.replace('<html lang="en">', `<html lang="en"${theme}>`)
						.replace('</head>', `${both?.head ?? ''}</head>`)
			: undefined
	});
	// A page's times are put in the zone its cookie names, and its colours in its theme.
	res.headers.append('vary', 'cookie');
	// Someone logged in is shown what is theirs: a page for no cache but theirs, and not kept.
	if (event.cookies.get('knotless_session')) res.headers.set('cache-control', 'private, no-store');
	return res;
};

/**
 * Asked of this site, XRPC queries are asked of knotless-serve
 * directly, and with the global fetch: knotless-serve can have the same
 * origin as the site it fronts, which Kit's own would answer itself.
 */
export const handleFetch: HandleFetch = ({ event, request, fetch }) => {
	const url = new URL(request.url);
	if (url.origin === event.url.origin && url.pathname.startsWith('/xrpc/')) {
		// The site it was asked of, for the addresses it answers in full.
		const asked = new Request(`${KNOTLESS_SERVE}${url.pathname}${url.search}`, request);
		asked.headers.set('x-forwarded-host', event.url.host);
		asked.headers.set('x-forwarded-proto', event.url.protocol.slice(0, -1));
		// Who asks, as the session cookie of someone logged in says: the
		// global fetch does not send the page's cookies itself.
		const cookie = event.request.headers.get('cookie');
		if (cookie) asked.headers.set('cookie', cookie);
		// The trace knotless-serve started for the page, for what it asks
		// to be logged under the same one.
		const trace = event.request.headers.get('traceparent');
		if (trace) asked.headers.set('traceparent', trace);
		// Named as the pages, which knotless-serve counts apart from the
		// clients that ask it: node would call itself `node`, as scripts do.
		asked.headers.set('user-agent', 'knotless-pages');
		return globalThis.fetch(asked);
	}
	return fetch(request);
};