Commits vergleichen
Keine gemeinsamen Commits. „web“ und „main“ haben vollständig unterschiedliche Historien.
2
.gitattributes
gevendort
Normale Datei
|
@ -0,0 +1,2 @@
|
||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
40
.github/workflows/cfpages-deploy.yml
gevendort
Normale Datei
|
@ -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
|
@ -0,0 +1,4 @@
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# Local Netlify folder
|
||||||
|
.netlify
|
3
.gitmodules
gevendort
Normale Datei
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "themes/duckquill"]
|
||||||
|
path = themes/duckquill
|
||||||
|
url = https://codeberg.org/daudix/duckquill.git
|
BIN
404.gif
Vorher Breite: | Höhe: | Größe: 4 KiB |
1
404.html
BIN
404.png
Vorher Breite: | Höhe: | Größe: 340 B |
9
LICENSE
Normale Datei
|
@ -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
|
@ -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
|
31
atom.xml
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</content>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</feed>
|
|
1
auto-render.min.js
gevendort
|
@ -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}()}));
|
|
|
@ -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.
|
|
BIN
card.png
Vorher Breite: | Höhe: | Größe: 1,2 MiB |
27
closable.js
|
@ -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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
406
comments.js
|
@ -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, "&")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
.replace(/"/g, """)
|
|
||||||
.replace(/'/g, "'");
|
|
||||||
}
|
|
||||||
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
|
@ -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
|
@ -0,0 +1,17 @@
|
||||||
|
+++
|
||||||
|
insert_anchor_links = "left"
|
||||||
|
title = "Home"
|
||||||
|
+++
|
||||||
|
|
||||||
|
{% crt() %}
|
||||||
|
```
|
||||||
|
╔──────────────────────────────────────────────────────────────────╗
|
||||||
|
│██╗---██╗███████╗███████╗██████╗--██████╗-██╗--██╗██╗--██╗██████╗-│
|
||||||
|
│██║---██║██╔════╝██╔════╝██╔══██╗██╔═████╗╚██╗██╔╝██║--██║╚════██╗│
|
||||||
|
│██║---██║███████╗█████╗--██████╔╝██║██╔██║-╚███╔╝-███████║-█████╔╝│
|
||||||
|
│██║---██║╚════██║██╔══╝--██╔══██╗████╔╝██║-██╔██╗-╚════██║██╔═══╝-│
|
||||||
|
│╚██████╔╝███████║███████╗██║--██║╚██████╔╝██╔╝-██╗-----██║███████╗│
|
||||||
|
│-╚═════╝-╚══════╝╚══════╝╚═╝--╚═╝-╚═════╝-╚═╝--╚═╝-----╚═╝╚══════╝│
|
||||||
|
╚──────────────────────────────────────────────────────────────────╝
|
||||||
|
```
|
||||||
|
{% end %}
|
Vorher Breite: | Höhe: | Größe: 247 KiB Nachher Breite: | Höhe: | Größe: 247 KiB |
9
content/blog/_index.md
Normale Datei
|
@ -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.
|
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
|
@ -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>
|
||||||
|
|
||||||
|

|
||||||
|
</figure>
|
Vorher Breite: | Höhe: | Größe: 503 KiB Nachher Breite: | Höhe: | Größe: 503 KiB |
|
@ -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
|
@ -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()
|
|
||||||
})
|
|
||||||
})();
|
|
|
@ -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)}
|
|
9
fuse.js
|
@ -1,8 +0,0 @@
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
renderMathInElement(document.body, {
|
|
||||||
delimiters: [
|
|
||||||
{ left: "$$", right: "$$", display: true },
|
|
||||||
{ left: "$", right: "$", display: false },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
1209
katex.css
1
katex.min.js
gevendort
1
mods.css
Vorher Breite: | Höhe: | Größe: 96 B |
Vorher Breite: | Höhe: | Größe: 103 KiB |
|
@ -1,4 +0,0 @@
|
||||||
User-agent: *
|
|
||||||
Disallow:
|
|
||||||
Allow: /
|
|
||||||
Sitemap: https://u42.dev/sitemap.xml
|
|
24
rss.xml
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</description>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
40
sass/mods.scss
Normale Datei
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
127
search-fuse.js
|
@ -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);
|
|
|
@ -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}]
|
|
25
sitemap.xml
|
@ -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>
|
|
Vorher Breite: | Höhe: | Größe: 69 KiB Nachher Breite: | Höhe: | Größe: 69 KiB |
Vorher Breite: | Höhe: | Größe: 69 KiB Nachher Breite: | Höhe: | Größe: 69 KiB |
Vorher Breite: | Höhe: | Größe: 365 KiB Nachher Breite: | Höhe: | Größe: 365 KiB |
Vorher Breite: | Höhe: | Größe: 150 KiB Nachher Breite: | Höhe: | Größe: 150 KiB |
Vorher Breite: | Höhe: | Größe: 54 B Nachher Breite: | Höhe: | Größe: 54 B |
Vorher Breite: | Höhe: | Größe: 30 KiB Nachher Breite: | Höhe: | Größe: 30 KiB |
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</content>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</feed>
|
|
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</description>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</content>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</feed>
|
|
|
@ -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/"><h2 id="randomness">Randomness</h2>
|
|
||||||
<figure>
|
|
||||||
<p><img src="https://u42.dev/blog/u42/randomness.webp" alt="The Office" /></p>
|
|
||||||
</figure>
|
|
||||||
</description>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
125
templates/partials/head.html
Normale Datei
|
@ -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>
|
|
@ -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
|