davideisinger.com

My personal website
Log | Files | Refs | README

README.md (5808B)


      1 # [davideisinger.com][1]
      2 
      3 [1]: https://davideisinger.com
      4 
      5 ## Local tools
      6 
      7 Run `bundle install` at the repository root to install the Ruby dependencies for
      8 `bin/archive`, `bin/elsewhere`, and `bin/newsletter`. Run these commands from the
      9 repository root. `bin/elsewhere URL ...` imports third-party articles;
     10 `bin/newsletter` creates a newsletter campaign from the latest published post.
     11 The image service in `bin/dither` retains its own Gemfile and bundle.
     12 
     13 Run `bin/test` for the local test suite (requires Python 3, Ruby, Git, and Hugo).
     14 Individual tests live in `test/`; Git hook helpers live in `.githooks/lib/`.
     15 `bin/refresh-dither-alt` remains available for image maintenance.
     16 
     17 SourceHut runs `bin/check-rss-template` during deployment. To run it locally, set
     18 `HUGO_VERSION` to the version in `.build.yml`:
     19 
     20 ```sh
     21 HUGO_VERSION=0.167.0 bin/check-rss-template
     22 ```
     23 
     24 ## Navigation and audio
     25 
     26 The shared header and its player stay in place during internal page navigation.
     27 A small, dependency-free script fetches the next HTML page and replaces the main
     28 content and footer, updating the URL, title, canonical link, focus, and scroll
     29 position. External links, downloads, modified clicks, and links with
     30 `data-no-navigation` use normal browser navigation. Failed requests and changed
     31 JavaScript or CSS assets fall back to a full page load. Without JavaScript, every
     32 page and link still works normally; audio then stops when leaving the page.
     33 
     34 The header switches to “Now playing” when playback starts. With JavaScript,
     35 the music page's players become play/pause buttons for that persistent player;
     36 selecting a track updates its title, source link, and audio in the header. The
     37 buttons reflect playback and elapsed time, even after leaving and returning to
     38 the music page. Without JavaScript, the native players remain available.
     39 Starting other embedded audio pauses the current player. Reloading the browser
     40 or leaving the site ends playback.
     41 
     42 The script is bundled by Hugo; Node.js is not required to build or deploy it.
     43 For browser regression tests, run `npm ci`, then `npm run test:navigation`.
     44 These tests use Hugo, a disposable local server, and Playwright (development only).
     45 On macOS they use installed Google Chrome; elsewhere run
     46 `npx playwright install chromium` first. Set `CHROME_BIN` to use another Chromium
     47 executable. The tests cover continuous playback, history, scroll restoration,
     48 focus, fragments, metadata, fallback navigation, and browsing without JavaScript.
     49 
     50 ## Image alt text
     51 
     52 `bin/encrypt IMAGE` encrypts an image and uses Codex to write plain, descriptive
     53 accessibility alt text for the copied `dither` shortcode.
     54 
     55 Regenerate existing, nonempty `dither` alt text with:
     56 
     57 ```sh
     58 bin/refresh-dither-alt --dry-run
     59 bin/refresh-dither-alt content/journal/dispatch-44-october-2026/index.md
     60 bin/refresh-dither-alt
     61 ```
     62 
     63 With no paths, the script scans all Markdown and HTML files under `content`.
     64 `--dry-run` checks image paths and lists matches without calling Codex or changing
     65 anything. A real run requires `openssl`, an authenticated `codex` CLI, and the
     66 repository's `secret.key`. Each image is decrypted into a temporary directory
     67 that is removed after generation, including on failure or interruption. Original
     68 images and encrypted files are left alone. Each post is saved only after all its
     69 alt text has been generated successfully; failures are reported and other posts
     70 continue. Completed posts remain updated if the run is interrupted. Review the
     71 resulting Git diff before publishing. Rerunning regenerates all selected alt text.
     72 
     73 ## Publishing Dispatches
     74 
     75 Enable the repository's Git hooks once per clone:
     76 
     77 ```sh
     78 git config core.hooksPath .githooks
     79 ```
     80 
     81 Before each commit, `.githooks/lib/check-staged-spelling` runs `npx cspell` on the staged
     82 contents of added, changed, or renamed `.md` and `.markdown` files throughout the
     83 repository. Unstaged edits and deleted files are skipped. This requires Python 3,
     84 Node.js, and npm (`npx`).
     85 
     86 Unknown words are added to `.dictionary`, which is sorted and deduplicated. If it
     87 changes, the commit is blocked so you can review `git diff -- .dictionary`.
     88 Remove actual typos from the dictionary and fix them in the Markdown; keep valid
     89 exceptions. Stage the corrected files and `.dictionary`, then retry the commit.
     90 The hook also blocks while `.dictionary` differs from its staged version, so
     91 retrying without reviewing and staging it does not silently accept new words.
     92 No files are automatically staged. Commits without staged Markdown skip spellcheck.
     93 
     94 Pushing to `origin`'s `main` checks newly added, non-draft Dispatches and existing
     95 Dispatches changing from draft to published. Their `date` must be no more than
     96 24 hours old. Edits or renames of already-published posts, draft posts, other
     97 branches, and other remotes are unaffected. The check reads the committed content
     98 being pushed and compares it with the remote's current commit.
     99 
    100 Before publishing, update the date and commit it:
    101 
    102 ```sh
    103 bin/timestamp content/journal/dispatch-44-october-2026/index.md
    104 git add content/journal/dispatch-44-october-2026/index.md
    105 git commit -m "Set publication date"
    106 git push origin main
    107 ```
    108 
    109 Without a filename, `bin/timestamp` still prints the timestamp and copies it to
    110 the clipboard. For intentional backdating, `git push --no-verify origin main`
    111 bypasses local push hooks for that push. The hook must be installed in each clone;
    112 it does not enforce dates on server-side merges or pushes from other clones.
    113 
    114 Run `test/dispatch-hook` to exercise the workflow with temporary local Git
    115 repositories, without contacting the publishing remote.
    116 Run `test/spelling-hook` to test the commit hook offline in a disposable
    117 repository with a simulated spellchecker.
    118 
    119 ---
    120 
    121 © [CC BY 4.0 License][2]
    122 
    123 [2]: https://creativecommons.org/licenses/by/4.0/deed.en