Init Commit

This commit is contained in:
2026-05-18 11:46:02 +02:00
commit 2de3502fbc
382 changed files with 19583 additions and 0 deletions
@@ -0,0 +1 @@
!function(){function e(e,t){document.addEventListener?e.addEventListener("scroll",t,!1):e.attachEvent("scroll",t)}function t(e){this.a=document.createElement("div"),this.a.setAttribute("aria-hidden","true"),this.a.appendChild(document.createTextNode(e)),this.b=document.createElement("span"),this.c=document.createElement("span"),this.h=document.createElement("span"),this.f=document.createElement("span"),this.g=-1,this.b.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;",this.c.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;",this.f.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;",this.h.style.cssText="display:inline-block;width:200%;height:200%;font-size:16px;max-width:none;",this.b.appendChild(this.h),this.c.appendChild(this.f),this.a.appendChild(this.b),this.a.appendChild(this.c)}function n(e,t){e.a.style.cssText="max-width:none;min-width:20px;min-height:20px;display:inline-block;overflow:hidden;position:absolute;width:auto;margin:0;padding:0;top:-999px;white-space:nowrap;font-synthesis:none;font:"+t+";"}function i(e){var t=e.a.offsetWidth,n=t+100;return e.f.style.width=n+"px",e.c.scrollLeft=n,e.b.scrollLeft=e.b.scrollWidth+100,e.g!==t&&(e.g=t,!0)}function o(t,n){function o(){var e=s;i(e)&&e.a.parentNode&&n(e.g)}var s=t;e(t.b,o),e(t.c,o),i(t)}function s(e,t){var n=t||{};this.family=e,this.style=n.style||"normal",this.weight=n.weight||"normal",this.stretch=n.stretch||"normal"}var a=null,d=null,r=null,c=null;function l(){return null===c&&(c=!!document.fonts),c}function h(){if(null===r){var e=document.createElement("div");try{e.style.font="condensed 100px sans-serif"}catch(e){}r=""!==e.style.font}return r}function u(e,t){return[e.style,e.weight,h()?e.stretch:"","100px",t].join(" ")}s.prototype.load=function(e,i){var s=this,r=e||"BESbswy",c=0,h=i||3e3,f=(new Date).getTime();return new Promise(function(e,i){if(l()&&!function(){if(null===d)if(l()&&/Apple/.test(window.navigator.vendor)){var e=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))(?:\.([0-9]+))/.exec(window.navigator.userAgent);d=!!e&&603>parseInt(e[1],10)}else d=!1;return d}()){var p=new Promise(function(e,t){!function n(){(new Date).getTime()-f>=h?t(Error(h+"ms timeout exceeded")):document.fonts.load(u(s,'"'+s.family+'"'),r).then(function(t){1<=t.length?e():setTimeout(n,25)},t)}()}),m=new Promise(function(e,t){c=setTimeout(function(){t(Error(h+"ms timeout exceeded"))},h)});Promise.race([m,p]).then(function(){clearTimeout(c),e(s)},i)}else!function(e){document.body?e():document.addEventListener?document.addEventListener("DOMContentLoaded",function t(){document.removeEventListener("DOMContentLoaded",t),e()}):document.attachEvent("onreadystatechange",function t(){"interactive"!=document.readyState&&"complete"!=document.readyState||(document.detachEvent("onreadystatechange",t),e())})}(function(){function d(){var t;(t=-1!=w&&-1!=v||-1!=w&&-1!=y||-1!=v&&-1!=y)&&((t=w!=v&&w!=y&&v!=y)||(null===a&&(t=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent),a=!!t&&(536>parseInt(t[1],10)||536===parseInt(t[1],10)&&11>=parseInt(t[2],10))),t=a&&(w==x&&v==x&&y==x||w==b&&v==b&&y==b||w==g&&v==g&&y==g)),t=!t),t&&(E.parentNode&&E.parentNode.removeChild(E),clearTimeout(c),e(s))}var l=new t(r),p=new t(r),m=new t(r),w=-1,v=-1,y=-1,x=-1,b=-1,g=-1,E=document.createElement("div");E.dir="ltr",n(l,u(s,"sans-serif")),n(p,u(s,"serif")),n(m,u(s,"monospace")),E.appendChild(l.a),E.appendChild(p.a),E.appendChild(m.a),document.body.appendChild(E),x=l.a.offsetWidth,b=p.a.offsetWidth,g=m.a.offsetWidth,function e(){if((new Date).getTime()-f>=h)E.parentNode&&E.parentNode.removeChild(E),i(Error(h+"ms timeout exceeded"));else{var t=document.hidden;!0!==t&&void 0!==t||(w=l.a.offsetWidth,v=p.a.offsetWidth,y=m.a.offsetWidth,d()),c=setTimeout(e,50)}}(),o(l,function(e){w=e,d()}),n(l,u(s,'"'+s.family+'",sans-serif')),o(p,function(e){v=e,d()}),n(p,u(s,'"'+s.family+'",serif')),o(m,function(e){y=e,d()}),n(m,u(s,'"'+s.family+'",monospace'))})})},"object"==typeof module?module.exports=s:(window.FontFaceObserver=s,window.FontFaceObserver.prototype.load=s.prototype.load)}();
@@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",function(){var e=[].slice.call(document.querySelectorAll("img.lazy")),t=[].slice.call(document.querySelectorAll(".lazy-background")),n=[].slice.call(document.querySelectorAll("[data-bg]"));if("IntersectionObserver"in window){let c=new IntersectionObserver(function(e,t){e.forEach(function(e){if(e.isIntersecting){let t=e.target;t.src=t.dataset.src,t.srcset=t.dataset.srcset,t.classList.remove("lazy"),c.unobserve(t)}})});e.forEach(function(e){c.observe(e)});let r=new IntersectionObserver(function(e,t){e.forEach(function(e){e.isIntersecting&&(e.target.classList.add("visible"),r.unobserve(e.target))})});t.forEach(function(e){r.observe(e)});let s=new IntersectionObserver(function(e,t){e.forEach(function(e){if(e.isIntersecting){let t=e.target;t.style.backgroundImage="url("+t.dataset.bg+")",s.unobserve(t)}})});n.forEach(function(e){s.observe(e)})}else e.forEach(function(e){e.src=e.dataset.src,e.srcset=e.dataset.srcset}),t.forEach(function(e){e.classList.add("visible")}),n.forEach(function(e){e.style.backgroundImage="url("+e.dataset.bg+")"})});
+10
View File
@@ -0,0 +1,10 @@
/*! lozad.js - v1.14.0 - 2019-10-19
* https://github.com/ApoorvSaxena/lozad.js
* Copyright (c) 2019 Apoorv Saxena; Licensed MIT */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).lozad=e()}(this,function(){"use strict";
/**
* Detect IE browser
* @const {boolean}
* @private
*/var d="undefined"!=typeof document&&document.documentMode,c={rootMargin:"0px",threshold:0,load:function(t){if("picture"===t.nodeName.toLowerCase()){var e=document.createElement("img");d&&t.getAttribute("data-iesrc")&&(e.src=t.getAttribute("data-iesrc")),t.getAttribute("data-alt")&&(e.alt=t.getAttribute("data-alt")),t.append(e)}if("video"===t.nodeName.toLowerCase()&&!t.getAttribute("data-src")&&t.children){for(var r=t.children,a=void 0,o=0;o<=r.length-1;o++)(a=r[o].getAttribute("data-src"))&&(r[o].src=a);t.load()}if(t.getAttribute("data-src")&&(t.src=t.getAttribute("data-src")),t.getAttribute("data-srcset")&&t.setAttribute("srcset",t.getAttribute("data-srcset")),t.getAttribute("data-background-image"))t.style.backgroundImage="url('"+t.getAttribute("data-background-image").split(",").join("'),url('")+"')";else if(t.getAttribute("data-background-image-set")){var i=t.getAttribute("data-background-image-set").split(","),n=i[0].substr(0,i[0].indexOf(" "))||i[0];// Substring before ... 1x
n=-1===n.indexOf("url(")?"url("+n+")":n,1===i.length?t.style.backgroundImage=n:t.setAttribute("style",(t.getAttribute("style")||"")+"background-image: "+n+"; background-image: -webkit-image-set("+i+"); background-image: image-set("+i+")")}t.getAttribute("data-toggle-class")&&t.classList.toggle(t.getAttribute("data-toggle-class"))},loaded:function(){}};function l(t){t.setAttribute("data-loaded",!0)}var b=function(t){return"true"===t.getAttribute("data-loaded")};return function(){var r,a,o=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".lozad",t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},e=Object.assign({},c,t),i=e.root,n=e.rootMargin,d=e.threshold,u=e.load,s=e.loaded,g=void 0;return"undefined"!=typeof window&&window.IntersectionObserver&&(g=new IntersectionObserver((r=u,a=s,function(t,e){t.forEach(function(t){(0<t.intersectionRatio||t.isIntersecting)&&(e.unobserve(t.target),b(t.target)||(r(t.target),l(t.target),a(t.target)))})}),{root:i,rootMargin:n,threshold:d})),{observe:function(){for(var t=function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:document;return t instanceof Element?[t]:t instanceof NodeList?t:e.querySelectorAll(t)}(o,i),e=0;e<t.length;e++)b(t[e])||(g?g.observe(t[e]):(u(t[e]),l(t[e]),s(t[e])))},triggerLoad:function(t){b(t)||(u(t),l(t),s(t))},observer:g}}});
File diff suppressed because one or more lines are too long
View File
@@ -0,0 +1 @@
let sectionIntersectOptions={rootMargin:"9999px 0px 0px 0px",threshold:.2};const onSectionIntersect=e=>{let t=0;animatedNodes.forEach(n=>{e.target.contains(n)&&(n.style.animationDelay=`${nodeDelayDelta*t+.1}s`,n.classList.add("rad-animate"),t++)})},onSectionIntersectChange=(e,t)=>{e.forEach(e=>{e.isIntersecting&&onSectionIntersect(e)})};let animationObserver=new IntersectionObserver(onSectionIntersectChange,sectionIntersectOptions);const animatedNodes=Array.from(document.querySelectorAll(".rad-fade-down, .rad-fade-in, .rad-fade-in-long, .rad-scale-down")),animatedSections=Array.from(document.querySelectorAll(".rad-animation-group")),nodeDelayDelta=.2,sectionDelayDelta=.2;animatedNodes.forEach((e,t)=>{e.classList.add("rad-waiting")}),animatedSections.forEach((e,t)=>{animationObserver.observe(e)});
+378
View File
@@ -0,0 +1,378 @@
summaryInclude = 60;
const fuseOptions = {
shouldSort: true,
includeMatches: true,
threshold: 0.0,
tokenize: true,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
{ name: "title", weight: 0.9 },
{ name: "contents", weight: 0.5 },
{ name: "tags", weight: 0.3 },
{ name: "categories", weight: 0.3 },
],
};
// Display error message in the search results container
function displayError(message) {
const searchResultsElement = document.getElementById("search-results");
if (searchResultsElement) {
const sanitizedMessage = DOMPurify.sanitize(message);
searchResultsElement.innerHTML = `<div class="alert alert-danger">${sanitizedMessage}</div>`;
} else {
console.error("Search results container not found");
}
}
// Safely get DOM element with error handling
function getElement(id) {
const element = document.getElementById(id);
if (!element) {
console.error(`Element with ID '${id}' not found`);
}
return element;
}
// Debounce function to prevent excessive search calls
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Function to update URL with search query
function updateURL(query) {
try {
// Create a URL object from the current URL
const url = new URL(window.location.href);
if (query && query.length >= 2) {
// Set or update the 's' parameter
url.searchParams.set("s", query);
} else {
// Remove the 's' parameter if query is empty or too short
url.searchParams.delete("s");
}
// Update the URL without reloading the page
window.history.replaceState({}, "", url.toString());
} catch (error) {
console.error("Error updating URL:", error);
// Continue without URL update - non-critical error
}
}
// Safe parameter extraction with error handling
function param(name) {
try {
const paramValue = (location.search.split(`${name}=`)[1] || "").split("&")[0];
return paramValue ? decodeURIComponent(paramValue).replace(/\+/g, " ") : "";
} catch (error) {
console.error(`Error parsing URL parameter '${name}':`, error);
return "";
}
}
// Get search query from URL parameter
const searchQuery = param("s");
try {
const searchInput = getElement("search-query");
const searchResults = getElement("search-results");
if (searchInput && searchQuery) {
searchInput.value = searchQuery;
executeSearch(searchQuery);
} else if (searchResults) {
searchResults.innerHTML =
"<div class='alert'>Please enter at least 2 characters to search</div>";
}
} catch (error) {
console.error("Error initializing search:", error);
displayError(
"There was a problem initializing the search. Please try again later.",
);
}
// Add event listener for real-time searching
document.addEventListener("DOMContentLoaded", () => {
try {
const searchInput = getElement("search-query");
if (!searchInput) {
throw new Error("Search input not found");
}
// Create debounced search function - 300ms is a good balance
const debouncedSearch = debounce((query) => {
// Update URL with current search query
updateURL(query);
const searchResults = getElement("search-results");
if (!searchResults) {
throw new Error("Search results container not found");
}
if (query.length >= 2) {
executeSearch(query);
} else if (query.length === 0 || query.length === 1) {
searchResults.innerHTML =
"<div class='alert'>Please enter at least 2 characters to search</div>";
}
}, 300);
// Set up input event for real-time searching
searchInput.addEventListener("input", function () {
const query = this.value.trim();
debouncedSearch(query);
});
// Handle form submission to prevent page reload
const searchForm = searchInput.closest("form");
if (searchForm) {
searchForm.addEventListener("submit", (e) => {
e.preventDefault();
const query = searchInput.value.trim();
if (query.length >= 2) {
updateURL(query);
executeSearch(query);
}
});
}
} catch (error) {
console.error("Error setting up search event listeners:", error);
displayError(
"There was a problem setting up the search functionality. Please try reloading the page.",
);
}
});
function executeSearch(searchQuery) {
try {
if (!searchQuery || typeof searchQuery !== "string") {
throw new Error("Invalid search query");
}
const searchResults = getElement("search-results");
if (!searchResults) {
throw new Error("Search results container not found");
}
// Show loading indicator
searchResults.innerHTML =
'<div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>';
fetch("/index.json")
.then((response) => {
if (!response.ok) {
throw new Error(
`Network response was not ok: ${response.status} ${response.statusText}`,
);
}
return response.json();
})
.then((data) => {
if (!Array.isArray(data)) {
throw new Error("Received invalid data format from server");
}
const pages = data;
const fuse = new Fuse(pages, fuseOptions);
const result = fuse.search(searchQuery);
// Clear previous results only when we have new results to show
searchResults.innerHTML = "";
if (result.length > 0) {
populateResults(result);
} else {
searchResults.insertAdjacentHTML(
"beforeend",
"<div class='alert'>No matches found</div>",
);
}
})
.catch((error) => {
console.error("Error executing search:", error);
displayError(`Failed to search: ${error.message}`);
});
} catch (error) {
console.error("Error in search execution:", error);
displayError("There was a problem with the search. Please try again later.");
}
}
function populateResults(result) {
try {
if (!Array.isArray(result)) {
throw new Error("Invalid search results");
}
const searchResults = getElement("search-results");
if (!searchResults) {
throw new Error("Search results container not found");
}
const templateElement = document.getElementById("search-result-template");
if (!templateElement) {
throw new Error("Search result template not found");
}
const templateDefinition = templateElement.innerHTML;
for (const [key, value] of result.entries()) {
if (!value || !value.item) {
console.warn("Skipping invalid search result item", value);
continue;
}
const contents = value.item.contents || "";
let snippet = "";
const snippetHighlights = [];
let start;
let end;
if (fuseOptions.tokenize) {
snippetHighlights.push(searchQuery);
} else {
if (value.matches) {
for (const mvalue of value.matches) {
if (!mvalue || typeof mvalue.key !== "string") {
continue;
}
if (
mvalue.key === "tags" ||
mvalue.key === "categories"
) {
snippetHighlights.push(mvalue.value);
} else if (
mvalue.key === "contents" &&
Array.isArray(mvalue.indices) &&
mvalue.indices.length > 0
) {
try {
start =
mvalue.indices[0][0] - summaryInclude > 0
? mvalue.indices[0][0] - summaryInclude
: 0;
end =
mvalue.indices[0][1] + summaryInclude < contents.length
? mvalue.indices[0][1] + summaryInclude
: contents.length;
snippet += contents.substring(start, end);
if (typeof mvalue.value === "string") {
const highlightValue =
mvalue.indices[0][1] - mvalue.indices[0][0] + 1;
if (
highlightValue > 0 &&
mvalue.indices[0][0] < mvalue.value.length
) {
snippetHighlights.push(
mvalue.value.substring(
mvalue.indices[0][0],
mvalue.indices[0][0] + highlightValue,
),
);
}
}
} catch (e) {
console.warn("Error processing match indices", e);
}
}
}
}
}
if (snippet.length < 1 && contents) {
snippet += contents.substring(0, summaryInclude * 2);
}
try {
// Insert the templated result
const output = render(templateDefinition, {
key: key,
title: value.item.title || "Untitled",
link: value.item.permalink || "#",
tags: value.item.tags || "",
categories: value.item.categories || "",
snippet: snippet || "No preview available",
});
searchResults.insertAdjacentHTML("beforeend", output);
// Add highlighting after insertion
for (const snipvalue of snippetHighlights) {
if (!snipvalue) continue;
const summaryElem = document.getElementById(`summary-${key}`);
if (summaryElem && typeof Mark !== "undefined") {
try {
const markInstance = new Mark(summaryElem);
markInstance.mark(snipvalue);
} catch (e) {
console.warn("Error highlighting text:", e);
}
}
}
} catch (error) {
console.error("Error rendering search result:", error);
}
}
} catch (error) {
console.error("Error populating results:", error);
displayError("There was a problem displaying search results.");
}
}
function render(templateString, data) {
try {
if (!templateString || !data) {
throw new Error("Invalid template or data");
}
let conditionalMatches, conditionalPattern, copy;
conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
// Since loop below depends on re.lastIndex, we use a copy to capture any manipulations
copy = templateString;
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
if (conditionalMatches.length < 3) continue;
if (data[conditionalMatches[1]]) {
// Valid key, remove conditionals, leave contents
copy = copy.replace(conditionalMatches[0], conditionalMatches[2]);
} else {
// Not valid, remove entire section
copy = copy.replace(conditionalMatches[0], "");
}
}
let result = copy;
// Now any conditionals removed we can do simple substitution
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
const value = data[key];
if (value !== undefined && value !== null) {
const find = `\\$\\{\\s*${key}\\s*\\}`;
const re = new RegExp(find, "g");
result = result.replace(re, value);
}
}
}
return result;
} catch (error) {
console.error("Error rendering template:", error);
return '<div class="alert alert-danger">Error rendering result</div>';
}
}
@@ -0,0 +1,27 @@
const scroll = new SmoothScroll('a[href*="#"]');
const navLinks = document.querySelectorAll('a.nav-link');
navLinks.forEach(navLink => {
navLink.addEventListener('click', (e) => {
const navbar = document.getElementById('navbarSupportedContent');
if (navbar && navbar.classList.contains('show')) {
simulateClick(document.querySelector('.navbar-toggler'));
}
});
});
/**
* Simulate a click event.
* @public
* @param {Element} elem the element to simulate a click on
* @see https://gomakethings.com/how-to-simulate-a-click-event-with-javascript/
*/
var simulateClick = function (elem) {
// Create our event (with options)
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
// If cancelled, don't dispatch our event
var canceled = !elem.dispatchEvent(evt);
};
@@ -0,0 +1,45 @@
class StickyHeader {
constructor(t) {
(this.header = t),
(this.body = document.querySelector("body")),
(this.thresholdPosition = 15),
(this.triggeredStickyClass = "header--sticky-triggered"),
(this.stickyClass = "header--sticky"),
(this.ticking = false),
(this.bodyPosition = 0),
window.addEventListener("DOMContentLoaded", () => this.initSticky()),
this.scrollChanged();
this.navbar = document.getElementById('navbarSupportedContent');
// add window resize listener
window.addEventListener("resize", () => this.resizeHandler());
}
initSticky() {
(this.headerStaticHeight = this.header.getBoundingClientRect().height),
this.header.classList.toggle(this.stickyClass, true),
window.addEventListener("scroll", () => this.scrollHandler());
}
scrollHandler() {
this.ticking ||
(window.requestAnimationFrame(() => {
this.scrollChanged(), (this.ticking = false);
}),
(this.ticking = true));
}
scrollChanged() {
(this.bodyPosition = Math.abs(this.body.getBoundingClientRect().top)),
this.bodyPosition > this.thresholdPosition
? this.header.classList.toggle(this.triggeredStickyClass, true)
: this.header.classList.toggle(this.triggeredStickyClass, false);
}
resizeHandler() {
// if the window size is larger than 992px and the navbar is displayed,
// toggle the navbar to hide it
if (window.innerWidth > 991) {
if (this.navbar?.classList.contains('show')) {
simulateClick(document.querySelector('.navbar-toggler'));
}
}
}
}
const stickyHeader = new StickyHeader(document.querySelector(".header"));
@@ -0,0 +1 @@
const radSubscriptionRequest=(e="",s={})=>fetch(e,{method:"POST",mode:"cors",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"},redirect:"follow",referrer:"no-referrer",body:JSON.stringify(s)}).then(e=>e.json()),makeSubscriptionRequest=async(e,s)=>{e.preventDefault();try{s.querySelector("#rad-subscription-submit").classList.add("is-loading"),await radSubscriptionRequest("",{email:s.querySelector("#rad-subscription-email").value}),s.classList.add("d-none"),document.querySelector("#rad-subscription-success").classList.remove("d-none"),document.querySelector("#rad-subscription-success").classList.add("d-flex")}catch(e){s.classList.add("d-none"),document.querySelector("#rad-subscription-fail").classList.remove("d-none"),document.querySelector("#rad-subscription-fail").classList.add("d-flex")}finally{s.querySelector("#rad-subscription-submit").classList.remove("is-loading")}},initRadSubscription=()=>{const e=document.querySelector("#rad-subscription");e&&e.addEventListener("submit",s=>makeSubscriptionRequest(s,e))};initRadSubscription();