Commits vergleichen

...

Keine gemeinsamen Commits. „web“ und „main“ haben vollständig unterschiedliche Historien.
web ... main

87 geänderte Dateien mit 535 neuen und 2647 gelöschten Zeilen

2
.gitattributes gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

40
.github/workflows/cfpages-deploy.yml gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,40 @@
name: Deploy Zola site to Cloudflare Pages
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-node-latest
steps:
# 1. Checkout the repository code
- name: Checkout repository
uses: actions/checkout@v3
# 2. Install Zola
- name: Install Zola
run: |
ZOLA_VERSION="0.20.0"
curl -fL -o zola.tar.gz https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz
tar -xzf zola.tar.gz
chmod +x zola
mv zola /usr/local/bin/
# 3. Initialize Submodules
- name: Initialize submodules
run: |
git submodule update --init --recursive
# 4. Build the site with Zola
- name: Build site with Zola
run: |
zola build --output-dir public
# 5. Publish to Cloudflare Pages
- name: Deploy to Cloudflare Pages
uses: https://github.com/cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy public --project-name=u42

4
.gitignore gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,4 @@
.vercel
# Local Netlify folder
.netlify

3
.gitmodules gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,3 @@
[submodule "themes/duckquill"]
path = themes/duckquill
url = https://codeberg.org/daudix/duckquill.git

Datei anzeigen

BIN
404.gif

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 4 KiB

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

BIN
404.png

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 340 B

9
LICENSE Normale Datei
Datei anzeigen

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2024 user0x42
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

12
README.md Normale Datei
Datei anzeigen

@ -0,0 +1,12 @@
# u42.dev
Personal Homepage
## Credits
- [Zola](https://getzola.org)
- [Duckquill](https://duckquill.daudix.one)
## Disclaimer
The project itself is licensed under the [**MIT**](LICENSE) license, and the images and logos owned by [**user0x42**](https://u42.dev) are licensed under the [**CC BY-NC 4.0**](https://creativecommons.org/licenses/by-nc/4.0/) license

Datei anzeigen

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>user0x42</title>
<subtitle>Home of a Random Dude</subtitle>
<link rel="self" type="application/atom+xml" href="https://u42.dev/atom.xml"/>
<link rel="alternate" type="text/html" href="https://u42.dev"/>
<generator uri="https://www.getzola.org/">Zola</generator>
<updated>2024-12-20T00:00:00+00:00</updated>
<id>https://u42.dev/atom.xml</id>
<entry xml:lang="en">
<title>Random</title>
<published>2024-12-20T00:00:00+00:00</published>
<updated>2024-12-20T00:00:00+00:00</updated>
<author>
<name>
user0x42
</name>
</author>
<link rel="alternate" type="text/html" href="https://u42.dev/blog/u42/"/>
<id>https://u42.dev/blog/u42/</id>
<content type="html" xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</content>
</entry>
</feed>

1
auto-render.min.js gevendort
Datei anzeigen

@ -1 +0,0 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};return function(){r.d(o,{default:function(){return d}});var e=r(771),t=r.n(e);const n=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},i=/^\\begin{/;var a=function(e,t){let r;const o=[],a=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;r=e.search(a),-1!==r;){r>0&&(o.push({type:"text",data:e.slice(0,r)}),e=e.slice(r));const a=t.findIndex((t=>e.startsWith(t.left)));if(r=n(t[a].right,e,t[a].left.length),-1===r)break;const l=e.slice(0,r+t[a].right.length),s=i.test(l)?l:e.slice(t[a].left.length,r);o.push({type:"math",data:s,rawData:l,display:t[a].display}),e=e.slice(r+t[a].right.length)}return""!==e&&o.push({type:"text",data:e}),o};const l=function(e,n){const r=a(e,n.delimiters);if(1===r.length&&"text"===r[0].type)return null;const o=document.createDocumentFragment();for(let e=0;e<r.length;e++)if("text"===r[e].type)o.appendChild(document.createTextNode(r[e].data));else{const i=document.createElement("span");let a=r[e].data;n.displayMode=r[e].display;try{n.preProcess&&(a=n.preProcess(a)),t().render(a,i,n)}catch(i){if(!(i instanceof t().ParseError))throw i;n.errorCallback("KaTeX auto-render: Failed to parse `"+r[e].data+"` with ",i),o.appendChild(document.createTextNode(r[e].rawData));continue}o.appendChild(i)}return o},s=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const s=l(o,t);if(s){for(let e=0;e<a;e++)r.nextSibling.remove();n+=s.childNodes.length-1,e.replaceChild(s,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&s(r,t)}}};var d=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},s(e,n)}}(),o=o.default}()}));

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1 +0,0 @@
<!doctype html><meta charset=utf-8><link href=https://u42.dev/blog/ rel=canonical><meta content="0; url=https://u42.dev/blog/" http-equiv=refresh><title>Redirect</title><p><a href=https://u42.dev/blog/>Click here</a> to be redirected.

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

BIN
card.png

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 1,2 MiB

Datei anzeigen

@ -1,27 +0,0 @@
const closable = document.querySelectorAll("details.closable");
closable.forEach((detail) => {
detail.addEventListener("toggle", () => {
if (detail.open) setTargetDetail(detail);
});
});
function setTargetDetail(targetDetail) {
closable.forEach((detail) => {
if (detail !== targetDetail) {
detail.open = false;
}
});
}
document.addEventListener("click", function (event) {
const isClickInsideDetail = [...closable].some((detail) =>
detail.contains(event.target)
);
if (!isClickInsideDetail) {
closable.forEach((detail) => {
detail.open = false;
});
}
});

Datei anzeigen

@ -1,406 +0,0 @@
// Taken from https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/
// Attachment, card, and spoiler code taken from https://github.com/cassidyjames/cassidyjames.github.io/blob/99782788a7e3ba3cc52d6803010873abd1b02b9e/_includes/comments.html#L251-L296
let blogPostAuthorText = document.getElementById("blog-post-author-text").textContent;
let boostsFromText = document.getElementById("boosts-from-text").textContent;
let dateLocale = document.getElementById("date-locale").textContent;
let favesFromText = document.getElementById("faves-from-text").textContent;
let host = document.getElementById("host").textContent;
let id = document.getElementById("id").textContent;
let lazyAsyncImage = document.getElementById("lazy-async-image").textContent;
let loadingText = document.getElementById("loading-text").textContent;
let noCommentsText = document.getElementById("no-comments-text").textContent;
let relAttributes = document.getElementById("rel-attributes").textContent;
let reloadText = document.getElementById("reload-text").textContent;
let sensitiveText = document.getElementById("sensitive-text").textContent;
let user = document.getElementById("user").textContent;
let viewCommentText = document.getElementById("view-comment-text").textContent;
let viewProfileText = document.getElementById("view-profile-text").textContent;
document.getElementById("load-comments").addEventListener("click", loadComments);
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function emojify(input, emojis) {
let output = input;
emojis.forEach((emoji) => {
let picture = document.createElement("picture");
let source = document.createElement("source");
source.setAttribute("srcset", escapeHtml(emoji.url));
source.setAttribute("media", "(prefers-reduced-motion: no-preference)");
let img = document.createElement("img");
img.className = "emoji";
img.setAttribute("src", escapeHtml(emoji.static_url));
img.setAttribute("alt", `:${emoji.shortcode}:`);
img.setAttribute("title", `:${emoji.shortcode}:`);
if (lazyAsyncImage == "true") {
img.setAttribute("decoding", "async");
img.setAttribute("loading", "lazy");
}
picture.appendChild(source);
picture.appendChild(img);
output = output.replace(`:${emoji.shortcode}:`, picture.outerHTML);
});
return output;
}
function loadComments() {
let commentsWrapper = document.getElementById("comments-wrapper");
commentsWrapper.innerHTML = "";
let loadCommentsButton = document.getElementById("load-comments");
loadCommentsButton.innerHTML = loadingText;
loadCommentsButton.disabled = true;
fetch(`https://${host}/api/v1/statuses/${id}/context`)
.then(function (response) {
return response.json();
})
.then(function (data) {
let descendants = data["descendants"];
if (
descendants &&
Array.isArray(descendants) &&
descendants.length > 0
) {
commentsWrapper.innerHTML = "";
descendants.forEach(function (status) {
console.log(descendants);
if (status.account.display_name.length > 0) {
status.account.display_name = escapeHtml(
status.account.display_name
);
status.account.display_name = emojify(
status.account.display_name,
status.account.emojis
);
} else {
status.account.display_name = status.account.username;
}
let instance = "";
if (status.account.acct.includes("@")) {
instance = status.account.acct.split("@")[1];
} else {
instance = host;
}
const isReply = status.in_reply_to_id !== id;
let op = false;
if (status.account.acct == user) {
op = true;
}
status.content = emojify(status.content, status.emojis);
let comment = document.createElement("article");
comment.id = `comment-${status.id}`;
comment.className = isReply ? "comment comment-reply" : "comment";
comment.setAttribute("itemprop", "comment");
comment.setAttribute("itemtype", "http://schema.org/Comment");
let avatarSource = document.createElement("source");
avatarSource.setAttribute(
"srcset",
escapeHtml(status.account.avatar)
);
avatarSource.setAttribute(
"media",
"(prefers-reduced-motion: no-preference)"
);
let avatarImg = document.createElement("img");
avatarImg.className = "avatar";
avatarImg.setAttribute(
"src",
escapeHtml(status.account.avatar_static)
);
avatarImg.setAttribute(
"alt",
`@${status.account.username}@${instance} avatar`
);
if (lazyAsyncImage == "true") {
avatarImg.setAttribute("decoding", "async");
avatarImg.setAttribute("loading", "lazy");
}
let avatarPicture = document.createElement("picture");
avatarPicture.appendChild(avatarSource);
avatarPicture.appendChild(avatarImg);
let avatar = document.createElement("a");
avatar.className = "avatar-link";
avatar.setAttribute("href", status.account.url);
avatar.setAttribute("rel", relAttributes);
avatar.setAttribute(
"title",
`${viewProfileText} @${status.account.username}@${instance}`
);
avatar.appendChild(avatarPicture);
comment.appendChild(avatar);
let instanceBadge = document.createElement("a");
instanceBadge.className = "instance";
instanceBadge.setAttribute("href", status.account.url);
instanceBadge.setAttribute(
"title",
`@${status.account.username}@${instance}`
);
instanceBadge.setAttribute("rel", relAttributes);
instanceBadge.textContent = instance;
let display = document.createElement("span");
display.className = "display";
display.setAttribute("itemprop", "author");
display.setAttribute("itemtype", "http://schema.org/Person");
display.innerHTML = status.account.display_name;
let header = document.createElement("header");
header.className = "author";
header.appendChild(display);
header.appendChild(instanceBadge);
comment.appendChild(header);
let permalink = document.createElement("a");
permalink.setAttribute("href", status.url);
permalink.setAttribute("itemprop", "url");
permalink.setAttribute("title", `${viewCommentText} ${instance}`);
permalink.setAttribute("rel", relAttributes);
permalink.textContent = new Date(
status.created_at
).toLocaleString(dateLocale, {
dateStyle: "long",
timeStyle: "short",
});
let timestamp = document.createElement("time");
timestamp.setAttribute("datetime", status.created_at);
timestamp.appendChild(permalink);
permalink.classList.add("external");
comment.appendChild(timestamp);
let main = document.createElement("main");
main.setAttribute("itemprop", "text");
if (status.sensitive == true || status.spoiler_text != "") {
let summary = document.createElement("summary");
if (status.spoiler_text == "") {
status.spoiler_text == sensitiveText;
}
summary.innerHTML = status.spoiler_text;
let spoiler = document.createElement("details");
spoiler.appendChild(summary);
spoiler.innerHTML += status.content;
main.appendChild(spoiler);
} else {
main.innerHTML = status.content;
}
comment.appendChild(main);
let attachments = status.media_attachments;
let SUPPORTED_MEDIA = ["image", "video", "gifv", "audio"];
let media = document.createElement("div");
media.className = "attachments";
if (
attachments &&
Array.isArray(attachments) &&
attachments.length > 0
) {
attachments.forEach((attachment) => {
if (SUPPORTED_MEDIA.includes(attachment.type)) {
let mediaElement;
switch (attachment.type) {
case "image":
mediaElement = document.createElement("img");
mediaElement.setAttribute("src", attachment.preview_url);
if (attachment.description != null) {
mediaElement.setAttribute("alt", attachment.description);
mediaElement.setAttribute("title", attachment.description);
}
if (lazyAsyncImage == "true") {
mediaElement.setAttribute("decoding", "async");
mediaElement.setAttribute("loading", "lazy");
}
if (status.sensitive == true) {
mediaElement.classList.add("spoiler");
}
media.appendChild(mediaElement);
break;
case "video":
mediaElement = document.createElement("video");
mediaElement.setAttribute("src", attachment.url);
mediaElement.setAttribute("controls", "");
if (attachment.description != null) {
mediaElement.setAttribute("aria-title", attachment.description);
mediaElement.setAttribute("title", attachment.description);
}
if (status.sensitive == true) {
mediaElement.classList.add("spoiler");
}
media.appendChild(mediaElement);
break;
case "gifv":
mediaElement = document.createElement("video");
mediaElement.setAttribute("src", attachment.url);
mediaElement.setAttribute("autoplay", "");
mediaElement.setAttribute("playsinline", "");
mediaElement.setAttribute("loop", "");
if (attachment.description != null) {
mediaElement.setAttribute("aria-title", attachment.description);
mediaElement.setAttribute("title", attachment.description);
}
if (status.sensitive == true) {
mediaElement.classList.add("spoiler");
}
media.appendChild(mediaElement);
break;
case "audio":
mediaElement = document.createElement("audio");
mediaElement.setAttribute("src", attachment.url);
mediaElement.setAttribute("controls", "");
if (attachment.description != null) {
mediaElement.setAttribute("aria-title", attachment.description);
mediaElement.setAttribute("title", attachment.description);
}
media.appendChild(mediaElement);
break;
}
let mediaLink = document.createElement("a");
mediaLink.setAttribute("href", attachment.url);
mediaLink.setAttribute("rel", relAttributes);
mediaLink.appendChild(mediaElement);
media.appendChild(mediaLink);
}
});
comment.appendChild(media);
}
let interactions = document.createElement("footer");
let boosts = document.createElement("a");
boosts.className = "boosts";
boosts.setAttribute("href", `${status.url}/reblogs`);
boosts.setAttribute("title", `${boostsFromText}`.replace("$INSTANCE", instance));
let boostsIcon = document.createElement("i");
boostsIcon.className = "icon";
boosts.appendChild(boostsIcon);
boosts.insertAdjacentHTML('beforeend', ` ${status.reblogs_count}`);
interactions.appendChild(boosts);
let faves = document.createElement("a");
faves.className = "faves";
faves.setAttribute("href", `${status.url}/favourites`);
faves.setAttribute("title", `${favesFromText}`.replace("$INSTANCE", instance));
let favesIcon = document.createElement("i");
favesIcon.className = "icon";
faves.appendChild(favesIcon);
faves.insertAdjacentHTML('beforeend', ` ${status.favourites_count}`);
interactions.appendChild(faves);
comment.appendChild(interactions);
if (status.card != null) {
let cardFigure = document.createElement("figure");
if (status.card.image != null) {
let cardImg = document.createElement("img");
cardImg.setAttribute("src", status.card.image);
cardImg.classList.add("no-hover");
cardFigure.appendChild(cardImg);
}
let cardCaption = document.createElement("figcaption");
let cardTitle = document.createElement("strong");
cardTitle.innerHTML = status.card.title;
cardCaption.appendChild(cardTitle);
if (status.card.description != null && status.card.description.length > 0) {
let cardDescription = document.createElement("p");
cardDescription.innerHTML = status.card.description;
cardCaption.appendChild(cardDescription);
}
cardFigure.appendChild(cardCaption);
let card = document.createElement("a");
card.className = "card";
card.setAttribute("href", status.card.url);
card.setAttribute("rel", relAttributes);
card.appendChild(cardFigure);
comment.appendChild(card);
}
if (op === true) {
comment.classList.add("op");
avatar.classList.add("op");
avatar.setAttribute(
"title",
`${blogPostAuthorText}: ` + avatar.getAttribute("title")
);
instanceBadge.classList.add("op");
instanceBadge.setAttribute(
"title",
`${blogPostAuthorText}: ` + instanceBadge.getAttribute("title")
);
}
commentsWrapper.innerHTML += comment.outerHTML;
});
}
else {
var statusText = document.createElement("p");
statusText.innerHTML = noCommentsText;
statusText.setAttribute("id", "comments-status");
commentsWrapper.appendChild(statusText);
}
loadCommentsButton.innerHTML = reloadText;
})
.catch(function (error) {
console.error('Error loading comments:', error);
})
.finally(function () {
loadCommentsButton.disabled = false;
});
}

247
config.toml Normale Datei
Datei anzeigen

@ -0,0 +1,247 @@
title = "user0x42"
base_url = "https://u42.dev"
description = "Home of a Random Dude"
theme = "duckquill"
compile_sass = true
minify_html = true
generate_feeds = true
# Only the first file will be used in the navbar feed button,
# other feeds will still be available in page's head.
feed_filenames = ["rss.xml", "atom.xml"]
build_search_index = true
author = "user0x42"
# Based on https://github.com/welpo/tabi
#
# To translate the entire theme, there must be a file with the same ISO 639-1 or BCP 47
# language code in the `i18n` directory of your site or the Duckquill theme.
# For example, "i18n/fr.toml" for French or "i18n/zh-Hans.toml" for Simplified Chinese.
# Otherwise the theme will be in English.
#
# ISO 639-1: https://localizely.com/iso-639-1-list/
# BCP 47: https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
default_language = "en"
taxonomies = [{ name = "tags", feed = true }]
[markdown]
highlight_code = true
highlight_theme = "css"
highlight_themes_css = [
{ theme = "solarized-dark", filename = "syntax-theme-dark.css" },
{ theme = "solarized-light", filename = "syntax-theme-light.css" },
]
smart_punctuation = true
bottom_footnotes = true
[search]
#index_format = "elasticlunr_json"
index_format = "fuse_json"
taxonomies = [{ name = "tags", feed = true }]
[extra]
# Which theme should be used by default (light/dark).
#
default_theme = "dark"
#
# Sets theme and browser theme color.
# See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color
accent_color = "#72BCDE"
# Ditto but for the dark theme.
# If not set regular variant will be used.
accent_color_dark = "#2d7ea0"
# Whether to fix low contrast in text selection, checkboxes, etc.
# Use only if the default doesn't provide enough contrast, e.g. the accent color is set to yellow.
#
fix_contrast = true
#
# Ditto but for the dark theme.
fix_contrast_dark = true
# Whether to use fonts bundled with Duckquill instead of system ones.
# Keep in mind that it also changes the style of headings.
#
bundled_fonts = false
#
# Use emoji as a favicon.
# Only one emoji is being rendered, everything else is truncated.
#
# emoji_favicon = "🦆"
#
# URL to website's issue tracker
issues_url = "https://code.xsiz.eu/user0x42/home/issues"
# URL to website's source code
source_url = "https://code.xsiz.eu/user0x42/home"
# Additional CSS styles; expects them to be in the "./static/" directory.
# If you are using Sass it will be generated there automatically.
#
styles = ["mods.css"]
#
# Additional JavaScript scripts; expects them to be in the "./static/" directory.
#
# scripts = [
# "YOUR_SCRIPT.js",
# ]
#
# Whether to show "copy code" button on all code blocks
# that have the language set.
# See https://www.getzola.org/documentation/content/syntax-highlighting/
show_copy_button = true
# Whether to show estimated read time in posts.
show_reading_time = true
#
# Whether to show a share button in article's quick actions.
# Uses https://shareopenly.org.
show_share_button = true
# Whether to show the backlinks button for linked articles in the article's quick actions
show_backlinks = true
# Whether to enable the KaTeX library for rendering LaTeX.
# Note: This will make your page significantly heavier.
# Instead, consider enabling it per page/section.
# katex = true
#
# Whether to render table of contents on all pages.
# Will not be rendered if page doesn't have any headings.
# Can be set per page/section.
# toc = true
#
# Whether to render inline table of contents at the top of all pages,
# in addition to floating quick navigation buttons.
# Can be set per page/section.
# toc_inline = true
#
# Whether to use numbered (ordered) list for table of contents.
# Can be set per page/section.
# toc_ordered = true
#
# Custom separator used across the theme.
# separator = "•"
# Custom separator used in title tag and posts metadata.
# title_separator = "-"
#
# Whether to use Content Security Policy.
# Keep in mind that although this can potentially increase security,
# it can break some stuff, in which case you will need to set custom policy.
#csp = [
# { directive = "font-src", domains = [
# "'self'",
# ] },
# { directive = "img-src", domains = [
# "'self'",
# "https:",
# "data:",
# ] },
# { directive = "media-src", domains = [
# "'self'",
# "https:",
# ] },
# { directive = "script-src", domains = [
# "'self'",
# "*.xsiz.eu",
# "*.u42.dev",
# "sha256-pXhG/jrX7WBLvkalI68mDNdSUQllQLcbydWC546OFIs=",
# ] },
# { directive = "style-src", domains = [
# "'self'",
# "'unsafe-inline'",
# ] },
# { directive = "frame-src", domains = [
# "https://player.vimeo.com",
# "https://www.youtube-nocookie.com",
# "https://toot.community",
# "*u42.dev",
# "*.xsiz.eu",
# ] },
# { directive = "connect-src", domains = [
# "https://toot.community",
# "*.xsiz.eu",
# "*u42.dev",
# ] },
# { directive = "frame-ancestors", domains = [
# "'none'",
# ] },
# { directive = "base-uri", domains = [
# "'none'",
# ] },
# { directive = "form-action", domains = [
# "'none'",
# ] },
#]
[extra.nav]
# Whether to automatically hide nav when not hovered or focused
auto_hide = false
# Whether to show the Atom/RSS feed button in the nav
show_feed = true
# Whether to show the manual theme switcher in the nav
show_theme_switcher = true
# Whether to show the link to the source repository in the nav
show_repo = true
# Links used in the nav.
# For local files use same link format as in Markdown,
# i.e. "@/blog/_index.md".
# See https://www.getzola.org/documentation/content/linking/#internal-links
#links = [
# { name = "Links", menu = [
# { url = "@/blog/_index.md", name = "Blog" },
# ] },
# { url = "https://diadz.de", name = "DIADZ" }
#]
links = [
{ url = "@/blog/_index.md", name = "Blog" },
{ url = "https://xsiz.eu", name = "XSIZ" },
]
[extra.footer]
# Links used in the footer.
# Same as the nav ones.
links = [
{ url = "@/blog/_index.md", name = "Blog" },
{ url = "https://xsiz.eu", name = "XSIZ" },
]
# Social links in the footer.
# Any URL-encoded SVG can be used as an icon.
# https://simpleicons.org is the recommended source of SVG icons.
# For URL encoding use https://yoksel.github.io/url-encoder/.
# Make sure that "external quotes" are set to "double".
socials = [
{ url = "https://code.xsiz.eu/user0x42", name = "XSIZ Code", icon = "%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512' viewBox='0 0 24 24'%3E%3Cmask id='lineMdCloudAltTagsTwotoneLoop0'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath stroke-dasharray='64' stroke-dashoffset='64' d='M7 19h11c2.21 0 4 -1.79 4 -4c0 -2.21 -1.79 -4 -4 -4h-1v-1c0 -2.76 -2.24 -5 -5 -5c-2.42 0 -4.44 1.72 -4.9 4h-0.1c-2.76 0 -5 2.24 -5 5c0 2.76 2.24 5 5 5Z'%3E%3Canimate fill='freeze' attributeName='stroke-dashoffset' dur='0.6s' values='64;0'/%3E%3Cset fill='freeze' attributeName='opacity' begin='0.7s' to='0'/%3E%3C/path%3E%3Cg fill='%23fff' stroke='none' opacity='0'%3E%3Ccircle cx='12' cy='10' r='6'%3E%3Canimate attributeName='cx' begin='0.7s' dur='30s' repeatCount='indefinite' values='12;11;12;13;12'/%3E%3C/circle%3E%3Crect width='9' height='8' x='8' y='12'/%3E%3Crect width='15' height='12' x='1' y='8' rx='6'%3E%3Canimate attributeName='x' begin='0.7s' dur='21s' repeatCount='indefinite' values='1;0;1;2;1'/%3E%3C/rect%3E%3Crect width='13' height='10' x='10' y='10' rx='5'%3E%3Canimate attributeName='x' begin='0.7s' dur='17s' repeatCount='indefinite' values='10;9;10;11;10'/%3E%3C/rect%3E%3Cset fill='freeze' attributeName='opacity' begin='0.7s' to='1'/%3E%3C/g%3E%3Cg fill='%23000' fill-opacity='0' stroke='none'%3E%3Ccircle cx='12' cy='10' r='4'%3E%3Canimate attributeName='cx' begin='0.7s' dur='30s' repeatCount='indefinite' values='12;11;12;13;12'/%3E%3C/circle%3E%3Crect width='9' height='6' x='8' y='12'/%3E%3Crect width='11' height='8' x='3' y='10' rx='4'%3E%3Canimate attributeName='x' begin='0.7s' dur='21s' repeatCount='indefinite' values='3;2;3;4;3'/%3E%3C/rect%3E%3Crect width='9' height='6' x='12' y='12' rx='3'%3E%3Canimate attributeName='x' begin='0.7s' dur='17s' repeatCount='indefinite' values='12;11;12;13;12'/%3E%3C/rect%3E%3Cset fill='freeze' attributeName='fill-opacity' begin='0.7s' to='1'/%3E%3Canimate fill='freeze' attributeName='opacity' begin='0.7s' dur='0.15s' values='1;0.7'/%3E%3C/g%3E%3Cg stroke-dasharray='6' stroke-dashoffset='6' stroke-linecap='square' stroke-linejoin='miter'%3E%3Cpath d='M7 14l2 2M7 14l2 -2'%3E%3Canimate fill='freeze' attributeName='stroke-dashoffset' begin='0.95s' dur='0.3s' values='6;0'/%3E%3CanimateMotion begin='1.25s' calcMode='linear' dur='6s' keyPoints='0;0.25;0.5;0.75;1' keyTimes='0;0.1;0.5;0.8;1' path='M0 0h-1h2z' repeatCount='indefinite'/%3E%3C/path%3E%3Cpath d='M15 14l-2 2M15 14l-2 -2'%3E%3Canimate fill='freeze' attributeName='stroke-dashoffset' begin='0.95s' dur='0.3s' values='6;0'/%3E%3CanimateMotion begin='1.25s' calcMode='linear' dur='6s' keyPoints='0;0.25;0.5;0.75;1' keyTimes='0;0.1;0.5;0.8;1' path='M0 0h1h-2z' repeatCount='indefinite'/%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/mask%3E%3Crect width='24' height='24' fill='%23ff6f00' mask='url(%23lineMdCloudAltTagsTwotoneLoop0)'/%3E%3C/svg%3E" },
{ url = "https://codeberg.org/user0x42", name = "Codeberg", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ECodeberg%3C/title%3E%3Cpath d='M11.955.49A12 12 0 0 0 0 12.49a12 12 0 0 0 1.832 6.373L11.838 5.928a.187.14 0 0 1 .324 0l10.006 12.935A12 12 0 0 0 24 12.49a12 12 0 0 0-12-12 12 12 0 0 0-.045 0zm.375 6.467l4.416 16.553a12 12 0 0 0 5.137-4.213z'/%3E%3C/svg%3E" },
{ url = "https://github.com/user0x42", name = "GitHub", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EGitHub%3C/title%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E" },
{ url = "https://social.vivaldi.net/@user0x42", name = "Mastodon", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EMastodon%3C/title%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E" },
]
# Whether to show "© Title, YEAR"
show_copyright = true
# Whether to show "Powered by Zola and Duckquill"
show_powered_by = true
# Whether to show link to website source
show_source = false
# Custom copyright text
#
# copyright = "© *Aperture* **Science** ~~Innovators~~, `1972`"
# Based on https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/
#
# Mastodon-powered commenting.
# Values can be overridden in the front-matter, e.g.
# for multi-author blogs or guest posts.
#
# These variables are also used for Mastodon verification,
# the needed rel="me" link is set in the head based on these.
[extra.comments]
# Your Mastodon API host; instance that you have an account on.
host = "social.vivaldi.net"
# Your Mastodon username; used to determine who the original poster is.
user = "user0x42"
# Whether to show the QR code to Mastodon post
show_qr = true
# GoatCounter analytics; enabled only if present in config.
# [extra.goatcounter]
# host = "YOUR_SERVER"
# user = "u42"
#
# Additional JavaScript scripts; expects them to be in the "./static/" directory.
#

17
content/_index.md Normale Datei
Datei anzeigen

@ -0,0 +1,17 @@
+++
insert_anchor_links = "left"
title = "Home"
+++
{% crt() %}
```
╔──────────────────────────────────────────────────────────────────╗
│██╗---██╗███████╗███████╗██████╗--██████╗-██╗--██╗██╗--██╗██████╗-│
│██║---██║██╔════╝██╔════╝██╔══██╗██╔═████╗╚██╗██╔╝██║--██║╚════██╗│
│██║---██║███████╗█████╗--██████╔╝██║██╔██║-╚███╔╝-███████║-█████╔╝│
│██║---██║╚════██║██╔══╝--██╔══██╗████╔╝██║-██╔██╗-╚════██║██╔═══╝-│
│╚██████╔╝███████║███████╗██║--██║╚██████╔╝██╔╝-██╗-----██║███████╗│
│-╚═════╝-╚══════╝╚══════╝╚═╝--╚═╝-╚═════╝-╚═╝--╚═╝-----╚═╝╚══════╝│
╚──────────────────────────────────────────────────────────────────╝
```
{% end %}

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 247 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 247 KiB

9
content/blog/_index.md Normale Datei
Datei anzeigen

@ -0,0 +1,9 @@
+++
title = "user0x42's Randomness"
sort_by = "date"
template = "article_list.html"
page_template = "article.html"
paginate_by = 2
+++
Blog full of Randomness.

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 1,1 MiB

Nachher

Breite:  |  Höhe:  |  Größe: 1,1 MiB

26
content/blog/u42/index.md Normale Datei
Datei anzeigen

@ -0,0 +1,26 @@
+++
authors = ["user0x42"]
title = "Random"
description = "This is peak randomness."
date = 2024-12-20
[taxonomies]
tags = ["Demo", "Test"]
[extra]
featured = true
banner = "darkness.gif"
toc = true
toc_inline = true
toc_ordered = true
trigger = "This page contains **AI Generated** art."
disclaimer = """
- **Hail** our AI Overlords.
- **DO NOT** be **MEAN** to them or **SUFFER** the consequences.
"""
+++
## Randomness
<figure>
![The Office](randomness.webp)
</figure>

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 503 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 503 KiB

Datei anzeigen

@ -1,57 +0,0 @@
// Based on https://www.roboleary.net/2022/01/13/copy-code-to-clipboard-blog.html
document.addEventListener("DOMContentLoaded", function () {
let blocks = document.querySelectorAll("pre[class^='language-']");
blocks.forEach((block) => {
if (navigator.clipboard) {
// Code block header title
let title = document.createElement("span");
let lang = block.getAttribute("data-lang");
title.innerHTML = lang;
// Copy button icon
let icon = document.createElement("i");
icon.classList.add("icon");
// Copy button
let button = document.createElement("button");
let copyCodeText = document.getElementById("copy-code-text").textContent;
button.setAttribute("title", copyCodeText)
button.appendChild(icon);
// Code block header
let header = document.createElement("div");
header.classList.add("header");
header.appendChild(title);
header.appendChild(button);
// Container that holds header and the code block itself
let container = document.createElement("div");
container.classList.add("pre-container");
container.appendChild(header);
// Move code block into the container
block.parentNode.insertBefore(container, block);
container.appendChild(block);
button.addEventListener("click", async () => {
await copyCode(block, header, button); // Pass the button here
});
}
});
async function copyCode(block, header, button) {
let code = block.querySelector("code");
let text = code.innerText;
await navigator.clipboard.writeText(text);
header.classList.add("active");
button.setAttribute("disabled", true);
header.addEventListener("animationend", () => {
header.classList.remove("active");
button.removeAttribute("disabled");
}, { once: true });
}
});

271
count.js
Datei anzeigen

@ -1,271 +0,0 @@
// GoatCounter: https://www.goatcounter.com
// This file is released under the ISC license: https://opensource.org/licenses/ISC
;(function() {
'use strict';
if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use.
window.goatcounter = window.goatcounter.vars
else
window.goatcounter = window.goatcounter || {}
// Load settings from data-goatcounter-settings.
var s = document.querySelector('script[data-goatcounter]')
if (s && s.dataset.goatcounterSettings) {
try { var set = JSON.parse(s.dataset.goatcounterSettings) }
catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) }
for (var k in set)
if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1)
window.goatcounter[k] = set[k]
}
var enc = encodeURIComponent
// Get all data we're going to send off to the counter endpoint.
var get_data = function(vars) {
var data = {
p: (vars.path === undefined ? goatcounter.path : vars.path),
r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer),
t: (vars.title === undefined ? goatcounter.title : vars.title),
e: !!(vars.event || goatcounter.event),
s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)],
b: is_bot(),
q: location.search,
}
var rcb, pcb, tcb // Save callbacks to apply later.
if (typeof(data.r) === 'function') rcb = data.r
if (typeof(data.t) === 'function') tcb = data.t
if (typeof(data.p) === 'function') pcb = data.p
if (is_empty(data.r)) data.r = document.referrer
if (is_empty(data.t)) data.t = document.title
if (is_empty(data.p)) data.p = get_path()
if (rcb) data.r = rcb(data.r)
if (tcb) data.t = tcb(data.t)
if (pcb) data.p = pcb(data.p)
return data
}
// Check if a value is "empty" for the purpose of get_data().
var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' }
// See if this looks like a bot; there is some additional filtering on the
// backend, but these properties can't be fetched from there.
var is_bot = function() {
// Headless browsers are probably a bot.
var w = window, d = document
if (w.callPhantom || w._phantom || w.phantom)
return 150
if (w.__nightmare)
return 151
if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate)
return 152
if (navigator.webdriver)
return 153
return 0
}
// Object to urlencoded string, starting with a ?.
var urlencode = function(obj) {
var p = []
for (var k in obj)
if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false)
p.push(enc(k) + '=' + enc(obj[k]))
return '?' + p.join('&')
}
// Show a warning in the console.
var warn = function(msg) {
if (console && 'warn' in console)
console.warn('goatcounter: ' + msg)
}
// Get the endpoint to send requests to.
var get_endpoint = function() {
var s = document.querySelector('script[data-goatcounter]')
if (s && s.dataset.goatcounter)
return s.dataset.goatcounter
return (goatcounter.endpoint || window.counter) // counter is for compat; don't use.
}
// Get current path.
var get_path = function() {
var loc = location,
c = document.querySelector('link[rel="canonical"][href]')
if (c) { // May be relative or point to different domain.
var a = document.createElement('a')
a.href = c.href
if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, ''))
loc = a
}
return (loc.pathname + loc.search) || '/'
}
// Run function after DOM is loaded.
var on_load = function(f) {
if (document.body === null)
document.addEventListener('DOMContentLoaded', function() { f() }, false)
else
f()
}
// Filter some requests that we (probably) don't want to count.
goatcounter.filter = function() {
if ('visibilityState' in document && document.visibilityState === 'prerender')
return 'visibilityState'
if (!goatcounter.allow_frame && location !== parent.location)
return 'frame'
if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/))
return 'localhost'
if (!goatcounter.allow_local && location.protocol === 'file:')
return 'localfile'
if (localStorage && localStorage.getItem('skipgc') === 't')
return 'disabled with #toggle-goatcounter'
return false
}
// Get URL to send to GoatCounter.
window.goatcounter.url = function(vars) {
var data = get_data(vars || {})
if (data.p === null) // null from user callback.
return
data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control.
var endpoint = get_endpoint()
if (!endpoint)
return warn('no endpoint found')
return endpoint + urlencode(data)
}
// Count a hit.
window.goatcounter.count = function(vars) {
var f = goatcounter.filter()
if (f)
return warn('not counting because of: ' + f)
var url = goatcounter.url(vars)
if (!url)
return warn('not counting because path callback returned null')
if (!navigator.sendBeacon(url)) {
// This mostly fails due to being blocked by CSP; try again with an
// image-based fallback.
var img = document.createElement('img')
img.src = url
img.style.position = 'absolute' // Affect layout less.
img.style.bottom = '0px'
img.style.width = '1px'
img.style.height = '1px'
img.loading = 'eager'
img.setAttribute('alt', '')
img.setAttribute('aria-hidden', 'true')
var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) }
img.addEventListener('load', rm, false)
document.body.appendChild(img)
}
}
// Get a query parameter.
window.goatcounter.get_query = function(name) {
var s = location.search.substr(1).split('&')
for (var i = 0; i < s.length; i++)
if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0)
return s[i].substr(name.length + 1)
}
// Track click events.
window.goatcounter.bind_events = function() {
if (!document.querySelectorAll) // Just in case someone uses an ancient browser.
return
var send = function(elem) {
return function() {
goatcounter.count({
event: true,
path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''),
title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''),
referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''),
})
}
}
Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) {
if (elem.dataset.goatcounterBound)
return
var f = send(elem)
elem.addEventListener('click', f, false)
elem.addEventListener('auxclick', f, false) // Middle click.
elem.dataset.goatcounterBound = 'true'
})
}
// Add a "visitor counter" frame or image.
window.goatcounter.visit_count = function(opt) {
on_load(function() {
opt = opt || {}
opt.type = opt.type || 'html'
opt.append = opt.append || 'body'
opt.path = opt.path || get_path()
opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')}
opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?'
if (opt.no_branding) opt.attr['src'] += '&no_branding=1'
if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style)
if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start)
if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end)
var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type]
if (!tag)
return warn('visit_count: unknown type: ' + opt.type)
if (opt.type === 'html') {
opt.attr['frameborder'] = '0'
opt.attr['scrolling'] = 'no'
}
var d = document.createElement(tag)
for (var k in opt.attr)
d.setAttribute(k, opt.attr[k])
var p = document.querySelector(opt.append)
if (!p)
return warn('visit_count: append not found: ' + opt.append)
p.appendChild(d)
})
}
// Make it easy to skip your own views.
if (location.hash === '#toggle-goatcounter') {
if (localStorage.getItem('skipgc') === 't') {
localStorage.removeItem('skipgc', 't')
alert('GoatCounter tracking is now ENABLED in this browser.')
}
else {
localStorage.setItem('skipgc', 't')
alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.')
}
}
if (!goatcounter.no_onload)
on_load(function() {
// 1. Page is visible, count request.
// 2. Page is not yet visible; wait until it switches to 'visible' and count.
// See #487
if (!('visibilityState' in document) || document.visibilityState === 'visible')
goatcounter.count()
else {
var f = function(e) {
if (document.visibilityState !== 'visible')
return
document.removeEventListener('visibilitychange', f)
goatcounter.count()
}
document.addEventListener('visibilitychange', f)
}
if (!goatcounter.no_events)
goatcounter.bind_events()
})
})();

Datei anzeigen

@ -1 +0,0 @@
@font-face{font-style:normal;font-weight:100 900;src:url("fonts/InterVariable.woff2") format("woff2");font-family:"Inter Variable";font-display:swap}@font-face{font-style:italic;font-weight:100 900;src:url("fonts/InterVariable-Italic.woff2") format("woff2");font-family:"Inter Variable";font-display:swap}@font-face{font-style:normal;font-weight:100 900;src:url("fonts/JetBrainsMono.woff2") format("woff2");font-family:"JetBrains Mono";font-display:swap}@font-face{font-style:italic;font-weight:100 900;src:url("fonts/JetBrainsMono-Italic.woff2") format("woff2");font-family:"JetBrains Mono";font-display:swap}body{font-family:"Inter Variable",var(--font-system-ui),var(--font-emoji)}h1,h2,h3,h4,h5,h6{font-weight:bold;font-family:"Inter Variable",var(--font-system-ui),var(--font-emoji)}h1{font-weight:900}pre,code,kbd,samp{font-family:"JetBrains Mono",var(--font-monospace-code)}

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Binäre Datei nicht angezeigt.

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,8 +0,0 @@
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
],
});
});

1209
katex.css

Datei-Diff unterdrückt, da er zu groß ist Diff laden

1
katex.min.js gevendort

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 96 B

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 103 KiB

Datei anzeigen

@ -1,4 +0,0 @@
User-agent: *
Disallow:
Allow: /
Sitemap: https://u42.dev/sitemap.xml

24
rss.xml
Datei anzeigen

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title>user0x42</title>
<link>https://u42.dev</link>
<description>Home of a Random Dude</description>
<generator>Zola</generator>
<language>en</language>
<atom:link href="https://u42.dev/rss.xml" rel="self" type="application/rss+xml"/>
<lastBuildDate>Fri, 20 Dec 2024 00:00:00 +0000</lastBuildDate>
<item>
<title>Random</title>
<pubDate>Fri, 20 Dec 2024 00:00:00 +0000</pubDate>
<author>user0x42</author>
<link>https://u42.dev/blog/u42/</link>
<guid>https://u42.dev/blog/u42/</guid>
<description xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</description>
</item>
</channel>
</rss>

40
sass/mods.scss Normale Datei
Datei anzeigen

@ -0,0 +1,40 @@
body {
font-family: "U42SansQuasiNerd", sans-serif;
}
@font-face {
font-family: "U42SansQuasiNerd";
src: url("/fonts/U42SansQuasiNerdFont-Extended.woff2") format("woff2");
font-weight: normal;
font-style: normal;
}
@import "../themes/duckquill/sass/_variables.scss";
@include theme-variables using ($theme) {
@if $theme == "dark" {
--bg-overlay: linear-gradient(rgb(0 0 0 / 0.6), rgb(0 0 0 / 0.6));
body {
font-family: "U42SansQuasiNerd", sans-serif;
background-image: var(--bg-overlay), url("bg.png");
background-position: center;
background-size: cover;
background-attachment: fixed;
}
} @else {
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
text-wrap: balance;
margin: 2rem 0 1rem;
font-weight: bold;
line-height: normal;
font-family: "U42SansQuasiNerd", sans-serif;
letter-spacing: 0em;
}

Datei anzeigen

@ -1,209 +0,0 @@
// Based on https://github.com/getzola/zola/blob/1ac1231de1e342bbaf4d7a51a8a9a40ea152e246/docs/static/search.js
function debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
timeout = null;
func.apply(context, args);
}, wait);
};
}
// Taken from mdbook
// The strategy is as follows:
// First, assign a value to each word in the document:
// Words that correspond to search terms (stemmer aware): 40
// Normal words: 2
// First word in a sentence: 8
// Then use a sliding window with a constant number of words and count the
// sum of the values of the words within the window. Then use the window that got the
// maximum sum. If there are multiple maximas, then get the last one.
// Enclose the terms in <b>.
function makeTeaser(body, terms) {
var TERM_WEIGHT = 40;
var NORMAL_WORD_WEIGHT = 2;
var FIRST_WORD_WEIGHT = 8;
var TEASER_MAX_WORDS = 30;
var stemmedTerms = terms.map(function (w) {
return elasticlunr.stemmer(w.toLowerCase());
});
var termFound = false;
var index = 0;
var weighted = []; // contains elements of ["word", weight, index_in_document]
// split in sentences, then words
var sentences = body.toLowerCase().split(". ");
for (var i in sentences) {
var words = sentences[i].split(" ");
var value = FIRST_WORD_WEIGHT;
for (var j in words) {
var word = words[j];
if (word.length > 0) {
for (var k in stemmedTerms) {
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
value = TERM_WEIGHT;
termFound = true;
}
}
weighted.push([word, value, index]);
value = NORMAL_WORD_WEIGHT;
}
index += word.length;
index += 1; // ' ' or '.' if last word in sentence
}
index += 1; // because we split at a two-char boundary '. '
}
if (weighted.length === 0) {
return body;
}
var windowWeights = [];
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
// We add a window with all the weights first
var curSum = 0;
for (var i = 0; i < windowSize; i++) {
curSum += weighted[i][1];
}
windowWeights.push(curSum);
for (var i = 0; i < weighted.length - windowSize; i++) {
curSum -= weighted[i][1];
curSum += weighted[i + windowSize][1];
windowWeights.push(curSum);
}
// If we didn't find the term, just pick the first window
var maxSumIndex = 0;
if (termFound) {
var maxFound = 0;
// backwards
for (var i = windowWeights.length - 1; i >= 0; i--) {
if (windowWeights[i] > maxFound) {
maxFound = windowWeights[i];
maxSumIndex = i;
}
}
}
var teaser = [];
var startIndex = weighted[maxSumIndex][2];
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
var word = weighted[i];
if (startIndex < word[2]) {
// missing text from index to start of `word`
teaser.push(body.substring(startIndex, word[2]));
startIndex = word[2];
}
// add <strong> around search terms
if (word[1] === TERM_WEIGHT) {
teaser.push("<strong>");
}
startIndex = word[2] + word[0].length;
teaser.push(body.substring(word[2], startIndex));
if (word[1] === TERM_WEIGHT) {
teaser.push("</strong>");
}
}
teaser.push("…");
return teaser.join("");
}
function formatSearchResultItem(item, terms) {
return '<div class="item">'
+ `<a href="${item.ref}">${item.doc.title}</a>`
+ `<span>${makeTeaser(item.doc.body, terms)}</span>`
+ '</div>';
}
function initSearch() {
var searchBar = document.getElementById("search-bar");
var searchContainer = document.getElementById("search-container");
var searchResults = document.getElementById("search-results");
var MAX_ITEMS = 10;
var options = {
bool: "AND",
fields: {
title: { boost: 2 },
body: { boost: 1 },
}
};
var currentTerm = "";
var index;
var initIndex = async function () {
if (index === undefined) {
let searchIndex = document.getElementById("search-index").textContent;
index = fetch(searchIndex)
.then(
async function (response) {
return await elasticlunr.Index.load(await response.json());
}
);
}
let res = await index;
return res;
}
searchBar.addEventListener("keyup", debounce(async function () {
var term = searchBar.value.trim();
if (term === currentTerm) {
return;
}
searchResults.style.display = term === "" ? "none" : "flex";
searchResults.innerHTML = "";
currentTerm = term;
if (term === "") {
return;
}
var results = (await initIndex()).search(term, options);
if (results.length === 0) {
searchResults.style.display = "none";
return;
}
for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) {
searchResults.innerHTML += formatSearchResultItem(results[i], term.split(" "));
}
}, 150));
document.addEventListener("keydown", function (event) {
if (event.key === "/") {
event.preventDefault();
toggleSearch();
}
});
document.getElementById("search-toggle").addEventListener("click", toggleSearch);
}
function toggleSearch() {
var searchContainer = document.getElementById("search-container");
var searchBar = document.getElementById("search-bar");
searchContainer.classList.toggle("active");
searchBar.toggleAttribute("disabled");
searchBar.focus();
}
if (document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
initSearch();
} else {
document.addEventListener("DOMContentLoaded", initSearch);
}

Datei anzeigen

@ -1,127 +0,0 @@
// Based on https://codeberg.org/daudix/duckquill/issues/101#issuecomment-2377169
let searchSetup = false;
let fuse;
async function initIndex() {
if (searchSetup) return;
const url = document.getElementById("search-index").textContent;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const options = {
includeScore: false,
includeMatches: true,
ignoreLocation: true,
threshold: 0.15,
keys: [
{ name: "title", weight: 3 },
{ name: "description", weight: 2 },
{ name: "body", weight: 1 }
]
};
fuse = new Fuse(await response.json(), options);
searchSetup = true;
console.log("Search index initialized successfully");
}
function toggleSearch() {
initIndex();
const searchBar = document.getElementById("search-bar");
const searchContainer = document.getElementById("search-container");
const searchResults = document.getElementById("search-results");
searchContainer.classList.toggle("active");
searchBar.toggleAttribute("disabled");
searchBar.focus();
}
function debounce(actual_fn, wait) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
actual_fn(...args);
}, wait);
};
};
function initSearch() {
const searchBar = document.getElementById("search-bar");
const searchResults = document.getElementById("search-results");
const searchContainer = document.getElementById("search-container");
const MAX_ITEMS = 10;
const MAX_RESULTS = 4;
let currentTerm = "";
searchBar.addEventListener("keyup", (e) => {
const searchVal = searchBar.value.trim();
const results = fuse.search(searchVal, { limit: MAX_ITEMS });
let html = "";
for (const result of results) {
html += makeTeaser(result, searchVal);
}
searchResults.innerHTML = html;
if (html) {
searchResults.style.display = "flex";
} else {
searchResults.style.display = "none";
}
});
function makeTeaser(result, searchVal) {
const TEASER_SIZE = 20;
let output = `<div class="search-result item"><a class="result-title" href=${result.item.url}>${result.item.title}</a>`;
for (const match of result.matches) {
if (match.key === "title") continue;
const indices = match.indices.sort((a, b) => Math.abs(a[1] - a[0] - searchVal.length) - Math.abs(b[1] - b[0] - searchVal.length)).slice(0, MAX_RESULTS);
const value = match.value;
for (const ind of indices) {
const start = Math.max(0, ind[0] - TEASER_SIZE);
const end = Math.min(value.length - 1, ind[1] + TEASER_SIZE);
output += "<span>"
+ value.substring(start, ind[0])
+ `<strong>${value.substring(ind[0], ind[1] + 1)}</strong>`
+ value.substring(ind[1] + 1, end)
+ "</span>";
}
if (match.indices.length > 4) {
const moreMatchesText = document.getElementById("more-matches-text").textContent;
output += `<span class="more-matches">${moreMatchesText}</span>`.replace("$MATCHES", `+${match.indices.length - MAX_RESULTS}`);
}
}
return output + "</div>";
}
/*window.addEventListener("click", function (event) {
if (searchSetup && searchBar.getAttribute("disabled") === null && !searchContainer.contains(event.target)) {
toggleSearch();
}
}, { passive: true });*/
document.addEventListener("keydown", function(event) {
if (event.key === "/") {
event.preventDefault();
toggleSearch();
}
});
document.getElementById("search-toggle").addEventListener("click", toggleSearch);
}
if (document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll))
initSearch();
else
document.addEventListener("DOMContentLoaded", initSearch);

Datei anzeigen

@ -1 +0,0 @@
[{"url":"https://u42.dev/blog/","title":"user0x42's Randomness","description":null,"body":"Blog full of Randomness.\n","path":null},{"url":"https://u42.dev/blog/u42/","title":"Random","description":null,"body":"Randomness\n\n\n\n","path":null},{"url":"https://u42.dev/","title":"Home","description":null,"body":"\n\t\n\n\n","path":null}]

Datei anzeigen

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://u42.dev/</loc>
</url>
<url>
<loc>https://u42.dev/blog/</loc>
</url>
<url>
<loc>https://u42.dev/blog/page/1/</loc>
</url>
<url>
<loc>https://u42.dev/blog/u42/</loc>
<lastmod>2024-12-20</lastmod>
</url>
<url>
<loc>https://u42.dev/tags/</loc>
</url>
<url>
<loc>https://u42.dev/tags/demo/</loc>
</url>
<url>
<loc>https://u42.dev/tags/test/</loc>
</url>
</urlset>

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 69 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 69 KiB

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 69 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 69 KiB

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 365 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 365 KiB

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 150 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 150 KiB

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 54 B

Nachher

Breite:  |  Höhe:  |  Größe: 54 B

Datei anzeigen

Vorher

Breite:  |  Höhe:  |  Größe: 30 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 30 KiB

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>user0x42 - Demo</title>
<subtitle>Home of a Random Dude</subtitle>
<link rel="self" type="application/atom+xml" href="https://u42.dev/tags/demo/atom.xml"/>
<link rel="alternate" type="text/html" href="https://u42.dev"/>
<generator uri="https://www.getzola.org/">Zola</generator>
<updated>2024-12-20T00:00:00+00:00</updated>
<id>https://u42.dev/tags/demo/atom.xml</id>
<entry xml:lang="en">
<title>Random</title>
<published>2024-12-20T00:00:00+00:00</published>
<updated>2024-12-20T00:00:00+00:00</updated>
<author>
<name>
user0x42
</name>
</author>
<link rel="alternate" type="text/html" href="https://u42.dev/blog/u42/"/>
<id>https://u42.dev/blog/u42/</id>
<content type="html" xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</content>
</entry>
</feed>

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title>user0x42 - Demo</title>
<link>https://u42.dev</link>
<description>Home of a Random Dude</description>
<generator>Zola</generator>
<language>en</language>
<atom:link href="https://u42.dev/tags/demo/rss.xml" rel="self" type="application/rss+xml"/>
<lastBuildDate>Fri, 20 Dec 2024 00:00:00 +0000</lastBuildDate>
<item>
<title>Random</title>
<pubDate>Fri, 20 Dec 2024 00:00:00 +0000</pubDate>
<author>user0x42</author>
<link>https://u42.dev/blog/u42/</link>
<guid>https://u42.dev/blog/u42/</guid>
<description xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</description>
</item>
</channel>
</rss>

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>user0x42 - Test</title>
<subtitle>Home of a Random Dude</subtitle>
<link rel="self" type="application/atom+xml" href="https://u42.dev/tags/test/atom.xml"/>
<link rel="alternate" type="text/html" href="https://u42.dev"/>
<generator uri="https://www.getzola.org/">Zola</generator>
<updated>2024-12-20T00:00:00+00:00</updated>
<id>https://u42.dev/tags/test/atom.xml</id>
<entry xml:lang="en">
<title>Random</title>
<published>2024-12-20T00:00:00+00:00</published>
<updated>2024-12-20T00:00:00+00:00</updated>
<author>
<name>
user0x42
</name>
</author>
<link rel="alternate" type="text/html" href="https://u42.dev/blog/u42/"/>
<id>https://u42.dev/blog/u42/</id>
<content type="html" xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</content>
</entry>
</feed>

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title>user0x42 - Test</title>
<link>https://u42.dev</link>
<description>Home of a Random Dude</description>
<generator>Zola</generator>
<language>en</language>
<atom:link href="https://u42.dev/tags/test/rss.xml" rel="self" type="application/rss+xml"/>
<lastBuildDate>Fri, 20 Dec 2024 00:00:00 +0000</lastBuildDate>
<item>
<title>Random</title>
<pubDate>Fri, 20 Dec 2024 00:00:00 +0000</pubDate>
<author>user0x42</author>
<link>https://u42.dev/blog/u42/</link>
<guid>https://u42.dev/blog/u42/</guid>
<description xml:base="https://u42.dev/blog/u42/">&lt;h2 id=&quot;randomness&quot;&gt;Randomness&lt;&#x2F;h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;u42.dev&#x2F;blog&#x2F;u42&#x2F;randomness.webp&quot; alt=&quot;The Office&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figure&gt;
</description>
</item>
</channel>
</rss>

125
templates/partials/head.html Normale Datei
Datei anzeigen

@ -0,0 +1,125 @@
<head>
<!-- {{ now() | date(format='%F %a %R') }} -->
<meta charset="UTF-8" />
<meta name="description" content="{{ config.description }}" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="{{ config.extra.accent_color | default(value='#9a9996') | safe }}" />
{%- if config.extra.accent_color_dark %}
<meta name="theme-color" content="{{ config.extra.accent_color_dark | safe }}" media="(prefers-color-scheme:dark)" />
{%- endif %}
{%- if config.extra.csp %}
{%- include "partials/csp.html" %}
{%- endif %}
<title>{% include "partials/title.html" %}</title>
<link rel="canonical" href="{{ current_url | default(value='/') | safe }}" />
{%- if config.extra.comments %}
<link rel="me" href="https://{{ config.extra.comments.host }}/@{{ config.extra.comments.user }}" />
<meta name="fediverse:creator" content="@{{ config.extra.comments.user }}@{{ config.extra.comments.host }}" />
{%- endif %}
{%- include "partials/favicon.html" %}
{%- if config.generate_feeds and config.feed_filenames %}
{% for feed in config.feed_filenames %}
{% if feed == "atom.xml" %}
<link rel="alternate" type="application/atom+xml" title="{{ config.title }} - Atom Feed" href="{{ get_url(path=feed) | safe }}">
{% elif feed == "rss.xml" %}
<link rel="alternate" type="application/rss+xml" title="{{ config.title }} - RSS Feed" href="{{ get_url(path=feed) | safe }}">
{% else %}
<link rel="alternate" href="{{ get_url(path=feed) | safe }}">
{% endif %}
{% endfor %}
{% endif %}
{%- include "partials/variables.html" %}
{%- set styles = [ "style.css" ] %}
{%- if config.extra.bundled_fonts %}
{%- set styles = styles | concat(with=["fonts.css"]) %}
{%- endif %}
{%- if page.extra.katex or section.extra.katex or config.extra.katex %}
{%- set styles = styles | concat(with=["katex.css"]) %}
{%- endif %}
{%- if config.extra.styles %}
{%- set styles = styles | concat(with=config.extra.styles) %}
{%- endif %}
{%- if page.extra.styles %}
{%- set styles = styles | concat(with=page.extra.styles) %}
{%- elif section.extra.styles %}
{%- set styles = styles | concat(with=section.extra.styles) %}
{%- endif %}
{%- if not config.extra.debug.no_styles %}
{%- for style in styles %}
<link type="text/css" rel="stylesheet" href="{{ get_url(path=style) | safe }}" />
{%- endfor %}
{%- if config.markdown.highlight_code and config.markdown.highlight_theme == "css" %}
{%- if config.markdown.highlight_themes_css | length > 0 %}
<link type="text/css" rel="stylesheet" href="{{ get_url(path='syntax-theme-light.css') }}" media="(prefers-color-scheme: light)" />
<link type="text/css" rel="stylesheet" href="{{ get_url(path='syntax-theme-dark.css') }}" media="(prefers-color-scheme: dark)" />
{%- else %}
<link type="text/css" rel="stylesheet" href="{{ get_url(path='syntax-theme.css') }}" />
{%- endif %}
{%- endif %}
{%- endif %}
{%- set scripts = ["closable.js"] %}
{%- if config.extra.show_copy_button %}
{%- set scripts = scripts | concat(with=["copy-button.js"]) %}
{%- endif %}
{%- if config.extra.goatcounter %}
{%- set scripts = scripts | concat(with=["count.js"]) %}
{%- endif %}
{%- if page.extra.katex or section.extra.katex or config.extra.katex %}
{%- set scripts = scripts | concat(with=["katex.min.js", "auto-render.min.js", "katex-init.js"]) %}
{%- endif %}
{%- if config.build_search_index %}
{%- if config.search.index_format == "elasticlunr_json" -%}
{%- set scripts = scripts | concat(with=["elasticlunr.min.js", "search-elasticlunr.js"]) %}
{%- elif config.search.index_format == "fuse_json" -%}
{%- set scripts = scripts | concat(with=["fuse.js", "search-fuse.js"]) %}
{%- endif -%}
{%- endif %}
{%- if config.extra.nav.show_theme_switcher %}
{%- set scripts = scripts | concat(with=["theme-switcher.js"]) %}
{%- endif %}
{%- if page.extra.comments.id %}
{%- set scripts = scripts | concat(with=["comments.js"]) %}
{%- endif %}
{%- if config.extra.scripts %}
{%- set scripts = scripts | concat(with=config.extra.scripts) %}
{%- endif %}
{%- if page.extra.scripts %}
{%- set scripts = scripts | concat(with=page.extra.scripts) %}
{%- elif section.extra.scripts %}
{%- set scripts = scripts | concat(with=section.extra.scripts) %}
{%- endif %}
{%- if scripts | length > 0 %}
{%- for script in scripts %}
<script type="text/javascript" defer {% if script == "count.js" %}data-goatcounter="https://{{ config.extra.goatcounter.user }}.{{ config.extra.goatcounter.host | default(value='goatcounter.com') }}/count"{% endif %} src="{{ get_url(path=script) | safe }}"></script>
{%- endfor %}
{%- endif %}
<script async src="https://anly.u42.dev/script.js" data-account-id="77bb6989-947c-49e7-82d5-f47829697762"></script>
<meta property="og:site_name" content="{{ config.title }}" />
<meta property="og:title" content="{% include 'partials/title.html' %}" />
<meta property="og:url" content="{{ current_url | default(value='/') | safe }}" />
<meta property="og:description" content="{% include 'partials/description.html' %}" />
<meta property="og:image" content="{% include 'partials/card.html' %}" />
<meta property="og:locale" content="{{ macros_translate::translate(key='date_locale', default='en_US', language_strings=language_strings) }}" />
</head>

Datei anzeigen

@ -1,104 +0,0 @@
// Theme Initialization
(function () {
// Get the default theme from the HTML data-theme attribute.
const defaultTheme = document.documentElement.getAttribute("data-theme");
// Set the data-default-theme attribute only if defaultTheme is not null.
if (defaultTheme) {
document.documentElement.setAttribute("data-default-theme", defaultTheme);
}
// Attempt to retrieve the current theme from the browser's local storage.
const storedTheme = localStorage.getItem("theme");
if (storedTheme && storedTheme !== "system") {
document.documentElement.setAttribute("data-theme", storedTheme);
} else if (defaultTheme && storedTheme !== "system") {
document.documentElement.setAttribute("data-theme", defaultTheme);
} else {
// If no theme is found in local storage and no default theme is set, hand over control to the CSS.
document.documentElement.removeAttribute("data-theme");
}
// Expose defaultTheme to the outer scope.
window.defaultTheme = defaultTheme;
})();
// Icon Update and Theme Switching
function setTheme(theme, saveToLocalStorage = false) {
if (theme === "system") {
document.documentElement.removeAttribute("data-theme");
} else {
document.documentElement.setAttribute("data-theme", theme);
}
if (saveToLocalStorage) {
localStorage.setItem("theme", theme);
} else {
localStorage.removeItem("theme");
}
// Update icon class based on the selected theme.
updateIconClass(theme);
// Update the active button based on the selected theme.
updateActiveButton(theme);
}
function resetTheme() {
// Reset the theme to the default or system preference if no default is set.
setTheme(window.defaultTheme || "system");
}
function switchTheme(theme) {
if (theme === "system") {
resetTheme();
} else {
setTheme(theme, true);
}
}
function updateIconClass(theme) {
const iconElement = document.querySelector("#theme-switcher summary .icon");
// Remove any existing theme classes
iconElement.classList.remove("light", "dark");
// Add the appropriate class based on the selected theme
if (theme === "light") {
iconElement.classList.add("light");
} else if (theme === "dark") {
iconElement.classList.add("dark");
}
}
function updateActiveButton(theme) {
// Remove .active class from all buttons
document.querySelectorAll('#theme-switcher button').forEach(button => {
button.classList.remove('active');
});
// Add .active class to the button corresponding to the current theme
const activeButton = document.querySelector(`#theme-${theme}`);
if (activeButton) {
activeButton.classList.add('active');
}
}
document.getElementById("theme-light").addEventListener("click", function () {
switchTheme("light");
});
document.getElementById("theme-dark").addEventListener("click", function () {
switchTheme("dark");
});
document.getElementById("theme-system").addEventListener("click", function () {
switchTheme("system");
});
// Update icon class on page load based on current theme
const currentTheme = localStorage.getItem("theme") || window.defaultTheme || "system";
updateIconClass(currentTheme);
updateActiveButton(currentTheme);
// Make the switchTheme function accessible globally
window.switchTheme = switchTheme;

1
themes/duckquill Submodul

@ -0,0 +1 @@
Subproject commit 66d2504350d37921be8a31c9cb24c151360fbd6e