Skip to content

Generate pages for nested files, not just top-level ones - #33

Merged
m-col merged 9 commits into
masterfrom
flatten-file-listing
Aug 30, 2026
Merged

Generate pages for nested files, not just top-level ones#33
m-col merged 9 commits into
masterfrom
flatten-file-listing

Conversation

@m-col

@m-col m-col commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Fixes gitja never generating pages for nested files, adds a foreach.tree.html per-object template (alongside foreach.blob.html and foreach.commit.html) so subtrees get their own generated page, and renames TreeFileTreeEntry/tree_recursiveentries for clarity, plus a new trees field listing every directory in the repo.

claude added 2 commits August 30, 2026 21:34
Both "tree" and "tree_recursive" (at the top-level package scope, and the
per-file scope on a directory entry) are misleadingly named - neither
actually recurses. "tree" is filtered to top-level entries; "tree_recursive"
is the exact same unfiltered top-level list (a no-op filter, since
top-level entries never contain a path separator); and per-file
`tree`/`tree_recursive` both just return one level of a directory's
immediate children (treeFileGetTreeRecursive literally just returns `fs`
unchanged). There was no existing way to get a real flat, full-depth
listing of a repo's files.

Add `flattenFiles` (Types.hs), which actually recurses into
FolderContents and collects only file/blob leaves, and expose it as a new
top-level `blobs` field in Repositories.hs's `package` scope. Left the
existing `tree`/`tree_recursive` fields untouched, since other templates
(and the readme/license lookup, which searches `tree`) may depend on
their current, if misleadingly-named, behavior.

Each entry's `path` in the flattened list is already the full path
relative to the repo root - the tree walk in Repositories.hs accumulates
this via prependParent as it descends, regardless of how deep a file is
nested.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
processRepo' only ever called the file-page generator on the top-level
tree (in both the force and non-force/getUpdatedFiles branches), never on
anything reachable through a directory's FolderContents. So gitja has
never actually written a file.html-equivalent page for anything nested in
a subdirectory, independent of the "blobs" field or any template - the
page itself was never generated, regardless of what a template linked to.

Flatten tree with flattenFiles before both generation paths, so a file's
depth no longer determines whether it gets a page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
@m-col m-col changed the title Expose a genuinely flattened file listing (blobs) Generate pages for nested files, not just top-level ones Aug 30, 2026
m-col pushed a commit to m-col/mcol.xyz that referenced this pull request Aug 30, 2026
gitja never generates pages for files nested in subdirectories, and
top-level "tree" only ever contains top-level entries (see
m-col/gitja#33, which also fixes this on gitja's side - needs a new
gitja release to take effect here, since deploy.yaml downloads a release
binary rather than building from source). Once that's out, this switches
to gitja's new flattened "blobs" field, listing every file at its full
path with no directory hierarchy - there's nothing for a directory entry
to link to anyway, so this is simpler than the earlier dead-link
workaround it replaces.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
claude added 5 commits August 30, 2026 21:37
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
Confirmed by reading the code: at both scopes (top-level package, and
per-file on a directory entry), tree_recursive was identical to tree.
Top-level tree's filter (notElem pathSeparator ...) was a no-op, since
the list it filters only ever contains top-level entries in the first
place - nested entries live inside each directory's own FolderContents,
never flattened into it. Per-file, treeFileGetTreeRecursive just returned
`fs` unchanged - no recursion despite the name. The docs described
tree_recursive as "a list of *all* of the repository's/directory's
contents", which was never actually true.

"tree" is git's own name for a tree object's entries (a git tree is not
itself recursive - that's exactly what it means for git to have separate
tree objects per directory), so keeping that name for "this tree's
entries" is accurate, not a simplification. Dropped the now-pointless
filter/atTop logic along with tree_recursive, and updated
DOCUMENTATION.md's Scopes/Attributes tables to match - "blobs" is
documented there too, since it existed but wasn't previously listed.

This doesn't add per-tree-entry pages for every object type a tree can
contain (blob/tree/commit-as-submodule) - just removes a redundant,
inaccurately-documented field. That's real future work, not this.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
blobs (leaves only) and tree_recursive (every entry, blobs and trees
alike, at any depth) are different things - collapsing tree_recursive
into blobs lost that distinction. Add flattenTree (Types.hs), the
tree-and-blob equivalent of flattenFiles - keeps every entry including
directories themselves as it descends, equivalent to `git ls-tree -r -t`.
Used for both the top-level "tree_recursive" (package scope, Repositories.hs)
and the per-file "tree_recursive" on a directory entry (treeAsLookup,
Types.hs).

flattenTree lives in Types.hs rather than alongside flattenFiles in
Repositories.hs, since it's needed by treeAsLookup there too and
Repositories.hs already depends on Types.hs (the reverse would be a
cycle).

Updated DOCUMENTATION.md's Scopes/Attributes tables to describe both
tree_recursive and blobs accurately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
Third special repo/ template, alongside commit.html and the newly-renamed
blob.html: tree.html, generated once per tree (directory) object at any
depth, mirroring how blob.html/commit.html already work per blob/commit.
Uses flattenTrees (Repositories.hs) to walk every tree object including
itself, and treeHref for its output path. Unlike blobs, a tree's own path
never appears in a commit diff, so there's no cheap way to tell whether a
tree needs regenerating from newCommits alone - tree pages are always
regenerated on every run rather than incrementally, which is simpler and
correct rather than risking the exact kind of silent staleness bug the
blob-generation fix earlier addressed.

"file" -> "blob" throughout (envFileTemplate/fileT/fileHref/fileDir ->
envBlobTemplate/blobT/blobHref/blobDir, output moves from file/ to
blob/), matching git's own object vocabulary and freeing up the name
"file" from colliding with anything tree-related.

Updated the three bundled templates (base/docs/stagit) so this doesn't
silently break them: file.html -> blob.html (dropping their now-truly-
unreachable is_directory branches, since blobs are never directories),
the existing once-per-repo file-listing tree.html -> files.html (freeing
the name for the new per-object template), and a real tree.html per-object
page for each, built from what those old is_directory branches were
already trying to do. Every href referencing the old file/ output
directory is updated to blob/, and files.html/tree.html's child links now
route to tree/ or blob/ depending on the entry's own type.

Updated DOCUMENTATION.md's folder structure, scopes and attributes tables
to describe blob/tree/commit as the three special per-object templates,
and the blob/tree attribute table entries as shared (most attributes
apply to both, a few are n/a on one side).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
m-col pushed a commit to m-col/mcol.xyz that referenced this pull request Aug 30, 2026
Matches m-col/gitja#33 (not yet released): file.html -> blob.html, the
file-listing tree.html -> files.html, and a real per-tree tree.html so
subdirectories actually get their own page once that release lands.
Every /code/<repo>/file/... link updates to /code/<repo>/blob/... -
including the qtools blog post link fixed earlier this session for the
same reason.

This won't do anything until a new gitja release exists (deploy.yaml
downloads gitja's latest release binary rather than building from
source) - until then /code will keep working exactly as it does now,
since the currently-released gitja binary doesn't know about blob.html
or the new tree.html and just ignores them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
m-col pushed a commit to m-col/mcol.xyz that referenced this pull request Aug 30, 2026
Matches m-col/gitja#33 (not yet released): file.html -> blob.html, the
file-listing tree.html -> files.html, and a real per-tree tree.html so
subdirectories actually get their own page once that release lands.
Every /code/<repo>/file/... link updates to /code/<repo>/blob/... -
including the qtools blog post link fixed earlier this session for the
same reason.

Sequencing matters here: the currently-released gitja binary looks for
"file.html" by exact name. Once this merges and deploy.yaml runs against
that old binary, it won't find file.html (renamed to blob.html) and will
silently stop generating individual blob/file content pages entirely -
the files.html listing and commit pages keep working fine (they're
unaffected), but every "view this file's contents" link will 404 until
gitja#33 is merged, released, and picked up by the next deploy. Consider
holding off merging this until that release exists, to avoid the gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
Fixes the CI failure on the previous commit: test.sh's golden-file test
still expected output under gitja/file/... (the pre-rename output
directory), and test/templates/repo/file.html was never updated to
match the blob rename. Renamed that test template to foreach.blob.html
(see below), updated its dumped "file"/"scope: file" labels to
"blob"/"scope: blob" (the values themselves - paths, hrefs, contents -
are unchanged, since it's the same underlying object under a renamed
scope), moved test/expected/gitja/file/ to test/expected/gitja/blob/
with matching label updates, and fixed test.sh's TESTS array paths.

Also rename the three special per-object templates to
foreach.blob.html/foreach.commit.html/foreach.tree.html (from
blob.html/commit.html/tree.html), across the bundled templates, the test
template, and Env.hs's lookups. Makes it visually obvious in a directory
listing which templates in repo/ run once per repo vs. once per object -
previously "blob.html"/"commit.html"/"tree.html" looked like just three
more arbitrarily-named repo templates alongside index.html/refs.html/etc,
despite being the special-cased ones.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
m-col pushed a commit to m-col/mcol.xyz that referenced this pull request Aug 30, 2026
Matches m-col/gitja#33: blob.html/commit.html/tree.html ->
foreach.blob.html/foreach.commit.html/foreach.tree.html, so it's visually
obvious which templates in repo/ run once per object vs. once per repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012RfZTyHvxLyVp4yaWmNvhN
… field

TreeEntry better reflects that these represent any tree object (blob, tree, or submodule), and entries/trees give the flattened lists clearer, distinct names.
@m-col
m-col merged commit ba94ae5 into master Aug 30, 2026
1 check passed
@m-col
m-col deleted the flatten-file-listing branch August 30, 2026 22:53
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.

2 participants