Skip to content

Refuse an album, tag or place that has no address of its own - #7

Merged
berb merged 2 commits into
mainfrom
fix/empty-and-duplicate-slugs
Oct 17, 2026
Merged

berb merged 2 commits into
mainfrom
fix/empty-and-duplicate-slugs

Conversation

@berb

@berb berb commented Oct 17, 2026

Copy link
Copy Markdown
Owner

slugify keeps ASCII only, so a name in another script reduces to "". An album Album|東京 was then written to photos/albums/_index.md, which the albums index overwrites, and its scoped pages loose beside it. A tag Москва did the same to the tags index. Names that differ only in what ASCII drops (Allgäu, Allgau) share a slug and were merged into one page with two index entries. Locations already refused a clash; nothing refused an empty slug, and albums and tags refused neither.

Stage 1 now fails, naming the names involved, on:

  • an empty slug for an album, tag or location,
  • two albums, or two tags, with one slug.

Only what gets a page is checked: items on published photographs. A library whose clashing names are only on unpublished photographs builds as before.

Tests: empty and clashing albums, tags and locations; the same tag on two photographs is fine; unpublished-only names are not checked.

Not done: a fixture under testdata/broken/ (needs committed image bytes) and a transliteration option for non-Latin names. The error message says to give the name at least one Latin letter or digit.

Each PR adds a line under Unreleased / Fixed in CHANGELOG.md, so merging several will conflict there; keep every line.

🤖 Generated with Claude Code

Claude Code and others added 2 commits October 17, 2026 07:41
…8, F-8)

slugify keeps ASCII only, so a name written in another script reduces to "".
An album called 東京 then had its page at photos/albums/_index.md, which the
albums index overwrote, and its scoped pages loose beside it; a tag called
Москва did the same to the tags index. Names that differ only in what ASCII
drops -- Allgäu and Allgau -- reduced to one slug and were merged into one page
with two entries in the index. Locations already refused a clash; none of the
three refused an empty slug.

Stage 1 now fails on an empty slug and on two albums or two tags with one slug,
naming both, for what has a page: those on published photographs. A library
whose clashing names are only on unpublished photographs builds as before.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…te-slugs

# Conflicts:
#	CHANGELOG.md
#	cmd/exposer/index_test.go
@berb
berb merged commit bf5cab5 into main Oct 17, 2026
1 check passed
@berb
berb deleted the fix/empty-and-duplicate-slugs branch October 17, 2026 08:54
berb added a commit that referenced this pull request Oct 17, 2026
slugify normalised with NFKD and kept what landed below 128, so a letter with
no ASCII form of its own simply disappeared: Weißbier slugged to weibier,
Tromsø to troms, Łódź to odz, Œuvre to uvre. A lost letter is bad enough as an
address; two names that lose different letters can also land on one slug,
which since #7 fails the build rather than merging two listings.

Those letters are now spelled as a reader would spell them -- ß ss, ø oe, œ oe,
æ ae, ł l, đ d, þ th, and the rest in spelledOut. A letter NFKD does decompose
is left to it, so ä stays a and no address a site has published moves.

That still leaves a name in another script with nothing: 東京 and Москва slug
to "", which #7 turned into a build failure with no way out but renaming the
album. So an address can now be declared in the library, which is where the
photographer's own names live: 'slug:' in an album file (R-3) or a location
file (R-10), and 'tag_slugs:' in exposer.yaml (R-18) for a tag, whose own file
is named for the slug this decides (R-19). A declared slug has to look like a
generated one, a declared slug that names nothing fails the build as an unused
description does, and an album file is named for the slug it declares.

The slugs an album, a place or a tag is published at are now resolved in one
place and written back onto every photograph that carries them, so the index
and the pages cannot disagree -- the failure R-3 already describes.

R-20 is new and says all of this, including that the rule changes only with a
major version: an address that is published is a promise (B-10).

Closes #9.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant