summaryrefslogtreecommitdiff
path: root/old_stuff/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'old_stuff/src/pages')
-rw-r--r--old_stuff/src/pages/404.astro25
-rw-r--r--old_stuff/src/pages/blogs.astro38
-rw-r--r--old_stuff/src/pages/blogs/[...slug].astro132
-rw-r--r--old_stuff/src/pages/index.astro275
-rw-r--r--old_stuff/src/pages/projects.astro63
-rw-r--r--old_stuff/src/pages/shell.astro438
-rw-r--r--old_stuff/src/pages/skills.astro51
7 files changed, 1022 insertions, 0 deletions
diff --git a/old_stuff/src/pages/404.astro b/old_stuff/src/pages/404.astro
new file mode 100644
index 0000000..9d3910e
--- /dev/null
+++ b/old_stuff/src/pages/404.astro
@@ -0,0 +1,25 @@
+---
+import TerminalBorder from "@components/TerminalBorder.astro";
+import Terminal from "@layouts/Terminal.astro";
+
+const url = new URL(Astro.request.url).pathname.substring(1);
+---
+
+<Terminal path="404">
+ <TerminalBorder header="Shell" extra="my-[0.625vw]">
+ <span>
+ <p id="cd">$ cd ~/{url}</p>
+ <p id="err" class="pt-[1vw]">
+ "{url}": No such file or directory (os error 2)
+ </p>
+ </span>
+ </TerminalBorder>
+</Terminal>
+<script>
+ document.addEventListener("DOMContentLoaded", () => {
+ const url = window.location.pathname.substring(1);
+ document.getElementById("cd")!.textContent = `$ cd ~/${url}`;
+ document.getElementById("err")!.textContent =
+ `"${url}": No such file or directory (os error 2)`;
+ });
+</script>
diff --git a/old_stuff/src/pages/blogs.astro b/old_stuff/src/pages/blogs.astro
new file mode 100644
index 0000000..7e1b576
--- /dev/null
+++ b/old_stuff/src/pages/blogs.astro
@@ -0,0 +1,38 @@
+---
+import Terminal from "@layouts/Terminal.astro";
+import TerminalBorder from "@components/TerminalBorder.astro";
+import BlogItem from "@components/BlogItem.astro";
+import { getCollection } from "astro:content";
+
+const blogs = (await getCollection("blogs"))
+ .sort((a, b) => +new Date(b.data.date) - +new Date(a.data.date))
+ .map((blog) => ({
+ title: blog.data.title,
+ description: blog.data.description,
+ date: blog.data.date,
+ href: "/blogs/" + blog.slug,
+ }));
+---
+
+<Terminal path="/home/kyren/blogs/">
+ <TerminalBorder
+ header="Shell"
+ extra="mb-[5vw] sm:mt-[0.625vw] sm:mb-[1.5625vw]"
+ >
+ <p>$ ls -lah -t --color=auto ~/blogs</p>
+ </TerminalBorder>
+ <div class="max-h-[80svh] sm:max-h-[24vw] overflow-y-auto">
+ {
+ blogs.map((blog) => (
+ <>
+ <BlogItem
+ title={blog.title}
+ description={blog.description ?? ""}
+ date={blog.date}
+ href={blog.href}
+ />
+ </>
+ ))
+ }
+ </div>
+</Terminal>
diff --git a/old_stuff/src/pages/blogs/[...slug].astro b/old_stuff/src/pages/blogs/[...slug].astro
new file mode 100644
index 0000000..a7394ca
--- /dev/null
+++ b/old_stuff/src/pages/blogs/[...slug].astro
@@ -0,0 +1,132 @@
+---
+import { getCollection } from "astro:content";
+import Terminal from "@layouts/Terminal.astro";
+import BlogItem from "@components/BlogItem.astro";
+import Link from "@components/Link.astro";
+import TerminalBorder from "@components/TerminalBorder.astro";
+
+export async function getStaticPaths() {
+ const blogEntries = await getCollection("blogs");
+ return blogEntries.map((blog) => ({
+ params: { slug: blog.slug },
+ props: { entry: blog },
+ }));
+}
+
+const { entry } = Astro.props;
+const { Content } = await entry.render();
+
+const blogs = await getCollection("blogs");
+const sortedBlogs = blogs.sort((a, b) => +b.data.date - +a.data.date);
+const currentIndex = sortedBlogs.findIndex((blog) => blog.slug === entry.slug);
+const previousBlog = sortedBlogs[currentIndex + 1] || undefined;
+const nextBlog = sortedBlogs[currentIndex - 1] || undefined;
+---
+
+<Terminal path="/home/kyren/blogs/">
+ <div class="blog-scroll w-full h-[85svh] sm:h-[30vw] overflow-y-auto pr-[1.25vw] border-box">
+ <div class="text-[130%] h-full">
+ <div class="text-[110%]">
+ <BlogItem
+ title={entry.data.title}
+ description={entry.data.description ?? ""}
+ date={entry.data.date}
+ />
+ </div>
+ <div class="markdown">
+ <Content components={{ a: Link }} />
+ </div>
+ <div class="mt-[1vw] px-[0.1vw] py-[0.625vw] grid grid-cols-2 gap-[1.25vw]">
+ {
+ previousBlog ? (
+ <TerminalBorder header="Previous Blog">
+ <span class="text-[var(--secondary)] truncate flex-1">
+ <Link href=`/blogs/${previousBlog.slug}` newTab={false}>
+ vim ~/blogs/{previousBlog.slug}.md
+ </Link>
+ </span>
+ </TerminalBorder>
+ ) : (
+ <div class="min-w-0 invisible" />
+ )
+ }
+ {
+ nextBlog ? (
+ <TerminalBorder header="Next Blog">
+ <div class="w-full flex items-center">
+ <span class="text-[var(--secondary)] truncate flex-1">
+ <Link href=`/blogs/${nextBlog.slug}` newTab={false}>
+ vim ~/blogs/{nextBlog.slug}.md
+ </Link>
+ </span>
+ </div>
+ </TerminalBorder>
+ ) : (
+ <div class="min-w-0 invisible" />
+ )
+ }
+ </div>
+ </div>
+ </div>
+</Terminal>
+
+<style is:global>
+ .markdown {
+ user-select: text;
+ font-size: 1.1rem;
+ }
+ .markdown a {
+ display: inline-block;
+ font-weight: normal;
+ }
+ .markdown code {
+ background: #333333;
+ color: var(--accent);
+ padding: 0 0.5em;
+ }
+ .markdown ul {
+ list-style-type: square;
+ margin-left: 1em;
+ margin-bottom: 1em;
+ font-size: 90%;
+ }
+ .markdown li {
+ margin-bottom: 0.5em;
+ }
+ .markdown p {
+ margin-bottom: 1em;
+ user-select: text;
+ }
+ .markdown strong {
+ font-weight: bold;
+ }
+ .markdown h2 {
+ color: var(--secondary);
+ font-size: 125%;
+ margin-bottom: 0.5em;
+ }
+ .markdown h3 {
+ color: var(--secondary);
+ font-size: 110%;
+ margin-bottom: 0.25em;
+ }
+ .expressive-code {
+ margin-bottom: 1em;
+ }
+</style>
+
+<script>
+ document.addEventListener('wheel', (e) => {
+ const box = document.querySelector('.blog-scroll');
+ if (!box) return;
+
+ // If scrolling the page itself, forward it to the box
+ const atTop = box.scrollTop === 0 && e.deltaY < 0;
+ const atBottom = box.scrollHeight - box.scrollTop === box.clientHeight && e.deltaY > 0;
+
+ if (!atTop && !atBottom) {
+ box.scrollTop += e.deltaY;
+ e.preventDefault();
+ }
+ }, { passive: false });
+</script>
diff --git a/old_stuff/src/pages/index.astro b/old_stuff/src/pages/index.astro
new file mode 100644
index 0000000..e286117
--- /dev/null
+++ b/old_stuff/src/pages/index.astro
@@ -0,0 +1,275 @@
+---
+import { getCollection } from "astro:content";
+import Terminal from "@layouts/Terminal.astro";
+import TerminalBorder from "@components/TerminalBorder.astro";
+import Link from "@components/Link.astro";
+import BlogItem from "@components/BlogItem.astro";
+
+const latestBlog = (await getCollection("blogs")).reduce((latest, blog) => {
+ const blogDate = new Date(blog.data.date);
+ return blogDate > new Date(latest.data.date) ? blog : latest;
+});
+
+const sshKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO7P9K9D5RkBk+JCRRS6AtHuTAc6cRpXfRfRMg/Kyren`;
+const fingerprint = `
++--[ED25519 256]--+
+| +. .. +.B|
+| + o..o . BB|
+| ..o oo.o =+E|
+| ... oo. + o.|
+| . S . = |
+| . . + o |
+| o o o . |
+| oo .o+ + |
+| ++ooo+= |
++----[SHA256]-----+`.trimStart();
+
+const aboutMe = `
+Hi! I'm Kyren, a software engineer and Game developer freelancer.
+I love working with low level languages and learning things deeply.
+I am also a terminal nerd and Linux enthusiast who uses NVIM btw.
+And when I am not coding I am most likely playing video games,
+watching Anime or solving Rubik's cubes fast.`.trimStart();
+
+const utcOffset = 3;
+
+const email = "contact at kyren.codes";
+
+---
+
+<Terminal path="/home/kyren/">
+ <!-- ================= -->
+ <!-- ==== Desktop ==== -->
+ <!-- ================= -->
+ <div id="content" class="w-0 h-0 invisible sm:w-full sm:h-full sm:visible">
+ <div class="w-[30%]">
+ <TerminalBorder header="Profile">
+ <div class="flex items-center space-x-[1.25vw] h-[9.5vw]">
+ <img
+ src="favicon.svg"
+ alt="picture"
+ class="h-[100%] object-cover"
+ />
+ <pre
+ class="sshKeyCopy text-[60%] hover:text-[var(--secondary)]">{fingerprint}</pre>
+ </div>
+ </TerminalBorder>
+ <TerminalBorder header="Email">
+ <span id="email" class="flex-1">{email}</span>
+ <button class="emailCopy hover:text-gray-700">
+ <svg
+ width="100%"
+ height="100%"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ >
+ <path
+ fill="currentColor"
+ fill-rule="evenodd"
+ d="M4 2a2 2 0 00-2 2v9a2 2 0 002 2h2v2a2 2 0 002 2h9a2 2 0 002-2V8a2 2 0 00-2-2h-2V4a2 2 0 00-2-2H4zm9 4V4H4v9h2V8a2 2 0 012-2h5zM8 8h9v9H8V8z"
+ ></path>
+ </svg>
+ </button>
+ </TerminalBorder>
+ <TerminalBorder header="Git Repos (main)">
+ <Link href="https://git.kyren.codes/Kyren223">
+ git.kyren.codes/Kyren223
+ </Link>
+ </TerminalBorder>
+ <TerminalBorder header="GitHub (secondary)">
+ <Link href="https://github.com/Kyren223">
+ github.com/Kyren223
+ </Link>
+ </TerminalBorder>
+ <TerminalBorder header="Discord">
+ <Link href="https://discord.com/users/481884415090229258">
+ Kyren223
+ </Link>
+ </TerminalBorder>
+ <!-- <TerminalBorder header="Timezone"> -->
+ <!-- <div class="flex justify-between w-full"> -->
+ <!-- <span class="text-left">UTC+{utcOffset}</span> -->
+ <!-- <span id="time" class="text-right">Loading...</span> -->
+ <!-- </div> -->
+ <!-- </TerminalBorder> -->
+ <div class="w-[334%]">
+ <TerminalBorder header="SSH Key">
+ <div class="sshKeyCopy w-[100%] flex items-center group">
+ <span
+ id="sshKey"
+ class="hover:text-[var(--alt)] cursor-pointer truncate flex-1 group-hover:text-[var(--alt)]"
+ >{sshKey}</span
+ >
+ <button class="group-hover:text-gray-700">
+ <svg
+ width="100%"
+ height="100%"
+ viewBox="0 0 24 24"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ >
+ <path
+ fill="currentColor"
+ fill-rule="evenodd"
+ d="M4 2a2 2 0 00-2 2v9a2 2 0 002 2h2v2a2 2 0 002 2h9a2 2 0 002-2V8a2 2 0 00-2-2h-2V4a2 2 0 00-2-2H4zm9 4V4H4v9h2V8a2 2 0 012-2h5zM8 8h9v9H8V8z"
+ ></path>
+ </svg>
+ </button>
+ </div>
+ </TerminalBorder>
+ </div>
+ </div>
+ <div class="w-[67%]">
+ <TerminalBorder header="Status">
+ <p class="text-[0.96vw]">
+ Working on <Link href="https://git.kyren.codes/kyren223/Krypton"
+ >Krypton
+ </Link> | Learning Langdev & Compiler Design | Available for hire
+ </p>
+ </TerminalBorder>
+ <TerminalBorder header="About Me" extra="my-[2.5vw]">
+ <p>{aboutMe}</p>
+ </TerminalBorder>
+ <BlogItem
+ header="Latest Blog Post"
+ title={latestBlog.data.title}
+ description={latestBlog.data.description ?? ""}
+ date={latestBlog.data.date}
+ href={"/blogs/" + latestBlog.slug}
+ />
+ </div>
+ </div>
+
+ <!-- ================ -->
+ <!-- ==== Mobile ==== -->
+ <!-- ================ -->
+ <div
+ class="w-full h-[80svh] visible sm:w-0 sm:h-0 sm:invisible overflow-y-auto overflow-x-hidden sm:overflow-visible"
+ >
+ <div class="mx-[1vw] mt-[1vw]">
+ <TerminalBorder header="Status">
+ <p>
+ Working on <Link href="https://github.com/kyren223/eko"
+ >EKO
+ </Link> | Learning Langdev & Compiler Design | Available for hire
+ </p>
+ </TerminalBorder>
+ <TerminalBorder header="About Me" extra="my-[5vw] sm:my-[2.5vw]">
+ <p>{aboutMe}</p>
+ </TerminalBorder>
+ <BlogItem
+ header="Latest Blog Post"
+ title={latestBlog.data.title}
+ description={latestBlog.data.description ?? ""}
+ date={latestBlog.data.date}
+ href={"/blogs/" + latestBlog.slug}
+ />
+ <div class="mt-[8vw]">
+ <TerminalBorder header="Email">
+ <span id="email" class="flex-1">{email}</span>
+ <button class="emailCopy hover:text-gray-700">
+ <svg
+ class="ml-[-4vw]"
+ xmlns="http://www.w3.org/2000/svg"
+ fill="none"
+ >
+ <path
+ fill="currentColor"
+ fill-rule="evenodd"
+ d="M4 2a2 2 0 00-2 2v9a2 2 0 002 2h2v2a2 2 0 002 2h9a2 2 0 002-2V8a2 2 0 00-2-2h-2V4a2 2 0 00-2-2H4zm9 4V4H4v9h2V8a2 2 0 012-2h5zM8 8h9v9H8V8z"
+ ></path>
+ </svg>
+ </button>
+ </TerminalBorder>
+ </div>
+ <TerminalBorder header="GitHub">
+ <Link href="https://github.com/Kyren223">
+ github.com/Kyren223
+ </Link>
+ </TerminalBorder>
+ <TerminalBorder header="Discord">
+ <Link href="https://discord.com/users/481884415090229258">
+ Kyren223
+ </Link>
+ </TerminalBorder>
+ <TerminalBorder header="Timezone">
+ <div class="flex justify-between w-full">
+ <span class="text-left">UTC+{utcOffset}</span>
+ <span id="time" class="text-right">Loading...</span>
+ </div>
+ </TerminalBorder>
+ <TerminalBorder header="SSH Key">
+ <div class="sshKeyCopy w-[100%] flex items-center group">
+ <span
+ id="sshKey"
+ class="hover:text-[var(--alt)] cursor-pointer truncate flex-1 group-hover:text-[var(--alt)]"
+ >{sshKey}</span
+ >
+ </div>
+ </TerminalBorder>
+ </div>
+ </div>
+</Terminal>
+
+<script define:vars={{ utcOffset }}>
+ function copyToClipboard(text) {
+ return function () {
+ console.log("Clicked");
+ navigator.clipboard
+ .writeText(text)
+ .then(() => {
+ console.log("Copied");
+ // TODO: show some feedback for copying
+ })
+ .catch((_err) => {
+ console.log("Error copying!");
+ // TODO: show same feedback but with err
+ });
+ };
+ }
+
+ const sshKey = document.getElementById("sshKey");
+ document.querySelectorAll(".sshKeyCopy").forEach((elem) => {
+ elem.addEventListener("click", copyToClipboard(sshKey.innerHTML));
+ });
+
+ const email = document.getElementById("email");
+ document.querySelectorAll(".emailCopy").forEach((elem) => {
+ elem.addEventListener("click", copyToClipboard(email.innerHTML));
+ });
+
+ const time = document.getElementById("time");
+ setInterval(
+ () => {
+ const now = new Date();
+ const myTime = new Date(now.getTime() + utcOffset * 3600 * 1000);
+ const hours = String(myTime.getUTCHours()).padStart(2, "0");
+ const minutes = String(myTime.getUTCMinutes()).padStart(2, "0");
+ const formattedTime = `${hours}:${minutes}`;
+ time.innerHTML = formattedTime;
+ },
+ 0,
+ 60 * 1000,
+ );
+</script>
+
+<style>
+ #content {
+ margin-top: 1.5vw;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ button {
+ background-color: var(--background);
+ color: var(--text);
+ border: 0;
+ font-size: 1.25vw;
+ cursor: pointer;
+ width: 1.5vw;
+ height: 1.5vw;
+ padding: 0;
+ line-height: 2.3vw;
+ }
+</style>
diff --git a/old_stuff/src/pages/projects.astro b/old_stuff/src/pages/projects.astro
new file mode 100644
index 0000000..9174b0e
--- /dev/null
+++ b/old_stuff/src/pages/projects.astro
@@ -0,0 +1,63 @@
+---
+import Terminal from "@layouts/Terminal.astro";
+import Project from "@components/Project.astro";
+---
+
+<Terminal path="/home/kyren/projects/">
+ <div
+ class="w-full max-h-[80svh] overflow-auto sm:overflow-visible"
+ >
+ <div class="sm:grid sm:gap-[1.25vw] sm:grid-cols-[2fr_3fr]">
+ <Project
+ title="CPU vs AI"
+ cd="cpu-vs-ai"
+ description="Game (made with Zig)"
+ href="https://github.com/The-Memory-Managers/cpu-vs-ai"
+ >
+ A tower defense game where an AI chip on your motherboard
+ generates bugs! Place CPUs to destroy the bugs!
+ Don't let them corrupt your RAM!
+ </Project>
+ <Project
+ title="Kapi"
+ cd="kapi"
+ description="Minecraft Plugins Framework"
+ href="https://github.com/KapiMC/Kapi"
+ >
+ A complete "batteries included" framework streamlining the
+ process of Minecraft plugin development. Enabling developers to
+ make impressive plugins with ease!
+ </Project>
+ <div
+ class="sm:col-span-2 sm:grid sm:grid-cols-[1fr_1fr_1fr] sm:gap-[1.25vw]"
+ >
+ <Project
+ title="Eko"
+ cd="eko"
+ description="Social Media Platform"
+ href="https://github.com/kyren223/eko"
+ >
+ A terminal-native alternative to Discord for Terminal nerds!
+ </Project>
+ <Project
+ title="Trident"
+ cd="trident"
+ description="IntelliJ Plugin"
+ href="https://github.com/Kyren223/Trident"
+ >
+ A blazingly fast way to navigate to your most used files.
+ minimize keystrokes and maximize productivity!
+ </Project>
+ <Project
+ title="Dotfiles"
+ cd="dotfiles"
+ description="Configuration"
+ href="https://git.kyren.codes/Kyren223/dotfiles"
+ dir="cd ~/"
+ >
+ My linux configuration, includes Neovim, tmux and others.
+ </Project>
+ </div>
+ </div>
+ </div>
+</Terminal>
diff --git a/old_stuff/src/pages/shell.astro b/old_stuff/src/pages/shell.astro
new file mode 100644
index 0000000..c1ae14e
--- /dev/null
+++ b/old_stuff/src/pages/shell.astro
@@ -0,0 +1,438 @@
+---
+import Terminal from "@layouts/Terminal.astro";
+import TerminalBorder from "@components/TerminalBorder.astro";
+---
+
+<Terminal path="/bin/bash">
+ <TerminalBorder header="Bash" extra="h-[62%] mt-[0.625vw] mb-[1.5625vw]">
+ <div id="output" class="flex flex-col"></div>
+ </TerminalBorder>
+ <TerminalBorder header="Shell" extra="font-['JetBrains_Mono']">
+ <pre>$ </pre>
+ <p id="input" contenteditable="true" spellcheck="false">
+ npm run buil<span>d</span>after
+ </p>
+ <input class="absolute opacity-0 w-0 h-0 p-0 m-0" autofocus />
+ </TerminalBorder>
+</Terminal>
+<script>
+ var prevCursor = -1;
+ var prevSelectionEnd = -1;
+ var swapped = false;
+ function getCursorText(inputElement) {
+ const text = inputElement.value;
+
+ const oCursorPos = inputElement.selectionStart;
+ const oSelectionEnd = inputElement.selectionEnd;
+
+ var cursorPos = oCursorPos;
+ var selectionEnd = oSelectionEnd;
+
+ if (
+ prevCursor != -1 &&
+ oCursorPos != oSelectionEnd &&
+ (prevSelectionEnd != oSelectionEnd ||
+ (prevSelectionEnd == oSelectionEnd &&
+ prevCursor == oCursorPos &&
+ swapped))
+ ) {
+ cursorPos = oSelectionEnd;
+ selectionEnd = oCursorPos;
+ prevSelectionEnd = oSelectionEnd;
+ swapped = true;
+ } else {
+ swapped = false;
+ }
+
+ prevCursor = oCursorPos;
+
+ var beforeCursor = text.substring(0, cursorPos);
+ var afterCursor = text.substring(cursorPos + 1);
+ var cursorChar = text[cursorPos] || "&nbsp;";
+ var selectedText = "";
+
+ if (selectionEnd > cursorPos) {
+ selectedText = text.substring(cursorPos + 1, selectionEnd);
+ afterCursor = text.substring(oSelectionEnd);
+ beforeCursor = text.substring(0, cursorPos);
+ } else if (selectionEnd < cursorPos) {
+ cursorChar = text[cursorPos - 1] || "&nbsp;";
+ selectedText = text.substring(selectionEnd, cursorPos - 1);
+ afterCursor = text.substring(cursorPos);
+ beforeCursor = text.substring(0, oCursorPos);
+ }
+
+ return {
+ beforeCursor,
+ afterCursor,
+ cursorChar,
+ selectedText,
+ swapped,
+ };
+ }
+
+ const output = document.getElementById("output")!!;
+ const fakeInput = document.getElementById("input")!!;
+ const input = document.querySelector("input")!!;
+ const cursorStyle =
+ "background-color: var(--text); color: var(--background);";
+ const visualStyle =
+ "background-color: var(--primary); color: var(--background);";
+
+ function updateShell() {
+ var { beforeCursor, afterCursor, cursorChar, selectedText, swapped } =
+ getCursorText(input);
+
+ input.focus();
+
+ const cursor = `<span style="${cursorStyle}">${cursorChar}</span>`;
+ const visual = `<span style="${visualStyle}">${selectedText}</span>`;
+
+ if (swapped) {
+ fakeInput.innerHTML = `${beforeCursor}${visual}${cursor}${afterCursor}`;
+ } else {
+ fakeInput.innerHTML = `${beforeCursor}${cursor}${visual}${afterCursor}`;
+ }
+
+ if (input.value.length >= 97) {
+ input.value = "";
+ updateShell();
+ write("segmentation fault (core dumped)");
+ updateTerminal();
+ }
+ }
+
+ function sleep(ms) {
+ return new Promise((resolve) => setTimeout(resolve, ms));
+ }
+
+ var maxLines = 15;
+ var terminal: string[] = [];
+ const rootDirs = [
+ "bin",
+ "boot",
+ "dev",
+ "etc",
+ "home",
+ "lib",
+ "lib64",
+ "lost+found",
+ "nix",
+ "proc",
+ "root",
+ "run",
+ "srv",
+ "sys",
+ "tmp",
+ "usr",
+ "var",
+ ];
+
+ function write(line: string) {
+ const maxChars = 98;
+
+ while (line.length > maxChars) {
+ terminal.push(line.slice(0, maxChars));
+ line = line.slice(maxChars);
+ }
+
+ terminal.push(line);
+
+ while (terminal.length > maxLines) {
+ terminal.shift();
+ }
+ }
+
+ function updateTerminal() {
+ var text = "";
+ for (let i = 0; i < terminal.length; i++) {
+ text += `<p>${terminal[i] == "" ? "&nbsp;" : terminal[i]}</p>`;
+ }
+
+ output.innerHTML = text;
+ }
+
+ var isSudo = false;
+ var rootPassword = "123";
+ var leftPasswordTries = 0;
+ var sudoCommand = "";
+ const knownCommands = [
+ "clear",
+ "test",
+ "whoami",
+ "pwd",
+ "sudo",
+ "rm",
+ "emacs",
+ "set",
+ ];
+
+ async function runCommand(input: string) {
+ if (leftPasswordTries != 0) {
+ if (input == rootPassword) {
+ // await sleep(1000);
+ leftPasswordTries = 0
+ isSudo = true;
+ runCommand(sudoCommand);
+ isSudo = false;
+ sudoCommand = "";
+ } else if (leftPasswordTries == 1) {
+ // await sleep(1000);
+ write("sudo: 3 incorrect password attempts");
+ leftPasswordTries -= 1;
+ sudoCommand = "";
+ } else {
+ // await sleep(1000);
+ write("Sorry, try again.");
+ write("[sudo] password for root:");
+ leftPasswordTries -= 1;
+ }
+ updateTerminal();
+ return;
+ }
+
+ if (!isSudo) {
+ write(`$ ${input}`);
+ console.log(`$ ${input}`);
+ }
+
+ var args = input.split(" ").slice(1);
+ var cmd = input.split(" ")[0];
+
+ if (cmd == "") return;
+
+ if (args.length == 0) {
+ switch (cmd) {
+ case "clear":
+ terminal = [];
+ break;
+
+ case "test":
+ if (isSudo) {
+ write('running "trying to get more info"...');
+ updateTerminal();
+ await sleep(1000);
+ write("fetching notes...");
+ updateTerminal();
+ await sleep(2000);
+ write(
+ "I love the look with 'set theme catppuccin', especially with the minecraft font!",
+ );
+ write("Been using it for a while in emacs");
+ updateTerminal();
+ await sleep(100);
+ write('test "trying to get more info" succeeded');
+ updateTerminal();
+ await sleep(100);
+ write("executed 1 test, 1 succeeded, 0 failed");
+ } else {
+ write('running "trying to get more info"...');
+ updateTerminal();
+ await sleep(1000);
+ write('test "trying to get more info" failed');
+ updateTerminal();
+ await sleep(100);
+ write("executed 1 test, 0 succeeded, 1 failed");
+ }
+ break;
+
+ case "whoami":
+ write("sandbox");
+ break;
+ case "pwd":
+ write("/home/sandbox");
+ break;
+
+ case "sudo":
+ write(`Usage: sudo [COMMAND]`);
+ break;
+
+ case "emacs":
+ write(`emacs: command not found`);
+ write(`The command 'emacs' is not available, but there is a similar command:`);
+ write(`- vim`);
+ write(`- nvim`);
+ break;
+
+ default:
+ if (knownCommands.includes(cmd)) {
+ write(`${cmd}: missing operand`);
+ write(`Try '${cmd} --help' for more information.`);
+ } else {
+ write(`${cmd}: command not found`);
+ }
+ break;
+ }
+ } else if (cmd == "rm") {
+ if (args.length == 2 && (args[0] == "-rf" || args[0] == "-fr")) {
+ if (args[1] == "/") {
+ write("rm: it is dangerous to operate recursively on '/'");
+ write(
+ "rm: use --no-preserve-root to override this failsafe",
+ );
+ } else if (args[1] == "." || args[1] == "..") {
+ write(
+ `rm: refusing to remove '.' or '..' directory: skipping '${args[1]}'`,
+ );
+ } else {
+ if (!args[1].startsWith("/")) {
+ args[1] = "/" + args[1];
+ }
+ write(`rm: cannot remove '${args[1]}': Permission denied`);
+ }
+ } else if (
+ args.length == 3 &&
+ (args[0] == "-rf" || args[0] == "-fr") &&
+ args[2] == "--no-preserve-root"
+ ) {
+ for (const dir of rootDirs) {
+ await sleep(30);
+ write(`rm: cannot remove '/${dir}': Permission denied`);
+ updateTerminal();
+ }
+ } else if (args.length == 1 && args[0] == "--help") {
+ write(`Usage: rm [OPTION]... [FILE]...`);
+ write(`Remove (unlink) the FILE(s).`);
+ } else {
+ write(`${cmd}: unrecognized options '${args.join(" ")}'`);
+ write(`Try '${cmd} --help' for more information.`);
+ }
+ } else if (cmd == "sudo") {
+ if (isSudo) {
+ if (knownCommands.includes(args[0])) {
+ runCommand(args.join(" "));
+ } else {
+ write(`${cmd}: ${args[0]}: command not found`);
+ }
+ isSudo = false;
+ } else {
+ sudoCommand = input;
+ leftPasswordTries = 3;
+ write("[sudo] password for root:");
+ }
+ } else if (cmd == "set" && args.length == 2 && args[0] == "font") {
+ var unknown = false;
+ switch (args[1]) {
+ case "default":
+ window.setTheme({
+ font: "Jetbrains Mono",
+ });
+ break;
+
+ case "minecraft":
+ window.setTheme({
+ font: "Monocraft",
+ });
+ break;
+
+ default:
+ unknown = true;
+ break;
+ }
+ if (unknown) {
+ write(`${cmd}: unknown ${args[0]} '${args[1]}'`);
+ } else {
+ write(`${cmd}: ${args[0]} set to '${args[1]}'`);
+ }
+ } else if (cmd == "set" && args.length == 2 && args[0] == "theme") {
+ var unknown = false;
+ switch (args[1]) {
+ case "default":
+ window.setTheme({
+ primary: "#54d7a9",
+ secondary: "#9b7eca",
+ accent: "#7ed4fb",
+ extra: "#8fcc75",
+ text: "#ffffff",
+ alt: "#999999",
+ background: "#000000",
+ });
+ break;
+
+ case "catppuccin":
+ window.setTheme({
+ primary: "#94e2d5",
+ secondary: "#b4befe",
+ accent: "#74c7ec",
+ extra: "#a6e3a1",
+ text: "#cdd6f4",
+ alt: "#585b70",
+ background: "#1e1e2e",
+ });
+ break;
+
+ case "invisible":
+ case "hide":
+ case "black":
+ case "dark":
+ window.setTheme({
+ primary: "#000000",
+ secondary: "#000000",
+ accent: "#000000",
+ extra: "#000000",
+ text: "#000000",
+ alt: "#000000",
+ background: "#000000",
+ });
+ break;
+
+ case "blind":
+ case "sun":
+ case "light":
+ case "white":
+ case "flashbang":
+ case "flashlight":
+ window.setTheme({
+ primary: "#009399",
+ secondary: "#440b8e",
+ accent: "#177282",
+ extra: "#40a02b",
+ text: "#000000",
+ alt: "#4d4d4d",
+ background: "#ffffff",
+ });
+ break;
+
+ case "banana":
+ window.setTheme({
+ primary: "#ffdd44",
+ secondary: "#9b7eca",
+ accent: "#7ed4fb",
+ extra: "#000000",
+ text: "#ffffff",
+ alt: "#999999",
+ background: "#000000",
+ });
+ break;
+
+ default:
+ unknown = true;
+ break;
+ }
+ if (unknown) {
+ write(`${cmd}: unknown ${args[0]} '${args[1]}'`);
+ } else {
+ write(`${cmd}: ${args[0]} set to '${args[1]}'`);
+ }
+ } else {
+ if (knownCommands.includes(cmd)) {
+ write(`${cmd}: unrecognized options '${args.join(" ")}'`);
+ } else {
+ write(`${cmd}: command not found`);
+ }
+ }
+
+ updateTerminal();
+ }
+
+ input.addEventListener("keydown", function (event) {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ runCommand(input.value);
+ input.value = "";
+ updateShell();
+ }
+ });
+
+ setInterval(updateShell, 50);
+</script>
diff --git a/old_stuff/src/pages/skills.astro b/old_stuff/src/pages/skills.astro
new file mode 100644
index 0000000..6d6f4b1
--- /dev/null
+++ b/old_stuff/src/pages/skills.astro
@@ -0,0 +1,51 @@
+---
+import Terminal from "@layouts/Terminal.astro";
+import RadarChart from "@components/RadarChart.astro";
+import TerminalBorder from "@components/TerminalBorder.astro";
+
+const max = 100;
+const data = [
+ { name: "Tooling", weight: 75 },
+ { name: "Backend", weight: 80 },
+ { name: "Gamedev", weight: 99 },
+ { name: "Low-Level", weight: 95 },
+ { name: "Frontend", weight: 15 },
+];
+
+const langs = [
+ "C/C++", "Golang", "Java", "SQL", "Python",
+ "Zig", "Rust", "Kotlin", "C#" ,"Lua"
+];
+const tools = [
+ "Git & GitHub & Gitea",
+ "SQLite and Firebase",
+ "Linux",
+ "Neovim and Tmux",
+];
+const frameworks = ["Raylib", "Spigot API", "Bubbletea", "Astro"];
+---
+
+<Terminal path="/home/kyren/skills.md">
+ <div class="sm:flex overflow-y-auto h-[80svh]">
+ <div class="sm:w-[60%] mt-[1vw] mx-[1vw] flex-column items-center">
+ <TerminalBorder header="Languages">
+ <div class="grid grid-cols-5 items-center gap-x-[5vw] sm:gap-x-[0.625vw]">
+ {langs.map((lang) => <p>{lang}</p>)}
+ </div>
+ </TerminalBorder>
+ <TerminalBorder header="Frameworks & Libraries" extra="my-[5vw] sm:my-[2.25vw]">
+ <div class="grid grid-cols-3 sm:grid-cols-1 items-center gap-x-[5vw] sm:gap-x-[0.625vw]">
+ {frameworks.map((framework) => <p>{framework}</p>)}
+ </div>
+ </TerminalBorder>
+ <TerminalBorder header="Tools">
+ <div class="grid grid-cols-2 sm:grid-cols-1 items-center gap-x-[5vw] sm:gap-x-[0.625vw]">
+ {tools.map((tool) => <p>{tool}</p>)}
+ </div>
+ </TerminalBorder>
+ </div>
+ <div class="sm:w-[40%] pt-[5vw] sm:pt-0 sm:pl-[1.25vw]">
+ <RadarChart max={max} data={data} />
+ </div>
+ </div>
+</Terminal>