summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordelta <darkussdelta@gmail.com>2025-02-03 22:58:46 +0100
committerdelta <darkussdelta@gmail.com>2025-02-03 22:58:46 +0100
commit41a6d16ef6a356bc286b0eafe267d04aeed174f3 (patch)
tree86fe71416dc5f802bacec930f9afadd453824423
initial commit
-rw-r--r--.gitignore1
-rw-r--r--.prettierignore3
-rw-r--r--.prettierrc.json14
-rw-r--r--.zs/config.yml13
-rwxr-xr-x.zs/current_date3
-rwxr-xr-x.zs/generate_nav27
-rwxr-xr-x.zs/include14
-rw-r--r--.zs/layout.html44
-rwxr-xr-x.zs/list90
-rwxr-xr-x.zs/posthook19
-rwxr-xr-x.zs/prehook3
-rwxr-xr-x.zs/scripts14
-rwxr-xr-x.zs/styles14
-rw-r--r--404.md2
-rw-r--r--apple-touch-icon.pngbin0 -> 2903 bytes
-rw-r--r--assets/css/404.css13
-rw-r--r--assets/css/index.css198
-rw-r--r--assets/css/posts.css7
-rw-r--r--assets/css/reset.css48
-rw-r--r--assets/icons/apple-touch-icon.pngbin0 -> 4938 bytes
-rw-r--r--assets/icons/favicon-16x16.pngbin0 -> 347 bytes
-rw-r--r--assets/icons/favicon-32x32.pngbin0 -> 675 bytes
-rw-r--r--assets/js/live.js225
-rw-r--r--assets/js/main.js41
-rw-r--r--blog/1.md6
-rw-r--r--blog/2.md6
-rw-r--r--favicon-16x16.pngbin0 -> 428 bytes
-rw-r--r--favicon-32x32.pngbin0 -> 709 bytes
-rw-r--r--index.md15
-rw-r--r--posts.md5
-rw-r--r--projects.md8
31 files changed, 833 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b98613
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.pub
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..576213e
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+.pub
+*.md
+assets/css/reset.css
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..3abfc1a
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,14 @@
+{
+ "printWidth": 160,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": false,
+ "quoteProps": "as-needed",
+ "jsxSingleQuote": false,
+ "trailingComma": "all",
+ "bracketSpacing": true,
+ "bracketSameLine": true,
+ "arrowParens": "always",
+ "proseWrap": "always"
+}
diff --git a/.zs/config.yml b/.zs/config.yml
new file mode 100644
index 0000000..d421309
--- /dev/null
+++ b/.zs/config.yml
@@ -0,0 +1,13 @@
+---
+title: delta.twoexem.com
+description: ma olin mi lon kulupu nanpa
+
+extensions:
+ - anchor
+ - definitionlist
+ - linkify
+ - footnote
+ - strikethrough
+ - table
+ - typography
+ - wikilink
diff --git a/.zs/current_date b/.zs/current_date
new file mode 100755
index 0000000..9b6fbbb
--- /dev/null
+++ b/.zs/current_date
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+printf %s "$(date -u +%Y-%m-%dT%H:%M:%S%Z)"
diff --git a/.zs/generate_nav b/.zs/generate_nav
new file mode 100755
index 0000000..28289af
--- /dev/null
+++ b/.zs/generate_nav
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+echo "/:home /projects.html:projects /posts.html:ramblings" | awk '
+function normalize(file) {
+ sub(".[^.]*$", "", file)
+ sub(".*/", "", file)
+ return file
+}
+
+{
+ for (i=1; i<=NF; i++) {
+ match($i, /:.+/)
+ name = substr($i, RSTART+1, RLENGTH)
+
+ match($i, /.+:/)
+ file = substr($i, RSTART, RLENGTH-1)
+
+ parsed_file = ENVIRON["ZS_FILE"]
+
+ if (normalize(file) == normalize(parsed_file) || (normalize(parsed_file) == "index" && file == "/")) {
+ name = sprintf("[%s]", name)
+ }
+
+ printf "<li><a href=\"%s\">%s</a></li>", file, name
+ if (i<NF) print ""
+ }
+}'
diff --git a/.zs/include b/.zs/include
new file mode 100755
index 0000000..84e73a5
--- /dev/null
+++ b/.zs/include
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+if [ ! $# = 1 ]; then
+ printf "Usage: %s <file>\n" "$(basename "$0")"
+ exit 0
+fi
+
+if [ -f "$1" ]; then
+ cat "$1"
+else
+ echo "error: file not found $1"
+fi
diff --git a/.zs/layout.html b/.zs/layout.html
new file mode 100644
index 0000000..a171791
--- /dev/null
+++ b/.zs/layout.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <!-- Meta Tags -->
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta property="og:title" content="{{ title }}" />
+ <meta property="og:type" content="website" />
+ <meta property="og:url" content="http://delta.twoexem.com" />
+ <meta property="og:description" content="{{ description }}" />
+ <meta name="theme-color" content="#ecb256">
+ <title>{{ title }} - darkuss' website</title>
+
+ <!-- Favicon -->
+ <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
+ <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
+ <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
+
+ <!-- Stylesheets -->
+ {{ styles }}
+
+ <!-- Scripts -->
+ {{ scripts }}
+ </head>
+
+ <body>
+ <div id="lower"></div>
+ <div id="upper">
+ <nav>
+ <ul>
+ {{ generate_nav }}
+ </ul>
+ </nav>
+ <div>
+ <main><div>{{ content }}</div></main>
+ <footer class="subtle">
+ <span>made with <span style="color: var(--red)">&lt;3</span> by darkuss</span
+ ><span>built with <a href="https://git.mills.io/prologic/zs">zs</a></span
+ ><span>last modified: <time datetime="{{ current_date }}">{{ current_date }}</time></span>
+ </footer>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/.zs/list b/.zs/list
new file mode 100755
index 0000000..854eab0
--- /dev/null
+++ b/.zs/list
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+# Define the directory to iterate over from the first argument
+dir="$1"
+
+# Initialize the variable to hold the HTML list and date-file pairs
+html=""
+date_file_pairs=""
+
+# Check if the directory exists
+if [ -d "$dir" ]; then
+ # Find all Markdown files in the directory and store them in a variable
+ md_files=$(find "$dir" -maxdepth 1 -type f -name "*.md")
+
+ # Process each Markdown file in a regular loop (not in a subshell)
+ for md_file in $md_files; do
+ # Extract front matter using sed, ensure the file is quoted
+ front_matter=$(sed -n '/^---$/,/^---$/p' "$md_file")
+
+ # Extract date
+ date=$(echo "$front_matter" | grep '^date:' | sed 's/^date:[[:space:]]*//')
+
+ # If no date is found, use a default date
+ if [ -z "$date" ]; then
+ date="01-01-1970" # Default date if none is found
+ fi
+
+ # Add the date and file to the date_file_pairs variable, using printf to correctly append newlines
+ date_file_pairs=$(printf "%s\n%s|%s" "$date_file_pairs" "$date" "$md_file")
+ done
+
+ # Sort the date and file pairs by date
+ sorted_date_file_pairs=$(printf "%s" "$date_file_pairs" | sort -r -t "|" -k 1,1.2n -k 1.4,1.6n -k 1.8,1.12n)
+
+ # Create a file descriptor to avoid subshell issues
+ exec 3<<EOF
+$sorted_date_file_pairs
+EOF
+
+ # Generate the navigation list
+ html="<ol class=\"list\">"
+ while IFS= read -r pair <&3; do
+ # Split the pair into date and filename using | as a delimiter
+ date=$(printf "%s" "$pair" | cut -d'|' -f1)
+ md_file=$(printf "%s" "$pair" | cut -d'|' -f2)
+
+ # Ensure md_file is not empty (safety check)
+ [ -z "$md_file" ] && continue
+
+ # Extract front matter again using sed, ensure md_file is quoted
+ front_matter=$(sed -n '/^---$/,/^---$/p' "$md_file")
+
+ # Extract title
+ title=$(echo "$front_matter" | grep '^title:' | sed 's/^title:[[:space:]]*//')
+
+ # Use filename as a fallback if title is empty
+ if [ -z "$title" ]; then
+ # Get the base filename without extension, quote the argument
+ base_name=$(basename "$md_file" .md)
+ # Replace hyphens and underscores with spaces for display
+ title=$(echo "$base_name" | sed 's/-/ /g' | sed 's/_/ /g')
+ # Capitalize each word
+ title=$(echo "$title" | awk '{ for (i=1; i<=NF; i++) $i=toupper(substr($i,1,1)) substr($i,2); print }')
+ fi
+
+ # Format the date using POSIX-compliant date formatting
+ if formatted_date=$(date -d "$date" '+%Y-%m-%d' 2>/dev/null); then
+ : # formatted_date is valid
+ else
+ formatted_date="$date"
+ fi
+
+ # Construct the link href, quote the argument
+ href="/$dir/$(basename "${md_file%.md}.html")"
+
+ # Append to the HTML list
+ html="$html<li><a href=\"$href\">$title</a><span class="subtle">(published: <time datetime=$formatted_date>$formatted_date</time>)</span></li>"
+ done
+ html="$html</ol>"
+
+ # Close file descriptor
+ exec 3<&-
+
+else
+ # If the directory doesn't exist, set a message
+ html="<p>No pages found.</p>"
+fi
+
+# Output the HTML list
+echo "$html"
diff --git a/.zs/posthook b/.zs/posthook
new file mode 100755
index 0000000..bcf1d52
--- /dev/null
+++ b/.zs/posthook
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+set -e
+
+minify_assets() {
+ p="$1"
+ t="$2"
+
+ find "$p" -type f -name "*.$t" | while read -r file; do
+ name="${file#"$p"}"
+ name="${name#"/"}"
+ minify -o "${p}/${name}" "$file"
+ done
+}
+
+if command -v minify > /dev/null; then
+ minify_assets "$ZS_OUTDIR" "css"
+ minify_assets "$ZS_OUTDIR" "js"
+fi
diff --git a/.zs/prehook b/.zs/prehook
new file mode 100755
index 0000000..c52d3c2
--- /dev/null
+++ b/.zs/prehook
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exit 0
diff --git a/.zs/scripts b/.zs/scripts
new file mode 100755
index 0000000..17320fc
--- /dev/null
+++ b/.zs/scripts
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+JS=""
+
+# Load live.js for non-production builds for faster development
+if [ -z "$ZS_PRODUCTION" ]; then
+ JS="$JS live"
+fi
+
+for js in $JS; do
+ printf "<script type=\"application/javascript\" src=\"assets/js/%s.js\"></script>\n" "$js"
+done
diff --git a/.zs/styles b/.zs/styles
new file mode 100755
index 0000000..62eb63f
--- /dev/null
+++ b/.zs/styles
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+CSS="reset index"
+CSS_ZS_FILE=$(echo $ZS_FILE | sed -e 's/.[^.]*$/.css/')
+
+for css in $CSS; do
+ printf "<link rel=\"stylesheet\" href=\"assets/css/%s.css\">\n" "$css"
+done
+
+if [ -f $(printf "assets/css/%s" "$CSS_ZS_FILE") ]; then
+ printf "<link rel=\"stylesheet\" href=\"assets/css/%s\">\n" "$CSS_ZS_FILE"
+fi
diff --git a/404.md b/404.md
new file mode 100644
index 0000000..edb33cc
--- /dev/null
+++ b/404.md
@@ -0,0 +1,2 @@
+# alas, there is nothing to be found here
+<div>if you got here via a link (be it external or from this site), please <a href="/">notify</a> me asap</div>
diff --git a/apple-touch-icon.png b/apple-touch-icon.png
new file mode 100644
index 0000000..d7896a4
--- /dev/null
+++ b/apple-touch-icon.png
Binary files differ
diff --git a/assets/css/404.css b/assets/css/404.css
new file mode 100644
index 0000000..b75ef00
--- /dev/null
+++ b/assets/css/404.css
@@ -0,0 +1,13 @@
+main {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+main > div {
+ text-align: center;
+}
+
+main > div > div {
+ color: var(--fg-low);
+}
diff --git a/assets/css/index.css b/assets/css/index.css
new file mode 100644
index 0000000..9f9ce62
--- /dev/null
+++ b/assets/css/index.css
@@ -0,0 +1,198 @@
+:root {
+ --font: "Iosevka Comfy Duo";
+
+ --fg-low: oklch(70% 0.01368 253.09);
+ --fg: oklch(80% 0.01368 253.09);
+ --fg-high: oklch(90% 0.01368 253.09);
+
+ --bg-lowest: oklch(15% 0.01368 253.09);
+ --bg-low: oklch(17.5% 0.01368 253.09);
+ --bg: oklch(20% 0.01368 253.09);
+ --bg-high: oklch(22.5% 0.01368 253.09);
+ --bg-highest: oklch(25% 0.01368 253.09);
+
+ --border: oklch(35% 0.023 253.09);
+ --border-variant: oklch(30% 0.023 253.09);
+
+ --red: oklch(80% 0.15765 24.728);
+ --red-bright: oklch(90% 0.15765 24.728);
+ --orange: oklch(80% 0.139 45.216);
+ --orange-bright: oklch(90% 0.139 45.216);
+ --yellow: oklch(80% 0.12758 76.402);
+ --yellow-bright: oklch(90% 0.12758 76.402);
+ --green: oklch(80% 0.11211 147.63);
+ --green-bright: oklch(90% 0.11211 147.63);
+ --cyan: oklch(80% 0.09919 181.49);
+ --cyan-bright: oklch(90% 0.09919 181.49);
+ --blue: oklch(80% 0.09994 249.58);
+ --blue-bright: oklch(90% 0.09994 249.58);
+ --purple: oklch(80% 0.09923 296.61);
+ --purple-bright: oklch(90% 0.09923 296.61);
+ --pink: oklch(80% 0.06662 9.2146);
+ --pink-bright: oklch(90% 0.06662 9.2146);
+
+ --border-radius: 5px;
+ --border-width: 2px;
+ --padding: 5px;
+ --padding-big: 10px;
+}
+
+body {
+ font-family: "Iosevka Comfy Duo";
+ background-color: var(--bg);
+ color: var(--fg);
+ display: flex;
+ gap: var(--padding-big);
+ min-height: 100vh;
+ padding: var(--padding-big);
+ box-sizing: border-box;
+ position: relative;
+}
+
+#lower {
+ --bar-size: 0.3em;
+ position: absolute;
+ z-index: -1;
+ bottom: 0;
+ right: 0;
+ aspect-ratio: 1 / 1;
+ height: calc(var(--bar-size) * 14); /* magic number */
+ background-image: linear-gradient(
+ -45deg,
+ transparent,
+ transparent var(--bar-size),
+ var(--blue) var(--bar-size),
+ var(--blue) calc(var(--bar-size) * 2),
+ transparent calc(var(--bar-size) * 2),
+ transparent calc(var(--bar-size) * 3),
+ var(--green) calc(var(--bar-size) * 3),
+ var(--green) calc(var(--bar-size) * 4),
+ transparent calc(var(--bar-size) * 4),
+ transparent calc(var(--bar-size) * 5),
+ var(--yellow) calc(var(--bar-size) * 5),
+ var(--yellow) calc(var(--bar-size) * 6),
+ transparent calc(var(--bar-size) * 6),
+ transparent calc(var(--bar-size) * 7),
+ var(--orange) calc(var(--bar-size) * 7),
+ var(--orange) calc(var(--bar-size) * 8),
+ transparent calc(var(--bar-size) * 8),
+ transparent calc(var(--bar-size) * 9),
+ var(--red) calc(var(--bar-size) * 9),
+ var(--red) calc(var(--bar-size) * 10),
+ transparent calc(var(--bar-size) * 10)
+ );
+}
+
+/*
+ * failsafe for when the viewport is too small and the rainbow overlaps the text
+ */
+main > div,
+footer > span {
+ background-color: var(--bg);
+}
+
+#upper {
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+}
+
+#upper > div {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ gap: var(--padding-big);
+ align-items: center;
+}
+
+.subtle {
+ color: var(--fg-low);
+}
+
+main {
+ flex-grow: 1;
+ width: 80vw;
+ line-height: 1.5;
+}
+
+nav > ul {
+ display: flex;
+}
+
+main,
+nav {
+ padding: var(--padding-big);
+}
+
+nav li:not(:last-of-type)::after,
+footer > span:not(:last-of-type)::after {
+ content: "|";
+ margin-left: var(--padding);
+ margin-right: var(--padding);
+ color: var(--border);
+}
+
+footer {
+ text-align: center;
+ padding: var(--padding);
+ font-size: 0.8em;
+}
+
+a,
+a:link {
+ color: var(--yellow);
+}
+
+a:visited {
+ color: var(--pink);
+}
+
+a:focus,
+a:hover {
+ color: var(--yellow-bright);
+}
+
+a:active {
+ color: var(--yellow);
+}
+
+h1 {
+ font-size: 1.5em;
+ margin-bottom: calc(var(--padding-big) * 2);
+}
+
+h2 {
+ font-size: 1.25em;
+ margin-bottom: calc(var(--padding-big) * 1.5);
+}
+
+p:not(:last-of-type) {
+ margin-bottom: var(--padding-big);
+}
+
+main li {
+ margin-left: var(--padding-big);
+ list-style-type: "- ";
+ list-style-position: inside;
+}
+
+main li::marker {
+ color: var(--border);
+}
+
+main ol,
+main ul {
+ padding-top: var(--padding);
+ gap: var(--padding);
+ display: flex;
+ flex-direction: column;
+}
+
+main ol:not(:last-child),
+main ul:not(:last-child) {
+ margin-bottom: var(--padding-big);
+}
+
+strong {
+ font-weight: bold;
+}
diff --git a/assets/css/posts.css b/assets/css/posts.css
new file mode 100644
index 0000000..50ca347
--- /dev/null
+++ b/assets/css/posts.css
@@ -0,0 +1,7 @@
+.list > li {
+ margin-left: 0;
+}
+
+.list > li > span {
+ float: right;
+}
diff --git a/assets/css/reset.css b/assets/css/reset.css
new file mode 100644
index 0000000..e29c0f5
--- /dev/null
+++ b/assets/css/reset.css
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
diff --git a/assets/icons/apple-touch-icon.png b/assets/icons/apple-touch-icon.png
new file mode 100644
index 0000000..bfdf6cc
--- /dev/null
+++ b/assets/icons/apple-touch-icon.png
Binary files differ
diff --git a/assets/icons/favicon-16x16.png b/assets/icons/favicon-16x16.png
new file mode 100644
index 0000000..adba0ac
--- /dev/null
+++ b/assets/icons/favicon-16x16.png
Binary files differ
diff --git a/assets/icons/favicon-32x32.png b/assets/icons/favicon-32x32.png
new file mode 100644
index 0000000..af10188
--- /dev/null
+++ b/assets/icons/favicon-32x32.png
Binary files differ
diff --git a/assets/js/live.js b/assets/js/live.js
new file mode 100644
index 0000000..a015d05
--- /dev/null
+++ b/assets/js/live.js
@@ -0,0 +1,225 @@
+/*
+ Live.js - One script closer to Designing in the Browser
+ Written for Handcraft.com by Martin Kool (@mrtnkl).
+
+ Version 4.
+ Recent change: Made stylesheet and mimetype checks case insensitive.
+
+ http://livejs.com
+ http://livejs.com/license (MIT)
+ @livejs
+
+ Include live.js#css to monitor css changes only.
+ Include live.js#js to monitor js changes only.
+ Include live.js#html to monitor html changes only.
+ Mix and match to monitor a preferred combination such as live.js#html,css
+
+ By default, just include live.js to monitor all css, js and html changes.
+
+ Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,
+ as a page reload due to a change in html or css would not re-include the bookmarklet.
+ To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify
+*/
+(function () {
+ var headers = { Etag: 1, "Last-Modified": 1, "Content-Length": 1, "Content-Type": 1 },
+ resources = {},
+ pendingRequests = {},
+ currentLinkElements = {},
+ oldLinkElements = {},
+ interval = 1000,
+ loaded = false,
+ active = { html: 1, css: 1, js: 1 };
+
+ var Live = {
+ // performs a cycle per interval
+ heartbeat: function () {
+ if (document.body) {
+ // make sure all resources are loaded on first activation
+ if (!loaded) Live.loadresources();
+ Live.checkForChanges();
+ }
+ setTimeout(Live.heartbeat, interval);
+ },
+
+ // loads all local css and js resources upon first activation
+ loadresources: function () {
+ // helper method to assert if a given url is local
+ function isLocal(url) {
+ var loc = document.location,
+ reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
+ return url.match(reg);
+ }
+
+ // gather all resources
+ var scripts = document.getElementsByTagName("script"),
+ links = document.getElementsByTagName("link"),
+ uris = [];
+
+ // track local js urls
+ for (var i = 0; i < scripts.length; i++) {
+ var script = scripts[i],
+ src = script.getAttribute("src");
+ if (src && isLocal(src)) uris.push(src);
+ if (src && src.match(/\blive.js#/)) {
+ for (var type in active) active[type] = src.match("[#,|]" + type) != null;
+ if (src.match("notify")) alert("Live.js is loaded.");
+ }
+ }
+ if (!active.js) uris = [];
+ if (active.html) uris.push(document.location.href);
+
+ // track local css urls
+ for (var i = 0; i < links.length && active.css; i++) {
+ var link = links[i],
+ rel = link.getAttribute("rel"),
+ href = link.getAttribute("href", 2);
+ if (href && rel && rel.match(new RegExp("stylesheet", "i")) && isLocal(href)) {
+ uris.push(href);
+ currentLinkElements[href] = link;
+ }
+ }
+
+ // initialize the resources info
+ for (var i = 0; i < uris.length; i++) {
+ var url = uris[i];
+ Live.getHead(url, function (url, info) {
+ resources[url] = info;
+ });
+ }
+
+ // add rule for morphing between old and new css files
+ var head = document.getElementsByTagName("head")[0],
+ style = document.createElement("style"),
+ rule = "transition: all .3s ease-out;";
+ css = [".livejs-loading * { ", rule, " -webkit-", rule, "-moz-", rule, "-o-", rule, "}"].join("");
+ style.setAttribute("type", "text/css");
+ head.appendChild(style);
+ style.styleSheet ? (style.styleSheet.cssText = css) : style.appendChild(document.createTextNode(css));
+
+ // yep
+ loaded = true;
+ },
+
+ // check all tracking resources for changes
+ checkForChanges: function () {
+ for (var url in resources) {
+ if (pendingRequests[url]) continue;
+
+ Live.getHead(url, function (url, newInfo) {
+ var oldInfo = resources[url],
+ hasChanged = false;
+ resources[url] = newInfo;
+ for (var header in oldInfo) {
+ // do verification based on the header type
+ var oldValue = oldInfo[header],
+ newValue = newInfo[header],
+ contentType = newInfo["Content-Type"];
+ switch (header.toLowerCase()) {
+ case "etag":
+ if (!newValue) break;
+ // fall through to default
+ default:
+ hasChanged = oldValue != newValue;
+ break;
+ }
+ // if changed, act
+ if (hasChanged) {
+ Live.refreshResource(url, contentType);
+ break;
+ }
+ }
+ });
+ }
+ },
+
+ // act upon a changed url of certain content type
+ refreshResource: function (url, type) {
+ switch (type.toLowerCase()) {
+ // css files can be reloaded dynamically by replacing the link element
+ case "text/css":
+ var link = currentLinkElements[url],
+ html = document.body.parentNode,
+ head = link.parentNode,
+ next = link.nextSibling,
+ newLink = document.createElement("link");
+
+ html.className = html.className.replace(/\s*livejs\-loading/gi, "") + " livejs-loading";
+ newLink.setAttribute("type", "text/css");
+ newLink.setAttribute("rel", "stylesheet");
+ newLink.setAttribute("href", url + "?now=" + new Date() * 1);
+ next ? head.insertBefore(newLink, next) : head.appendChild(newLink);
+ currentLinkElements[url] = newLink;
+ oldLinkElements[url] = link;
+
+ // schedule removal of the old link
+ Live.removeoldLinkElements();
+ break;
+
+ // check if an html resource is our current url, then reload
+ case "text/html":
+ if (url != document.location.href) return;
+
+ // local javascript changes cause a reload as well
+ case "text/javascript":
+ case "application/javascript":
+ case "application/x-javascript":
+ document.location.reload();
+ }
+ },
+
+ // removes the old stylesheet rules only once the new one has finished loading
+ removeoldLinkElements: function () {
+ var pending = 0;
+ for (var url in oldLinkElements) {
+ // if this sheet has any cssRules, delete the old link
+ try {
+ var link = currentLinkElements[url],
+ oldLink = oldLinkElements[url],
+ html = document.body.parentNode,
+ sheet = link.sheet || link.styleSheet,
+ rules = sheet.rules || sheet.cssRules;
+ if (rules.length >= 0) {
+ oldLink.parentNode.removeChild(oldLink);
+ delete oldLinkElements[url];
+ setTimeout(function () {
+ html.className = html.className.replace(/\s*livejs\-loading/gi, "");
+ }, 100);
+ }
+ } catch (e) {
+ pending++;
+ }
+ if (pending) setTimeout(Live.removeoldLinkElements, 50);
+ }
+ },
+
+ // performs a HEAD request and passes the header info to the given callback
+ getHead: function (url, callback) {
+ pendingRequests[url] = true;
+ var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XmlHttp");
+ xhr.open("HEAD", url, true);
+ xhr.onreadystatechange = function () {
+ delete pendingRequests[url];
+ if (xhr.readyState == 4 && xhr.status != 304) {
+ xhr.getAllResponseHeaders();
+ var info = {};
+ for (var h in headers) {
+ var value = xhr.getResponseHeader(h);
+ // adjust the simple Etag variant to match on its significant part
+ if (h.toLowerCase() == "etag" && value) value = value.replace(/^W\//, "");
+ if (h.toLowerCase() == "content-type" && value) value = value.replace(/^(.*?);.*?$/i, "$1");
+ info[h] = value;
+ }
+ callback(url, info);
+ }
+ };
+ xhr.send();
+ },
+ };
+
+ // start listening
+ if (document.location.protocol != "file:") {
+ if (!window.liveJsLoaded) Live.heartbeat();
+
+ window.liveJsLoaded = true;
+ } else if (window.console) console.log("Live.js doesn't support the file protocol. It needs http.");
+})();
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..5bc2d41
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,41 @@
+// Toggle the navigation menu and theme
+document.addEventListener("DOMContentLoaded", function () {
+ var menuToggle = document.getElementById("menu-toggle");
+ var mainNav = document.getElementById("main-nav");
+ var themeToggle = document.getElementById("theme-toggle");
+ var body = document.body;
+
+ // Menu toggle functionality
+ menuToggle.addEventListener("click", function () {
+ mainNav.classList.toggle("open");
+ });
+
+ // Theme toggle functionality
+ themeToggle.addEventListener("click", function () {
+ // Toggle between 'light' and 'dark' themes
+ var currentTheme = body.getAttribute("data-theme") || "light";
+ var newTheme = currentTheme === "dark" ? "light" : "dark";
+ body.setAttribute("data-theme", newTheme);
+ localStorage.setItem("theme", newTheme);
+ });
+
+ // On page load, set the theme from localStorage or system preference
+ var storedTheme = localStorage.getItem("theme");
+ if (storedTheme) {
+ body.setAttribute("data-theme", storedTheme);
+ } else {
+ // Detect system preference
+ var prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
+ var defaultTheme = prefersDarkScheme ? "dark" : "light";
+ body.setAttribute("data-theme", defaultTheme);
+ }
+
+ // Listen for changes in the system color scheme
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", function (e) {
+ var storedTheme = localStorage.getItem("theme");
+ if (!storedTheme) {
+ var newColorScheme = e.matches ? "dark" : "light";
+ body.setAttribute("data-theme", newColorScheme);
+ }
+ });
+});
diff --git a/blog/1.md b/blog/1.md
new file mode 100644
index 0000000..8de0cf0
--- /dev/null
+++ b/blog/1.md
@@ -0,0 +1,6 @@
+---
+date: 04-05-2016
+title: How to rule the world
+---
+
+# 1
diff --git a/blog/2.md b/blog/2.md
new file mode 100644
index 0000000..7cb10b1
--- /dev/null
+++ b/blog/2.md
@@ -0,0 +1,6 @@
+---
+date: 04-08-2015
+title: I'm out of touch
+---
+
+# 1
diff --git a/favicon-16x16.png b/favicon-16x16.png
new file mode 100644
index 0000000..af5d82d
--- /dev/null
+++ b/favicon-16x16.png
Binary files differ
diff --git a/favicon-32x32.png b/favicon-32x32.png
new file mode 100644
index 0000000..9892780
--- /dev/null
+++ b/favicon-32x32.png
Binary files differ
diff --git a/index.md b/index.md
new file mode 100644
index 0000000..c6b68e3
--- /dev/null
+++ b/index.md
@@ -0,0 +1,15 @@
+---
+title: Homepage
+---
+
+# hello! cześć! привіт! привет! toki!
+## I, darkuss <span class="subtle">/'daɹ̠kʏs:/</span>, welcome you to this little corner of the internet
+
+I primarily use lua and rust, although I also know html, css/scss and js/ts. I'm currently studying networking/hosting.
+I listen to plethora of different genres and artists, from [ShibayanRecords](https://shibayan.info/) to [The Hatters](https://thehatters.band/)
+
+if you feel like getting to know me, or simply want to talk to me, you can find me here:
+- matrix - [@deltaaaa:matrix.org](matrix:u/deltaaaa:matrix.org?action=chat)
+- discord - [darkuss_](https://discord.id/?prefill=770804101332074547)
+- soulseek - delta
+- email (__heavily__ discouraged, i check it __once in a blue moon__) - darkusss at proton dot me
diff --git a/posts.md b/posts.md
new file mode 100644
index 0000000..1ce7e1a
--- /dev/null
+++ b/posts.md
@@ -0,0 +1,5 @@
+---
+title: Ramblings
+---
+
+{{ list blog }}
diff --git a/projects.md b/projects.md
new file mode 100644
index 0000000..b86148e
--- /dev/null
+++ b/projects.md
@@ -0,0 +1,8 @@
+---
+title: Projects
+---
+
+- [dots](https://git.twoexem.com/dots.git) - my awesomewm config
+- [libmusa](https://git.twoexem.com/libmusa.git) - a library for exposing apis of different music services under a single, unified interface
+- [tufumo](https://git.twoexem.com/tufumo.git) - a music player oriented at power users, powered by [libmusa](https://git.twoexem.com/libmusa.git) and inspired by [symfonium](https://www.symfonium.app/)
+- [website](https://git.twoexem.com/website.git) - the very website that you're reading right now