aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/+page.svelte
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-03-12 15:04:31 +0100
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-03-12 15:04:31 +0100
commit114dc8c8549a4a1271d43c42c7931209b5a9f5b5 (patch)
tree4646c7ec8ccfab89d75ee9d7b464f87bc6d457cf /src/routes/+page.svelte
parent8b2de4edf7a2b7ae5c4bcf6aa0b63313da80b46d (diff)
downloadmem-estrogen-zone-114dc8c8549a4a1271d43c42c7931209b5a9f5b5.tar.gz
mem-estrogen-zone-114dc8c8549a4a1271d43c42c7931209b5a9f5b5.tar.bz2
mem-estrogen-zone-114dc8c8549a4a1271d43c42c7931209b5a9f5b5.tar.lz
mem-estrogen-zone-114dc8c8549a4a1271d43c42c7931209b5a9f5b5.zip

feat: properly handle skip-animation

Diffstat (limited to 'src/routes/+page.svelte')
-rw-r--r--src/routes/+page.svelte417
1 files changed, 3 insertions, 414 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index b5c8d91..f70592b 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -12,421 +12,10 @@
* You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-->
+
<script lang="ts">
- import logo from './boot-logo.webp';
import './anim.css';
- import { architecture, hostname, tty, versions } from './distro-info';
- import { login, ttyLines, type RenderBlock, type TTYText } from './shared';
- import { onDestroy, onMount } from 'svelte';
- import { base } from '$app/paths';
-
- const initTagLine = `line flex flex-row flex-wrap gap-3 justify-between`;
-
- const fsckFileCount = Math.floor(Math.random() * 32768 + 6732);
- const fsckTotalCount = Math.round(
- (fsckFileCount / 6732) * 753664 + Math.random() * 10000,
- );
- const blocksTotal = Math.floor(Math.random() * 8000000 + 4000000);
- const blocksCount = Math.floor(Math.random() * 600000 + 200000);
-
- const lanLeastSignificantIPPart = Math.floor(Math.random() * 253 + 2);
-
- let {
- skipAnimation = false,
- }: {
- skipAnimation?: boolean;
- } = $props();
- onMount(() => {
- if (skipAnimation && location.pathname !== base + '/skip-animation')
- history.replaceState({}, '', base + '/skip-animation');
- });
-
- let isScripted = $state(false);
- onMount(() => (isScripted = true));
- onDestroy(() => (isScripted = false));
+ import IndexPage from './IndexPage.svelte';
</script>
-<svelte:head>
- <title>/~mem/</title>
- <meta name="description" content="memdmp's pure-css homepage demo thing" />
-</svelte:head>
-
-{#snippet tagLeft(colour: string)}
- <span class="text-[{colour}]">*</span>
-{/snippet}
-{#snippet okTagLeft()}
- {@render tagLeft('#51f051')}
-{/snippet}
-{#snippet tagRight(innerText: string, innerColour: string)}
- <span class="text-[#5f5fff]">[</span>
- <span class="text-[{innerColour}]">{innerText}</span>
- <span class="text-[#5f5fff]">]</span>
-{/snippet}
-{#snippet okTagRight()}
- {@render tagRight('ok', '#51f051')}
-{/snippet}
-{#snippet okLine(text: string, classes?: string, rightClass?: string)}
- <div class="{initTagLine}{classes ? ' ' + classes : ''}">
- <div class="left">
- {@render okTagLeft()}
- {text}
- </div>
- <div class="right{rightClass ? ' ' + rightClass : ''}">
- {@render okTagRight()}
- </div>
- </div>
-{/snippet}
-{#snippet ttyTextInnerRenderer(section: RenderBlock)}
- <span
- class="ttytext-block {section.colour
- ? ` text-[${section.colour}]`
- : ''}{section.bg ? ` bg-[${section.bg}]` : ''} {section.weight
- ? ` ${['', 'font-thin', 'font-extralight', 'font-light', 'font-normal', 'font-medium', 'font-semibold', 'font-bold', 'font-extrabold', 'font-black'][section.weight / 100]}`
- : ''}{typeof section.italic === 'undefined'
- ? ''
- : section.italic
- ? ' italic'
- : ' not-italic'}{typeof section.underlined === 'undefined'
- ? ''
- : section.underlined
- ? ` underline`
- : ' no-underline'} inline"
- >{#if section.raw}{@html section.value}{:else}{#each section.value
- .split('\n')
- .map( (l, i, a) => (i === a.length - 1 ? [0, l] : [1, l]), ) as [nl, l]}{l}{#if nl}<br
- />{/if}{/each}{/if}</span
- >
-{/snippet}
-{#snippet ttyTextMiddleRenderer(
- section: RenderBlock,
- line: TTYText & { kind: 'text' },
-)}
- {#if section.url}
- {#if typeof section.url === 'string'}
- {#if section.url.startsWith('newtab:')}
- {@const url = section.url.substring(7)}
- <a
- href={url.startsWith('/') ? base + url : url}
- target="_blank"
- rel="noopener noreferrer"
- class="no-underline text-inherit"
- download={section.dl}>{@render ttyTextInnerRenderer(section)}</a
- >
- {:else if section.url.startsWith('currenttab:')}
- {@const url = section.url.substring(11)}
- <a
- href={url.startsWith('/') ? base + url : url}
- class="no-underline text-inherit"
- download={section.dl}>{@render ttyTextInnerRenderer(section)}</a
- >
- {:else}
- ERR: Unknown Link Format
- {/if}
- {:else}
- <span
- onclick={() =>
- typeof section.url !== 'function' ? void 0 : section.url(line)}
- onkeypress={() =>
- typeof section.url !== 'function' ? void 0 : section.url(line)}
- role="link"
- tabindex="0">{@render ttyTextInnerRenderer(section)}</span
- >
- {/if}
- {:else}
- {@render ttyTextInnerRenderer(section)}
- {/if}
-{/snippet}
-{#snippet ttyText(line: TTYText)}
- {#if line.kind === 'text'}
- {#if (line.renderrestriction ?? 'everywhere') === 'everywhere' || line.renderrestriction === 'noscript' || (line.renderrestriction === 'js-only' && isScripted)}
- {#if line.renderrestriction === 'noscript'}
- <noscript class="inline-block max-w-[100%] {line.classes.join(' ')}"
- >{#each line.value as v}{@render ttyTextMiddleRenderer(
- v,
- line,
- )}{/each}</noscript
- >
- {:else}
- <span class="inline-block max-w-[100%] {line.classes.join(' ')}"
- >{#each line.value as v}{@render ttyTextMiddleRenderer(
- v,
- line,
- )}{/each}</span
- >
- {/if}
- {/if}
- {/if}
-{/snippet}
-
-<div class="hidden">
- {#each ['inline-block', 'block', 'flex', 'inline-flex', 'max-w-full', 'font-thin', 'font-extralight', 'font-light', 'font-normal', 'font-medium', 'font-semibold', 'font-bold', 'font-extrabold', 'font-black'] as c}
- <span class={c}></span>
- {/each}
-</div>
-
-<div
- class="fixed top-0 left-0 w-screen h-screen font-mono"
- id="app"
- class:skip-animation={skipAnimation}
->
- <div
- id="bios"
- class="flex flex-col items-center justify-between relative font-bios text-lg"
- >
- <div class="top flex items-center justify-center flex-col">
- <div class="inner text-[#999999]">
- <p class="leading-4 mt-8 -mb-8 max-w-[36rem]">
- <span class="bdsdxe-load"
- >BdsDxe: loading Boot0002 "UEFI Misc Device" from PciRoot
- (0x0)/Pci(0x2,0x4)/Pci(0x0,0x0)</span
- ><br />
- <span class="bdsdxe-start"
- >BdsDxe: starting Boot0002 "UEFI Misc Device" from PciRoot
- (0x0)/Pci(0x2,0x4)/Pci(0x0,0x0)</span
- >
- </p>
- </div>
- </div>
- <div class="middle">
- <img
- src={logo}
- alt="Bootloader Logo"
- class="w-32 h-32 flex items-center justify-center"
- />
- </div>
- <div
- class="bottom flex flex-col items-stretch justify-center text-center gap-0.5 w-full pb-4"
- >
- <div class="start-text">Start boot option</div>
- <div
- class="bar h-4"
- style={`background-image: url("data:image/svg+xml,${encodeURIComponent(`<svg width="32" height="32" viewbox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
- <rect x="1" y="1" width="30" height="30" fill="white" stroke="black" stroke-width="2"/>
-</svg>
-`)}");background-size:contain;`}
- ></div>
- </div>
- </div>
- <div id="grub" class="font-grub text-sm">
- <div
- class="relative p-4 flex items-stretch justify-stretch flex-col w-screen h-screen"
- >
- <p class="title text-[#a2a2a2] mb-4 h-4 text-center">
- GNU GRUB &nbsp;version 2.12
- </p>
- <div
- class="outer-border border-2 border-[#a8a8a8] border-solid h-full px-1 py-2 flex flex-col items-stretch"
- >
- <div class="entry bg-[#a8a8a8] text-[#000] text-left">
- *Alpine Linux {versions.alpine.number}, with {versions.kernel
- .humanReadable}
- </div>
- <div class="entry text-[#a8a8a8] text-left">
- &nbsp;UEFI Firmware Setup
- </div>
- </div>
- <p class="footer text-[#a2a2a2] my-4 text-left pl-2">
- <span class="block pl-6">
- Use the ↑ and ↓ keys to select which entry is highlighted.<br />
- Press enter to boot the selected OS, `e' to edit the commands before booting
- or `c' for a command-line.<br />
- </span>
- The highlighted entry will be executed automatically in
- <span class="grub-2s inline-block">2</span><span
- class="grub-1s inline-block">1</span
- >s.
- </p>
- </div>
- </div>
- <div id="grub-term" class="font-grub text-sm text-left text-[#a2a2a2]">
- <p class="p-8">
- &nbsp;&nbsp;Booting `Alpine Linux {versions.alpine.number}, with {versions
- .kernel.humanReadable}'<br /><br /><span class="load-kernel"
- >Loading {versions.kernel.humanReadable} ...</span
- ><br /><span class="load-ramdisk">Loading initial ramdisk ...</span>
- </p>
- </div>
- <!--
- flex col reverse and mb auto are hacks for it to auto scroll to bottom(!)
- flex col reverse only works due to nested inner (which would be at bottom of screen, if it wasnt for mb-auto div above it)
- -->
- <div id="openrc" class="overflow-y-auto flex flex-col-reverse">
- <div class="mb-auto"></div>
- <div class="font-mono leading-4 text-[#b9b9b9] flex flex-col p-4">
- <div class="line">
- &nbsp;&nbsp;<span class="text-[#51f051]">OpenRC</span>
- <span class="text-[#4bdfdf]">{versions.openrc}</span>
- is starting up Linux
- <span class="text-[#5f5fff]">{versions.kernel.id} ({architecture})</span
- >
- </div>
- <div class="line">&ZeroWidthSpace;</div>
- {@render okLine('/proc/ is already mounted')}
- {@render okLine('Mounting /run ...')}
- {@render okLine('/run/openrc: creating directory')}
- {@render okLine('/run/lock: creating directory', 'openrc-boot-step-1')}
- {@render okLine('/run/lock: correcting owner', 'openrc-boot-step-1')}
- {@render okLine('Caching service dependencies ...', 'openrc-boot-step-1')}
- {@render okLine('Remounting devtmpfs on /dev ...', 'openrc-boot-step-2')}
- {@render okLine('Mounting /dev/mqueue ...', 'openrc-boot-step-3')}
- {@render okLine('Mounting security filesystem ...', 'openrc-boot-step-4')}
- {@render okLine('Mounting debug filesystem ...', 'openrc-boot-step-5')}
- {@render okLine(
- 'Mounting persistent storage (pstore) filesystem ...',
- 'openrc-boot-step-5',
- )}
- {@render okLine('Mounting efivarfs filesystem ...', 'openrc-boot-step-5')}
- {@render okLine('Starting busybox mdev ...', 'openrc-boot-step-6')}
- {@render okLine('Scanning hardware for mdev ...', 'openrc-boot-step-6')}
- {@render okLine('Loading hardware drivers ...', 'openrc-boot-step-7')}
- {@render okLine('Loading modules ...', 'openrc-boot-step-8')}
- {@render okLine(
- 'Setting system clock using the hardware clock [UTC] ...',
- 'openrc-boot-step-9',
- )}
- {@render okLine('Checking local filesystems ...', 'openrc-boot-step-10')}
- <div class="line openrc-boot-step-11">
- /dev/mapper/bepis: clean, {fsckFileCount}/{fsckTotalCount} files, {blocksCount}/{blocksTotal}
- blocks
- </div>
- {@render okLine(
- 'Remounting root filesystem read/write ...',
- 'openrc-boot-step-12',
- )}
- {@render okLine('Remounting filesystems ...', 'openrc-boot-step-13')}
- {@render okLine('Activating swap devices ...', 'openrc-boot-step-14')}
- {@render okLine('Mounting local filesystems ...', 'openrc-boot-step-15')}
- {@render okLine(
- 'Configuring kernel parameters ...',
- 'openrc-boot-step-16',
- )}
- {@render okLine('Creating user login records ...', 'openrc-boot-step-17')}
- {@render okLine('Setting hostname ...', 'openrc-boot-step-18')}
- {@render okLine('Setting keymap ...', 'openrc-boot-step-19')}
- {@render okLine('Starting networking ...', 'openrc-boot-step-20')}
- {@render okLine('\xa0\xa0lo ...', 'openrc-boot-step-21')}
- {@render okLine('\xa0\xa0eth0 ...', 'openrc-boot-step-22')}
- <div class="line openrc-boot-step-22">udhcpd: started</div>
- <div class="line openrc-boot-step-23">udhcpd: broadcasting discover</div>
- <!-- TODO: configurable subnet uwu -->
- <div class="line openrc-boot-step-24">
- udhcpd: broadcasting select for 192.168.1.{lanLeastSignificantIPPart},
- server 192.168.1.1
- </div>
- <div class="line openrc-boot-step-25">
- udhcpd: lease of 192.168.1.{lanLeastSignificantIPPart} obtained from 192.168.1.1,
- lease time 3600
- </div>
- {@render okLine(
- 'Seeding random number generator ...',
- 'openrc-boot-step-26',
- )}
- {@render okLine(
- 'Seeding 256 bits without crediting',
- 'openrc-boot-step-26',
- )}
- {@render okLine(
- 'Saving 256 bits of creditable seed for next boot',
- 'openrc-boot-step-26',
- )}
- {@render okLine('Starting logbookd ...', 'openrc-boot-step-27')}
- {@render okLine('Starting busybox acpid ...', 'openrc-boot-step-28')}
- {@render okLine('Starting busybox crond ...', 'openrc-boot-step-29')}
- {@render okLine('Starting busybox ntpd ...', 'openrc-boot-step-29')}
- <div class="line openrc-boot-step-30">&ZeroWidthSpace;</div>
- <div class="line openrc-boot-step-30">
- Welcome to Alpine Linux {versions.alpine
- .number}{#if versions.alpine.isEdge}&nbsp;(edge){/if}
- </div>
- <div class="line openrc-boot-step-30">
- Kernel {versions.kernel.humanReadable} on an {architecture} (/dev/{tty})
- </div>
- <div class="line openrc-boot-step-30">&ZeroWidthSpace;</div>
- <div class="line openrc-boot-step-30">
- {hostname} login:&nbsp;<span class="openrc-username"
- >{#each login.username
- .split('')
- .map((v, i) => [v, i] as const) as [char, idx]}<span
- class="openrc-username-char openrc-username-char-{idx} inline-block"
- >{char}</span
- >{/each}</span
- ><span class="openrc-hide-at-login-prompt-username-done"
- ><span class="openrc-username-anim"
- ><code class="hidden-after-anim">_</code></span
- ></span
- ><span class="openrc-pw-line"
- ><br />
- Password:&nbsp;<span class="openrc-password-anim"
- ><code class="hidden-after-anim">_</code></span
- ></span
- >
- </div>
- <!-- TODO: Animate login and launching a tui here (for js enjoyers) or a minimal terminal after clearing the screen, and a no js screen alongside a plaintext version of the thing (for schizo noscript lovers) -->
- <div class="hidden-after-anim">
- <span class="openrc-hide-at-last-boot-step inline-block">
- <pre class="flashing-cursor">_</pre>
- </span>
- </div>
- <div class="line ttylines-openrc font-mono text-[#070505] flex flex-col">
- {#each ttyLines.filter(((maxidx) => (_, i) => i < (maxidx === -1 ? Infinity : maxidx))(ttyLines.findIndex((v) => v.kind === 'clear'))) as line}
- {@render ttyText(line)}
- {/each}
- </div>
- </div>
- </div>
- {#if ttyLines.find((v) => v.kind === 'clear')}
- {#each ttyLines
- .map((v, i) => [v, i] as const)
- .filter(([v]) => v.kind === 'clear')
- .map((v, i, a) => [v[1], a[i + 1]?.[1], i]) as [idx, nextIdx, clearIdx]}
- <div
- id="tty-{clearIdx}"
- class="overflow-y-auto max-h-screen flex flex-col-reverse"
- >
- <div class="mb-auto"></div>
- <div class="font-mono leading-4 text-[#070505] flex flex-col p-4">
- {#each ttyLines.filter((_, i) => i >= idx && i < (nextIdx ?? Infinity)) as line}
- {@render ttyText(line)}
- {/each}
- </div>
- </div>
- {/each}
- {/if}
-</div>
-
-<style>
- @keyframes flashing-cursor {
- 0% {
- opacity: 0;
- }
- 49% {
- opacity: 0;
- }
- 50% {
- opacity: 1;
- }
- 99% {
- opacity: 1;
- }
- 100% {
- opacity: 0;
- }
- }
- .flashing-cursor {
- animation-name: flashing-cursor;
- animation-duration: 0.4s;
- animation-iteration-count: infinite;
- animation-timing-function: linear;
- }
- .hidden-after-anim {
- margin-top: -99999vh;
- margin-bottom: 99999vh;
- margin-left: -99999vw;
- margin-right: 99999vw;
- transform: scaleX(0);
- opacity: 0;
- }
- .ttytext-block {
- white-space-collapse: preserve-spaces;
- }
-</style>
+<IndexPage />