Compare commits

...

11 Commits

Author SHA1 Message Date
bd7588b819 Change directory for deployment
All checks were successful
Deploy Astro / Build and Deploy (push) Successful in 1m41s
Signed-off-by: Daniel Kluge <c0ntroller@noreply.git.c0ntroller.de>
2025-01-05 18:56:47 +01:00
138ad075ea footer-nav ohne transition (fehleranfällig)
All checks were successful
Deploy Astro / Build and Deploy (push) Successful in 27m28s
2024-03-03 16:26:46 +01:00
c2d70f0988 Astro audit
Some checks failed
Deploy Astro / Build and Deploy (push) Has been cancelled
2024-03-03 16:06:35 +01:00
e339b21f66 Uniform icon size class 2024-03-03 15:58:24 +01:00
c40af33d1d Upgrade astro 2024-03-03 15:49:13 +01:00
dafbda9509 Upgrade astro-icons
All checks were successful
Deploy Astro / Build and Deploy (push) Successful in 24m55s
2024-03-03 15:18:06 +01:00
8a670bd0bb Add icons json
Some checks failed
Deploy Astro / Build and Deploy (push) Failing after 23m8s
2024-03-03 12:13:17 +01:00
bd9c74d6f3 More styling
Some checks failed
Deploy Astro / Build and Deploy (push) Failing after 24m25s
2024-03-02 21:04:14 +01:00
5d5af62baf npm audit fix
Some checks failed
Deploy Astro / Build and Deploy (push) Failing after 24m25s
2024-03-02 18:20:44 +01:00
d4396a5acc Terminal work
Some checks failed
Deploy Astro / Build and Deploy (push) Has been cancelled
2024-03-02 18:13:28 +01:00
0ebcf1d5a2 Add view transition 2024-03-02 17:52:29 +01:00
36 changed files with 3658 additions and 8373 deletions

View File

@ -26,6 +26,6 @@ jobs:
username: ${{ secrets.SSH_USERNAME }} username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }} key: ${{ secrets.SSH_KEY }}
source: "dist/*" source: "dist/*"
target: /var/www/website/dev target: /srv/website/dev
overwrite: true overwrite: true
strip_components: 1 strip_components: 1

View File

@ -1,24 +1,23 @@
import { defineConfig } from "astro/config"; import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx"; import mdx from "@astrojs/mdx";
import a11yEmoji from "@fec/remark-a11y-emoji"; import a11yEmoji from "@fec/remark-a11y-emoji";
import wasmPack from 'vite-plugin-wasm-pack'; import wasmPack from 'vite-plugin-wasm-pack';
import icon from "astro-icon";
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [mdx()], prefetch: {
prefetchAll: true
},
integrations: [mdx(), icon()],
markdown: { markdown: {
remarkPlugins: [ remarkPlugins: [a11yEmoji],
a11yEmoji
],
shikiConfig: { shikiConfig: {
theme: "one-dark-pro" theme: "one-dark-pro"
} }
}, },
// Copy wasm-terminal to the build directory // Copy wasm-terminal to the build directory
vite: { vite: {
plugins: [ plugins: [wasmPack([], ['@c0ntroller/wasm-terminal'])]
wasmPack([],['@c0ntroller/wasm-terminal'])
]
} }
}); });

11742
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,16 +10,18 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/check": "^0.3.1", "@astrojs/check": "^0.5.6",
"@astrojs/mdx": "^1.1.5", "@astrojs/mdx": "^2.1.1",
"@c0ntroller/wasm-terminal": ">=0.1.0", "@c0ntroller/wasm-terminal": ">=0.1.0",
"astro": "^3.6.0", "astro": "^4.4.9",
"astro-icon": "^0.8.1", "astro-icon": "^1.1.0",
"sass": "^1.69.5", "sass": "^1.69.5",
"typescript": "^5.3.2" "typescript": "^5.3.2"
}, },
"devDependencies": { "devDependencies": {
"@fec/remark-a11y-emoji": "^4.0.2", "@fec/remark-a11y-emoji": "^4.0.2",
"@iconify-json/mdi": "^1.1.64",
"@iconify-json/simple-icons": "^1.1.93",
"astro-themes": "^0.2.4", "astro-themes": "^0.2.4",
"remark-code-extra": "^1.0.1", "remark-code-extra": "^1.0.1",
"vite-plugin-wasm-pack": "0.1.11" "vite-plugin-wasm-pack": "0.1.11"

View File

@ -4,14 +4,15 @@ interface Props {
description: string; description: string;
published?: Date; published?: Date;
path: string; path: string;
slug: string;
} }
const { title, description, published, path } = Astro.props; const { title, description, /*published, */path, slug } = Astro.props;
--- ---
<a href={path} class="nostyle"> <a href={path} class="nostyle">
<div class="card"> <div class="card" transition:name={`markdown-border-${slug}`}>
<h3>{title}</h3> <h3 transition:name={`markdown-title-${slug}`}>{title}</h3>
<p>{description}</p> <p>{description}</p>
</div> </div>
</a> </a>

View File

@ -1,6 +1,5 @@
--- ---
import { getCollection, getEntry } from "astro:content"; import { getCollection, getEntry, type CollectionEntry } from "astro:content";
import type { CollectionEntry } from "astro:content";
interface Props { interface Props {
collectionName: CollectionEntry<"diaryMainPages">["slug"]; collectionName: CollectionEntry<"diaryMainPages">["slug"];

View File

@ -1,6 +1,5 @@
--- ---
import { getCollection, getEntry } from "astro:content"; import { getCollection, getEntry, type CollectionEntry } from "astro:content";
import type { CollectionEntry } from "astro:content";
interface Props { interface Props {
collectionName: CollectionEntry<"diaryMainPages">["slug"]; collectionName: CollectionEntry<"diaryMainPages">["slug"];
@ -104,6 +103,7 @@ select {
border-radius: 1em; border-radius: 1em;
border: 1px solid var(--blog_content-border); border: 1px solid var(--blog_content-border);
background: var(--blog_background-main); background: var(--blog_background-main);
color: var(--blog_color);
} }

View File

@ -1,13 +1,13 @@
--- ---
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import { Icon } from "astro-icon"; import { Icon } from "astro-icon/components";
import ThemeSwitch from "./ThemeSwitch.astro"; import ThemeSwitch from "./ThemeSwitch.astro";
import logo from "./logo.png"; import logo from "./logo.png";
--- ---
<nav class="navigation"> <nav class="navigation">
<a href="/" class="nostyle imgContainer"> <a href="/" class="nostyle imgContainer">
<Image src={logo} alt="Logo" class="logoImg" /> <Image src={logo} alt="Logo" class="logoImg" loading="eager" />
</a> </a>
<div class="navLink"> <div class="navLink">
<a href="/" class="nostyle"> <a href="/" class="nostyle">
@ -15,9 +15,9 @@ import logo from "./logo.png";
<span class="linkIcon" <span class="linkIcon"
><Icon ><Icon
name="mdi:home" name="mdi:home"
size="2em"
title="Home and Projects" title="Home and Projects"
id="mdi_nav_home" id="mdi_nav_home"
class="icon-2em"
/></span /></span
> >
</a> </a>
@ -28,7 +28,7 @@ import logo from "./logo.png";
<span class="linkIcon" <span class="linkIcon"
><Icon ><Icon
name="mdi:account" name="mdi:account"
size="2em" class="icon-2em"
title="About Me" title="About Me"
id="mdi_nav_aboutme" id="mdi_nav_aboutme"
/></span /></span
@ -40,7 +40,7 @@ import logo from "./logo.png";
<a href="/terminal" class="nostyle"> <a href="/terminal" class="nostyle">
<Icon <Icon
name="mdi:console" name="mdi:console"
size="2em" class="icon-2em"
title="Terminal" title="Terminal"
id="mdi_nav_terminal" id="mdi_nav_terminal"
/> />

View File

@ -1,11 +1,11 @@
--- ---
import { Icon } from "astro-icon"; import { Icon } from "astro-icon/components";
--- ---
<div class="switch"> <div class="switch" transition:persist="theme-switch">
<Icon name="mdi:language-javascript" title="Theme switching needs JS to be enabled." data-theme-ph /> <Icon name="mdi:language-javascript" title="Theme switching needs JS to be enabled." data-theme-ph class="icon-15em" />
<Icon name="mdi:white-balance-sunny" title="Switch to dark theme" data-theme-sun /> <Icon name="mdi:white-balance-sunny" title="Switch to dark theme" data-theme-sun class="icon-15em" />
<Icon name="mdi:weather-night" title="Switch to light theme" data-theme-moon /> <Icon name="mdi:weather-night" title="Switch to light theme" data-theme-moon class="icon-15em" />
</div> </div>
<script> <script>
@ -26,18 +26,34 @@ import { Icon } from "astro-icon";
const switchThemeDark = () => { const switchThemeDark = () => {
document.dispatchEvent(new CustomEvent('set-theme', { detail: 'dark' })); document.dispatchEvent(new CustomEvent('set-theme', { detail: 'dark' }));
moons.forEach(m => m.classList.remove("fadeOut")); moons.forEach(m => m.classList.remove("fadeOut", "fadeOutDone"));
moons.forEach(m => m.classList.add("fadeIn")); moons.forEach(m => m.classList.add("fadeIn"));
suns.forEach(s => s.classList.remove("fadeIn")); setTimeout(() => moons.forEach(m => {
m.classList.add("fadeInDone");
m.classList.remove("fadeIn");
}), 250); // After 0.2s animation is completed
suns.forEach(s => s.classList.remove("fadeIn", "fadeInDone"));
suns.forEach(s => s.classList.add("fadeOut")); suns.forEach(s => s.classList.add("fadeOut"));
setTimeout(() => suns.forEach(s => {
s.classList.add("fadeOutDone");
s.classList.remove("fadeOut");
}), 250); // After 0.2s animation is completed
} }
const switchThemeLight = () => { const switchThemeLight = () => {
document.dispatchEvent(new CustomEvent('set-theme', { detail: 'light' })); document.dispatchEvent(new CustomEvent('set-theme', { detail: 'light' }));
moons.forEach(m => m.classList.remove("fadeIn")); moons.forEach(m => m.classList.remove("fadeIn", "fadeInDone"));
moons.forEach(m => m.classList.add("fadeOut")); moons.forEach(m => m.classList.add("fadeOut"));
suns.forEach(s => s.classList.remove("fadeOut")); setTimeout(() => moons.forEach(m => {
m.classList.add("fadeOutDone");
m.classList.remove("fadeOut");
}), 250); // After 0.2s animation is completed
suns.forEach(s => s.classList.remove("fadeOut", "fadeOutDone"));
suns.forEach(s => s.classList.add("fadeIn")); suns.forEach(s => s.classList.add("fadeIn"));
setTimeout(() => suns.forEach(s => {
s.classList.add("fadeInDone");
s.classList.remove("fadeIn");
}), 250); // After 0.2s animation is completed
} }
moons.forEach(m => m.addEventListener("click", switchThemeLight)); moons.forEach(m => m.addEventListener("click", switchThemeLight));
@ -66,11 +82,21 @@ import { Icon } from "astro-icon";
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
.fadeOutDone {
opacity: 0;
transform: translate(0, -100%);
}
.fadeIn { .fadeIn {
animation: fadeIn 0.2s ease-in-out; animation: fadeIn 0.2s ease-in-out;
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
.fadeInDone {
opacity: 1;
transform: translate(0, 0);
}
.placeHolder { .placeHolder {
opacity: 1 !important; opacity: 1 !important;
transform: translate(0, 0) !important; transform: translate(0, 0) !important;

View File

@ -1,5 +1,5 @@
--- ---
import { Icon } from "astro-icon"; import { Icon } from "astro-icon/components";
import Skills from "../data/skills.json"; import Skills from "../data/skills.json";
type Skill = (typeof Skills.cards)[number]; type Skill = (typeof Skills.cards)[number];
@ -40,7 +40,7 @@ const cardStyle = {
.map((skill) => ( .map((skill) => (
<div class="skillBar"> <div class="skillBar">
<div class="barName"> <div class="barName">
<Icon name={skill.icon} /> <Icon name={skill.icon} class="icon-2em" />
</div> </div>
<div <div
class="percentBar" class="percentBar"
@ -61,7 +61,7 @@ const cardStyle = {
<> <>
<div class="badge"> <div class="badge">
<span> <span>
<Icon name={additional.icon} /> <Icon name={additional.icon} class="icon-1em" />
</span> </span>
<span>{additional.name}</span> <span>{additional.name}</span>
</div> </div>
@ -202,7 +202,6 @@ const cardStyle = {
} }
& > div:first-of-type { & > div:first-of-type {
height: 2em;
grid-row: 1/3; grid-row: 1/3;
} }

View File

@ -5,6 +5,7 @@ const projectsCol = defineCollection({
type: "content", type: "content",
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
site_title: z.string().optional(),
description: z.string(), description: z.string(),
descriptionShort: z.string(), descriptionShort: z.string(),
repository: z.string().url().optional(), repository: z.string().url().optional(),
@ -19,6 +20,7 @@ const diaryMainPages = defineCollection({
type: "content", type: "content",
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
site_title: z.string().optional(),
description: z.string(), description: z.string(),
descriptionShort: z.string(), descriptionShort: z.string(),
repository: z.string().url().optional(), repository: z.string().url().optional(),
@ -33,6 +35,7 @@ const diarySubPages = defineCollection({
type: "content", type: "content",
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
site_title: z.string().optional(),
repository: z.string().url().optional(), repository: z.string().url().optional(),
relatedWebsite: z.string().url().optional(), relatedWebsite: z.string().url().optional(),
published: z.date().optional(), published: z.date().optional(),

View File

@ -6,6 +6,4 @@ descriptionShort: "Me learning Rust (German)."
relatedWebsite: https://doc.rust-lang.org/book/ relatedWebsite: https://doc.rust-lang.org/book/
--- ---
# Learning Rust
In this diary I want to document my progress through the [Rust book](https://doc.rust-lang.org/book/) and documenting some stuff for myself. In this diary I want to document my progress through the [Rust book](https://doc.rust-lang.org/book/) and documenting some stuff for myself.

View File

@ -8,8 +8,6 @@ published: 2022-06-13T13:07:27.205Z
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import screenshot from "./data_infoscreen/screenshot.jpg"; import screenshot from "./data_infoscreen/screenshot.jpg";
# Infoscreen
This document is about a screen that shows information. This document is about a screen that shows information.
Shocking, I know. Shocking, I know.

View File

@ -1,13 +1,11 @@
--- ---
title: Overleaf Git Sync title: Overleaf Sync with Git
description: "Overleaf is a LaTeX editor for the web and honestly great to use. But there is no way to back up your project to a cloud drive or git without paying them money. Even the self-hosted community version has no such functionality. I decided that's BS and made my own script to sync a project to git." description: "Overleaf is a LaTeX editor for the web and honestly great to use. But there is no way to back up your project to a cloud drive or git without paying them money. Even the self-hosted community version has no such functionality. I decided that's BS and made my own script to sync a project to git."
descriptionShort: "I created a script that pushes Overleaf projects to a git remote." descriptionShort: "I created a script that pushes Overleaf projects to a git remote."
repository: "https://git.c0ntroller.de/c0ntroller/overleaf-git-sync" repository: "https://git.c0ntroller.de/c0ntroller/overleaf-git-sync"
published: 2022-10-18T17:56:27+02:00 published: 2022-10-18T17:56:27+02:00
--- ---
# Overleaf Sync with Git
## The Problem ## The Problem
When I was writing some important stuff for uni I wanted as many backups as possible. When I was writing some important stuff for uni I wanted as many backups as possible.

View File

@ -1,13 +1,11 @@
--- ---
title: Photo Sync title: Google Photo Sync
description: "Giving random apps access to your Google Photos can be bad. To still use an album as screensaver etc. I wrote this script. It syncs all your photos to your drive while giving you maximum privacy." description: "Giving random apps access to your Google Photos can be bad. To still use an album as screensaver etc. I wrote this script. It syncs all your photos to your drive while giving you maximum privacy."
descriptionShort: "A script that syncs a Google Photos album to your drive." descriptionShort: "A script that syncs a Google Photos album to your drive."
repository: https://git.c0ntroller.de/c0ntroller/google-photo-album-sync repository: https://git.c0ntroller.de/c0ntroller/google-photo-album-sync
published: 2022-08-08T12:19:20+02:00 published: 2022-08-08T12:19:20+02:00
--- ---
# Google Photo Sync
Why give up privacy for a screensaver? Why give up privacy for a screensaver?
## Storytime ## Storytime

View File

@ -6,8 +6,6 @@ repository: "https://git.c0ntroller.de/c0ntroller/simple-callback-server"
published: 2022-10-18T17:56:27+02:00 published: 2022-10-18T17:56:27+02:00
--- ---
# Simple Callback Server
This is probably my simplest project. This is probably my simplest project.
## What is this? ## What is this?

View File

@ -6,8 +6,6 @@ repository: https://git.c0ntroller.de/c0ntroller/frontpage
published: 2022-10-18T17:56:27+02:00 published: 2022-10-18T17:56:27+02:00
--- ---
# Terminal
Hello and welcome to my website. This documentation is for the [cli on my website](https://c0ntroller.de/terminal) so check it out if you haven't! Hello and welcome to my website. This documentation is for the [cli on my website](https://c0ntroller.de/terminal) so check it out if you haven't!
## Why did I do this? ## Why did I do this?

View File

@ -7,8 +7,6 @@ relatedWebsite: https://tu-fast.de/
published: 2022-06-23T12:53:07.207Z published: 2022-06-23T12:53:07.207Z
--- ---
# TUfast
My work on a browser extension that is used by multiple thousand students. My work on a browser extension that is used by multiple thousand students.
## What is TUfast? ## What is TUfast?

View File

@ -5,8 +5,6 @@ sorting: 0
slug: hello-world slug: hello-world
--- ---
# Hello world!
_[Link zum Buch](https://doc.rust-lang.org/book/ch01-02-hello-world.html)_ _[Link zum Buch](https://doc.rust-lang.org/book/ch01-02-hello-world.html)_
## How to `println!` ## How to `println!`

View File

@ -5,8 +5,6 @@ sorting: 1
slug: cargo slug: cargo
--- ---
# Cargo
_[Link zum Buch](https://doc.rust-lang.org/book/ch01-03-hello-cargo.html)_ _[Link zum Buch](https://doc.rust-lang.org/book/ch01-03-hello-cargo.html)_
## Was ist Cargo? ## Was ist Cargo?

View File

@ -5,8 +5,6 @@ sorting: 2
slug: higher-lower-game slug: higher-lower-game
--- ---
# Erstes Spiel
[Link zum Buch](https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html) [Link zum Buch](https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html)
## Projekt erstellen ## Projekt erstellen

View File

@ -5,8 +5,6 @@ sorting: 3
slug: konzepte slug: konzepte
--- ---
# Konzepte
[Link zum Buch](https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html) [Link zum Buch](https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html)

View File

@ -5,8 +5,6 @@ sorting: 4
slug: ownership slug: ownership
--- ---
# Ownership
[Link zum Buch](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html) [Link zum Buch](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html)
## Was ist das? ## Was ist das?

View File

@ -5,8 +5,6 @@ sorting: 5
slug: structs slug: structs
--- ---
# Structs
[Link zum Buch](https://doc.rust-lang.org/book/ch05-00-structs.html) [Link zum Buch](https://doc.rust-lang.org/book/ch05-00-structs.html)
## Was sind Structs ## Was sind Structs

View File

@ -1,12 +1,11 @@
--- ---
title: Enums & Matching title: Enums & Matching
site_title: Enums und Pattern Matching
published: 2022-10-18T17:56:26+02:00 published: 2022-10-18T17:56:26+02:00
sorting: 6 sorting: 6
slug: enums slug: enums
--- ---
# Enums und Pattern Matching
[Link zum Buch](https://doc.rust-lang.org/book/ch06-00-enums.html) [Link zum Buch](https://doc.rust-lang.org/book/ch06-00-enums.html)
## Enums ## Enums

View File

@ -5,8 +5,6 @@ sorting: 7
slug: projektmanagement slug: projektmanagement
--- ---
# How to: Projektmanagement
[Link zum Buch](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html) [Link zum Buch](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)
## Packages, Crates, Modules, was? ## Packages, Crates, Modules, was?

View File

@ -5,8 +5,6 @@ sorting: 8
slug: collections slug: collections
--- ---
# Standard Collections
[Link zum Buch](https://doc.rust-lang.org/book/ch08-00-common-collections.html) [Link zum Buch](https://doc.rust-lang.org/book/ch08-00-common-collections.html)
## `Vec<T>` - Vektoren ## `Vec<T>` - Vektoren

View File

@ -5,8 +5,6 @@ sorting: 9
slug: errors-and-panic slug: errors-and-panic
--- ---
# Errors und `panic!`
[Link zum Buch](https://doc.rust-lang.org/book/ch09-00-error-handling.html) [Link zum Buch](https://doc.rust-lang.org/book/ch09-00-error-handling.html)
## `panic!` ## `panic!`

View File

@ -1,21 +1,24 @@
--- ---
import Navbar from "../components/LayoutComponents/Navbar.astro"; import { ViewTransitions } from 'astro:transitions';
import Themes from "astro-themes"; import Themes from "astro-themes";
import Icon from "astro-icon"; import { Icon } from "astro-icon/components";
import Navbar from "../components/LayoutComponents/Navbar.astro";
import socials from "../data/socials.json"; import socials from "../data/socials.json";
interface Props { interface Props {
title: string; title: string;
showAfterMain?: boolean; showAfterMain?: boolean;
mainTransitionName?: string;
} }
const { title, showAfterMain } = Astro.props; const { title, showAfterMain, mainTransitionName } = Astro.props;
--- ---
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<Themes defaultTheme="dark" /> <Themes defaultTheme="dark" />
<ViewTransitions />
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta <meta
@ -115,18 +118,18 @@ const { title, showAfterMain } = Astro.props;
<title>{title}</title> <title>{title}</title>
</head> </head>
<body> <body>
<span id="top" aria-hidden></span> <span id="top" aria-hidden="true"></span>
<header> <header transition:persist="nav">
<Navbar /> <Navbar />
</header> </header>
<main> <main transition:name={ mainTransitionName || "main" }>
<slot /> <slot />
</main> </main>
{showAfterMain ? <div class="after-main"> {showAfterMain ? <div class="after-main">
<slot name="after-main" /> <slot name="after-main" />
</div> : null </div> : null
} }
<footer id="bottom"> <footer id="bottom" transition:persist="footer">
<span style="visibility:hidden">▲</span> <span style="visibility:hidden">▲</span>
<span class="spacer"></span> <span class="spacer"></span>
<span class="footerContent"> <span class="footerContent">
@ -134,8 +137,8 @@ const { title, showAfterMain } = Astro.props;
<span class="divider">|</span> <span class="divider">|</span>
{socials.flatMap((social, i) => ( {socials.flatMap((social, i) => (
i !== 0 ? i !== 0 ?
[<span class="divider">|</span>, <a href={social.url} target="_blank" rel="noreferrer" class="socialIcon"><Icon name={social.icon} title={social.name} /></a>] : [<span class="divider">|</span>, <a href={social.url} target="_blank" rel="noreferrer" class="socialIcon"><Icon name={social.icon} title={social.name} class="socialIcon" /></a>] :
[<a href={social.url} target="_blank" rel="noreferrer" class="socialIcon"><Icon name={social.icon} title={social.name} /></a>] [<a href={social.url} target="_blank" rel="noreferrer" class="socialIcon"><Icon name={social.icon} title={social.name} class="socialIcon" /></a>]
))} ))}
<span class="divider">|</span> <span class="divider">|</span>
<a class="nocolor" target="_blank" href="mailto:admin-website@c0ntroller.de" rel="noreferrer">Contact</a> <a class="nocolor" target="_blank" href="mailto:admin-website@c0ntroller.de" rel="noreferrer">Contact</a>
@ -301,4 +304,20 @@ const { title, showAfterMain } = Astro.props;
h6 { h6 {
color: var(--blog_color-accent-dark); color: var(--blog_color-accent-dark);
} }
.icon-1em {
height: 1em;
width: 1em;
}
.icon-15em {
height: 1.5em;
width: 1.5em;
}
.icon-2em {
height: 2em;
width: 2em;
}
</style> </style>

View File

@ -1,9 +1,10 @@
--- ---
import Layout from "./Layout.astro"; import Layout from "./Layout.astro";
import { Icon } from "astro-icon"; import { Icon } from "astro-icon/components";
interface Props { interface Props {
title: string; title: string;
slug: string;
published?: Date; published?: Date;
srcPath?: string; srcPath?: string;
moreLinks?: { moreLinks?: {
@ -12,20 +13,21 @@ interface Props {
}[]; }[];
} }
const { title, srcPath, published, moreLinks } = Astro.props; const { title, srcPath, published, moreLinks, slug } = Astro.props;
const gitUrl = `https://git.c0ntroller.de/c0ntroller/frontpage/src/branch/dev/src/content/${srcPath}` const gitUrl = `https://git.c0ntroller.de/c0ntroller/frontpage/src/branch/dev/src/content/${srcPath}`
--- ---
<Layout title={title} showAfterMain={Astro.slots.has("footer-nav")}> <Layout title={title} showAfterMain={Astro.slots.has("footer-nav")} mainTransitionName={`markdown-border-${slug}`}>
{Astro.slots.has("main-nav") ? {Astro.slots.has("main-nav") ?
<slot name="main-nav" /> : <slot name="main-nav" /> :
null} null}
{ moreLinks && moreLinks.length !== 0 ? { moreLinks && moreLinks.length !== 0 ?
<div class="more"> <div class="more">
{ moreLinks.map(l => <a href={l.href} referrerpolicy="no-referrer" class="nostyle" style={{ display: "inline-block", width: "2em" }}><Icon name={l.icon} /></a>) } { moreLinks.map(l => <a href={l.href} referrerpolicy="no-referrer" class="nostyle"><Icon name={l.icon} class="icon-2em" /></a>) }
</div> </div>
: null} : null}
<h1 transition:name={`markdown-title-${slug}`}>{title}</h1>
<slot /> <slot />
{ published || srcPath ? <> { published || srcPath ? <>
<hr /> <hr />

View File

@ -38,7 +38,7 @@ if (diaryMain.data.repository) {
} }
--- ---
<MarkdownLayout title={diaryMain.data.title} srcPath={`diaryMainPages/${diaryMain.id}`} moreLinks={moreLinks}> <MarkdownLayout title={diaryMain.data.site_title || diaryMain.data.title} slug={diaryMain.slug} srcPath={`diaryMainPages/${diaryMain.id}`} moreLinks={moreLinks}>
<Content /> <Content />
<h2>Pages</h2> <h2>Pages</h2>

View File

@ -27,7 +27,7 @@ const { entry } = Astro.props;
const { Content } = await entry.render(); const { Content } = await entry.render();
--- ---
<MarkdownLayout title={entry.data.title} srcPath={`${diary}/${entry.id}`} published={entry.data.published}> <MarkdownLayout title={entry.data.site_title || entry.data.title} slug={entry.slug} srcPath={`${diary}/${entry.id}`} published={entry.data.published}>
<DiaryNavTop collectionName="rust" slot="main-nav" /> <DiaryNavTop collectionName="rust" slot="main-nav" />
<Content /> <Content />
<DiaryNavBar collectionName="rust" slot="footer-nav" /> <DiaryNavBar collectionName="rust" slot="footer-nav" />

View File

@ -29,12 +29,12 @@ if (entry.data.relatedWebsite) {
if (entry.data.repository) { if (entry.data.repository) {
moreLinks.push({ moreLinks.push({
href: entry.data.repository, href: entry.data.repository,
icon: "bi:git", icon: "simple-icons:git",
}); });
} }
--- ---
<MarkdownLayout title={entry.data.title} srcPath={`projects/${entry.id}`} published={entry.data.published} moreLinks={moreLinks}> <MarkdownLayout title={entry.data.site_title || entry.data.title} slug={entry.slug} srcPath={`projects/${entry.id}`} published={entry.data.published} moreLinks={moreLinks}>
<Content /> <Content />
</MarkdownLayout> </MarkdownLayout>

View File

@ -22,11 +22,11 @@ const diaries = (await getCollection("diaryMainPages")).sort((a, b) => a.data.la
</p> </p>
<h2>Projects</h2> <h2>Projects</h2>
<div class="contentList"> <div class="contentList">
{ projects.map(p => <ContentCard title={p.data.title} description={p.data.description} path={`/blog/${p.slug}`} />) } { projects.map(p => <ContentCard title={p.data.title} description={p.data.description} path={`/blog/${p.slug}`} slug={p.slug} />) }
</div> </div>
<h2>Diaries</h2> <h2>Diaries</h2>
<div class="contentList"> <div class="contentList">
{ diaries.map(p => <ContentCard title={p.data.title} description={p.data.description} path={`/blog/${p.slug}`} />) } { diaries.map(p => <ContentCard title={p.data.title} description={p.data.description} path={`/blog/${p.slug}`} slug={p.slug} />) }
</div> </div>
</Layout> </Layout>

View File

@ -1,6 +1,6 @@
--- ---
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import { Icon } from "astro-icon"; import { Icon } from "astro-icon/components";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import SkillCard from "../components/SkillCard.astro"; import SkillCard from "../components/SkillCard.astro";
@ -15,7 +15,7 @@ const age = new Date().getFullYear() - 1998 - (new Date().getMonth() <= 10 ? 1 :
<Layout title="About me"> <Layout title="About me">
<h1>This is me.</h1> <h1>This is me.</h1>
<div class="photo"> <div class="photo">
<Image src={pic} alt="Me" /> <Image src={pic} alt="Me" loading="eager" />
</div> </div>
<div class="personal"> <div class="personal">
<p class="preText"> <p class="preText">
@ -67,16 +67,16 @@ const age = new Date().getFullYear() - 1998 - (new Date().getMonth() <= 10 ? 1 :
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
class="nocolor" class="nocolor"
style={{ width: "2em" }} aria-label={`Link to my ${social.name} profile`}
> >
<Icon name={social.icon} /> <Icon name={social.icon} class="icon-2em" />
</a> </a>
)) ))
} }
</div> </div>
<h2>Achievements</h2> <h2>Achievements</h2>
{achievements.map((achievement) => <div class="achievement"> {achievements.map((achievement) => <div class="achievement">
<Icon name={achievement.icon} /><span>{achievement.description}</span> <Icon name={achievement.icon} class="icon-2em" /><span>{achievement.description}</span>
</div>)} </div>)}
<h2>Skills</h2> <h2>Skills</h2>
{skills.cards.map((card) => <SkillCard card={card} />)} {skills.cards.map((card) => <SkillCard card={card} />)}

View File

@ -7,7 +7,7 @@ const screenVersion = `${date.getFullYear()}${date.getMonth()+1}${date.getDate()
const wasmVersion = wasmData.version; const wasmVersion = wasmData.version;
--- ---
<Layout title="Terminal"> <Layout title="Terminal" showAfterMain>
<div class="screen" data-terminal-screen> <div class="screen" data-terminal-screen>
<div data-terminal-output> <div data-terminal-output>
<noscript><pre>You need to enable JavaScript to use this terminal.</pre></noscript> <noscript><pre>You need to enable JavaScript to use this terminal.</pre></noscript>
@ -20,33 +20,50 @@ const wasmVersion = wasmData.version;
@@@@@ @@@@@@@@@@ @@@@@ @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@
@@@@@@@@@@@@@@@W#MW@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@W#MW@@@@@@@@@@@@@@@ @@@@@@@@@
@@@@@########*****pkaMB@@@@@@@@mb@@@@@ @@@@@@@ @@@@@######## pkaMB@@@@@@@@mb@@@@@ @@@@@@@
@@@@@*************pwdhoh@@@@@$OOOOOw*##@@@@ @ @@@@ @@@@@ pwdhoh@@@@@$OOOOOw ##@@@@ @ @@@@
@@@@@************dOOOOOOOOOO0OOOOOO*******#@@ @ @@@ @@@@@ dOOOOOOOOOO0OOOOOO #@@ @ @@@
@@@@************pOOOOOOOOOOOOOOZ#**********#@@ @ @@@@ pOOOOOOOOOOOOOOZ# #@@ @
@@@@************oOOOOOOOOOOOOa***************#@ @@@@ oOOOOOOOOOOOOa #@
@@@@@***********odwwpdda********************** @@@@@ odwwpdda
@@@@@********************************** @@@@@
@@@@@@@@@$#*###MMB@@@@@@@@@@@@</pre> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</pre>
</div> </div>
<div class="input"><pre class="user">user@cer0</pre><pre>:</pre><pre class="pwd">/</pre><pre class="dollar">$&nbsp;</pre><input type="text" data-terminal-input autofocus /></div> <div class="input"><pre class="user">user@cer0</pre><pre>:</pre><pre class="pwd">/</pre><pre class="dollar">$&nbsp;</pre><input type="text" data-terminal-input /></div>
</div> </div>
<template data-terminal-user-cmd> <template data-terminal-user-cmd>
<pre><pre class="user">user@cer0</pre><pre>:</pre><pre class="pwd"></pre><pre class="dollar">$&nbsp;</pre><pre class="user-cmd"></pre></pre> <pre><pre class="user">user@cer0</pre><pre>:</pre><pre class="pwd"></pre><pre class="dollar">$&nbsp;</pre><pre class="user-cmd"></pre></pre>
</template> </template>
<div slot="after-main" class="more">
Read more about the development of this terminal&nbsp;<a href="/blog/wasm-terminal" class="nocolor">here</a>.
</div>
</Layout> </Layout>
<script> <script>
(async () => { (async () => {
const wasm = import("@c0ntroller/wasm-terminal"); const wasm = import("@c0ntroller/wasm-terminal");
const outputs = document.querySelectorAll("[data-terminal-output]") as NodeListOf<HTMLPreElement>; const outputs = document.querySelectorAll("[data-terminal-output]") as NodeListOf<HTMLDivElement>;
const inputs = document.querySelectorAll("[data-terminal-input]") as NodeListOf<HTMLInputElement>; const inputs = document.querySelectorAll("[data-terminal-input]") as NodeListOf<HTMLInputElement>;
const screens = document.querySelectorAll("[data-terminal-screen]") as NodeListOf<HTMLDivElement>; const screens = document.querySelectorAll("[data-terminal-screen]") as NodeListOf<HTMLDivElement>;
const template = document.querySelector("[data-terminal-user-cmd]") as HTMLTemplateElement; const template = document.querySelector("[data-terminal-user-cmd]") as HTMLTemplateElement;
screens.forEach((s) => s.addEventListener("click", () => inputs[0]?.focus())) screens.forEach((s) => s.addEventListener("click", () => inputs[0]?.focus()));
screens.forEach((screen) => {
new MutationObserver((changes) => {
const totalNewHeight = changes.reduce((prev, change) => {
change.addedNodes.forEach(n => prev += (n as HTMLPreElement).clientHeight || 0);
return prev;
}, 0);
if (screen.scrollTop + screen.clientHeight >= screen.scrollHeight - totalNewHeight - 40) {
screen.scrollTo(0, screen.scrollHeight);
}
}).observe(screen, { childList: true, subtree: true });
});
const { default: init, Console } = await wasm; const { default: init, Console } = await wasm;
@ -69,20 +86,23 @@ const wasmVersion = wasmData.version;
inputLine.querySelector(".user-cmd")!.textContent = cmd; inputLine.querySelector(".user-cmd")!.textContent = cmd;
inputLine.querySelector(".pwd")!.textContent = prevPwd; inputLine.querySelector(".pwd")!.textContent = prevPwd;
outputs.forEach((output) => { outputs.forEach((output) => {
output.prepend(inputLine); output.append(inputLine);
}); });
const resp = c.execute(cmd); input.value = "";
if (resp) { if (cmd) {
const outputLine = document.createElement("pre"); const resp = c.execute(cmd);
outputLine.textContent = resp
outputs.forEach((output) => { if (resp) {
output.prepend(outputLine); const outputLine = document.createElement("pre");
}); outputLine.textContent = resp
outputs.forEach((output) => {
output.append(outputLine);
});
}
} }
input.value = "";
updatePwd(); updatePwd();
} }
}); });
@ -106,7 +126,7 @@ const wasmVersion = wasmData.version;
padding: 10px; padding: 10px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-y: scroll; overflow-y: auto;
pre > pre { pre > pre {
display: inline-block; display: inline-block;
@ -121,7 +141,7 @@ const wasmVersion = wasmData.version;
[data-terminal-output] { [data-terminal-output] {
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column;
} }
} }
@ -148,6 +168,7 @@ const wasmVersion = wasmData.version;
input { input {
font-family: "Cascadia Code", monospace; font-family: "Cascadia Code", monospace;
display: inline-block; display: inline-block;
width: 100%;
flex-grow: 2; flex-grow: 2;
font-size: 1rem; font-size: 1rem;
padding: 0; padding: 0;
@ -157,6 +178,7 @@ const wasmVersion = wasmData.version;
appearance: none !important; appearance: none !important;
outline: none; outline: none;
caret-shape: block; caret-shape: block;
color: #fff;
&::-moz-focus-outer, &::-moz-focus-inner, &:focus, &:focus *, &:-moz-focusring, &:-moz-focusring * { &::-moz-focus-outer, &::-moz-focus-inner, &:focus, &:focus *, &:-moz-focusring, &:-moz-focusring * {
border: none !important; border: none !important;
@ -166,4 +188,12 @@ const wasmVersion = wasmData.version;
} }
} }
.more {
display: flex;
justify-content: center;
align-items: center;
font-style: italic;
padding: 5px;
}
</style> </style>