diff options
feat: things
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/+page.svelte | 3 | ||||
-rw-r--r-- | src/routes/shared.ts | 626 |
2 files changed, 376 insertions, 253 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d047f05..d96dda2 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -36,7 +36,8 @@ skipAnimation?: boolean; } = $props(); onMount(() => { - if (skipAnimation) window.history.pushState({}, "", "/skip-animation"); + if (skipAnimation && location.pathname !== "/skip-animation") + history.replaceState({}, "", "/skip-animation"); }); let isScripted = $state(false); diff --git a/src/routes/shared.ts b/src/routes/shared.ts index a5ff683..ff5b574 100644 --- a/src/routes/shared.ts +++ b/src/routes/shared.ts @@ -11,7 +11,7 @@ export const biosSteps = 3; export const biosStepInterval = 1000; const wpmToTypingSpeed = (wpm: number, avgWordLen: number) => - (1 / (wpm * avgWordLen / 60)) * 1000; + (1 / ((wpm * avgWordLen) / 60)) * 1000; const averageWordLength = 4.793; const typingInfo = (wpm = 80) => ({ @@ -23,7 +23,7 @@ export const getDelay = (typingInfo: TypingSpeed) => (Math.random() * 2 - 1) * typingInfo.typingDeviation + typingInfo.typingSpeedAvg; export const login = { - username: 'lain', + username: "lain", passwordLength: 12, ...typingInfo(100), // one usually has muscle memory for well-known frequently-typed credentials, hence higher wpm }; @@ -38,30 +38,35 @@ export type RenderBlock = { url?: | `newtab:${string}` | `currenttab:${string}` - | ((textObj: TTYText & { kind: 'text' }) => void); + | ((textObj: TTYText & { kind: "text" }) => void); bg?: string; raw?: boolean; dl?: string; }; -export type TTYText = { - kind: 'text'; - renderrestriction?: 'everywhere' | 'js-only' | 'noscript'; - value: RenderBlock[]; - id: string; - classes: string[]; -} | { - kind: 'removeNode'; - removedId: string; - removedItemClassList: string[]; -} | { - kind: 'time'; - delay: number; -} | { - kind: 'cursorVisibility'; - visible: boolean; -} | { - kind: 'clear'; -}; +export type TTYText = + | { + kind: "text"; + renderrestriction?: "everywhere" | "js-only" | "noscript"; + value: RenderBlock[]; + id: string; + classes: string[]; + } + | { + kind: "removeNode"; + removedId: string; + removedItemClassList: string[]; + } + | { + kind: "time"; + delay: number; + } + | { + kind: "cursorVisibility"; + visible: boolean; + } + | { + kind: "clear"; + }; export type Only<Obj, Keys extends keyof Obj> = { [k in Keys]: Obj[k]; }; @@ -70,36 +75,30 @@ export type Diff< [k: string]: unknown; }, U extends keyof T, -> = ({ [P in keyof T]: P } & { [P in U]: never } & { [x: string]: never })[ - keyof T -]; +> = ({ [P in keyof T]: P } & { [P in U]: never } & { + [x: string]: never; +})[keyof T]; export type Omit< T extends { [k: string]: unknown; }, K extends keyof T, -> = Pick< - T, - Diff<T, K> ->; +> = Pick<T, Diff<T, K>>; export const ttyLines: TTYText[] = (() => { const lines: TTYText[] = []; let ids: string[] = []; const byId = new Map<string, TTYText>(); let i = 69420; let defaultRenderRestriction: Only< - TTYText & { kind: 'text' }, - 'renderrestriction' - >['renderrestriction'] = 'everywhere'; - type LimitedRenderBlock = Omit<RenderBlock, 'value'>; - type RenderBlockArg = [ - text: string, - options?: LimitedRenderBlock, - ]; + TTYText & { kind: "text" }, + "renderrestriction" + >["renderrestriction"] = "everywhere"; + type LimitedRenderBlock = Omit<RenderBlock, "value">; + type RenderBlockArg = [text: string, options?: LimitedRenderBlock]; /** due to hellish css constraints, each text() call creates its own line - however, each block in a text() is joined on the same line. */ const text = ( globalOptions: - | Only<TTYText & { kind: 'text' }, 'renderrestriction'> + | Only<TTYText & { kind: "text" }, "renderrestriction"> | RenderBlockArg, ...blocks: RenderBlockArg[] ) => { @@ -110,12 +109,12 @@ export const ttyLines: TTYText[] = (() => { globalOptions = {}; } const txt = { - kind: 'text', - renderrestriction: globalOptions.renderrestriction ?? - defaultRenderRestriction, + kind: "text", + renderrestriction: + globalOptions.renderrestriction ?? defaultRenderRestriction, value: blocks.map(([t, o]) => ({ value: t, - colour: '#b9b9b9', + colour: "#b9b9b9", ...o, })), id, @@ -127,40 +126,34 @@ export const ttyLines: TTYText[] = (() => { }; const wait = (time: number) => lines.push({ - kind: 'time', + kind: "time", delay: time, }); const del = (id: string | number) => { - const removedId = typeof id === 'string' - ? id - : id >= 0 - ? ids[id] - : ids[ids.length + id]; + const removedId = + typeof id === "string" ? id : id >= 0 ? ids[id] : ids[ids.length + id]; const r = byId.get(removedId); - if (r?.kind === 'text') { + if (r?.kind === "text") { lines.push({ - kind: 'removeNode', + kind: "removeNode", removedId, removedItemClassList: r.classes, }); - r.classes.push('ttytext-removed-after-done'); + r.classes.push("ttytext-removed-after-done"); } ids = ids.filter((v) => v !== removedId); }; const delSince = (id: string | number) => { - const removedId = typeof id === 'string' - ? id - : id >= 0 - ? ids[id] - : ids[ids.length + id]; + const removedId = + typeof id === "string" ? id : id >= 0 ? ids[id] : ids[ids.length + id]; const idIndex = ids.indexOf(removedId); for (let i = idIndex; i < ids.length; i++) { const removedId = ids[i]; const r = byId.get(removedId); - if (r?.kind === 'text') { - r.classes.push('ttytext-removed-after-done'); + if (r?.kind === "text") { + r.classes.push("ttytext-removed-after-done"); lines.push({ - kind: 'removeNode', + kind: "removeNode", removedId, removedItemClassList: r.classes, }); @@ -170,17 +163,20 @@ export const ttyLines: TTYText[] = (() => { }; const getLast = () => { const v = byId.get(ids[ids.length - 1]); - if (v?.kind == 'text') { + if (v?.kind == "text") { return v.value; } else return null; }; const overwriteLast = (...newValue: RenderBlockArg[]) => { const v = byId.get(ids[ids.length - 1]); - const l = v?.kind == 'text' ? v.renderrestriction : 'everywhere'; + const l = v?.kind == "text" ? v.renderrestriction : "everywhere"; del(-1); - return text({ - renderrestriction: l, - }, ...newValue); + return text( + { + renderrestriction: l, + }, + ...newValue, + ); }; const replaceLast = ( handler: (newValue: RenderBlockArg[]) => RenderBlockArg[], @@ -192,7 +188,7 @@ export const ttyLines: TTYText[] = (() => { [ v.value, Object.fromEntries( - Object.entries(v).filter(([k]) => k !== 'value'), + Object.entries(v).filter(([k]) => k !== "value"), ), ] as const, ), @@ -200,284 +196,410 @@ export const ttyLines: TTYText[] = (() => { ); const everyTTYClear: (() => void)[] = []; const clear = () => { - if (lines.find((v) => v.kind === 'clear')) { - delSince(lines.findLastIndex((v) => v.kind === 'clear')); + if (lines.find((v) => v.kind === "clear")) { + delSince(lines.findLastIndex((v) => v.kind === "clear")); } - lines.push({ kind: 'clear' }); + lines.push({ kind: "clear" }); everyTTYClear.forEach((v) => v()); }; everyTTYClear.push(() => { - text({ - renderrestriction: 'noscript', - }, ['This browser does not support JS. Your experience may be degraded.', { - bg: '#ff0000', - colour: '#dedede', - }], ['\n', {}]); + text( + { + renderrestriction: "noscript", + }, + [ + "This browser does not support JS. Your experience may be degraded.", + { + bg: "#ff0000", + colour: "#dedede", + }, + ], + ["\n", {}], + ); }); everyTTYClear.forEach((v) => v()); // wait(300); - text({ renderrestriction: 'js-only' }, [ + text({ renderrestriction: "js-only" }, [ ((v) => v[Math.floor(Math.random() * v.length)])([ - 'cool beats are stored in the balls', - 'found xml documents in the firmware', + "cool beats are stored in the balls", + "found xml documents in the firmware", 'overhead: "I don\'t consent" "hey thats my line"', - 'uwu', - 'i regret making this hellhole of a codebase', + "uwu", + "i regret making this hellhole of a codebase", ]), { - colour: '#777777', + colour: "#777777", }, ]); wait(1000); clear(); text( - ['lain', { - colour: '#FFFF53', - weight: 700, - }], - [' in '], - ['mem.estrogen.zone', { - colour: '#17B117', - weight: 700, - }], - [' in '], - ['~', { - colour: '#53FFFF', - weight: 700, - }], + [ + "lain", + { + colour: "#FFFF53", + weight: 700, + }, + ], + [" in "], + [ + "mem.estrogen.zone", + { + colour: "#17B117", + weight: 700, + }, + ], + [" in "], + [ + "~", + { + colour: "#53FFFF", + weight: 700, + }, + ], ); text( - ['❯ ', { colour: '#53FF53', weight: 600 }], - [''], - ['', { colour: '#777777' }], + ["❯ ", { colour: "#53FF53", weight: 600 }], + [""], + ["", { colour: "#777777" }], ); { - const targetstr = '/usr/bin/env wel'; + const targetstr = "/usr/bin/env wel"; const completions = [ '/bin/sh -c "$(/usr/bin/env curl -fsSL https://blahaj.estrogen.zone/)"', - '/usr/local/bin/become-estradiol', - '/usr/bin/shellutil ansi cheatsheet 24bit', - '/usr/bin/env sh', - '/usr/bin/env wc -l src/routes/anim.css', - '/usr/bin/env welcome -c ~/.local/share/welcome.toml', + "/usr/local/bin/become-estradiol", + "/usr/bin/shellutil ansi cheatsheet 24bit", + "/usr/bin/env sh", + "/usr/bin/env wc -l src/routes/anim.css", + "/usr/bin/env welcome -c ~/.local/share/welcome.toml", ]; - for (const c of [...targetstr.split(''), 'COMPLETE']) { + for (const c of [...targetstr.split(""), "COMPLETE"]) { replaceLast((l) => { const prompt = l[l.length - 2]; const suggestions = l[l.length - 1]; - if (c === 'COMPLETE') { + if (c === "COMPLETE") { prompt[0] += suggestions[0]; - suggestions[0] = ''; + suggestions[0] = ""; } else { prompt[0] += c; const completion = completions.find((v) => v.startsWith(prompt[0])); if (completion) { suggestions[0] = completion.substring(prompt[0].length); - } else suggestions[0] = ''; + } else suggestions[0] = ""; } return l; }); - if (c === 'COMPLETE') { + if (c === "COMPLETE") { wait(100); } else wait(50 + Math.random() * 100); } - text(['Preparing...']); + text(["Preparing..."]); wait(200); } wait(1000); clear(); - text( - ['Welcome to'], - [''], - [' the Estrogen Zone!\n\n'], - ); + text(["Welcome to"], [""], [" the Estrogen Zone!\n\n"]); wait(300); - for (const c of ' my corner of'.split('')) { + for (const c of " my corner of".split("")) { replaceLast((l) => { l[1][0] += c; return l; }); wait(70); } - text( - ['Places you can find me:', { - colour: '#7a7a7a', - }], - ); + text([ + "Places you can find me:", + { + colour: "#7a7a7a", + }, + ]); wait(300); text( - [' - ', { - colour: '#7a7a7a', - }], - ['Estradiol SourceHut: ', { colour: '#cdcdcd' }], + [ + " - ", + { + colour: "#7a7a7a", + }, + ], + ["estrogen.zone git: ", { colour: "#cdcdcd" }], ); wait(100); - replaceLast((v) => [...v, ['sh.estrogen.zone/~memdmp', { - colour: '#99aaff', - underlined: true, - weight: 700, - url: 'newtab:https://sh.estrogen.zone/~memdmp', - }]]); + replaceLast((v) => [ + ...v, + [ + "git.estrogen.zone", + { + colour: "#99aaff", + underlined: true, + weight: 700, + url: "newtab:https://git.estrogen.zone", + }, + ], + ]); wait(100); text( - [' - ', { - colour: '#7a7a7a', - }], - ['On jsr: ', { colour: '#cdcdcd' }], + [ + " - ", + { + colour: "#7a7a7a", + }, + ], + ["On jsr: ", { colour: "#cdcdcd" }], ); wait(600); - replaceLast((v) => [...v, ['jsr.io/@memdmp', { - colour: '#f7df23', - underlined: true, - weight: 700, - url: 'newtab:https://sh.estrogen.zone/~memdmp', - }]]); + replaceLast((v) => [ + ...v, + [ + "jsr.io/@memdmp", + { + colour: "#f7df23", + underlined: true, + weight: 700, + url: "newtab:https://jsr.io/@memdmp", + }, + ], + ]); wait(200); text( - [' - ', { - colour: '#7a7a7a', - }], - ['In random hackerspaces', { colour: '#aaaaaa' }], + [ + " - ", + { + colour: "#7a7a7a", + }, + ], + ["In random hackerspaces", { colour: "#aaaaaa" }], ); wait(600); - text( - ['\nYou may find these useful:', { - colour: '#7a7a7a', - }], - ); + text([ + "\nYou may find these useful:", + { + colour: "#7a7a7a", + }, + ]); wait(400); text( - [' - ', { - colour: '#7a7a7a', - }], - ['GPG Root Key: ', { colour: '#cdcdcd' }], + [ + " - ", + { + colour: "#7a7a7a", + }, + ], + ["GPG Root Key: ", { colour: "#cdcdcd" }], ); wait(1000); - replaceLast((v) => [...v, ['B546778F06BBCC8EC167DB3CD919706487B8B6DE', { - colour: '#58C7F3', - underlined: true, - weight: 700, - url: 'currenttab:/keys/memdmp/primary.pgp', - dl: 'memdmp-primary.pgp', - }]]); + replaceLast((v) => [ + ...v, + [ + "B546778F06BBCC8EC167DB3CD919706487B8B6DE", + { + colour: "#58C7F3", + underlined: true, + weight: 700, + url: "currenttab:/keys/memdmp/primary.pgp", + dl: "memdmp-primary.pgp", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, [' (root key)', { - colour: '#999999', - }]]); + replaceLast((v) => [ + ...v, + [ + " (root key)", + { + colour: "#999999", + }, + ], + ]); wait(400); - text( - [' - ', { - colour: '#7a7a7a', - }], - ); + text([ + " - ", + { + colour: "#7a7a7a", + }, + ]); wait(70); - replaceLast( - (v) => [...v, ['GPG Git Key: ', { colour: '#cdcdcd' }]], - ); + replaceLast((v) => [ + ...v, + ["GPG Git Key: ", { colour: "#cdcdcd" }], + ]); wait(100); - replaceLast((v) => [...v, ['5134F05BD8D9DB8C6C0E1515A9439D346AB6DF4E', { - colour: '#F0A3B3', - underlined: true, - weight: 700, - url: 'currenttab:/keys/memdmp/git.pgp', - dl: 'memdmp-git.pgp', - }]]); + replaceLast((v) => [ + ...v, + [ + "5134F05BD8D9DB8C6C0E1515A9439D346AB6DF4E", + { + colour: "#F0A3B3", + underlined: true, + weight: 700, + url: "currenttab:/keys/memdmp/git.pgp", + dl: "memdmp-git.pgp", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, [' (', { - colour: '#999999', - }], ['signed', { - colour: '#F0A3B3', - underlined: true, - weight: 500, - url: 'currenttab:/keys/memdmp/git.pgp.sig', - dl: 'memdmp-git.pgp.sig', - }], [')', { colour: '#999999' }]]); + replaceLast((v) => [ + ...v, + [ + " (", + { + colour: "#999999", + }, + ], + [ + "signed", + { + colour: "#F0A3B3", + underlined: true, + weight: 500, + url: "currenttab:/keys/memdmp/git.pgp.sig", + dl: "memdmp-git.pgp.sig", + }, + ], + [")", { colour: "#999999" }], + ]); wait(45); - text( - [' - ', { - colour: '#7a7a7a', - }], - ); + text([ + " - ", + { + colour: "#7a7a7a", + }, + ]); wait(70); - replaceLast( - ( - v, - ) => [...v, ['GPG Release Signing Key: ', { - colour: '#cdcdcd', - }]], - ); + replaceLast((v) => [ + ...v, + [ + "GPG Release Signing Key: ", + { + colour: "#cdcdcd", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, ['0D93102265071798C7B65A4C9F0739B9E0C8FD60', { - colour: '#ffffff', - underlined: true, - weight: 700, - url: 'currenttab:/keys/memdmp/release.pgp', - dl: 'memdmp-release.pgp', - }]]); + replaceLast((v) => [ + ...v, + [ + "0D93102265071798C7B65A4C9F0739B9E0C8FD60", + { + colour: "#ffffff", + underlined: true, + weight: 700, + url: "currenttab:/keys/memdmp/release.pgp", + dl: "memdmp-release.pgp", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, [' (', { - colour: '#999999', - }], ['signed', { - colour: '#ffffff', - underlined: true, - weight: 500, - url: 'currenttab:/keys/memdmp/release.pgp.sig', - dl: 'memdmp-release.pgp.sig', - }], [')', { colour: '#999999' }]]); + replaceLast((v) => [ + ...v, + [ + " (", + { + colour: "#999999", + }, + ], + [ + "signed", + { + colour: "#ffffff", + underlined: true, + weight: 500, + url: "currenttab:/keys/memdmp/release.pgp.sig", + dl: "memdmp-release.pgp.sig", + }, + ], + [")", { colour: "#999999" }], + ]); wait(100); - text( - [' - ', { - colour: '#7a7a7a', - }], - ); + text([ + " - ", + { + colour: "#7a7a7a", + }, + ]); wait(35); - replaceLast( - ( - v, - ) => [...v, ['Source Code: ', { - colour: '#cdcdcd', - }]], - ); + replaceLast((v) => [ + ...v, + [ + "Source Code: ", + { + colour: "#cdcdcd", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, ['git.sh.estrogen.zone/~memdmp/mem.estrogen.zone', { - colour: '#F0A3B3', - underlined: true, - weight: 700, - url: 'newtab:/upstream/', - }]]); + replaceLast((v) => [ + ...v, + [ + "git.estrogen.zone/mem-estrogen-zone", + { + colour: "#F0A3B3", + underlined: true, + weight: 700, + url: "newtab:/upstream/", + }, + ], + ]); wait(100); - text( - [' - ', { - colour: '#7a7a7a', - }], - ); + text([ + " - ", + { + colour: "#7a7a7a", + }, + ]); wait(35); - replaceLast( - ( - v, - ) => [...v, ['Canaries: ', { - colour: '#cdcdcd', - }]], - ); + replaceLast((v) => [ + ...v, + [ + "Canaries: ", + { + colour: "#cdcdcd", + }, + ], + ]); wait(100); - replaceLast((v) => [...v, ['/canaries/', { - colour: '#58C7F3', - underlined: true, - weight: 700, - url: 'currenttab:/canaries/', - }]]); + replaceLast((v) => [ + ...v, + [ + "/canaries/", + { + colour: "#58C7F3", + underlined: true, + weight: 700, + url: "currenttab:/canaries/", + }, + ], + ]); wait(5000); text([ `<button style="padding: 12px 12px;background: #fff2;margin-top: 0.4rem;border-radius: 0.7rem;opacity:0.1;margin-top:3rem;" data-el="le funny button">have a button :3</button>`, { raw: true, - url: () => alert('i abused too much css for this i wanna cry now'), + url: () => alert("i abused too much css for this i wanna cry now"), }, ]); + wait(200); + text( + { renderrestriction: "js-only" }, + [ + "next time, you may want to ", + { + colour: "#fff2", + }, + ], + [ + `skip the animation<img style="opacity:0;position:fixed;top:0;left:0;width:0px;height:0px;pointer-events:none;" src='about:blank' onerror='setTimeout(()=>{if(location.pathname==="/skip-animation")document.querySelector(${JSON.stringify(`a[href=${JSON.stringify("/skip-animation")}]`)}).parentElement.remove();else document.querySelector(${JSON.stringify(`a[href=${JSON.stringify("about:blank")}]`)}).remove();},1)' />`, + { + url: "currenttab:/skip-animation", + colour: "#fff2", + underlined: true, + raw: true, + }, + ], + ); // |