Highlight old posts in Hugo

I added a small notice that appears on posts older than a year. It was important to me that this notice not show up on photo-only posts — after all, photos rarely lose their relevance. First I wrote a working version myself, then had a language model further optimize the code. Now I’m running the following variant: {{- /* Tags prüfen */ -}} {{- $tags := default (slice) .Params.tags -}} {{- $tagsLower := apply $tags "lower" "." -}} {{- $hasPhoto := in $tagsLower "photo" -}} {{- /* Relevantes Datum bestimmen und Stichtag berechnen */ -}} {{- $pageDate := time.AsTime (or .Lastmod .PublishDate .Date) -}} {{- $oneYearAgo := (now).AddDate -1 0 0 -}} {{- /*Hinweis nur auf echten Seiten, mit gültigem Datum, älter als 1 Jahr und nicht beim Tag "photo" */ -}} {{- if and .IsPage (not $hasPhoto) (gt ($pageDate.Unix) 0) (lt $pageDate $oneYearAgo) -}} <div class="alert alert-warning"> Hinweis: Dieser Artikel ist über ein Jahr alt. Die Informationen könnten veraltet sein. </div> {{- end -}} The text was automatically translated from German into English. The German quotations were also translated in sense. ...

October 21, 2025 · 1 min · 182 words

Bookmarklet Blogging

I recently came across an interesting Bookmarklet bei Nicolas. It’s meant to make link-blogging easier for anyone with a GitHub-hosted blog. The script isn’t perfect yet, but it inspired me to develop it further. Here’s my version of the bookmarklet (function() { // Funktion zum Erstellen eines "Slug" aus einem Text const slugify = text => { let str = text.toString(); // Den Text als Zeichenkette behandeln str = str.replaceAll("/", " "); // Schrägstriche (/) durch Leerzeichen ersetzen str = str.normalize("NFD"); // Unicode normalisieren (diakritische Zeichen trennen) str = str.replace(/[^\w\s-]+/g, ""); // Sonderzeichen entfernen (außer Buchstaben, Zahlen, Leerzeichen, Bindestriche) str = str.toLowerCase(); // In Kleinbuchstaben umwandeln str = str.replace(/\s+/g, " "); // Mehrere Leerzeichen auf ein einzelnes reduzieren str = str.trim(); // Führende und endende Leerzeichen entfernen str = str.replace(/ +/g, "-"); // Alle Leerzeichen durch Bindestriche ersetzen return str; // Slug zurückgeben }; // Titel der aktuellen Seite aus dem Dokument abrufen let pageTitle = window.document.title; // Falls ein Text markiert ist, diesen als "linkSelection" setzen, ansonsten leer let linkSelection = "getSelection" in window ? window.getSelection().toString().trim() : ""; // Inhalt für den Link ermitteln: // Zuerst den markierten Text verwenden, falls vorhanden, ansonsten eine Meta-Beschreibung, // oder den ersten Absatz im <main>, <article>, oder <p>-Tag let linkContent = linkSelection || window.document.querySelector("head meta[name=description]")?.content.trim() || window.document.querySelector("main p")?.textContent.trim() || window.document.querySelector("article p")?.textContent.trim() || window.document.querySelector("p")?.textContent.trim(); // Die URL der aktuellen Seite let linkUrl = window.location.href; // Eingabeaufforderung für den Link-Titel (Standardwert: Seiten-Titel) let title = window.prompt("Title of the link?", pageTitle); if (title !== null) { // Nur fortfahren, wenn der Benutzer einen Titel angegeben hat // Eingabeaufforderung für den Link-Slug (Standardwert: aus Titel generierter Slug) let slug = window.prompt("Slug of the link?", slugify(title)); if (slug !== null) { // Nur fortfahren, wenn der Benutzer einen Slug angegeben hat // Das aktuelle Datum und die Uhrzeit im ISO-Format abrufen und in lesbare Form bringen const currentDate = (new Date()).toISOString().replace("T", " ").replace(/\.\d{3}Z/, " +00:00"); // Dateiinhalt für den Blogeintrag erstellen let fileContent = `---\n` + `date: ${currentDate}\n` + `title: "${title}"\n` + `authors: "maik"\n` + `tags: []\n` + `---\n\n` + `[${title}](${linkUrl} "${title}") für ${linkUrl}\n\n` + `${linkContent ? linkContent.replaceAll("\n", "\n> ") : ""}\n`; // GitHub-URL für das Erstellen einer neuen Datei zusammenbauen let githubUrl = `https://github.com/Maik-Wi/blog/new/main/?` + `filename=${`content/notes/${currentDate.slice(0, 10)}-${slug}-index.md`}` + `&value=${encodeURIComponent(fileContent)}` + `&message=${encodeURIComponent(`New link: ${title}`)}`; // Die URL in einem neuen Fenster öffnen, sodass der Nutzer sie bei GitHub weiterbearbeiten kann window.open(githubUrl); } } })(); The text was automatically translated from German into English. The German quotations were also translated in sense. ...

August 19, 2024 · 2 min · 414 words

Externe Umleitung in Hugo

As a blogger today, I wanted to redirect URLs that point to a subdirectory to an external destination. In the blog post ‘Using Hugo as a redirect service’ by Daniel Terhorst-North I came across a very lean solution. To achieve this, the following file must be created in the theme folder: /layouts/redirect/single.html. The following source code must be added to the file: {{- template "_internal/alias.html" (dict "Permalink" .Params.target) -}} You can now create a file and define the redirect with the following four lines. The filename also determines the directory of the source URL: ...

December 17, 2023 · 1 min · 117 words

Apple Store Notifier

Apple announced new products a few days ago. As always, stock in the stores is limited. If you’re smart, you check online whether the product you want is available at your local Apple Store. If you’re lazy, use the following Python script to automate that. Note: Pushover is required. #!/usr/bin/env python3 import requests import os import time def fetch_availability(product_number, store_id): payload = { "store": store_id, "little": False, "mt": "regular", "parts.0": product_number, "fts": True, } url = "https://www.apple.com/de/shop/fulfillment-messages" r = requests.get(url, params=payload) data = r.json() stores = data["body"]["content"]["pickupMessage"]["stores"] store = next(store for store in stores if store["storeNumber"] == store_id) avail = store["partsAvailability"][product_number] return { "store_name": store.get("storeName"), "available": avail.get("pickupDisplay") != "ineligible", "store_pickup_quote": avail.get("storePickupQuote"), "pickup_search_quote": avail.get("pickupSearchQuote"), "pickup_display": avail.get("pickupDisplay"), } def assemble_availability_text(product_number, store_ids): avail_text = "" for store_id in store_ids: avail = fetch_availability(product_number, store_id) avail_text += f'{avail["store_name"]}: {avail["store_pickup_quote"]}\n' return avail_text def create_file_if_not_exists(filepath): if not os.path.exists(filepath): with open(filepath, "w") as f: f.write("") def do_it(part_no, store_ids, **kwargs): availability_text = assemble_availability_text(part_no, store_ids) create_file_if_not_exists("/tmp/cache.txt") with open("/tmp/cache.txt", "r+", encoding="utf-8") as f: if f.read() == availability_text: print("No Changes", flush=True) else: print("Changes detected", availability_text, flush=True) if kwargs["pushover_enabled"] == "1": requests.post( "https://api.pushover.net/1/messages.json", data={ "token": kwargs["pushover_token"], "user": kwargs["pushover_user"], "message": availability_text, "title": "CHANGES DETECTED", }, headers={"Content-Type": "application/x-www-form-urlencoded"}, ) f.truncate(0) f.seek(0) f.write(availability_text) if __name__ == "__main__": while True: do_it( os.environ["MONITORED_PART_NO"], os.environ["MONITORED_STORES"].split(","), pushover_enabled=os.environ["PUSHOVER_ENABLED"], pushover_token=os.environ["PUSHOVER_TOKEN"], pushover_user=os.environ["PUSHOVER_USER"], ) time.sleep(int(os.environ["POLLING_DELAY_SECONDS"])) The script is in the repository dprandzioch/apple-store-notifier on GitHub. ...

March 19, 2022 · 2 min · 243 words

Ghost Bookmarklet

After switching from Grav to Ghost I have to tweak a few articles. To be able to quickly jump from the frontend to the backend, I wrote a super-simple bookmarklet. Just save the following code as a bookmark. javascript:window.location.href=window.location.href+'/edit'; After you click the bookmark, the browser will navigate to http://DEINEBLOG.URL/edit and, if you’re logged in, you can edit the article directly. The text was automatically translated from German into English. The German quotations were also translated in sense. ...

December 23, 2021 · 1 min · 78 words