Kategorie: Praxis

  • Dateiumbenennung nach Velsz in Bridge

    Wir machen das in zwei Stufen: zuerst bereinigen wir alle üblichen Datumsangaben in dem Ordner, in dem wir die Umbenennung vornehmen wollen, dann machen wir die Umbenennung in Bridge.

    Vorbereitungsskript zur Bereinigung von Dateinamen (vor der Umbenennung in Adobe Bridge)

    Mein Python-Skript dient dazu, Datumseinträge aus Dateinamen zu entfernen, bevor die eigentliche Umbenennung mit Adobe Bridge erfolgt. Es hilft mir dabei, doppelte oder inkonsistente Datumsangaben zu vermeiden, wenn Bridge später ein neues Datum hinzufügt.

    Was mein Skript macht

    • Durchsucht den Ordner, in dem sich das Skript befindet
    • Erkennt typische Datumsformate im Dateinamen:
      • YYYY-MM-DD (z. B. 2023-08-07)
      • DD-MM-YYYY (z. B. 07-08-2023)
      • YYYYMMDD oder DDMMYYYY (z. B. 20230807)
      • YYMMDD oder DDMMYY (z. B. 230807)
    • Entfernt diese Datumsbestandteile aus dem Dateinamen
    • Lässt die Dateiendung unverändert
    • Gibt eine Rückmeldung, ob eine Datei umbenannt wurde oder nicht (aber nur, wenn man über Commandline/Konsole aufruft)

    Anwendung

    1. Ich speichere das Skript im gleichen Ordner wie die zu bereinigenden Dateien.
    2. Dann führe ich das Skript aus (z. B. mit Python über die Konsole) und dann
    3. Starte ich Adobe Bridge und wende meine Umbenennungsvorlage an.

    Nachfolgend das Python-Script, das ich verwende. Einfach markieren und kopieren, dann beispielsweise als rename_cleaner.py speichern.

    import os
    import re

    # 📍 Get the folder where the script is located
    folder_path = os.path.dirname(os.path.abspath(__file__))

    # 🧠 Regex pattern to match common date formats in filenames
    date_pattern = re.compile(
    r'(\d{4}-\d{2}-\d{2})|' # YYYY-MM-DD
    r'(\d{2}-\d{2}-\d{4})|' # DD-MM-YYYY
    r'(\d{8})|' # YYYYMMDD or DDMMYYYY
    r'(\d{6})' # YYMMDD or DDMMYY
    )

    # 🚀 Loop through files in the folder
    for filename in os.listdir(folder_path):
    file_path = os.path.join(folder_path, filename)

    # Skip folders
    if not os.path.isfile(file_path):
    continue

    name, ext = os.path.splitext(filename)

    # 🧹 Remove date patterns from filename
    cleaned_name = date_pattern.sub('', name).strip('-_ ')

    # 🏷️ Build new filename
    new_filename = f"{cleaned_name}{ext}"
    new_path = os.path.join(folder_path, new_filename)

    # 🔁 Rename file if name changed
    if filename != new_filename:
    os.rename(file_path, new_path)
    print(f"✅ Renamed: {filename} → {new_filename}")
    else:
    print(f"⏩ Skipped (no change): {filename}")

    Anleitung zur Verwendung der Batch-Umbenennungsvorlage in Adobe Bridge

    Dateiname der Vorlage: standard-nach-velsz.setting
    Kompatibel mit: Adobe Bridge 2022, 2023, 2024

    So verwendest du meine Vorlage nach Velsz1

    1. Datei kopieren: Kopiere die Datei standard-nach-velsz.setting in folgenden Ordner auf deinem Computer:

    Windows:

    C:\Users\<USERNAME>\AppData\Roaming\Adobe\Bridge <version>\Batch Rename Settings\

    macOS:

    /Users/<USERNAME>/Library/Application Support/Adobe/Bridge <version>/Batch Rename Settings2

    1. Starte Adobe Bridge.
    2. Markiere alle Dateien, die umbenannt werden sollen.
    3. Gehe zu Werkzeuge > Stapelumbenennung
    4. Lade die heruntergeladene Vorlage standard-nach-velsz, oder:
    5. Wähle folgende Einstellungen
      • Zielordner: Gleicher Ordner (oder ein neuer)
      • Neuer Dateiname:
        • Datum/Uhrzeit. Erstellungsdatum. JJJJMMTT (YYYMMDD)
        • Text: –
        • Beibehaltener Dateiname. Name. Kleinbuchstaben.
    6. Klicke auf Umbenennen, um die Änderungen anzuwenden.
    1. Vergleiche dazu u.a. „Lightroom Classic und CC: das umfassende Handbuch“ von István Velsz ↩︎
    2. Dank für den richtigen Pfad an wckdtalls Kommentar hier: https://community.adobe.com/t5/bridge-discussions/batch-rename-presets/m-p/13085459#M35134 ↩︎
  • Artikellinks aus WordPress in Linkwarden speichern

    Ein kurzer Snippet zum Ausprobieren. Benötigt WordPress und Linkwarden.1 Damit werden alle Links, die sich in einem Artikel bestimmter Kategorien befinden, beim Veröffentlichen zum Speichern an Linkwarden geschickt. Linkwarden schickt diese dann auch an archive.org, damit sie auch öffentlich verfügbar bleiben.

    Kontext dazu: Mein Mastodon‑Post hier, und dieser Bluesky‑Post.

    // Hooks into the WordPress publish_post action.
    // When a post is published, it triggers the send_post_links_to_linkwarden function.
    add_action('publish_post', 'send_post_links_to_linkwarden', 10, 2);

    function send_post_links_to_linkwarden($post_ID, $post) {
    // Only proceed if the post is in one of these categories.
    $preferred_categories = ['CHANGE_ME', 'CHANGE_ME_TOO'];

    // Set post_title
    $post_title = sanitize_text_field($post->post_title);


    // Get the category slugs of the published post.
    $post_categories = wp_get_post_categories($post_ID, ['fields' => 'slugs']);

    // Skip processing if the post doesn't belong to one of the preferred categories.
    if (empty(array_intersect($preferred_categories, $post_categories))) {
    error_log("[Linkwarden] Skipping post ID $post_ID because it is not in preferred categories.");
    return;
    }

    // Define the Linkwarden API base URL and access token.
    $api_base_url = ' https://YOUR_LINKWARDEN_URL/api/v1';
    $api_token = 'YOUR_API_TOKEN';

    // Extract all URLs from the post content.
    $content = $post->post_content;
    $urls = wp_extract_urls($content);

    // Exit if no URLs were found in the post.
    if (empty($urls)) {
    error_log("[Linkwarden] No URLs found in post ID $post_ID");
    return;
    }

    // Remove duplicate URLs.
    $urls = array_unique($urls);

    // Send each URL found in the post to the Linkwarden API.
    foreach ($urls as $url) {
    // Create the body of the request with the URL, post title as title and tag.
    $body = [
    'url' => $url,
    'title' => $post->post_title,
    'tags' => [ ['name'=> $post_title] ],
    'collectionId' => [
    'id' => COLLECTION_ID_NUMBER_NO_QUOTES_FOR_ME_PLEASE
    ],
    ];

    // Make a POST request to the Linkwarden /links endpoint.
    $response = wp_remote_post("{$api_base_url}/links", [
    'headers' => [
    'Authorization' => 'Bearer ' . $api_token,
    'Content-Type' => 'application/json',
    ],
    'body' => wp_json_encode($body),
    'timeout' => 10,
    ]);

    // Log an error if the HTTP request fails.
    if (is_wp_error($response)) {
    error_log("[Linkwarden] HTTP request error for URL $url: " . $response->get_error_message());
    continue;
    }

    // Check the response code to confirm successful addition.
    $code = wp_remote_retrieve_response_code($response);
    if ($code !== 201 && $code !== 200) {
    error_log("[Linkwarden] Unexpected response code $code for URL $url. Response: " . wp_remote_retrieve_body($response));
    } else {
    error_log("[Linkwarden] Successfully added URL $url from post ID $post_ID");
    }
    }
    }
    1. Getestet mit selbst-gehostetem Linkwarden als Docker-Volume. ↩︎
  • Satzspiegelrechner

    Was macht der Satzspiegelrechner?

    Der Satzspiegel­rechner ist ein Tool zur Visualisierung und Berechnung des Satzspiegels für ein Buchformat, hier exemplarisch für A5‑Seiten.
    Er zeigt, wie viele Zeilen bei einer vorgegebenen Buchstaben­höhe und einem fest­gelegten Zeilen­abstand auf die Seite passen, und stellt den Satz­spiegel (den be­druckbaren Bereich) mit typischen Seiten­rändern dar. So kann man Layout‑Parameter wie Buchstaben­höhe und Zeilen­abstand experimentell anpassen und direkt sehen, wie sich der Satzspiegel verändert.

    Wichtig: Dieses Tool ist aktuell noch ein Work in Progress – es befindet sich in einer sehr frühen Entwicklungsphase.

    Danke an Andreas Maxbauer für die Inspiration.

  • CRT-Pixel-Shader-Brush für BlackInk

    Dieses kurze Shader-Skript erzeugt RGB-Streifen entlang der Pinselbewegung und eignet sich als visuelles Experiment oder Ausgangspunkt für eigene Brush-Designs. Es kann direkt in BlackInk eingefügt werden – dazu einfach den Code in den „Brush Pixel Shader Editor“ kopieren und als neue Konfiguration speichern.

    Die Streifen entstehen durch eine einfache Modulo-Logik: Jede dritte Spalte wird abwechselnd rot, grün oder blau eingefärbt. Die Frequenz lässt sich über die uv.x-Skalierung anpassen. Die Berechnung erfolgt auf Basis der Pinselrichtung und ‑länge, wodurch das Muster dynamisch auf die Strichführung reagiert.

    cfg {
    name = "Vertical RGB Stripes";
    renderingTime = 60;
    }

    float4 main(idatas i) {
    // Normalize stroke space UVs
    box2 b = box2FromCenterAxe(i.strokeStartPos, length(i.strokePos - i.strokeStartPos), normalizeSafe(i.strokePos - i.strokeStartPos));
    float2 uv = 4 * b.toCenter(i.pos) / b.size;

    // Scale up horizontal frequency
    float stripe = floor(uv.x * 60); // visible stripes

    // Simple stripe pattern: R, G, B
    float3 col = float3(0.0, 0.0, 0.0);
    if (mod(stripe, 3) == 0) {
    col.r = 1.0;
    } else if (mod(stripe, 3) == 1) {
    col.g = 1.0;
    } else {
    col.b = 1.0;
    }

    return float4(col, 1.0);
    }
  • Projekt: 9 Monate Social Media Wall

    Projekt: 9 Monate Social Media Wall

    Seit August letzten Jahres betreibe ich eine WordPress‑Instanz, deren einzige Funktion darin besteht, bestimmte Posts von mir auf diversen Social-Media-Webseiten zu archivieren.

    Ziel dieses Projekts ist es, meine eigenen Inhalte außerhalb der jeweiligen Plattformen verfügbar und vor allem durchsuchbar zu machen – meiner Er­fahrung nach ist die wichtigste Funktion sozialer Netzwerke die Suche, bzw. die Durch­suchbarkeit.

    Screenshot der Landingpage meines Social‑Media‑Archivs
    Mein Projekt „ASCA – Automated Social Content Archive“

    Leider wird diese Funktion häufig dadurch eingeschränkt, dass die Betreiber solcher Plattformen Inhalte nur registrierten Nutzern zugänglich machen. Mein Archiv wirkt diesem Umstand entgegen und stellt meine Beiträge in einer Weise bereit, die meiner Idee eines eigenen öffentlichen Archivs gerecht wird.

    Umgesetzt habe ich das Projekt einerseits mit WordPress, das sich erneut als Lösung für etwa 80 % aller Web­projekte anbietet, andererseits mit dem Automatisierungs­dienst ifttt (ich habe darüber – wenn auch nur kurz – bereits geschrieben, u. a. hier: https://www.mariobreskic.de/nach-dem-bachelor-vertiefung-der-grundlagen/).

    Screenshot meiner IFTTT-Applets mit dem Stichwort #asca
    Screenshot meiner IFTTT-Applets mit dem Stichwort #asca

    Mit ifttt habe ich sogenannte Applets erstellt, die ausgewählte Social-Media-Accounts nach dem Hashtag #asca durchsuchen. Entsprechende Beiträge werden anschließend als WordPress‑Posts in meinem Archiv gespeichert und veröffentlicht – automatisch.

    Ich plane, diese Automatik künftig noch zu verfeinern, da ich mich zunehmend in Richtung eines achtsameren Social-Media-Marketings bewege: Ich möchte auf meinen Kanälen nur noch Inhalte mit Substanz und Botschaft veröffentlichen – nicht mehr jede Moment­aufnahme. Doch das ist (noch) Zukunfts­musik.

    Der Clou an der Sache ist für mich, dass eine neue Betrachtungs­ebene meiner Beiträge entsteht – eine Art Vogel­perspektive: Hashtags werden aus den ursprünglichen Posts übernommen und verbinden Inhalte plattform­übergreifend – ob Instagram, Threads, Twitter oder Tumblr.

    Screenshot des Hashtags automation in meinem Social‑Media‑Archiv
    Screenshot des Hashtags „automation“ in meinem Social‑Media‑Archiv
    Einzelansicht eines archivierten Beitrags mit sogenannter Tag‑Wolke rechts

    Da ich das Projekt seit August 2024 als built in public führe, möchte ich es auch weiterhin trans­parent halten – weil mir die Idee gehört, die eigenen Beiträge zu besitzen und selbst zu speichern. Dass mein Content somit die Plattform überdauert, auf der er ursprünglich veröffentlicht wurde, hat für mich einen ganz eigenen Charme.

    Mein August ist zwar bereits voll verplant, aber vielleicht schaffe ich es trotzdem, ein oder zwei Sätze über dieses Projekt zu schreiben, wenn es dann ein Jahr alt ist. Bei Fragen zu den Applets oder Plugins darf man mich gern kontaktieren. Ich würde mich freuen, wenn sich weitere Gestalter für diese Form des öffentlichen Archivierens interessieren.

    Völlig automatisch läuft das Archiv allerdings nicht: Statt meine Bilder und Videos von den Servern Dritter einzubetten, lade ich eigene Versionen hoch – in deutlich höherer Qualität als auf Social-Media-Plattformen üblich und mit urheber­rechtlich relevanten Informationen versehen.

    Ansicht des Beitragsbildes im Content‑Credentials‑Inspector

    Permalink zu dem Projekt „ASCA ‑ Automated Social Content Archive“.

  • Update 4: Change Notes 26.01.2025

    Update 4: Change Notes 26.01.2025

    Website:

    • Vom bisherigen Theme auf das Standard‑WordPress‑Theme „Twenty Twenty-Five” migriert, um innerhalb des Baukastens von WordPress flexibel bleiben zu können
    • Mein Status‑Widget funktioniert jetzt mittels des WordPress‑internen „Abfrage‑Loop“, anstatt mithilfe des Plugins „Display Posts”. Plugin ist damit obsolet
    • Mit dem Umstieg auf das neue Theme wurde auch das Plugin „Elementor” obsolet, da mit den Defaults von WordPress ein Funktionsumfang erreicht wird, den ich wahrscheinlich nicht einmal benötige
    • Nach wie vor gibt es den visuellen Bug der Zeilenhöhe mit Fußnoten, den man immer noch mit CSS auf die gleiche Art und Weise beseitigt:
      • sup {line-height: 0 !important;}
    • Es werden jetzt keine Shortcodes mehr verwendet
    • Die Website ist somit insgesamt leichter geworden, was mir auch ein Anliegen ist.

  • Update 3: Change Notes 20.01.2025

    Tumblr:

    • Von „Code & Canvas” zu meinem eigenen Namen umbenannt
    • URL bzw. Account‑Namen mit Bindestrich angepasst, weil aufgrund der Funktionsweise Tumblrs zwar ein Account‑Name ohne Bindestrich existiert, dieser aber für mich nicht verfügbar bleibt
    • Rückwirkend den Hashtag „code and canvas” durch „mariobreskic“ ersetzt, um diese Veränderungen zu betonen

    social.mariobreskic.de:

    • Alle archivierten Einträge der ehemaligen URL von „Code & Canvas” rückwirkend editiert, damit abgehende Hyperlinks weiterhin und in Zukunft auch übergangslos mit dem neuen Account‑Namen auf Tumblr funktionieren; der bisher verwendete Hashtag „code and canvas” bleibt für ältere Einträge im Archiv jedoch erhalten

    Update vom 27.02.2025: diese Veränderungen habe ich wieder rückgängig gemacht.

    Ifttt:

    • Applets wurden angepasst, um private und öffentliche Archivierungen zu berücksichtigen.
  • Update 2: Change Notes 12.01.2025

    • Seite „Werkzeuge” gelöscht
    • Links zu Now in den Footer versetzt und aus der Navigationsleiste entfernt
    • Links zu der Post‑Kategorie „Status”, sowie zur neu erstellten Seite Networks der Navigationsleiste hinzugefügt
    • Links zu Sozialen Netzwerken aus dem Footer entfernt und in die neue Seite Networks übertragen
    • Links zu Sozialen Netzwerken nach meiner Aktivitätshäufigkeit dort sortiert
    • Diverse Status‑Posts mit Links versehen.
  • Update 1: Change Notes 16.12.2024

    Weil das den Rahmen der Kategorie Status sprengt, hier eine Liste der neuesten Änderungen:

    Nachtrag vom 13. 01. 2025: Aufgrund von persönlicher Veränderung im Umgang mit dem Web sind die durchgestrichenen Angaben nicht mehr aktuell, werden hier aber auch nicht gelöscht.

    1. Letztere beiden Links geben auch ein paar Tipps zur Verwendung der Add‑ons, so wie ich sie selber auch verwende. ↩︎
  • Ich wollte Statusupdates machen können

    Den Statuscrawl links oben auf https:­//­www.­helenazhang.­com/ fand ich cool, also habe ich mir auch einen gebastelt, der mittels des WordPress‑Plugins https:­//­displayposts.­com/ so funktioniert:

    Ich legte die Kategorie „Status“ mit den Unterkategorien „Hört”, „Liest“, „Schaut“, „Studiert“ und „Spielt“ an, um die verschiedenen Statusupdates besser kategorisieren zu können (und damit man auch buddeln gehen kann; ich wollte einen Papertrail hinterlassen können, d.h. dass ich auch selbst nachschauen kann, was ich so gepostet habe, ich steh’ ja aufs Archivieren und Verarbeiten von Daten).

    Dann erstellte ich ein Elementor‑Template mit einer Icon‑Liste, wählte die passenden Icons aus und formatierte den Shortcode für jeden Eintrag auf dieser Liste so:

    [display-posts category="hoert" posts_per_page="1" include_excerpt="false" include_excerpt_dash="false" include_content="true" wrapper="div" wrapper_class="custom-status hoert custom-status-post-latest" include_title="false"]

    Dann fügte ich dem Template, das meine Landing Page formatiert, den Shortcode des obigen Elementor‑Elementor hinzu, und ab jetzt wird immer das neueste Statusupdate der jeweiligen Kategorie angezeigt, klebte dem Link zu Home noch das Etikett HOT auf, und schrieb diesen Artikel.1

    1. Seit dem Update vom 26. 01. 2025 funktioniert die Website anders, siehe dazu auch Update 004: Change Notes 26. 01. 2025 ↩︎