1
Fork 0
mirror of https://github.com/RGBCube/Site synced 2025-07-29 12:07:47 +00:00

treewide: site redesign

This commit is contained in:
RGBCube 2025-06-01 21:32:33 +03:00
parent 3d663619e6
commit 4b146bbe4e
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
80 changed files with 1842 additions and 1117 deletions

20
.gitignore vendored
View file

@ -1,9 +1,14 @@
*
!.gitignore
!site/
!site/_includes/
!site/assets/
!site/blog/
!site/**/
!*.nu
!*.ts
!*.css
!*.md
!*.vto
@ -12,11 +17,4 @@
!*.webp
!*.woff2
!.gitignore
!*.json
!*.lock
!*.ts
!*.tsx
!*.nu
!deno.*

View file

@ -1,20 +1,20 @@
# RGBCube's Homepage
The official website and link portal of RGBCube and his work.
The home directory and journal of RGBCube and his work.
## Building
To build the site, you will need deno, simply run this command:
```
```sh
deno task build
```
and the site contents will be under the `_site/` directory.
and the site contents will be under the `_site` directory.
## License
All the human writing (non-HTML and not templating related) under the `site/`
All the human writing (non-HTML and not templating related) under the `site`
directory is licensed under
[CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/).
@ -22,7 +22,7 @@ The other HTML and templating code is licensed under the GPU General Public
License (`LICENSE_GPL.md`):
```
Copyright (C) 2023-present RGBCube
Copyright (C) 2023-present RGBCube
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,87 +0,0 @@
import lume from "lume/mod.ts";
import codeHighlight from "lume/plugins/code_highlight.ts";
import esbuild from "lume/plugins/esbuild.ts";
import feed from "lume/plugins/feed.ts";
import jsx from "lume/plugins/jsx.ts";
import minifyHTML from "lume/plugins/minify_html.ts";
import sitemap from "lume/plugins/sitemap.ts";
const site = lume({
src: "./site",
server: {
debugBar: false,
},
});
site.add(".");
site.use(jsx());
site.process([".html"], (pages) => {
pages.forEach((page) => {
const document = page.document!;
document.querySelectorAll("table").forEach((table) => {
const div = document.createElement("div");
table.classList.add("rotated");
div.classList.add("overflow", "rotated");
table.parentNode!.insertBefore(div, table);
div.appendChild(table);
});
document.querySelectorAll("pre code").forEach((code) => {
const pre = code.parentElement!;
const div = document.createElement("div");
code.classList.add("rotated");
pre.classList.add("rotated");
div.classList.add("overflow", "rotated");
pre.parentNode?.insertBefore(div, pre);
div.appendChild(pre);
});
});
});
site.use(feed({
output: ["/blog.rss", "/blog.json"],
query: "type=article",
sort: "date=asc",
limit: Infinity,
info: {
title: "RGBCube's Blog",
description:
"The blog where RGBCube dumps his schizophrenic ramblings about software and all the likes.",
generator: false,
},
items: {
title: "=title",
description: "=description",
published: "=date",
content: "$.content",
},
}));
site.use(sitemap({
items: {
// @ts-ignore: We don't want lastmods.
lastmod: null,
},
}));
site.use(esbuild());
site.use(codeHighlight());
site.use(minifyHTML({
options: {
minify_css: true,
minify_js: true,
},
}));
export default site;

View file

@ -14,7 +14,7 @@ def main [] {
if (pwd | str starts-with "/data/data/com.termux") {
sync ./ nine:site
ssh -qtt nine "
ssh -tt nine "
cd site
LUME_DRAFTS=false nix run default#deno -- task build --location https://rgbcu.be/
"
@ -28,13 +28,13 @@ def main [] {
let host = "root@best";
ssh -qtt $host "
ssh -tt $host "
rm --force --recursive /var/www/site
mkdir /var/www/site
"
sync --chown nginx:users ./ ($host + ":/var/www/site")
ssh -qtt $host "
ssh -tt $host "
chown nginx:users -R /var/www
chmod 775 -R /var/www
"

View file

@ -1,24 +1,26 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "lume",
"types": [
"lume/types.ts"
]
"imports": {
"lume/": "https://deno.land/x/lume@v3.0.2/",
"lume/jsx-runtime": "https://deno.land/x/ssx@v0.1.10/jsx-runtime.ts"
},
"tasks": {
"lume": "echo \"import 'lume/cli.ts'\" | deno run --allow-all -",
"lume": "echo \"import 'lume/cli.ts'\" | deno run --allow-all - --config site.ts",
"build": "deno task lume",
"serve": "deno task lume --serve"
},
"imports": {
"std/": "https://deno.land/std@0.217.0/",
"lume/": "https://deno.land/x/lume@v3.0.2/",
"lume/jsx-runtime": "https://deno.land/x/ssx@v0.1.9/jsx-runtime.ts"
"compilerOptions": {
"types": [
"lume/types.ts"
],
"jsx": "react-jsx",
"jsxImportSource": "lume"
},
"unstable": [
"temporal"
],
"lint": {
"plugins": [
"https://deno.land/x/lume@v3.0.1/lint.ts"
"https://deno.land/x/lume@v3.0.2/lint.ts"
]
}
}

295
deno.lock generated
View file

@ -21,6 +21,7 @@
"jsr:@std/http@1.0.16": "1.0.16",
"jsr:@std/json@^1.0.2": "1.0.2",
"jsr:@std/jsonc@1.0.2": "1.0.2",
"jsr:@std/media-types@1.1.0": "1.1.0",
"jsr:@std/media-types@^1.1.0": "1.1.0",
"jsr:@std/net@^1.0.4": "1.0.4",
"jsr:@std/path@1.0.8": "1.0.8",
@ -32,7 +33,8 @@
"jsr:@std/toml@^1.0.3": "1.0.6",
"jsr:@std/yaml@1.0.6": "1.0.6",
"jsr:@std/yaml@^1.0.5": "1.0.6",
"npm:@lumeland/ssx@*": "0.1.10",
"npm:@tailwindcss/node@4.1.7": "4.1.7",
"npm:@tailwindcss/oxide@4.1.7": "4.1.7",
"npm:@types/estree@1.0.6": "1.0.6",
"npm:estree-walker@3.0.3": "3.0.3",
"npm:highlight.js@11.11.1": "11.11.1",
@ -41,8 +43,8 @@
"npm:markdown-it-deflist@3.0.0": "3.0.0",
"npm:markdown-it@14.1.0": "14.1.0",
"npm:meriyah@6.0.5": "6.0.5",
"npm:react@*": "19.0.0",
"npm:remove-markdown@0.6.2": "0.6.2"
"npm:remove-markdown@0.6.2": "0.6.2",
"npm:tailwindcss@4.1.7": "4.1.7"
},
"jsr": {
"@davidbonnet/astring@1.8.6": {
@ -103,7 +105,7 @@
"jsr:@std/encoding@^1.0.10",
"jsr:@std/fmt@^1.0.8",
"jsr:@std/html@^1.0.4",
"jsr:@std/media-types",
"jsr:@std/media-types@^1.1.0",
"jsr:@std/net",
"jsr:@std/path@^1.0.9",
"jsr:@std/streams"
@ -144,8 +146,150 @@
}
},
"npm": {
"@lumeland/ssx@0.1.10": {
"integrity": "sha512-mZQYxtXkFYAUnFhXH+nOzhxp32ZsRMmiTLBNlrZu5qtXgHh+5PE5i1fVZ8leZ4yxOC0besV4PYZ78wQlf2Ggog=="
"@ampproject/remapping@2.3.0": {
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dependencies": [
"@jridgewell/gen-mapping",
"@jridgewell/trace-mapping"
]
},
"@emnapi/core@1.4.3": {
"integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==",
"dependencies": [
"@emnapi/wasi-threads",
"tslib"
]
},
"@emnapi/runtime@1.4.3": {
"integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==",
"dependencies": [
"tslib"
]
},
"@emnapi/wasi-threads@1.0.2": {
"integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==",
"dependencies": [
"tslib"
]
},
"@isaacs/fs-minipass@4.0.1": {
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
"dependencies": [
"minipass"
]
},
"@jridgewell/gen-mapping@0.3.8": {
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dependencies": [
"@jridgewell/set-array",
"@jridgewell/sourcemap-codec",
"@jridgewell/trace-mapping"
]
},
"@jridgewell/resolve-uri@3.1.2": {
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="
},
"@jridgewell/set-array@1.2.1": {
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="
},
"@jridgewell/sourcemap-codec@1.5.0": {
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"@jridgewell/trace-mapping@0.3.25": {
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dependencies": [
"@jridgewell/resolve-uri",
"@jridgewell/sourcemap-codec"
]
},
"@napi-rs/wasm-runtime@0.2.10": {
"integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==",
"dependencies": [
"@emnapi/core",
"@emnapi/runtime",
"@tybys/wasm-util"
]
},
"@tailwindcss/node@4.1.7": {
"integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
"dependencies": [
"@ampproject/remapping",
"enhanced-resolve",
"jiti",
"lightningcss",
"magic-string",
"source-map-js",
"tailwindcss"
]
},
"@tailwindcss/oxide-android-arm64@4.1.7": {
"integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg=="
},
"@tailwindcss/oxide-darwin-arm64@4.1.7": {
"integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg=="
},
"@tailwindcss/oxide-darwin-x64@4.1.7": {
"integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw=="
},
"@tailwindcss/oxide-freebsd-x64@4.1.7": {
"integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw=="
},
"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.7": {
"integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g=="
},
"@tailwindcss/oxide-linux-arm64-gnu@4.1.7": {
"integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA=="
},
"@tailwindcss/oxide-linux-arm64-musl@4.1.7": {
"integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A=="
},
"@tailwindcss/oxide-linux-x64-gnu@4.1.7": {
"integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg=="
},
"@tailwindcss/oxide-linux-x64-musl@4.1.7": {
"integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA=="
},
"@tailwindcss/oxide-wasm32-wasi@4.1.7": {
"integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
"dependencies": [
"@emnapi/core",
"@emnapi/runtime",
"@emnapi/wasi-threads",
"@napi-rs/wasm-runtime",
"@tybys/wasm-util",
"tslib"
]
},
"@tailwindcss/oxide-win32-arm64-msvc@4.1.7": {
"integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw=="
},
"@tailwindcss/oxide-win32-x64-msvc@4.1.7": {
"integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ=="
},
"@tailwindcss/oxide@4.1.7": {
"integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
"dependencies": [
"@tailwindcss/oxide-android-arm64",
"@tailwindcss/oxide-darwin-arm64",
"@tailwindcss/oxide-darwin-x64",
"@tailwindcss/oxide-freebsd-x64",
"@tailwindcss/oxide-linux-arm-gnueabihf",
"@tailwindcss/oxide-linux-arm64-gnu",
"@tailwindcss/oxide-linux-arm64-musl",
"@tailwindcss/oxide-linux-x64-gnu",
"@tailwindcss/oxide-linux-x64-musl",
"@tailwindcss/oxide-wasm32-wasi",
"@tailwindcss/oxide-win32-arm64-msvc",
"@tailwindcss/oxide-win32-x64-msvc",
"detect-libc",
"tar"
]
},
"@tybys/wasm-util@0.9.0": {
"integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==",
"dependencies": [
"tslib"
]
},
"@types/estree@1.0.6": {
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
@ -156,6 +300,19 @@
"argparse@2.0.1": {
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"chownr@3.0.0": {
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="
},
"detect-libc@2.0.4": {
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="
},
"enhanced-resolve@5.18.1": {
"integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"dependencies": [
"graceful-fs",
"tapable"
]
},
"entities@4.5.0": {
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
@ -165,21 +322,79 @@
"@types/estree@1.0.7"
]
},
"graceful-fs@4.2.11": {
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"highlight.js@11.11.1": {
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="
},
"jiti@2.4.2": {
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="
},
"lightningcss-darwin-arm64@1.30.1": {
"integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="
},
"lightningcss-darwin-x64@1.30.1": {
"integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="
},
"lightningcss-freebsd-x64@1.30.1": {
"integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="
},
"lightningcss-linux-arm-gnueabihf@1.30.1": {
"integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="
},
"lightningcss-linux-arm64-gnu@1.30.1": {
"integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="
},
"lightningcss-linux-arm64-musl@1.30.1": {
"integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="
},
"lightningcss-linux-x64-gnu@1.30.1": {
"integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="
},
"lightningcss-linux-x64-musl@1.30.1": {
"integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="
},
"lightningcss-wasm@1.30.1": {
"integrity": "sha512-KJTnKEn0REV6DoJzxG0m5EKVEFA1CVE1isDYpXjsuqWXwLKFPJtA9Z9BSzPZJwAZFN2KaUzy+IWGP59p5bm2sA==",
"dependencies": [
"napi-wasm"
]
},
"lightningcss-win32-arm64-msvc@1.30.1": {
"integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="
},
"lightningcss-win32-x64-msvc@1.30.1": {
"integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="
},
"lightningcss@1.30.1": {
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
"dependencies": [
"detect-libc",
"lightningcss-darwin-arm64",
"lightningcss-darwin-x64",
"lightningcss-freebsd-x64",
"lightningcss-linux-arm-gnueabihf",
"lightningcss-linux-arm64-gnu",
"lightningcss-linux-arm64-musl",
"lightningcss-linux-x64-gnu",
"lightningcss-linux-x64-musl",
"lightningcss-win32-arm64-msvc",
"lightningcss-win32-x64-msvc"
]
},
"linkify-it@5.0.0": {
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dependencies": [
"uc.micro"
]
},
"magic-string@0.30.17": {
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dependencies": [
"@jridgewell/sourcemap-codec"
]
},
"markdown-it-attrs@4.3.1_markdown-it@14.1.0": {
"integrity": "sha512-/ko6cba+H6gdZ0DOw7BbNMZtfuJTRp9g/IrGIuz8lYc/EfnmWRpaR3CFPnNbVz0LDvF8Gf1hFGPqrQqq7De0rg==",
"dependencies": [
@ -206,20 +421,55 @@
"meriyah@6.0.5": {
"integrity": "sha512-SrMqQCox7TTwtftWKHy/ZaVe+ZRpRl20pAgDo+PS9hzcAJrMjYsBJQPPiLXTnjztrqdfGS+Zz99r6Bwvydta1w=="
},
"minipass@7.1.2": {
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
},
"minizlib@3.0.2": {
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
"dependencies": [
"minipass"
]
},
"mkdirp@3.0.1": {
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="
},
"napi-wasm@1.1.3": {
"integrity": "sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg=="
},
"punycode.js@2.3.1": {
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="
},
"react@19.0.0": {
"integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="
},
"remove-markdown@0.6.2": {
"integrity": "sha512-EijDXJZbzpGbQBd852ViUzcqgpMujthM+SAEHiWCMcZonRbZ+xViWKLJA/vrwbDwYdxrs1aFDjpBhcGrZoJRGA=="
},
"source-map-js@1.2.1": {
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
},
"tailwindcss@4.1.7": {
"integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg=="
},
"tapable@2.2.2": {
"integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="
},
"tar@7.4.3": {
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
"dependencies": [
"@isaacs/fs-minipass",
"chownr",
"minipass",
"minizlib",
"mkdirp",
"yallist"
]
},
"tslib@2.8.1": {
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"uc.micro@2.1.0": {
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
},
"yallist@5.0.0": {
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="
}
},
"remote": {
@ -346,8 +596,6 @@
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4",
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d",
"https://deno.land/x/esbuild@v0.25.4/mod.js": "566ac37ed8acdb49b5cd72e0276de4014eb47b112a8ef31e30659220d8119226",
"https://deno.land/x/lume@v3.0.1/core/utils/lume_config.ts": "3715adca952a4c6054b0f4a25792859ae683a85b11c225b36d027ac26baabe95",
"https://deno.land/x/lume@v3.0.1/lint.ts": "4b369361e0cff20a8dfd9e3ff8cb642aa805e7532825ea3a5378eb1f80901fc6",
"https://deno.land/x/lume@v3.0.2/cli.ts": "a3254363ab2d55df4ff1f25e253f5edc53da1088c33a74efe36e605e74bb67c4",
"https://deno.land/x/lume@v3.0.2/cli/build.ts": "a3acda3c702d6a51a8fe65ea3abc17813deea0db71e442de6120a747f56a2466",
"https://deno.land/x/lume@v3.0.2/cli/build_worker.ts": "34781766980dcee3c433aaa65df138168cb163a2cbd89bac53efce167ed6bfbf",
@ -378,13 +626,16 @@
"https://deno.land/x/lume@v3.0.2/core/searcher.ts": "19530e0149ca925334f98052863a52cdfbbeea9977342b209829999a34e816a6",
"https://deno.land/x/lume@v3.0.2/core/server.ts": "19cdd234f18c601d8386c7aa6d589616ce367fc571a96d4715f220a522e17ae8",
"https://deno.land/x/lume@v3.0.2/core/site.ts": "2fd2103559eeed80574947c5b357b05c0d55d90e6135d82ffd2e5facac4bfef0",
"https://deno.land/x/lume@v3.0.2/core/slugifier.ts": "614c35473ea6a5b91b70a0cbd0df87c137e6572cf154cb3e1c5e514f520f9676",
"https://deno.land/x/lume@v3.0.2/core/source.ts": "d4dbe91058369ffaf23778da7e8d8287234f3901eed378accb7933e76529a216",
"https://deno.land/x/lume@v3.0.2/core/utils/cli_options.ts": "ce8731a5e9c23b95217b6967dc4e5c434637a33d16806189acc6a87728b2e649",
"https://deno.land/x/lume@v3.0.2/core/utils/concurrent.ts": "cb0775b3d95f3faa356aa3a3e489dccef8807ed93cc4f84fcf5bc81e87c29504",
"https://deno.land/x/lume@v3.0.2/core/utils/css_urls.ts": "aab446be75151a054524f8f913809dca722bf1da40c174745688208d8513ff53",
"https://deno.land/x/lume@v3.0.2/core/utils/data_values.ts": "589eb8299f7e767a10c2f2c4b9ef03ca9e79ba232b7f22fd151be9d1d68e1dc0",
"https://deno.land/x/lume@v3.0.2/core/utils/date.ts": "3eb0b0e2ea15a95cdfe737be70cd4f48cbe49401928cb04c25a230f411ab2478",
"https://deno.land/x/lume@v3.0.2/core/utils/digest.ts": "445b387983391af73269686292a65bb677119a25a327776885ff1242a9397ad8",
"https://deno.land/x/lume@v3.0.2/core/utils/dom.ts": "fffb0c0c3ae613282e0447c3e4c122a62f44c776771d525a0ca09759883b4b9e",
"https://deno.land/x/lume@v3.0.2/core/utils/dom_links.ts": "f4a197edd4a77b504e82d097613b02684fb5ba73cd415608b913bc658e6ddb28",
"https://deno.land/x/lume@v3.0.2/core/utils/env.ts": "d2440f14ad27e65b0a42b35a52f59ccce0430dd52950bd5df103bb1c9ba1a4a7",
"https://deno.land/x/lume@v3.0.2/core/utils/format.ts": "387a489e505978d87f0a6d591d902bd493ea2c3b8a6a75f768d79c47c31272f2",
"https://deno.land/x/lume@v3.0.2/core/utils/generator.ts": "1e664e9fd4c469e38a0acf5c94fd49dac4f38cb6334563ea4b7fc498b5958877",
@ -415,18 +666,21 @@
"https://deno.land/x/lume@v3.0.2/deps/hex.ts": "828718f24a780ff3ade8d0a8a5b57497cb31c257560ef12af99b6eb1a31e3bbd",
"https://deno.land/x/lume@v3.0.2/deps/highlight.ts": "e8f830a1137ff7e8246ce21518452b8cbf8089db409458c6d9c31040c11d8428",
"https://deno.land/x/lume@v3.0.2/deps/http.ts": "6d9add7c6fe0c0381050aa773ae8590166ccc84c5115d2cde271320c315a110d",
"https://deno.land/x/lume@v3.0.2/deps/icons.ts": "4379e1443d982ab4f85237342d165ae54c981cdb7e06480c222d208999e21f15",
"https://deno.land/x/lume@v3.0.2/deps/init.ts": "05d45af66ebdfe63e43540618f51ece8f99d98dc49de890f10eeb43abe9ed0f3",
"https://deno.land/x/lume@v3.0.2/deps/jsonc.ts": "79f0eddc3c9e593310eb8e5918eb1506b1c7d7816e4ecb96894f634ecbe626ff",
"https://deno.land/x/lume@v3.0.2/deps/lightningcss.ts": "5f5167c6eb306ef759f0043f8f33f2eaf63c69210aa1aa837505e990ee619c46",
"https://deno.land/x/lume@v3.0.2/deps/markdown_it.ts": "24c1c0fd18c99b9067d9ff5d051f934cb7c3446e6afbad934f6268af8d1ceb4d",
"https://deno.land/x/lume@v3.0.2/deps/media_types.ts": "fab5c276f8abd1db34ed7c5ccdc3d88f7a1a075cc1d1156919cab0ef35587afc",
"https://deno.land/x/lume@v3.0.2/deps/minify_html.ts": "4dff2674ed8b4d068a487c46c5f222e910869e21db62f6dc5dc93cff89be30eb",
"https://deno.land/x/lume@v3.0.2/deps/path.ts": "a1a2e0269901d5eb033bfcaef9eab71e761c91edacb184098245b6468123e11d",
"https://deno.land/x/lume@v3.0.2/deps/remove-markdown.ts": "e304dcdd2c1042a1de5b2df53c9c8c39f4462307f95d13e4b2fa1ded26851013",
"https://deno.land/x/lume@v3.0.2/deps/ssx.ts": "2095ddc308fa4736fa91f96a9cd7d4dd3fe1fd70cdf477a13742e02f8818e7d9",
"https://deno.land/x/lume@v3.0.2/deps/tailwindcss.ts": "df89be40eca607d0ba4f4fc8e82957c19dee40eaab59e51eea040ab0ae518b24",
"https://deno.land/x/lume@v3.0.2/deps/toml.ts": "c9eb39b7b5c313d0c83d9b5c3295e22b5cf3dfd730677c305a5466f7dd2d1f8e",
"https://deno.land/x/lume@v3.0.2/deps/vento.ts": "56cfaa39bc2bc8d67f4460a46e29f9174df223dffcb815bda0d8a8cd1cd19f75",
"https://deno.land/x/lume@v3.0.2/deps/xml.ts": "a2171f6ed75576354faa685ebd62b63cf1d4ee518477f295604526416dd27e2f",
"https://deno.land/x/lume@v3.0.2/deps/yaml.ts": "d0f41ff80ce1eee045a87bf055c199b5c6f316571dcad0fff99fba17e34990a2",
"https://deno.land/x/lume@v3.0.2/lint.ts": "4b369361e0cff20a8dfd9e3ff8cb642aa805e7532825ea3a5378eb1f80901fc6",
"https://deno.land/x/lume@v3.0.2/middlewares/logger.ts": "c96f1a9f9d5757555b6f141865ce8551ac176f90c8ee3e9ad797b2b400a9a567",
"https://deno.land/x/lume@v3.0.2/middlewares/no_cache.ts": "0119e3ae3a596ab12c42df693b93e5b03dd9608e289d862242751a9739438f35",
"https://deno.land/x/lume@v3.0.2/middlewares/no_cors.ts": "4d24619b5373c98bcc3baf404db47ba088c87ac8538ea1784e58d197b81d4d02",
@ -434,26 +688,33 @@
"https://deno.land/x/lume@v3.0.2/middlewares/reload.ts": "7639d19e7a92979ac8dd9536040ed8c6c638e08cd75139895cf8e9266c830810",
"https://deno.land/x/lume@v3.0.2/middlewares/reload_client.js": "64dca5eda6e36a0871d237d3006ad5c6b0bba2a6928b314b22d7242fb3bb296f",
"https://deno.land/x/lume@v3.0.2/mod.ts": "4ed2edf622df6109304095952f8a02844f5abc2992b6c9886af632b058f1a8f4",
"https://deno.land/x/lume@v3.0.2/plugins/check_urls.ts": "787e4d9376e76e4a2377236097d43d055d6f030110d70d4e997699f6764312f3",
"https://deno.land/x/lume@v3.0.2/plugins/code_highlight.ts": "ac6327e688e9e8fbd7798bdcc5f76b46d27db3e22ea3b74f545dc3296e8a1261",
"https://deno.land/x/lume@v3.0.2/plugins/esbuild.ts": "74d275124a2cc547fedfa2ae59392b44a475eb31b497dbff0c741179af139515",
"https://deno.land/x/lume@v3.0.2/plugins/extract_date.ts": "38af8e5960d66a74a72977eb19521da4353ab32d3941e97c1526aa3b91175a9e",
"https://deno.land/x/lume@v3.0.2/plugins/feed.ts": "b07aed4cda270cfaacb26f9974dbb962f936dbfde4d770c53e478e4682c791e1",
"https://deno.land/x/lume@v3.0.2/plugins/icons.ts": "c69428254024d694eca34f9b5c4888aedf83d2d9b38f860533952c28cc814333",
"https://deno.land/x/lume@v3.0.2/plugins/inline.ts": "737d7de09d196476b55ecbe7ddb0e651ba2d5d39ca5a418cb15ff48e124907c1",
"https://deno.land/x/lume@v3.0.2/plugins/json.ts": "5c49499e56b919ec848d4118ec97dd4fe0a323a6cc4c648dc45ab55297614c12",
"https://deno.land/x/lume@v3.0.2/plugins/jsx.ts": "952dfe644efc6e4f1bf72f8a68e682d0680fdfb44ee5f868ca6dfd04cf87e77f",
"https://deno.land/x/lume@v3.0.2/plugins/markdown.ts": "7e82d897c1e35bf119dcd18b6aec7a6ba5aa06848897b34ff9cd161ec7c8757e",
"https://deno.land/x/lume@v3.0.2/plugins/minify_html.ts": "f8a817bc43107389d0ce4ce9a048ced06c001407da34e9e2b8ef7a19db90c933",
"https://deno.land/x/lume@v3.0.2/plugins/modify_urls.ts": "9c1b7cc856038d46b64f395065d2852f9b4af94ef9a41c2e9e3021d448b1d3b6",
"https://deno.land/x/lume@v3.0.2/plugins/modules.ts": "4e177c0ffe972b9deef10db2bf0ae52b405418af4dbac03db9e7ffbd6a3ec6ae",
"https://deno.land/x/lume@v3.0.2/plugins/paginate.ts": "6a1a9a24d0fabed2f722a6a6f29d98559219c69475685034181816e82d367f2e",
"https://deno.land/x/lume@v3.0.2/plugins/redirects.ts": "5ae50e20bc32b0e8836920148b25ea3ae057a209b62691a67471fa4a52e6507a",
"https://deno.land/x/lume@v3.0.2/plugins/resolve_urls.ts": "910dbccd25fcacacc72d577a3df37c5f3cc4adce0ec52b2fc8903863c2e2afae",
"https://deno.land/x/lume@v3.0.2/plugins/search.ts": "5acb5be828bbbd012fb9226cb97ec3e370d43d05aa44d16e7e7d50bab368b442",
"https://deno.land/x/lume@v3.0.2/plugins/sitemap.ts": "cd701c4c8c3d3db827781c393a059f0cff98e609f00442b66ac883a1c7c3c08a",
"https://deno.land/x/lume@v3.0.2/plugins/slugify_urls.ts": "8b6ccaae23c2d5f49debf8363e3a6df9fcb60dc66b2d11c3d8b09b89f4261431",
"https://deno.land/x/lume@v3.0.2/plugins/source_maps.ts": "490efa0e103d9133078117f6e855b4b1351292f562c75bda5f3240d45dacbe52",
"https://deno.land/x/lume@v3.0.2/plugins/tailwindcss.ts": "eb17c46f560b4b70a3eb950ec7aad788dc76d3b51b7c0f9aed39435afa93d49d",
"https://deno.land/x/lume@v3.0.2/plugins/toml.ts": "e5bf35ed4915587acd453f002b00ae9b88c1782cadc25c703d7642a390af43ea",
"https://deno.land/x/lume@v3.0.2/plugins/url.ts": "15f2e80b6fcbf86f8795a3676b8d533bab003ac016ff127e58165a6ac3bffc1a",
"https://deno.land/x/lume@v3.0.2/plugins/vento.ts": "908ffbf31864507afa72c506584f2d28c2449b57a339ddfe8a7220eecf082766",
"https://deno.land/x/lume@v3.0.2/plugins/yaml.ts": "d0ebf37c38648172c6b95c502753a3edf60278ab4f6a063f3ca00f31e0dd90cc",
"https://deno.land/x/lume@v3.0.2/types.ts": "5f580502f366b9b25106eb72d49b30d9af7715c8a304fe6e21f382d3c2a4cc38",
"https://deno.land/x/ssx@v0.1.9/css.ts": "39972fa9e375465b82e4fbf735dcc727acc89fdd836f93a395cfb3ccab54e7f0",
"https://deno.land/x/ssx@v0.1.9/html.ts": "5ad7bfd7a6a5b676b2686d406c105bbb02bea537183d95e0c04e76853a9ee155",
"https://deno.land/x/ssx@v0.1.9/jsx-runtime.ts": "d0df99b2a626dbe06d0fc5d968746bb070672365f15e7fdd3b84285843af3148",
"https://deno.land/x/ssx@v0.1.10/css.ts": "39972fa9e375465b82e4fbf735dcc727acc89fdd836f93a395cfb3ccab54e7f0",
"https://deno.land/x/ssx@v0.1.10/html.ts": "5ad7bfd7a6a5b676b2686d406c105bbb02bea537183d95e0c04e76853a9ee155",
"https://deno.land/x/ssx@v0.1.10/jsx-runtime.ts": "f3d37c172698f0b0d7510c2023119264057cbc64a5602d4ca9091e80199a2abe",
"https://deno.land/x/vento@v1.13.0/bare.ts": "b6cdcc245d4626832ab3a7fb4f2885541e997d2806334d8048d39401fa63d50e",
"https://deno.land/x/vento@v1.13.0/deps.ts": "155958dfada8d8cb3c8a001413c759928647b23e0e9db25195614549b58d085f",
"https://deno.land/x/vento@v1.13.0/mod.ts": "53262793b5e0176acdec84aa9c34ed3ecb0c45cc9d396bf34a06ed4ad3d9930a",

130
site.ts Normal file
View file

@ -0,0 +1,130 @@
import lume from "lume/mod.ts";
import extract_date from "lume/plugins/extract_date.ts";
import code_highlight from "lume/plugins/code_highlight.ts";
import redirects from "lume/plugins/redirects.ts";
import tailwindcss from "lume/plugins/tailwindcss.ts";
import resolve_urls from "lume/plugins/resolve_urls.ts";
import slugify_urls from "lume/plugins/slugify_urls.ts";
import check_urls from "lume/plugins/check_urls.ts";
import inline from "lume/plugins/inline.ts";
import feed from "lume/plugins/feed.ts";
import sitemap from "lume/plugins/sitemap.ts";
import minify_html from "lume/plugins/minify_html.ts";
const site_name = "RGBCube";
const site_description =
"The home directory and journal of RGBCube and his work.";
const author = "RGBCube";
const color = "#00FFFF";
const path_assets = "/assets";
const site = lume({
src: "./site",
server: {
debugBar: false,
},
});
site.data("layout", "default.vto");
site.data("site_name", site_name);
site.data("title", site_name);
site.data("description", site_description);
site.data("author", author);
site.data("color", color);
site.add(".");
site.process([".html"], (pages) => {
pages.forEach((page) => {
const document = page.document;
document.querySelectorAll("table").forEach((element) => {
const wrapper = document.createElement("div");
element.classList.add("transform-[rotateX(180deg)]");
wrapper.classList.add(
"transform-[rotateX(180deg)]",
"overflow-x-auto",
);
element.parentNode!.insertBefore(wrapper, element);
wrapper.appendChild(element);
});
document.querySelectorAll("pre code").forEach((code) => {
const element = code.parentElement!;
const wrapper = document.createElement("div");
element.classList.add("transform-[rotateX(180deg)]");
wrapper.classList.add(
"transform-[rotateX(180deg)]",
"overflow-x-auto",
);
element.parentNode!.insertBefore(wrapper, element);
wrapper.appendChild(element);
});
});
});
site.use(extract_date());
site.use(redirects());
site.use(tailwindcss());
site.use(code_highlight());
site.use(resolve_urls());
site.use(slugify_urls({
extensions: "*",
}));
site.use(check_urls({
strict: true,
throw: true,
}));
site.use(feed({
output: ["/blog.rss", "/blog.json"],
query: "type=article",
sort: "date=asc",
limit: Infinity,
info: {
title: site_name,
description: site_description,
authorName: author,
image: `${path_assets}/icons/icon.webp`,
icon: `${path_assets}/icons/icon.webp`,
color,
generator: false,
},
items: {
content: "$ .article-content",
},
}));
site.use(sitemap({
items: {
// @ts-ignore: We don't want lastmods.
lastmod: null,
},
}));
site.use(inline());
site.use(minify_html({
options: {
minify_css: true,
minify_js: true,
},
}));
export default site;

View file

@ -1,71 +0,0 @@
import Cube from "./_includes/cube.tsx";
export const title = "404";
export const viewportFixed = true;
export default (_data: Lume.Data, helpers: Lume.Helpers) => {
const face = (
<>
<div className="frame">
<a href={helpers.url("/", true)}>
404
</a>
</div>
<div className="square black"></div>
<div className="square magenta"></div>
<div className="square magenta"></div>
<div className="square black"></div>
</>
);
return (
<>
<Cube
front={face}
back={face}
left={face}
right={face}
top={face}
bottom={face}
/>
<style
dangerouslySetInnerHTML={{
__html: `
.face {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
box-shadow: 0 0 10px var(--foreground);
}
.square {
width: 100%;
height: 100%;
}
.black {
background-color: black;
}
.magenta {
background-color: magenta;
}
.frame {
position: absolute;
z-index: 99999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: black;
}
`,
}}
>
</style>
</>
);
};

30
site/404.vto Normal file
View file

@ -0,0 +1,30 @@
---
title: <20>
---
<style>
cube-face {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
box-shadow: 0 0 10px var(--foreground);
}
</style>
{{ set cube_face }}
<div class="absolute -z-1 size-[100%] shadow-[0_0_10px_black] dark:shadow-[0_0_10px_white]"></div>
<a class="size-[100%] bg-black hover:bg-[olive]" href={{ "/" |> url(true) }}></a>
<a class="size-[100%] bg-[magenta] hover:bg-[greenyellow]" href={{ "/" |> url(true) }}></a>
<a class="size-[100%] bg-[magenta] hover:bg-[greenyellow]" href={{ "/" |> url(true) }}></a>
<a class="size-[100%] bg-black hover:bg-[olive]" href={{ "/" |> url(true) }}></a>
{{ /set }}
{{ set cube_face_front = cube_face }}
{{ set cube_face_back = cube_face }}
{{ set cube_face_left = cube_face }}
{{ set cube_face_right = cube_face }}
{{ set cube_face_top = cube_face }}
{{ set cube_face_bottom = cube_face }}
{{ include "cube.vto" }}

View file

@ -1,10 +0,0 @@
{
"layout": "base.vto",
"type": "website",
"color": "#00FFFF",
"description": "The official website and link portal of RGBCube and his work.",
"thumbnail": null,
"viewportFixed": false
}

View file

@ -2,13 +2,4 @@
layout: text.vto
---
<div class="content">{{ content }}</div>
{{ if tags.length !== 0 }}
<p>Tags: {{ tags.join(", ") }}</p>
{{ /if }}
<p>
Also, if you are a dinosaur that enjoys good technology, check out my
<a href="/blog.rss">RSS Feed</a>.
</p>
<div class="article-content">{{ content }}</div>

View file

@ -1,165 +0,0 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0{{ viewportFixed ? ', maximum-scale=1.0, user-scalable=0' : '' }}">
<meta name="darkreader-lock">
<title>{{ title }}</title>
<meta property="og:title" content="{{ title }}">
<meta property="og:site_name" content="{{ title }}">
<meta name="twitter:title" content="{{ title }}">
<meta name="description" content="{{ description }}">
<meta property="og:description" content="{{ description }}">
<meta name="twitter:description" content="{{ description }}">
<meta name="theme-color" content="{{ color }}">
<link rel="alternate" type="application/rss+xml" href="/blog.rss">
<link rel="alternate" type="application/feed+json" href="/blog.json">
<meta property="og:type" content="{{ type }}">
<meta property="og:locale" content="en">
<link rel="canonical" href="{{ url |> url(true) }}">
<meta property="og:url" content="{{ url |> url(true) }}">
<meta name="twitter:url" content="{{ url |> url(true) }}">
<meta name="author" content="RGBCube">
<meta property="og:article:author" content="RGBCube">
<meta name="twitter:creator" content="HSVSphere">
{{ if tags.length !== 0 }}
<meta name="keywords" content="{{ tags.join(', ') }}">
<meta property="og:article:tag" content="{{ tags.join(', ') }}">
{{ /if }}
{{ if date }} <!-- For some reason this is always true, even though I do not set it. -->
<meta property="og:article:published_time" content="{{ date }}">
{{ /if }}
{{ if thumbnail }}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{ thumbnail }}">
<meta property="og:image" content="{{ thumbnail }}">
{{ else }}
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/assets/icon.webp">
{{ /if }}
<link rel="icon" href="/assets/icon.gif">
<link rel="apple-touch-icon" href="/assets/icon.webp">
<link rel="preload" as="font" type="font/woff2" href="/assets/BaiJamjureeMedium.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/BaiJamjureeMediumItalic.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/BaiJamjureeBold.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/BaiJamjureeBoldItalic.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/JetBrainsMonoMedium.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/JetBrainsMonoMediumItalic.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/JetBrainsMonoBold.woff2" crossorigin>
<link rel="preload" as="font" type="font/woff2" href="/assets/JetBrainsMonoBoldItalic.woff2" crossorigin>
</head>
<body>
<style>
@font-face {
font-family: "Bai Jamjuree";
font-weight: normal;
src: url("/assets/BaiJamjureeMedium.woff2") format("woff2");
}
@font-face {
font-family: "Bai Jamjuree";
font-style: italic;
font-weight: normal;
src: url("/assets/BaiJamjureeMediumItalic.woff2") format("woff2");
}
@font-face {
font-family: "Bai Jamjuree";
font-weight: bold;
src: url("/assets/BaiJamjureeBold.woff2") format("woff2");
}
@font-face {
font-family: "Bai Jamjuree";
font-style: italic;
font-weight: bold;
src: url("/assets/BaiJamjureeBoldItalic.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-weight: normal;
src: url("/assets/JetBrainsMonoMedium.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-style: italic;
font-weight: normal;
src: url("/assets/JetBrainsMonoMediumItalic.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-weight: bold;
src: url("/assets/JetBrainsMonoBold.woff2") format("woff2");
}
@font-face {
font-family: "JetBrains Mono";
font-style: italic;
font-weight: bold;
src: url("/assets/JetBrainsMonoBoldItalic.woff2") format("woff2");
}
@media (prefers-color-scheme: dark) {
:root {
--background: black;
--foreground: white;
--link: yellow;
}
}
@media (prefers-color-scheme: light) {
:root {
--background: white;
--foreground: black;
--link: red;
}
}
html {
font-family: "Bai Jamjuree";
}
code,
pre {
font-family: "JetBrains Mono";
}
* {
box-sizing: border-box;
position: relative;
min-width: 0;
}
html,
body {
background-color: var(--background);
color: var(--foreground);
height: 100%;
width: 100%;
margin: 0;
}
a {
text-decoration-line: none;
}
</style>
{{ content }}
</body>
</html>

View file

@ -1,117 +0,0 @@
interface CubeProps {
front?: Node;
back?: Node;
left?: Node;
right?: Node;
top?: Node;
bottom?: Node;
}
const Cube = (props: CubeProps) => (
<>
<style
dangerouslySetInnerHTML={{
__html: `
html {
font-size: min(9vw, 9vh, 4.5rem);
overscroll-behavior: none;
}
a {
color: black;
font-weight: bold;
}
.frame {
background-color: white;
width: min-content;
padding: 0 0.3rem;
border-radius: 1rem;
user-select: none;
}
.frame:hover {
background-color: var(--link);
}
.scene {
height: 100dvh;
width: 100dvw;
perspective: 15rem;
display: flex;
align-items: center;
justify-content: center;
}
.cube {
height: 5rem;
width: 5rem;
position: relative;
transform: translateZ(-calc(2.5rem - 1px));
transform-style: preserve-3d;
}
.face {
width: 5rem;
height: 5rem;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
}
.front {
transform: rotateY(0deg) translateZ(calc(2.5rem - 1px));
}
.top {
/* Guess what? Yeah, you guessed right. Safari can't render shit. */
transform: rotateX(89.99999999999999deg) translateZ(calc(2.5rem - 1px));
}
.back {
transform: rotateY(180deg) translateZ(calc(2.5rem - 1px));
}
.bottom {
transform: rotateX(-89.99999999999999deg) translateZ(calc(2.5rem - 1px));
}
.right {
transform: rotateY(89.99999999999999deg) translateZ(calc(2.5rem - 1px));
}
.left {
transform: rotateY(-89.99999999999999deg) translateZ(calc(2.5rem - 1px));
}
`,
}}
>
</style>
<div className="scene">
<div className="cube">
<div className="face front">{props.front}</div>
<div className="face back">{props.back}</div>
<div className="face left">{props.left}</div>
<div className="face right">{props.right}</div>
<div className="face top">{props.top}</div>
<div className="face bottom">{props.bottom}</div>
</div>
</div>
<script src="/assets/cube.js"></script>
</>
);
export default Cube;

259
site/_includes/cube.vto Normal file
View file

@ -0,0 +1,259 @@
<style>
:root {
--cube-width: 5rem;
}
html {
font-size: min(9vw, 9vh, 4.5rem);
}
/* Guess what? Yeah, you guessed right. Safari can't render shit. */
.cube-face-front { transform: rotateY(0deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
.cube-face-top { transform: rotateX( 89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
.cube-face-back { transform: rotateY(180deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
.cube-face-bottom { transform: rotateX(-89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
.cube-face-right { transform: rotateY( 89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
.cube-face-left { transform: rotateY(-89.99999999999999deg) translateZ(calc(var(--cube-width) / 2 - 1px)); }
</style>
<cube-scene class="
h-dvh w-dvw
overscroll-none
flex items-center justify-center
perspective-[calc(var(--cube-width)*3)]
">
<cube-itself class="
size-(--cube-width)
transform-3d transform-[translateZ(-calc(var(--cube-width)/2-1px))]
">
{{> const style = `
size-(--cube-width) absolute
flex items-center justify-center
` }}
<cube-face draggable="false" class="{{ style }} cube-face-front"> {{ cube_face_front }} </cube-face>
<cube-face draggable="false" class="{{ style }} cube-face-back"> {{ cube_face_back }} </cube-face>
<cube-face draggable="false" class="{{ style }} cube-face-left"> {{ cube_face_left }} </cube-face>
<cube-face draggable="false" class="{{ style }} cube-face-right"> {{ cube_face_right }} </cube-face>
<cube-face draggable="false" class="{{ style }} cube-face-top"> {{ cube_face_top }} </cube-face>
<cube-face draggable="false" class="{{ style }} cube-face-bottom"> {{ cube_face_bottom }} </cube-face>
</cube-itself>
</cube-scene>
<script>
"use strict";
const Vec = (x, y, z) => ({
x,
y,
z,
length() {
return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2);
},
scale(factor) {
return Vec(
this.x * factor,
this.y * factor,
this.z * factor,
);
},
normalize() {
let length = this.length();
length = length == 0 ? 1 : length;
return Vec(
this.x / length,
this.y / length,
this.z / length,
);
},
});
Vec.ZERO = Vec(0, 0, 0);
Vec.sum = (a, b) => Vec(
a.x + b.x,
a.y + b.y,
a.z + b.z,
);
Vec.sub = (a, b) => Vec(
a.x - b.x,
a.y - b.y,
a.z - b.z,
);
const Quat = (x, y, z, w) => ({
x,
y,
z,
w,
});
Quat.fromAxis = (axis) => {
const angle = axis.length();
axis = axis.normalize();
const half = angle / 2;
const sinHalf = Math.sin(half);
const cosHalf = Math.cos(half);
const x = axis.x * sinHalf;
const y = axis.y * sinHalf;
const z = axis.z * sinHalf;
const w = cosHalf;
return Quat(x, y, z, w);
};
Quat.mul = (a, b) => Quat(
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
);
const friction = 3;
const sensitivity = 0.01;
// One minute.
const screensaverTimeoutMs = 1 * 60 * 1000;
const mouse = {
down: false,
lastMove: -screensaverTimeoutMs,
previous: Vec.ZERO,
};
const orient = {
element: document.querySelector("cube-itself"),
quat: Quat(0, 0, 0, 1),
set(q) {
this.quat = q;
this.element.style.transform =
`rotate3d(${q.x}, ${q.y}, ${q.z}, ${Math.acos(q.w) * 2}rad)`;
},
get() {
return this.quat;
},
};
let velocity = Vec.ZERO;
let impulseThisFrame = Vec.ZERO;
const handleUp = () => {
mouse.down = false;
};
document.addEventListener("mouseup", handleUp);
document.addEventListener("touchend", handleUp);
const handleDown = (event) => {
mouse.down = true;
velocity = Vec.ZERO;
};
document.addEventListener("mousedown", handleDown);
document.addEventListener("touchstart", handleDown);
const handleMove = (event) => {
// Disables scrolling.
event.preventDefault();
if (!mouse.down) return;
const newMouse = Vec(event.clientX, event.clientY, 0);
const timeDelta = (globalThis.performance.now() - mouse.lastMove) / 1000;
if (timeDelta > 0.1) {
// This is a fresh scroll.
mouse.previous = newMouse;
}
const delta = Vec.sub(newMouse, mouse.previous);
mouse.previous = newMouse;
mouse.lastMove = globalThis.performance.now();
const axis = Vec(-delta.y, delta.x, 0)
.normalize()
.scale(delta.length() * sensitivity);
impulseThisFrame = Vec.sum(impulseThisFrame, axis);
const rotation = Quat.fromAxis(axis);
orient.set(Quat.mul(rotation, orient.get()));
};
document.addEventListener("mousemove", handleMove);
document.addEventListener("touchmove", (event) => {
const delta = event.changedTouches[0];
event.clientX = delta.clientX;
event.clientY = delta.clientY;
handleMove(event);
});
let lastUpdate = 0;
const updateFrame = (timestamp) => {
if (lastUpdate == 0) lastUpdate = timestamp;
const delta = (timestamp - lastUpdate) / 1000;
lastUpdate = timestamp;
if (mouse.down) {
velocity = impulseThisFrame.scale(1 / delta);
impulseThisFrame = Vec.ZERO;
requestAnimationFrame(updateFrame);
return;
}
const decay = Math.exp(-delta * friction);
const effectiveDelta = friction > 0 ? (1 - decay) / friction : delta;
let theta = effectiveDelta * velocity.length();
velocity.x *= decay;
velocity.y *= decay;
velocity.z *= decay;
if (friction > 0 && velocity.length() < 0.00001) {
theta += velocity.length() / friction;
velocity.x = 0;
velocity.y = 0;
velocity.z = 0;
}
if (globalThis.performance.now() - mouse.lastMove > screensaverTimeoutMs) {
const impulse = Vec(0.7, 0.7, -0.7);
velocity = Vec.sum(impulse.scale(effectiveDelta * 3), velocity);
}
const axis = Vec(velocity.x, velocity.y, velocity.z)
.normalize()
.scale(theta);
const rotation = Quat.fromAxis(axis);
orient.set(Quat.mul(rotation, orient.get()));
requestAnimationFrame(updateFrame);
};
updateFrame(0);
</script>

View file

@ -0,0 +1,63 @@
---
layout: null
---
<head>
<!-- CHARSET -->
<meta charset="UTF-8">
<!-- VIEWPORT -->
<meta name="viewport" content="width=device-width,initial-scale=1.0{{ if prevent_zoom }},maximum-scale=1.0,user-scalable=0{{ /if }}">
<!-- NUKE DARKREADER -->
<meta name="darkreader-lock">
<!-- META -->
{{ if title }} <title>{{ title }}</title> {{ /if }}
{{ if description }} <meta name="description" content="{{ description }}"> {{ /if }}
{{ if author }} <meta name="author" content="{{ author }}"> {{ /if }}
{{ if keywords }} <meta name="keywords" content="{{ keywords.join(",") }}"> {{ /if }}
<!-- FANCY -->
<link rel="icon" href="/assets/icons/icon.gif">
<meta name="theme-color" content="{{ color }}">
<!-- ALTERNATIVE FORMATS -->
<link rel="alternate" type="application/rss+xml" href="/blog.rss">
<link rel="alternate" type="application/feed+json" href="/blog.json">
<!-- CANONICAL URL -->
<link rel="canonical" href="{{ url |> url(true) }}">
<!-- OPENGRAPH CONTAINMENT ZONE -->
{{ if title }} <meta property="og:title" name="title" content="{{ title }}"> {{ /if }}
{{ if description}} <meta property="og:description" content="{{ description }}"> {{ /if }}
<meta property="og:type" content="{{ type ?? "website" }}">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="{{ site_name }}">
<meta property="og:url" content="{{ url |> url(true) }}">
{{ if thumbnail }}
<meta property="og:image" name="image" content="{{ thumbnail |> url(true) }}">
{{ else }}
<meta property="og:image" name="image" content="{{ "/assets/icons/icon.webp" |> url(true) }}">
{{ /if }}
<!-- TWITTER CONTAINMENT ZONE -->
{{ if title }} <meta name="twitter:title" content="{{ title }}"> {{ /if }}
<meta name="twitter:creator" content="HSVSphere">
{{ if thumbnail }}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{ thumbnail |> url(true) }}">
{{ else }}
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="{{ "/assets/icons/icon.webp" |> url(true) }}">
{{ /if }}
<!-- STYLES -->
<link href="/assets/css/fonts.css" rel="stylesheet" inline>
<link href="/assets/css/default.css" rel="stylesheet" inline>
</head>
<body class="bg-white text-black dark:bg-black dark:text-white">
{{ content }}
</body>

View file

@ -1,196 +1,47 @@
---
layout: base.vto
layout: default.vto
---
<style>
/* Centering */
html,
body {
display: flex;
justify-content: center;
}
<div class="flex justify-center">
<div class="block text-xl w-[min(100vw,50rem)]">
.centered {
font-size: large;
<nav class="
transform-[rotateX(180deg)]
text-black text-2xl font-bold
absolute w-[inherit] z-999
overflow-x-auto
">
<div class="transform-[rotateX(180deg)] flex items-start justify-evenly">
{{> const style = `
flex-auto text-center px-3 pt-3 pb-2
bg-white font-[ecrou] border-2 border-black
origin-bottom
md:hover:text-[300%] ease-[cubic-bezier(1,-0.07,0.57,1.56)] md:duration-200
display: initial;
width: min(100vw - 2rem, 50rem);
}
md:hover:not-active:after:content-['?']
md:active:after:content-['!!'] active:after:italic
/* Make wrapping pretty */
h1,
h2,
h3,
h4 {
text-wrap: balance;
}
p {
text-wrap: pretty;
}
/* Rotate nav, tables and codeblocks so the scrollbar is at the top */
.rotated {
transform: rotateX(180deg);
}
/* Make tables and other elements scroll horizontally */
.overflow {
overflow-x: auto;
}
/* Style nav */
nav {
font-size: larger;
word-break: normal;
overflow-wrap: normal;
overflow-x: auto;
background-color: white;
padding: 0.3rem 0.6rem;
/* Rotated 180deg so it's top instead of bottom. */
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
}
@media (prefers-color-scheme: light) {
nav {
border: 0.15rem solid black;
border-bottom-width: 0;
}
}
nav a {
color: black;
font-weight: bold;
margin-right: 0.6rem;
}
/* Make images fit */
p:has(img) {
display: flex;
justify-content: center;
}
img {
max-width: 100%;
height: auto;
}
/* Style content */
.content {
overflow-wrap: break-word;
}
a {
color: var(--link);
}
a:hover {
font-style: italic;
}
blockquote {
border-left: 0.15rem solid var(--foreground);
padding: 0.05rem 1rem;
margin: 1.3rem 1rem;
}
@media (prefers-color-scheme: dark) {
blockquote {
background-color: #222;
}
}
@media (prefers-color-scheme: light) {
blockquote {
background-color: #EEE;
}
}
/* Style tables */
table {
border-collapse: collapse;
white-space: nowrap;
}
/* Doesn't seem to work with the scrolling? */
/* thead {
position: sticky;
top: 0;
} */
th, td {
border: 0.15rem solid var(--foreground);
padding: 0.3rem;
}
th {
background-color: var(--foreground);
color: var(--background);
}
/* Codeblocks */
.rotated:has(pre) {
padding: 0.6rem;
border: 0.15rem solid var(--foreground);
}
pre {
margin: 0;
}
@media (prefers-color-scheme: dark) {
.hljs-attr { color: lightblue; }
.hljs-built_in { color: firebrick; }
.hljs-keyword { color: firebrick; }
.hljs-number { color: mediumslateblue; }
.hljs-string { color: limegreen; }
.hljs-title { color: lightcoral; }
.hljs-type { color: aquamarine; }
}
@media (prefers-color-scheme: light) {
.hljs-attr { color: darkblue; }
.hljs-built_in { color: darkred; }
.hljs-keyword { color: darkred; }
.hljs-number { color: darkslateblue; }
.hljs-string { color: darkgreen; }
.hljs-title { color: darkgoldenrod; }
.hljs-type { color: darkcyan; }
}
/* The end */
hr {
border: 0.15rem solid var(--foreground);
}
footer {
display: flex;
justify-content: center;
font-size: small;
margin-bottom: 1rem;
padding-top: 0.5rem;
}
</style>
<div class="centered">
<nav class="rotated">
<div class="rotated">
<a href="/">HOME</a>
<a href="/about">ABOUT</a>
<a href="/blog">BLOG</a>
<a href="/contact">CONTACT</a>
</div>
</nav>
nuclear
` }}
<style>.right-delete:has(+ *:hover) { border-right-width: 0; }</style>
<a class="nav-link {{ style }} right-delete" href="/">home</a>
<a class="nav-link {{ style }} right-delete not-hover:border-l-0" href="/about/">about</a>
<a class="nav-link {{ style }} right-delete not-hover:border-l-0" href="/blog/">blog</a>
<a class="nav-link {{ style }} not-hover:border-l-0" href="/contact/">contact</a>
</div>
</nav>
{{> const padding = 4 }} <!-- Keep in sync with -mx-N in default.css. -->
<div class="text-content p-{{ padding }} pt-{{ padding + 12 }}">
{{ content }}
<hr>
<footer>Copyright {{ new Date().getFullYear() }} © RGBCube</footer>
</div>
<hr class="border-2 border-black dark:border-white">
<footer class="flex justify-center text-sm pt-1 pb-2 wrap-anywhere">
Copyright {{ Temporal.Now.plainDateISO().year }} ©
<a href="/"><img class="pl-0.5 pt-0.25 size-5" src="/assets/icons/icon.gif" alt="RGBCube"></a>
</footer>
</div>
</div>

View file

@ -1,31 +1,10 @@
---
layout: text.vto
title: About
title: about:rgbcube
---
## Hi.
<div class="shake">
I'm yet another high schooler that is interested in programming. I'm from
Türkiye 🇹🇷.
# [TODO](#)
I primarily use [Rust](https://rust-lang.org) and also know quite a bit of
Python, [**Nix**](https://nixos.org/), [Nushell](https://nushell.sh/), a little
bit of Java, Kotlin, Go, and JavaScript (No frameworks, though!).
I created this site using [Lume](https://lume.land/). It is served by Nginx on
my small VPS that runs [NixOS](https://nixos.org/).
I also host other services like Synapse (Matrix homeserver), Forgejo, Nextcloud
and Grafana on the VPS, which are all configured using Nix.
Historically, this blog was made using Rust, [Axum](https://lib.rs/crates/axum),
[Maud](https://maud.lambda.xyz/) and a bunch of other neat crates (some which I
created, like [embd-rs](https://github.com/RGBCube/embd-rs), which sped up
development). But I decided to abandon this strategy as I was reinventing too
much for just a simple static website. Development was also _really_ slow on a
i5 from 2015 so I decided to ditch it and use Lume.
Here is the up to date
[GitHub repository for said site](https://github.com/RGBCube/Site), and here is
the
[historical version written in Rust](https://github.com/RGBCube/Site/tree/rust-legacy).
</div>

Binary file not shown.

Binary file not shown.

Binary file not shown.

256
site/assets/css/default.css Normal file
View file

@ -0,0 +1,256 @@
@import "tailwindcss";
@theme {
--font-sans: "Exo 2";
--font-serif: "Exo 2";
--font-mono: "Ubuntu Mono";
@keyframes blink {
0%, 100% {
opacity: 100%;
}
50% {
opacity: 0%;
}
}
--animate-blink: blink 0.2s steps(1) infinite;
@keyframes blink-red-white {
0%, 100% {
background-color: red;
}
50% {
background-color: white;
}
}
--animate-blink-red-white: blink-red-white 0.2s steps(1) infinite;
@keyframes to-the-future {
0% {
transform: skewX(0deg);
}
100% {
transform: skewX(-89.9deg);
}
}
--animate-to-the-future: to-the-future 50ms cubic-bezier(
0.16,
0.56,
0.44,
0.93
) 1;
@keyframes shake-x {
0%, 100% {}
50% {
transform: translateX(4px);
}
}
--animate-shake-x: shake-x 0.07s linear infinite;
@keyframes shake-y {
0%, 100% {}
50% {
transform: translateY(4px);
}
}
--animate-shake-y: shake-y 0.08s linear infinite;
@keyframes slide-down-shake {
0% {
transform: translateY(-100%);
}
70% {
transform: translateY(0);
}
75% {
transform: translateY(0) translateX(2px);
}
80% {
transform: translateY(0) translateX(-2px);
}
85% {
transform: translateY(0) translateX(1px);
}
90% {
transform: translateY(0) translateX(-1px);
}
95% {
transform: translateY(0) translateX(0.5px);
}
100% {
transform: translateY(0) translateX(0);
}
}
--animate-slide-down-shake: slide-down-shake 0.8s linear forwards;
}
.shake {
@apply animate-shake-x;
& > * {
@apply animate-shake-y;
}
}
.nuclear {
&:active {
@apply animate-blink-red-white text-white;
-webkit-text-stroke: 0.05rem black;
}
&:hover {
@apply text-white;
-webkit-text-stroke: 0.05rem black;
&:not(:active) {
background: repeating-linear-gradient(
45deg,
yellow 0rem,
yellow 0.625rem,
black 0.625rem,
black 1.25rem
);
}
}
}
.text-content {
@apply space-y-3;
* {
@apply wrap-break-word text-pretty;
&:not(ol, ul) {
@apply space-y-3;
}
}
h1, h2, h3, h4, h5, h6 {
@apply text-balance before:pr-2 font-bold;
}
h1 {
@apply text-4xl before:content-["#"];
}
h2 {
@apply text-3xl before:content-["##"];
}
h3 {
@apply text-2xl before:content-["###"];
}
h4 {
@apply text-xl before:content-["####"];
}
p {
&:has(img) {
@apply flex justify-center;
}
}
a {
@apply inline-block wrap-anywhere text-[red] dark:text-[yellow] px-1 pb-0.75
border-2 border-[transparent] border-dashed;
* {
@apply wrap-anywhere;
}
&:hover {
@apply border-[red] dark:border-[yellow];
}
&:active {
@apply border-[fuchsia] dark:border-[springgreen] animate-to-the-future;
}
}
table {
@apply border-collapse whitespace-nowrap;
}
th, td {
@apply p-1 border-2;
}
th {
@apply bg-black text-white border-black dark:bg-white dark:text-black
dark:border-white;
}
td {
@apply border-black dark:border-white;
}
pre:has(> code) {
@apply px-3 py-2;
}
div:has(> pre code) {
@apply border-2 border-black dark:border-white;
}
li {
@apply relative pl-4;
&::before {
@apply content-[""] absolute left-0 size-2 top-1/2 -translate-y-1/3
rotate-45 border-t-2 border-r-2 border-black dark:border-white;
}
&:hover {
&::before {
@apply size-4 -translate-x-2/3 border-[red] dark:border-[yellow];
}
}
}
hr {
@apply border-1 border-black dark:border-white
-mx-4; /* Keep in sync with p-N in text.vto. */
}
blockquote {
@apply border-l-2 pl-4 py-2 border-black bg-[#eee] dark:border-white
dark:bg-[#222];
}
.hljs-attr {
@apply text-[darkblue] dark:text-[lightblue];
}
.hljs-built_in {
@apply text-[darkred] dark:text-[firebrick];
}
.hljs-comment {
@apply italic text-[dimgray] dark:text-[darkgray];
}
.hljs-keyword {
@apply text-[darkred] dark:text-[firebrick];
}
.hljs-number {
@apply text-[darkslateblue] dark:text-[mediumslateblue];
}
.hljs-string {
@apply text-[darkgreen] dark:text-[limegreen];
}
.hljs-symbol {
@apply text-[darkgoldenrod] dark:text-[gold];
}
.hljs-title {
@apply text-[indianred] dark:text-[lightcoral];
}
.hljs-type {
@apply text-[darkcyan] dark:text-[aquamarine];
}
}

595
site/assets/css/fonts.css Normal file
View file

@ -0,0 +1,595 @@
@font-face {
font-family: "Exo 2";
font-style: italic;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-cyrillic-ext-italic.woff2") format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Exo 2";
font-style: italic;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-cyrillic-italic.woff2") format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Exo 2";
font-style: italic;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-vietnamese-italic.woff2") format("woff2");
unicode-range:
U+0102-0103,
U+0110-0111,
U+0128-0129,
U+0168-0169,
U+01A0-01A1,
U+01AF-01B0,
U+0300-0301,
U+0303-0304,
U+0308-0309,
U+0323,
U+0329,
U+1EA0-1EF9,
U+20AB;
}
@font-face {
font-family: "Exo 2";
font-style: italic;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-latin-ext-italic.woff2") format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Exo 2";
font-style: italic;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-latin-italic.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "Exo 2";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-cyrillic-ext-normal.woff2") format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Exo 2";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-cyrillic-normal.woff2") format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Exo 2";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-vietnamese-normal.woff2") format("woff2");
unicode-range:
U+0102-0103,
U+0110-0111,
U+0128-0129,
U+0168-0169,
U+01A0-01A1,
U+01AF-01B0,
U+0300-0301,
U+0303-0304,
U+0308-0309,
U+0323,
U+0329,
U+1EA0-1EF9,
U+20AB;
}
@font-face {
font-family: "Exo 2";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-latin-ext-normal.woff2") format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Exo 2";
font-style: normal;
font-weight: 100 900;
font-display: block;
src: url("/assets/fonts/Exo_2-latin-normal.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url(/assets/fonts/Ubuntu_Mono-italic-400-cyrillic-ext.woff2)
format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-400-cyrillic.woff2")
format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-400-greek-ext.woff2")
format("woff2");
unicode-range: U+1F00-1FFF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-400-greek.woff2") format("woff2");
unicode-range:
U+0370-0377,
U+037A-037F,
U+0384-038A,
U+038C,
U+038E-03A1,
U+03A3-03FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-400-latin-ext.woff2")
format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-400-latin.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-cyrillic-ext.woff2")
format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-cyrillic.woff2")
format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-greek-ext.woff2")
format("woff2");
unicode-range: U+1F00-1FFF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-greek.woff2") format("woff2");
unicode-range:
U+0370-0377,
U+037A-037F,
U+0384-038A,
U+038C,
U+038E-03A1,
U+03A3-03FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-latin-ext.woff2")
format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: italic;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-italic-700-latin.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-cyrillic-ext.woff2")
format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-cyrillic.woff2")
format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-greek-ext.woff2")
format("woff2");
unicode-range: U+1F00-1FFF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-greek.woff2") format("woff2");
unicode-range:
U+0370-0377,
U+037A-037F,
U+0384-038A,
U+038C,
U+038E-03A1,
U+03A3-03FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-latin-ext.woff2")
format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 400;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-400-latin.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-cyrillic-ext.woff2")
format("woff2");
unicode-range:
U+0460-052F,
U+1C80-1C8A,
U+20B4,
U+2DE0-2DFF,
U+A640-A69F,
U+FE2E-FE2F;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-cyrillic.woff2")
format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-greek-ext.woff2")
format("woff2");
unicode-range: U+1F00-1FFF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-greek.woff2") format("woff2");
unicode-range:
U+0370-0377,
U+037A-037F,
U+0384-038A,
U+038C,
U+038E-03A1,
U+03A3-03FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-latin-ext.woff2")
format("woff2");
unicode-range:
U+0100-02BA,
U+02BD-02C5,
U+02C7-02CC,
U+02CE-02D7,
U+02DD-02FF,
U+0304,
U+0308,
U+0329,
U+1D00-1DBF,
U+1E00-1E9F,
U+1EF2-1EFF,
U+2020,
U+20A0-20AB,
U+20AD-20C0,
U+2113,
U+2C60-2C7F,
U+A720-A7FF;
}
@font-face {
font-family: "Ubuntu Mono";
font-style: normal;
font-weight: 700;
font-display: block;
src: url("/assets/fonts/Ubuntu_Mono-normal-700-latin.woff2") format("woff2");
unicode-range:
U+0000-00FF,
U+0131,
U+0152-0153,
U+02BB-02BC,
U+02C6,
U+02DA,
U+02DC,
U+0304,
U+0308,
U+0329,
U+2000-206F,
U+20AC,
U+2122,
U+2191,
U+2193,
U+2212,
U+2215,
U+FEFF,
U+FFFD;
}
@font-face {
font-family: "ecrou";
font-display: block;
src: url("/assets/fonts/ecrou.woff2") format("woff2");
}

View file

@ -1,241 +0,0 @@
"use strict";
class Vec3 {
x: number;
y: number;
z: number;
constructor(x: number, y: number, z: number) {
this.x = x;
this.y = y;
this.z = z;
}
static zero() {
return new Vec3(0, 0, 0);
}
length() {
return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2);
}
scale(factor: number) {
this.x *= factor;
this.y *= factor;
this.z *= factor;
return this;
}
normalize() {
const length = this.length();
if (length != 0) {
this.x /= length;
this.y /= length;
this.z /= length;
}
return this;
}
static sub(v: Vec3, t: Vec3) {
return new Vec3(
v.x - t.x,
v.y - t.y,
v.z - t.z,
);
}
static sum(v: Vec3, t: Vec3) {
return new Vec3(
v.x + t.x,
v.y + t.y,
v.z + t.z,
);
}
}
class Quat {
x: number;
y: number;
z: number;
w: number;
constructor(x: number, y: number, z: number, w: number) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
static fromAxis(axis: Vec3) {
const angle = axis.length();
axis.normalize();
const half = angle / 2;
const sinHalf = Math.sin(half);
const cosHalf = Math.cos(half);
const x = axis.x * sinHalf;
const y = axis.y * sinHalf;
const z = axis.z * sinHalf;
const w = cosHalf;
return new Quat(x, y, z, w);
}
static mul(q: Quat, r: Quat) {
return new Quat(
q.w * r.x + q.x * r.w + q.y * r.z - q.z * r.y,
q.w * r.y - q.x * r.z + q.y * r.w + q.z * r.x,
q.w * r.z + q.x * r.y - q.y * r.x + q.z * r.w,
q.w * r.w - q.x * r.x - q.y * r.y - q.z * r.z,
);
}
}
const friction = 3;
const sensitivity = 0.01;
const mouse = {
down: false,
lastMove: -10000,
previous: Vec3.zero(),
};
const orient = {
__cube: document.querySelector(".cube"),
__value: new Quat(0, 0, 0, 1),
set(value: Quat) {
this.__value = value;
const q = this.__value;
// @ts-ignore: Style will never be null.
this.__cube.style.transform = `rotate3d(${q.x}, ${q.y}, ${q.z}, ${
Math.acos(q.w) * 2
}rad)`;
},
get(): Quat {
return this.__value;
},
};
let velocity = Vec3.zero();
let impulseThisFrame = Vec3.zero();
const handleUp = () => {
mouse.down = false;
};
document.addEventListener("mouseup", handleUp);
document.addEventListener("touchend", handleUp);
const handleDown = (event: MouseEvent | TouchEvent) => {
// Disables link dragging that occurs when spinning.
event.preventDefault();
mouse.down = true;
velocity = Vec3.zero();
};
document.addEventListener("mousedown", handleDown);
document.addEventListener("touchstart", handleDown);
const handleMove = (event: MouseEvent) => {
// Disables scrolling.
event.preventDefault();
if (!mouse.down) return;
const newMouse = new Vec3(event.clientX, event.clientY, 0);
const timeDelta = (globalThis.performance.now() - mouse.lastMove) / 1000;
if (timeDelta > 0.1) {
// This is a fresh scroll.
mouse.previous = newMouse;
}
const delta = Vec3.sub(newMouse, mouse.previous);
mouse.previous = newMouse;
mouse.lastMove = globalThis.performance.now();
const axis = new Vec3(-delta.y, delta.x, 0)
.normalize()
.scale(delta.length() * sensitivity);
impulseThisFrame = Vec3.sum(impulseThisFrame, axis);
const rotation = Quat.fromAxis(axis);
orient.set(Quat.mul(rotation, orient.get()));
};
document.addEventListener("mousemove", handleMove);
document.addEventListener("touchmove", (event) => {
const delta = event.changedTouches[0];
// @ts-ignore: We are overriding this for it to work as a MouseEvent.
event.clientX = delta.clientX;
// @ts-ignore:
event.clientY = delta.clientY;
handleMove(event as object as MouseEvent);
});
let lastUpdate = 0;
const updateFrame = (timestamp: number) => {
if (lastUpdate == 0) lastUpdate = timestamp;
const delta = (timestamp - lastUpdate) / 1000;
lastUpdate = timestamp;
if (mouse.down) {
velocity = impulseThisFrame.scale(1 / delta);
impulseThisFrame = Vec3.zero();
} else {
const decay = Math.exp(-delta * friction);
const effectiveDelta = friction > 0 ? (1 - decay) / friction : delta;
let theta = effectiveDelta * velocity.length();
velocity.x *= decay;
velocity.y *= decay;
velocity.z *= decay;
if (friction > 0 && velocity.length() < 0.00001) {
theta += velocity.length() / friction;
velocity.x = 0;
velocity.y = 0;
velocity.z = 0;
}
if (globalThis.performance.now() - mouse.lastMove > 10000) {
const impulse = new Vec3(0.7, 0.7, -0.7);
velocity = Vec3.sum(impulse.scale(effectiveDelta * 3), velocity);
}
const axis = new Vec3(velocity.x, velocity.y, velocity.z)
.normalize()
.scale(theta);
const rotation = Quat.fromAxis(axis);
orient.set(Quat.mul(rotation, orient.get()));
}
requestAnimationFrame(updateFrame);
};
updateFrame(0);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 402 KiB

After

Width:  |  Height:  |  Size: 402 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -1,21 +1,20 @@
---
layout: text.vto
title: Blog
title: about:blog
---
<h1>Blog Articles</h1>
<h1>Blog Articles
<a class="-translate-y-4 text-sm font-[ecrou] pt-1 -ml-2" href="/blog.rss">rss</a>
<a class="-translate-y-4 text-sm font-[ecrou] pt-1 -ml-3" href="/blog.json">json</a>
</h1>
Are you old? Then you might want to check out my super cool
<a href="/blog.rss">RSS Feed</a> too!
<p>Here is where I dump all my schizophenic and sometimes coherent ramblings. Take a look!</p>
<ul>
{{ for article of search.pages("type=article", "order=asc date=desc")}}
<li>
<p>
<a href="{{ article.url }}">{{ article.date.toISOString().slice(0, 10) }}</a>:
{{ article.title }}
</p>
<code><a href="{{ article.url }}">{{ article.date.toISOString().slice(0, 10) }}</a></code>
<div class="inline-block">{{ article.title |> md }}</div>
</li>
{{ /for }}
</ul>

View file

@ -1,6 +0,0 @@
{
"layout": "article.vto",
"type": "article",
"description": null
}

4
site/blog/_data.ts Normal file
View file

@ -0,0 +1,4 @@
export default {
layout: "article.vto",
type: "article",
};

View file

@ -4,7 +4,7 @@ description: Or how I missed the school bus because of a cosmic ray.
date: 2024-04-02
tags:
keywords:
- time
- unix-timestamps
---
@ -54,11 +54,11 @@ Maybe the 11th bit got flipped, making it increment 1024?
Aha! So the 11th bit got flipped by something. And that something was probably a
cosmic ray.
EDIT: It was not a cosmic ray. As pointed out by
[@BenjaminRi's comment on lobste.rs](https://lobste.rs/s/jb1o6q/cosmic_drift#c_1ztluj)
it was either a bug or storage corruption as the alarm ran late the next day.
You should still create more than one alarm just in case if you are using a
phone prone to this, however.
> **EDIT:** It was not a cosmic ray. As pointed out by
> [@BenjaminRi's comment on lobste.rs](https://lobste.rs/s/jb1o6q/cosmic_drift#c_1ztluj)
> it most likely was either a bug or storage corruption as the alarm ran late
> the next day. You should still create more than one alarm just in case if you
> are using a phone prone to this, however.
My main takeaway from this event is to create more than one alarm, for extra
redundancy. Who knew being prone to sleeping in could save you from your alarm

View file

@ -1,13 +1,13 @@
---
title: .gitignore is inherently Sisyphean
title: "`.gitignore` is inherently Sisyphean"
description: And how to roll the rock over the edge.
color: "#A5804C"
thumbnail: /assets/sisyphus-ds-store.webp
thumbnail: /assets/images/sisyphus-ds-store.webp
date: 2024-09-30
tags:
keywords:
- vcs
---
@ -17,7 +17,7 @@ You just started a new project. You ran `cargo init`, `poetry init` and
Those commands created the necessary files to work, it also added the following
lines to your .gitignore:
```text
```ignore
target
__pycache__
bin
@ -36,12 +36,12 @@ You start reviewing the code and notice a file quite out of place: `.DS_Store`.
You ask the person what it is, he says he has no clue.
![Hundreds of thousands of merge requests on GitHub trying
to gitignore .DS_Store](/assets/github-ds-store-mr-list.webp)
to gitignore .DS_Store](/assets/images/github-ds-store-mr-list.webp)
Whatever. You just delete the file from the branch and add the file's name to
the repositories gitignore:
```text
```ignore
target
__pycache__
bin
@ -56,7 +56,7 @@ request. You look at it, and see that there is a whole directory that is
irrelevant. You tell that person to delete the directory from the branch and add
it to the gitignore. The gitignore lives on:
```text
```ignore
target
__pycache__
bin
@ -67,7 +67,7 @@ bin
Then, someone that uses IntelliJ IDEA commits five hundred XML files and the
`.idea` directory. You repeat this process:
```text
```ignore
target
__pycache__
bin
@ -84,7 +84,7 @@ Hell. You feel like a mythic god undergoing punishment for cheating death and
deceiving the underworld.
![Sisyphus pushing up a boulder that has .DS_Store written
on it](/assets/sisyphus-ds-store.webp)
on it](/assets/images/sisyphus-ds-store.webp)
How do you escape this endless loop of ignoring files that sneak in? Maybe by
educating every single merge request author? Nope, that definitely won't work,
@ -95,7 +95,7 @@ Luckily, you realize that you can turn the blacklist of files (the gitignore) to
a whitelist, by just ignoring everything and manually un-ignoring desired files.
You change your gitignore to this:
```text
```ignore
*
!.gitignore

View file

@ -4,7 +4,7 @@ description: How the absolutely cursed HTMNIX project works.
date: 2024-03-04
tags:
keywords:
- html
- nix
---
@ -26,9 +26,6 @@ snippet that uses it:
<.html>
```
> (hightlight.js shits the bed while highlighting this abomination - just ignore
> it)
You are probably thinking furiously right now, maybe you've noticed something:
> Aha! In Nix, `<foo>` is used to find stuff from the Nix path like so:
@ -45,8 +42,8 @@ You are somewhat correct. But not quite.
Nix `<foo>` expressions actually boil down to a call of the builtin
`__findFile`, like so:
```shell
nix-instantiate --parse --expr "<foo>"
```nix
# nix-instantiate --parse --expr "<foo>"
(__findFile __nixPath "foo")
```

View file

@ -5,13 +5,13 @@ description: And revealing how cursed Nix is.
date: 2024-04-15
draft: true
tags:
keywords:
- nix
---
I was surfing the web a few weeks ago, and I came across this iceberg chart:
![The Nix Iceberg](/assets/nix-iceberg.webp)
![The Nix Iceberg](/assets/images/nix-iceberg.webp)
[Here's the original source for this image,
created by @leftpaddotpy, @puckipedia,
@ -262,7 +262,7 @@ allows flakes to be configured in "flake compile time". Let's say you have a
flake that provides a binary. Let's also assume you can run it with the
following Nix CLI invokation:
```shell
```sh
nix run github:me/hello-world
```
@ -292,7 +292,7 @@ is an ugly hack. You can do this in your flake:
And override the `debug-mode` input like so, to run a debug binary instead:
```shell
```sh
nix run github:me/hello-world --override debug-mode github:boolean-option/true
```
@ -502,7 +502,7 @@ This syntax is a way to check for the existence of a key in an attribute set.
<h2>
```shell
```sh
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3
```
@ -515,7 +515,7 @@ You can use nix-shell as a script interpreter to allow scripts written in
arbitrary languages to obtain their own dependencies via Nix. This is done by
starting the script with the following lines:
```shell
```sh
#!/usr/bin/env nix-shell
#!nix-shell -i real-interpreter --packages packages
```

View file

@ -1,10 +1,10 @@
---
title: Swap the ı and i key on your keyboard for faster modal editing
title: Swap the `ı` and `i` key on your keyboard for faster modal editing
description: How to swap the ı and i key on your Turkish keyboard on Linux.
date: 2024-05-20
tags:
keywords:
- localisation
- modal-editors
---
@ -12,7 +12,7 @@ tags:
If you have ever used a Turkish-Q keyboard in combination with a modal editor
before, you might have noticed that the `i` key is pretty far off to the side:
![The placement of the `i` key on the Turkish-Q layout](/assets/turkish-q-i.webp)
![The placement of the `i` key on the Turkish-Q layout](/assets/images/turkish-q-i.webp)
This blog post will guide you on how to swap the `ı` key with the `i` key (but
not the `I` and `İ` keys). This will be a great change if you write primarily in
@ -119,7 +119,7 @@ This is how it is done on NixOS:
And this is how it is done on Arch:
```shell
```sh
cat << :end
include "/usr/share/kbd/keymaps/i386/qwerty/trq.map"

View file

@ -1,16 +1,38 @@
---
layout: text.vto
title: Contact
title: about:telecommunication
---
You can contact me via:
- Discord: `rgbcube` or `RGBCube#4777`
- E-Mail: [`contact@rgbcu.be`](mailto:contact@rgbcu.be)
- Matrix: [`@rgbcube:rgbcu.be`](https://matrix.to/#/@rgbcube:rgbcu.be)
- Matrix (preferred):
[`@rgbcube:rgbcu.be`](https://matrix.to/#/@rgbcube:rgbcu.be)
- Discord: [`rgbcube`](https://discord.com/users/512640455834337290)
- E-Mail: <a id="bot-block">`contact[at][this-web-site]`</a>
Here are some other useful links as well:
- [GitHub](https://github.com/RGBCube)
- [Twitch](https://www.twitch.tv/rgbcube)
- [X](https://x.com/HSVSphere)
<script>
const real = [
[20, 22], // ma
[18, 20], // il
[16, 18], // to
[22, 23], // :
[12, 15], // con
[8, 12], // tact
[15, 16], // @
[4, 7], // rgb
[12, 13], // cu
[0, 1], // .
[2, 4], // be
].map(([start, end]) => ".ubergbetactcon@toilma:".substring(start, end))
.join("");
const element = document.getElementById("bot-block");
element.href = real;
element.children[0].innerHTML = real.substring(7);
</script>

View file

@ -1,105 +0,0 @@
import Cube from "./_includes/cube.tsx";
export const title = "RGBCube";
export const viewportFixed = true;
export default (
<>
<Cube
front={
<a href="/about">
<div className="frame">about</div>
</a>
}
top={
<a href="https://github.com/RGBCube">
<div className="frame">github</div>
</a>
}
right={
<a href="/contact">
<div className="frame">contact</div>
</a>
}
left={
<a href="/blog">
<div className="frame">blog</div>
</a>
}
/>
<style
dangerouslySetInnerHTML={{
__html: `
.face::after {
z-index: -1;
content: "";
height: inherit;
width: inherit;
position: absolute;
}
/* I do not regret writing this. It's beautiful. */
.front {
background: linear-gradient(to bottom, cyan, blue);
}
.front::after {
background: linear-gradient(to bottom, white, magenta);
mask-image: linear-gradient(to left, magenta, transparent);
}
.top {
background: linear-gradient(to bottom, lime, cyan);
}
.top::after {
background: linear-gradient(to bottom, yellow, white);
mask-image: linear-gradient(to left, white, transparent);
}
.back {
background: linear-gradient(to bottom, yellow, red);
}
.back::after {
background: linear-gradient(to bottom, lime, black);
mask-image: linear-gradient(to left, black, transparent);
}
.bottom {
background: linear-gradient(to bottom, blue, black);
}
.bottom::after {
background: linear-gradient(to bottom, magenta, red);
mask-image: linear-gradient(to left, red, transparent);
}
.right {
background: linear-gradient(to bottom, white, magenta);
}
.right::after {
background: linear-gradient(to bottom, yellow, red);
mask-image: linear-gradient(to left, red, transparent);
}
.left {
background: linear-gradient(to bottom, lime, black);
}
.left::after {
background: linear-gradient(to bottom, cyan, blue);
mask-image: linear-gradient(to left, blue, transparent);
}
`,
}}
>
</style>
</>
);

90
site/index.vto Normal file
View file

@ -0,0 +1,90 @@
<style>
cube-face::after {
z-index: -1;
content: "";
height: inherit;
width: inherit;
position: absolute;
}
.cube-face-front {
background: linear-gradient(to bottom, cyan, blue);
&::after {
background: linear-gradient(to bottom, white, magenta);
mask-image: linear-gradient(to left, magenta, transparent);
}
}
.cube-face-top {
background: linear-gradient(to bottom, lime, cyan);
&::after {
background: linear-gradient(to bottom, yellow, white);
mask-image: linear-gradient(to left, white, transparent);
}
}
.cube-face-back {
background: linear-gradient(to bottom, yellow, red);
&::after {
background: linear-gradient(to bottom, lime, black);
mask-image: linear-gradient(to left, black, transparent);
}
}
.cube-face-bottom {
background: linear-gradient(to bottom, blue, black);
&::after {
background: linear-gradient(to bottom, magenta, red);
mask-image: linear-gradient(to left, red, transparent);
}
}
.cube-face-right {
background: linear-gradient(to bottom, white, magenta);
&::after {
background: linear-gradient(to bottom, yellow, red);
mask-image: linear-gradient(to left, red, transparent);
}
}
.cube-face-left {
background: linear-gradient(to bottom, lime, black);
&::after {
background: linear-gradient(to bottom, cyan, blue);
mask-image: linear-gradient(to left, blue, transparent);
}
}
</style>
{{> const style = `
bg-white font-[ecrou] text-black text-sm
select-none
px-1 pt-0.5 transform-[translateY(calc(-var(--spacing)*0.5/2))]
nuclear
` }}
{{ set cube_face_front }}
<a draggable="false" class="{{ style }}" href="/about/">about</a>
{{ /set }}
{{ set cube_face_top }}
<a draggable="false" class="{{ style }}" href="https://github.com/RGBCube">github</a>
{{ /set }}
{{ set cube_face_right }}
<a draggable="false" class="{{ style }}" href="/contact/">contact</a>
{{ /set }}
{{ set cube_face_left }}
<a draggable="false" class="{{ style }}" href="/blog/">blog</a>
{{ /set }}
{{ include "cube.vto" }}