CI / Typecheck, test, build (pull_request) Successful in 26s
The plain address is the one thing that button must not offer -- followed in the browser the rewrite rules are installed in, it comes straight back here -- so there is nothing to show until there is a browser to hand it to. The copy button and the selectable URL were always the part carrying the weight; the open link now ships hidden and the script reveals it along with the scheme. That also settles what the button should say. It went back to "Open on <platform>": the browser's name was there to explain a tap that went nowhere, and a button that is not shown until it works needs no such explanation. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KF5YF3iZVKbezwALap8LYd
62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
import { html, type Raw } from './html.ts';
|
|
|
|
export function layout(title: string, body: Raw): string {
|
|
return `<!doctype html>
|
|
${html`<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
<meta name="robots" content="noindex, nofollow">
|
|
<meta name="referrer" content="no-referrer">
|
|
<meta name="color-scheme" content="light dark">
|
|
<title>${title}</title>
|
|
<link rel="stylesheet" href="/static/app.css">
|
|
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
|
|
</head>
|
|
<body>
|
|
<main>${body}</main>
|
|
<script src="/static/app.js" type="module"></script>
|
|
</body>
|
|
</html>`}`;
|
|
}
|
|
|
|
/**
|
|
* Indicative brand accents. The written label is what actually identifies
|
|
* the platform; the colour is only there to make it recognisable at a
|
|
* glance.
|
|
*/
|
|
const ACCENT: Record<string, { color: string; monogram: string }> = {
|
|
x: { color: '#0f1419', monogram: '✕' },
|
|
threads: { color: '#3b3b3b', monogram: '@' },
|
|
instagram: { color: '#c13584', monogram: 'IG' },
|
|
tiktok: { color: '#fe2c55', monogram: '♪' },
|
|
bluesky: { color: '#0085ff', monogram: 'B' },
|
|
reddit: { color: '#ff4500', monogram: 'r' },
|
|
};
|
|
|
|
export function badge(platform: string, label: string): Raw {
|
|
const accent = ACCENT[platform] ?? { color: '#666', monogram: '?' };
|
|
return html`<span class="badge" style="--accent: ${accent.color}">
|
|
<span class="badge__mark" aria-hidden="true">${accent.monogram}</span>
|
|
<span class="badge__label">${label}</span>
|
|
</span>`;
|
|
}
|
|
|
|
/** The copy control, plus the URL itself so it is always selectable even if
|
|
* the clipboard API is unavailable.
|
|
*
|
|
* The open link ships hidden: followed in the browser the rewrite rules are
|
|
* installed in, it redirects straight back here, so it is only worth showing
|
|
* once a browser has been picked to hand it to. The script reveals it, and
|
|
* the href in the markup is the plain address it starts from. */
|
|
export function originalUrlBlock(originalUrl: string, platformLabel: string): Raw {
|
|
return html`<div class="original">
|
|
<button type="button" class="copy" data-url="${originalUrl}">
|
|
<span class="copy__idle">Copy original link</span>
|
|
<span class="copy__done" hidden>Copied</span>
|
|
</button>
|
|
<a class="original__open" href="${originalUrl}" rel="noopener noreferrer nofollow" target="_blank" hidden>Open on ${platformLabel}</a>
|
|
<p class="original__url"><code>${originalUrl}</code></p>
|
|
</div>`;
|
|
}
|