aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/+page.svelte3
-rw-r--r--src/routes/shared.ts626
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,
+ },
+ ],
+ );
//