<feed xmlns='http://www.w3.org/2005/Atom'>
<title>mono.git/cgithub/src/scraper.test.ts, branch test</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://git.mou.fo/2026/mono.git/atom/cgithub/src/scraper.test.ts?h=test</id>
<link rel='self' href='http://git.mou.fo/2026/mono.git/atom/cgithub/src/scraper.test.ts?h=test'/>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/'/>
<updated>2026-09-04T03:28:52Z</updated>
<entry>
<title>Handle route errors in middleware</title>
<updated>2026-09-04T03:28:52Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-09-04T03:08:08Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=5bfe8b345d2ee92111a2363321a248adb4f5195a'/>
<id>urn:sha1:5bfe8b345d2ee92111a2363321a248adb4f5195a</id>
<content type='text'>
Every page route wrapped its scrape in tryRender, which awaited the
promise, rendered the template on success, and turned a failure into a
redirect or an error page. Hono's onError does that mapping for all of
them at once, so handlers now await their scrape inline and both
wrappers are gone. Fragments under /api/ still fail as an empty body
rather than a page; onError checks for them first, since a fragment
turns a redirect into a 404 instead of following it.

RedirectError becomes an abstract base with InternalRedirectError and
ExternalRedirectError under it, so the handler dispatches on the type
instead of sniffing the location for an https:// prefix.

One behavior change: a thrown value that is not an Error no longer
renders error.eta, because Hono only routes Error instances to onError.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QERwoRJhuqMhKzzCUW4Skv
</content>
</entry>
<entry>
<title>Link blobs to their history and back</title>
<updated>2026-09-04T02:16:44Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-09-03T05:37:35Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=a61a96c6d72d4297b2539f4033fbfbd0a3d178ab'/>
<id>urn:sha1:a61a96c6d72d4297b2539f4033fbfbd0a3d178ab</id>
<content type='text'>
Nothing in a commits payload says whether the path it lists is a file or
a directory: currentBlobPath, despite the name, is only the path filter,
and is set for a directory just the same. GitHub's own UI cannot tell
either, and points its browse button at /blob/&lt;oid&gt;/&lt;path&gt; so that the
redirect resolves a file to its blob. We do the same, and the blob route
already turns that redirect into one of our own tree URLs.

Breadcrumbs now stay in the view they were clicked from, so walking up
from a history lands in the history of each parent directory rather than
in its listing. The last crumb remains the page you are already on.

A path with no commits now says so rather than rendering an empty page.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01R7pRKdmTvNDgT4ZXrwkbH8
</content>
</entry>
<entry>
<title>Fix drifted tests</title>
<updated>2026-09-03T05:22:13Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-09-03T05:21:00Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=f951c579f7093cc5c61bcb3c0905c7a6729df065'/>
<id>urn:sha1:f951c579f7093cc5c61bcb3c0905c7a6729df065</id>
<content type='text'>
Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01NWDWkWbj5oZCGQEYoybMrV
</content>
</entry>
<entry>
<title>Render repository wikis</title>
<updated>2026-09-03T05:09:10Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-09-03T04:08:06Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=4c66a07a995c0d551cd284d6e72826b4f7748bab'/>
<id>urn:sha1:4c66a07a995c0d551cd284d6e72826b4f7748bab</id>
<content type='text'>
Wikis are one of the last parts of GitHub still served as plain Rails
HTML, with no embedded JSON to read, so this scrapes the markup: a page
and any older revision of it, the _Sidebar and _Footer a wiki can
define, and the page index. Every page is already in the sidebar of
every page, since the "Show N more pages" button only unhides the rest,
so linking the whole wiki costs no second request.

Routes mirror GitHub's and resolve in its order, so an underscore name
reserved for its own actions (_pages, _history, _new, _edit) can never
be mistaken for a page; the ones we don't serve fall through to the
usual redirect. A slug reaches us decoded and has to be encoded again
rather than interpolated the way a ref is, or a page named C# would
truncate at the fragment.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_013rQG1io1i4GJQW5RFcXNGd
</content>
</entry>
<entry>
<title>Display PDF blobs</title>
<updated>2026-08-27T18:53:38Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-08-27T18:08:06Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=0d60b8c8235c3c07f675aba7a56dd37b62519f9e'/>
<id>urn:sha1:0d60b8c8235c3c07f675aba7a56dd37b62519f9e</id>
<content type='text'>
GitHub renders a PDF with a viewer of its own and so ships no content for
one, leaving the blob view with nothing to show. Its raw bytes come as
application/octet-stream, which browsers download rather than display, so
serve them from a new embed route that retypes them and point an &lt;object&gt;
at that.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01BErPR92xppzGFXkPqXPYj2
</content>
</entry>
<entry>
<title>Handle blobs GitHub cannot preview</title>
<updated>2026-08-12T05:42:59Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-08-12T05:38:24Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=e8461b57674b9c4e6ed93151d06dbc6149703178'/>
<id>urn:sha1:e8461b57674b9c4e6ed93151d06dbc6149703178</id>
<content type='text'>
Binary files with no preview (a .ttf, say) have no rawLines, no
colorizedLines and no richText, so the blob view's final branch threw on
a null textLines and the page 500ed. Offer the raw file instead.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Read the About box and latest release from JSON</title>
<updated>2026-08-11T22:25:26Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-08-11T21:41:01Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=21310d0366c0f21e73c1f4f78d38370edfb59445'/>
<id>urn:sha1:21310d0366c0f21e73c1f4f78d38370edfb59445</id>
<content type='text'>
GitHub rebuilt the repository sidebar, so the selectors parseRepoInfo used
matched nothing and the About box rendered empty. Everything but the latest
release is in the page's embedded payload as sidebarAbout; the latest release
is only in the _sidebar JSON already fetched for languages, so it arrives with
that fragment and is moved beside the release count.
</content>
</entry>
<entry>
<title>Add language percentages to repo pages</title>
<updated>2026-08-11T12:13:58Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-08-11T12:09:47Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=0be1fdd2635fbc49d7451d3711b5772e1e9990e2'/>
<id>urn:sha1:0be1fdd2635fbc49d7451d3711b5772e1e9990e2</id>
<content type='text'>
GitHub no longer server-renders the repository sidebar; its React UI
lazily fetches /:owner/:repo/_sidebar as JSON, which carries the
language breakdown (name, percentage, color). getGitHubLanguages() uses
that endpoint, and a new /api/:owner/:repo/languages fragment route
renders the bar and legend the same way refs and latest-commit already
work, so repo page loads still cost a single scrape.

The latest-commit placeholder loader in refs.js is generalized over
.placeholder[data-src] so both placeholders share it.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Add async branch/tag dropdown and latest-commit bar</title>
<updated>2026-07-23T03:25:26Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-07-21T21:46:58Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=6240cf1c6b73b7ed34ff5816b53333382c229f5c'/>
<id>urn:sha1:6240cf1c6b73b7ed34ff5816b53333382c229f5c</id>
<content type='text'>
Adds two lazily-fetched UI pieces to match vanilla GitHub while keeping
initial page loads plain server-rendered HTML: a branch/tag selector
(native &lt;dialog&gt;, CSS anchor-positioned to its button, light-dismissed
via closedby="any") and a latest-commit bar above the file listing.
Both are populated by new /api/:owner/:repo/refs/:type and
/api/:owner/:repo/latest-commit/:branch/:path routes; the latter calls
GitHub's own /latest-commit JSON endpoint (the same one the React UI
uses) rather than scraping the full commit history page.
</content>
</entry>
<entry>
<title>Replace null overview files with HTML comments</title>
<updated>2026-07-15T05:46:06Z</updated>
<author>
<name>Joe Mou</name>
<email>dev@mou.fo</email>
</author>
<published>2026-07-15T05:46:06Z</published>
<link rel='alternate' type='text/html' href='http://git.mou.fo/2026/mono.git/commit/?id=9fbb5f0d68a131b55bc172d46b75705f2842af04'/>
<id>urn:sha1:9fbb5f0d68a131b55bc172d46b75705f2842af04</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
