summaryrefslogtreecommitdiff
path: root/cgithub/src/app.ts
diff options
context:
space:
mode:
authorJoe Mou <dev@mou.fo>2026-09-03 00:08:06 -0400
committerJoe Mou <dev@mou.fo>2026-09-03 01:09:10 -0400
commit4c66a07a995c0d551cd284d6e72826b4f7748bab (patch)
tree35c53f0713a0903ed4c44d53ed17a4f47deaf4af /cgithub/src/app.ts
parent1b9d13fce99b9d798dd604f402699bb47cb1627e (diff)
Render repository wikis
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rQG1io1i4GJQW5RFcXNGd
Diffstat (limited to 'cgithub/src/app.ts')
-rw-r--r--cgithub/src/app.ts32
1 files changed, 32 insertions, 0 deletions
diff --git a/cgithub/src/app.ts b/cgithub/src/app.ts
index 33b408e..956a8cb 100644
--- a/cgithub/src/app.ts
+++ b/cgithub/src/app.ts
@@ -16,6 +16,8 @@ import {
getGitHubReleases,
getGitHubRepo,
getGitHubTree,
+ getGitHubWiki,
+ getGitHubWikiPages,
GitHubHTTPError,
RedirectError,
} from "./scraper.ts";
@@ -146,6 +148,36 @@ export function createApp(eta: Eta) {
return new Response(response.body, { headers: { "Content-Type": contentType } });
});
+ // GitHub's own wiki URLs, in the order it resolves them: names beginning with
+ // an underscore are reserved for its actions (_pages, _new, _edit, ...), so a
+ // page can never be mistaken for one.
+ app.get("/:owner/:repo/wiki", async (c) => {
+ const { owner, repo } = c.req.param();
+ return tryRender(c, "wiki.eta", getGitHubWiki(owner, repo));
+ });
+
+ app.get("/:owner/:repo/wiki/_pages", async (c) => {
+ const { owner, repo } = c.req.param();
+ return tryRender(c, "wikiPages.eta", getGitHubWikiPages(owner, repo));
+ });
+
+ // An older revision of a page renders exactly like its current one.
+ app.get("/:owner/:repo/wiki/:page/:oid", async (c) => {
+ const { owner, repo, page, oid } = c.req.param();
+ if (page.startsWith("_") || !/^[0-9a-f]{40}$/.test(oid)) {
+ return redirectToGitHub(c, githubUrlFor(c));
+ }
+ return tryRender(c, "wiki.eta", getGitHubWiki(owner, repo, page, oid));
+ });
+
+ app.get("/:owner/:repo/wiki/:page", async (c) => {
+ const { owner, repo, page } = c.req.param();
+ if (page.startsWith("_")) {
+ return redirectToGitHub(c, githubUrlFor(c));
+ }
+ return tryRender(c, "wiki.eta", getGitHubWiki(owner, repo, page));
+ });
+
app.get("/:owner/:repo/issues", async (c) => {
const { owner, repo } = c.req.param();
const q = c.req.query("q");