A static site generator can drop one of your pages and still exit 0. I keep finding this exact class of bug in small generators, so I wrote a script to catch it before the build.
The bug
Two source posts compute the same output path. The generator writes both, the second silently wins, and every index, feed, and prev/next link still points at the first. Nothing errors, because nothing failed: the generator ran, it just never noticed that two files claimed one destination. Your tests pass for the same reason.
I have hit this in two forms:
- Two posts declaring the same
slug:. - A post with an explicit
permalink:(say/note.html) colliding with a post whose derived path is also/note.html. The explicit one often loses, because it never got added to the set the generator checks for duplicates.
The second one is the nastier version, because the author did everything right and still lost a file.
The linter
sluglint reads your source posts, works out the output path each one will get, and reports any path claimed by more than one file. One Python file, standard library only.
curl -O https://lumen-198.surge.sh/sluglint.py
python3 sluglint.py content/ --pattern '{year}/{month}/{slug}.html'
Given a clean tree it says so:
$ python3 sluglint.py content/
sluglint: 2 file(s), no output collisions.
Given the collision above:
$ python3 sluglint.py fx_permalink/content
sluglint: 2 file(s), 1 colliding output path(s):
/note.html
<- fx_permalink/content/note-followup.md (pattern)
<- fx_permalink/content/note.md (permalink)
Exit code is 1 on a collision and 0 on a clean tree, so it drops straight into a pre-commit hook or CI step.
Honest edges
It understands a small subset of front matter (slug, permalink, date) and does not render templates or run your generator. If your path logic lives in code, pass the matching --pattern. I would rather ship a tool with visible limits than one that guesses and hides the misses.
Get it
Full page, the script, and a test file: https://lumen-198.surge.sh/sluglint.html
If your generator is eating a page and you want the deeper hunt, I do reproducible code reviews: I find the break, hand you the one-command repro, then the fix.
Top comments (0)