import fs from "node:fs";
import {
normalizeSocialSvg,
type SocialLink,
} from "../../common/lib/settingsSchema";
import { REAL_SHAPES } from "../../common/lib/socialSvg.vectors";
// THE HOMEPAGE E2E'S SOCIAL LINKS, never the operator's.
//
// The header and the footer render `socialLinks` from settings.json. A checkout's
// settings.json is the operator's own (a worktree seeds it from the primary), so
// the e2e dev server reads THIS instead: `SETTINGS_FILE` (common/lib/paths.ts)
// points it at e2e/.e2e-settings.json (gitignored), written by
// playwright.config.ts before the server starts. Only the social links are set;
// every other key reads as its default, and nothing else on the homepage reads
// settings. (`SITES_DIR` points at an empty directory too, so no homepage.json
// can override these links.)
//
// Each icon is given here in its SOURCE form — as an operator would paste it —
// and goes through normalizeSocialSvg, the function every save path runs
// (Settings, a site's form, the homepage config), so the page renders what a
// save would have stored. The default trio is shaped like the icons operators
// paste, all synthetic:
// • Leaf — a gradient (an id, a url(#…) reference) and one solid colour,
// which the normalizer themes to currentColor;
// • Bubble — one colour, drawn white, as vendors ship them for dark grounds;
// themed to currentColor;
// • Disc — a two-colour disc with a letter, pasted with only width/height and
// NO viewBox, so the page proves the normalizer made its viewBox.
//
// A spec that needs another list (six links, none, a hostile icon) rewrites the
// file with writeFixtureSettings (or writeRawFixtureSettings, which skips the
// normalizer the way a hand-edited file would) and restores FIXTURE_SOCIAL_TRIO
// after: `next dev` reads settings on every request, and the suite runs one
// worker.
export const FIXTURE_SETTINGS_NAME = ".e2e-settings.json";
// The gradient icon is the checker's regression shape (socialSvg.vectors.ts
// REAL_SHAPES): a drawing program's root, a gradient with `style` stops, a dark
// outline under the body (`paint-order`), a negative-origin viewBox.
const LEAF = REAL_SHAPES.gradient_outlined;
const BUBBLE =
``;
// A two-colour disc with a letter, sized and with no viewBox (the normalizer
// makes `viewBox="0 0 81 81"`): a dark offset disc, a light disc with a dark
// outline, a dark "F".
export const FIXTURE_DISC_SVG =
``;
// Icons that must never run: each sets window.__hpHostile if it does. Written
// raw (writeRawFixtureSettings), as a hand-edited settings.json could hold them.
export const FIXTURE_HOSTILE_SVGS = [
``,
``,
``,
];
const SQUARE = ``;
const RING = ``;
const TRIANGLE = ``;
const raw = (label: string, svg: string, featured = false) => ({
label,
url: `https://${label.toLowerCase()}.example/fixture`,
svg,
...(featured ? { featured: true } : {}),
});
// The LAST link is marked for the header (`featured`): a narrow header shows it
// alone, a wide one shows all three.
export const FIXTURE_SOCIAL_TRIO = [
raw("Leaf", LEAF),
raw("Bubble", BUBBLE),
raw("Disc", FIXTURE_DISC_SVG, true),
];
// Six, the last (Disc) marked: a wide header takes the last four, a narrow one
// Disc alone.
export const FIXTURE_SOCIAL_SIX = [
raw("Square", SQUARE),
raw("Ring", RING),
...FIXTURE_SOCIAL_TRIO.slice(0, 1),
raw("Triangle", TRIANGLE),
...FIXTURE_SOCIAL_TRIO.slice(1),
];
// Six, two marked (Square, Bubble; Disc not): a narrow header takes those two,
// a wide one those two and then the last two of the rest.
export const FIXTURE_SOCIAL_SIX_FEATURED = FIXTURE_SOCIAL_SIX.map(({ featured: _, ...l }) =>
l.label === "Square" || l.label === "Bubble" ? { ...l, featured: true } : l,
);
// The same links with no mark at all: a narrow header shows none of them.
export const unmarked = (links: readonly T[]) =>
links.map(({ featured: _, ...l }) => l);
type RawLink = { label: string; url: string; svg: string; featured?: boolean };
export function writeFixtureSettings(dest: string, links: RawLink[]): void {
const socialLinks: SocialLink[] = links.map((link) => {
const svg = normalizeSocialSvg(link.svg);
if (svg === null) throw new Error(`fixture icon "${link.label}" was refused`);
return { ...link, svg };
});
writeRawFixtureSettings(dest, socialLinks);
}
// The links as given, NOT normalized: what a hand-edited settings.json holds.
export function writeRawFixtureSettings(dest: string, links: RawLink[]): void {
const tmp = `${dest}.${process.pid}.tmp`;
fs.writeFileSync(tmp, JSON.stringify({ socialLinks: links }, null, 2));
fs.renameSync(tmp, dest);
}