summaryrefslogtreecommitdiff
path: root/cgithub/views
diff options
context:
space:
mode:
authorJoe Mou <dev@mou.fo>2026-09-04 21:26:21 -0400
committerJoe Mou <dev@mou.fo>2026-09-04 21:49:59 -0400
commit53ac3bc511a45e4e2e3f234a8b8dcf853b0c38d9 (patch)
treed887da14050b199aca617a4f46d52763a2da7073 /cgithub/views
parent5bfe8b345d2ee92111a2363321a248adb4f5195a (diff)
Split the page shell out of the repository layout
layout.eta was two things at once: the HTML shell every page needs and the repository chrome around it. owner.eta, being the one page that is not about a repository, could use neither and carried its own copy of the shell, which had drifted -- its footer named no build commit and did not link to the original page on GitHub. The shell moves to views/layouts/base.eta, taking its title and any deferred scripts as layout data, and the chrome to views/layouts/repo.eta, a layout over it that adds the clone commands, nav, search box, and the "/" shortcut that focuses it. Repository pages point at repo.eta and render as before; owner.eta uses base.eta directly and so gains the footer it was missing. Templates now live in more than one directory, so scripts/build.ts walks views/ recursively and keys each template by its path underneath it. Names crossing a directory are written from the views root ("/layouts/base.eta"), the one form both Eta's filesystem resolver and the precompiled resolver in worker.ts agree on; siblings stay relative. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ba5p88cWtCq42vf3uweweL
Diffstat (limited to 'cgithub/views')
-rw-r--r--cgithub/views/blob.eta2
-rw-r--r--cgithub/views/commits.eta2
-rw-r--r--cgithub/views/issues.eta2
-rw-r--r--cgithub/views/layout.eta66
-rw-r--r--cgithub/views/layouts/base.eta17
-rw-r--r--cgithub/views/layouts/repo.eta59
-rw-r--r--cgithub/views/owner.eta107
-rw-r--r--cgithub/views/pulls.eta2
-rw-r--r--cgithub/views/release.eta2
-rw-r--r--cgithub/views/releases.eta2
-rw-r--r--cgithub/views/repo.eta2
-rw-r--r--cgithub/views/tree.eta2
-rw-r--r--cgithub/views/wiki.eta2
-rw-r--r--cgithub/views/wikiPages.eta2
14 files changed, 134 insertions, 135 deletions
diff --git a/cgithub/views/blob.eta b/cgithub/views/blob.eta
index 2014b14..9f6706e 100644
--- a/cgithub/views/blob.eta
+++ b/cgithub/views/blob.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta"); it.searchType = "code" %>
+<% layout("/layouts/repo.eta"); it.searchType = "code" %>
<%~ include("./_nav.eta", {...it, view: "blob"}) %>
diff --git a/cgithub/views/commits.eta b/cgithub/views/commits.eta
index c29693d..a80ef07 100644
--- a/cgithub/views/commits.eta
+++ b/cgithub/views/commits.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta") %>
+<% layout("/layouts/repo.eta") %>
<%~ include("./_nav.eta", {...it, view: "commits"}) %>
diff --git a/cgithub/views/issues.eta b/cgithub/views/issues.eta
index 646da46..754afb8 100644
--- a/cgithub/views/issues.eta
+++ b/cgithub/views/issues.eta
@@ -1,4 +1,4 @@
-<% layout("./layout"); it.searchType = "issues" %>
+<% layout("/layouts/repo.eta"); it.searchType = "issues" %>
<table>
<% for (const issue of it.issues) { %>
diff --git a/cgithub/views/layout.eta b/cgithub/views/layout.eta
deleted file mode 100644
index 37289dd..0000000
--- a/cgithub/views/layout.eta
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title><%= it.repo.owner %>/<%= it.repo.name %> - <%= it.path || '/' %></title>
- <link rel="stylesheet" href="/static/style.css">
- <script src="/static/refs.js" defer></script>
-</head>
-<body>
- <div class="box">
- <div class="repo"><a href="/<%= it.repo.owner %>"><%= it.repo.owner %></a>/<a href="/<%= it.repo.owner %>/<%= it.repo.name %>"><%= it.repo.name %></a></div>
- <pre><code>git clone https://github.com/<%= it.repo.owner %>/<%= it.repo.name %>.git
-git clone git@github.com:<%= it.repo.owner %>/<%= it.repo.name %>.git</code></pre>
- <nav>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>">Code</a>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/issues">Issues</a>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/pulls">Pull requests</a>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/releases">Releases</a>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/wiki">Wiki</a>
- <% if (it.branch) { %>
- <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/commits/<%= it.branch %><%= it.path && it.path !== '/' ? '/' + it.path : '' %>">Commits</a>
- <% } %>
- </nav>
- <form action="/<%= it.repo.owner %>/<%= it.repo.name %>/search" method="get">
- <input id="search-input" type="text" name="q" placeholder="Search…" value="<%= it.q ?? "" %>">
- <select name="type">
- <option value="issues" <%= it.searchType === "issues" ? "selected" : "" %>>Issues</option>
- <option value="pullrequests" <%= it.searchType === "pullrequests" ? "selected" : "" %>>Pull requests</option>
- <option value="code" <%= it.searchType === "code" || it.searchType == null ? "selected" : "" %>>Code</option>
- </select>
- <button type="submit">Search</button>
- </form>
- </div>
-
- <%~ it.body %>
-
- <footer>Generated by cgithub commit <code><%= it.buildCommit %></code> · <a href="<%= it.githubUrl %>" rel="noreferrer">View original</a></footer>
-
- <script>
- document.addEventListener("keydown", function(e) {
- let shortcut = "";
- if (e.ctrlKey || e.metaKey) shortcut += "C-";
- if (e.altKey) shortcut += "A-";
- if (e.shiftKey) shortcut += "S-";
- shortcut += e.key;
-
- if (shortcut === "Escape") {
- document.activeElement.blur();
- return;
- }
-
- if (["INPUT", "TEXTAREA", "SELECT"].includes(document.activeElement.tagName)) {
- return;
- }
-
- if (shortcut === "/") {
- e.preventDefault();
- const input = document.getElementById('search-input');
- input.select();
- input.scrollIntoView({ block: "nearest" });
- }
- });
- </script>
-</body>
-</html>
diff --git a/cgithub/views/layouts/base.eta b/cgithub/views/layouts/base.eta
new file mode 100644
index 0000000..fb644f5
--- /dev/null
+++ b/cgithub/views/layouts/base.eta
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title><%= it.title %></title>
+ <link rel="stylesheet" href="/static/style.css">
+ <% for (const src of it.scripts ?? []) { %>
+ <script src="<%= src %>" defer></script>
+ <% } %>
+</head>
+<body>
+ <%~ it.body %>
+
+ <footer>Generated by cgithub commit <code><%= it.buildCommit %></code> · <a href="<%= it.githubUrl %>" rel="noreferrer">View original</a></footer>
+</body>
+</html>
diff --git a/cgithub/views/layouts/repo.eta b/cgithub/views/layouts/repo.eta
new file mode 100644
index 0000000..e4f7880
--- /dev/null
+++ b/cgithub/views/layouts/repo.eta
@@ -0,0 +1,59 @@
+<%
+layout("/layouts/base.eta", {
+ title: `${it.repo.owner}/${it.repo.name} - ${it.path || "/"}`,
+ scripts: ["/static/refs.js"],
+})
+%>
+
+<div class="box">
+ <div class="repo"><a href="/<%= it.repo.owner %>"><%= it.repo.owner %></a>/<a href="/<%= it.repo.owner %>/<%= it.repo.name %>"><%= it.repo.name %></a></div>
+ <pre><code>git clone https://github.com/<%= it.repo.owner %>/<%= it.repo.name %>.git
+git clone git@github.com:<%= it.repo.owner %>/<%= it.repo.name %>.git</code></pre>
+ <nav>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>">Code</a>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/issues">Issues</a>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/pulls">Pull requests</a>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/releases">Releases</a>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/wiki">Wiki</a>
+ <% if (it.branch) { %>
+ <a href="/<%= it.repo.owner %>/<%= it.repo.name %>/commits/<%= it.branch %><%= it.path && it.path !== '/' ? '/' + it.path : '' %>">Commits</a>
+ <% } %>
+ </nav>
+ <form action="/<%= it.repo.owner %>/<%= it.repo.name %>/search" method="get">
+ <input id="search-input" type="text" name="q" placeholder="Search…" value="<%= it.q ?? "" %>">
+ <select name="type">
+ <option value="issues" <%= it.searchType === "issues" ? "selected" : "" %>>Issues</option>
+ <option value="pullrequests" <%= it.searchType === "pullrequests" ? "selected" : "" %>>Pull requests</option>
+ <option value="code" <%= it.searchType === "code" || it.searchType == null ? "selected" : "" %>>Code</option>
+ </select>
+ <button type="submit">Search</button>
+ </form>
+</div>
+
+<%~ it.body %>
+
+<script>
+ document.addEventListener("keydown", function(e) {
+ let shortcut = "";
+ if (e.ctrlKey || e.metaKey) shortcut += "C-";
+ if (e.altKey) shortcut += "A-";
+ if (e.shiftKey) shortcut += "S-";
+ shortcut += e.key;
+
+ if (shortcut === "Escape") {
+ document.activeElement.blur();
+ return;
+ }
+
+ if (["INPUT", "TEXTAREA", "SELECT"].includes(document.activeElement.tagName)) {
+ return;
+ }
+
+ if (shortcut === "/") {
+ e.preventDefault();
+ const input = document.getElementById('search-input');
+ input.select();
+ input.scrollIntoView({ block: "nearest" });
+ }
+ });
+</script>
diff --git a/cgithub/views/owner.eta b/cgithub/views/owner.eta
index e5667fb..b3304fb 100644
--- a/cgithub/views/owner.eta
+++ b/cgithub/views/owner.eta
@@ -1,65 +1,54 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title><%= it.name ? `${it.name} (${it.login})` : it.login %></title>
- <link rel="stylesheet" href="/static/style.css">
-</head>
-<body>
- <div class="box">
- <% if (it.avatarUrl) { %>
- <img class="avatar" src="<%= it.avatarUrl %>" alt="" width="64" height="64">
- <% } %>
- <div class="repo"><%= it.name || it.login %></div>
- <div><%= it.login %><%= it.type === "organization" ? " (organization)" : "" %></div>
- <% if (it.location) { %>
- <div><%= it.location %></div>
- <% } %>
- <% if (it.nav.length > 0) { %>
- <nav>
- <% for (const item of it.nav) { %>
- <a href="<%= item.href %>"><%= item.text %></a>
- <% } %>
- </nav>
- <% } %>
- </div>
+<% layout("/layouts/base.eta", { title: it.name ? `${it.name} (${it.login})` : it.login }) %>
- <% if (it.bio || it.links.length > 0 || it.followers || it.company) { %>
- <div class="box repo-info">
- <% if (it.bio) { %>
- <div class="description"><%= it.bio %></div>
- <% } %>
- <% for (const link of it.links) { %>
- <div class="detail"><img src="/static/icons/link.svg" alt="" class="icon"> <a href="<%= link.href %>" rel="noopener noreferrer"><%= link.text %></a></div>
- <% } %>
- <% if (it.followers) { %>
- <div class="detail"><img src="/static/icons/eye.svg" alt="" class="icon"> <%= it.followers %> followers<%= it.following ? ` · ${it.following} following` : "" %></div>
- <% } %>
- <% if (it.company) { %>
- <div class="detail"><%= it.company %></div>
- <% } %>
- </div>
+<div class="box">
+ <% if (it.avatarUrl) { %>
+ <img class="avatar" src="<%= it.avatarUrl %>" alt="" width="64" height="64">
<% } %>
-
- <% if (it.pinned.length > 0) { %>
- <section>
- <h2>Pinned</h2>
- <% for (const repo of it.pinned) { %>
- <%~ include("./_ownerRepo", { repo, login: it.login }) %>
- <% } %>
- </section>
+ <div class="repo"><%= it.name || it.login %></div>
+ <div><%= it.login %><%= it.type === "organization" ? " (organization)" : "" %></div>
+ <% if (it.location) { %>
+ <div><%= it.location %></div>
<% } %>
-
- <% if (it.repos.length > 0) { %>
- <section>
- <h2>Repositories</h2>
- <% for (const repo of it.repos) { %>
- <%~ include("./_ownerRepo", { repo, login: it.login }) %>
+ <% if (it.nav.length > 0) { %>
+ <nav>
+ <% for (const item of it.nav) { %>
+ <a href="<%= item.href %>"><%= item.text %></a>
<% } %>
- </section>
+ </nav>
<% } %>
+</div>
+
+<% if (it.bio || it.links.length > 0 || it.followers || it.company) { %>
+ <div class="box repo-info">
+ <% if (it.bio) { %>
+ <div class="description"><%= it.bio %></div>
+ <% } %>
+ <% for (const link of it.links) { %>
+ <div class="detail"><img src="/static/icons/link.svg" alt="" class="icon"> <a href="<%= link.href %>" rel="noopener noreferrer"><%= link.text %></a></div>
+ <% } %>
+ <% if (it.followers) { %>
+ <div class="detail"><img src="/static/icons/eye.svg" alt="" class="icon"> <%= it.followers %> followers<%= it.following ? ` · ${it.following} following` : "" %></div>
+ <% } %>
+ <% if (it.company) { %>
+ <div class="detail"><%= it.company %></div>
+ <% } %>
+ </div>
+<% } %>
- <footer>Generated by cgithub</footer>
-</body>
-</html>
+<% if (it.pinned.length > 0) { %>
+ <section>
+ <h2>Pinned</h2>
+ <% for (const repo of it.pinned) { %>
+ <%~ include("./_ownerRepo", { repo, login: it.login }) %>
+ <% } %>
+ </section>
+<% } %>
+
+<% if (it.repos.length > 0) { %>
+ <section>
+ <h2>Repositories</h2>
+ <% for (const repo of it.repos) { %>
+ <%~ include("./_ownerRepo", { repo, login: it.login }) %>
+ <% } %>
+ </section>
+<% } %>
diff --git a/cgithub/views/pulls.eta b/cgithub/views/pulls.eta
index 9ec5ca1..697f6b1 100644
--- a/cgithub/views/pulls.eta
+++ b/cgithub/views/pulls.eta
@@ -1,4 +1,4 @@
-<% layout("./layout"); it.searchType = "pullrequests" %>
+<% layout("/layouts/repo.eta"); it.searchType = "pullrequests" %>
<table>
<% for (const pull of it.pulls) { %>
diff --git a/cgithub/views/release.eta b/cgithub/views/release.eta
index 46dd5db..64cca35 100644
--- a/cgithub/views/release.eta
+++ b/cgithub/views/release.eta
@@ -1,3 +1,3 @@
-<% layout("./layout.eta") %>
+<% layout("/layouts/repo.eta") %>
<%~ include("./_release.eta", { repo: it.repo, release: it.release, linkToDetail: false }) %>
diff --git a/cgithub/views/releases.eta b/cgithub/views/releases.eta
index 840908c..4ede28b 100644
--- a/cgithub/views/releases.eta
+++ b/cgithub/views/releases.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta") %>
+<% layout("/layouts/repo.eta") %>
<% for (const release of it.releases) { %>
<%~ include("./_release.eta", { repo: it.repo, release, linkToDetail: true }) %>
diff --git a/cgithub/views/repo.eta b/cgithub/views/repo.eta
index 5dc6beb..60746df 100644
--- a/cgithub/views/repo.eta
+++ b/cgithub/views/repo.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta") %>
+<% layout("/layouts/repo.eta") %>
<% if (it.info) { %>
<div class="box repo-info">
diff --git a/cgithub/views/tree.eta b/cgithub/views/tree.eta
index 41ded06..fabf5b9 100644
--- a/cgithub/views/tree.eta
+++ b/cgithub/views/tree.eta
@@ -1,3 +1,3 @@
-<% layout("./layout.eta"); it.searchType = "code" %>
+<% layout("/layouts/repo.eta"); it.searchType = "code" %>
<%~ include("./_tree.eta", it) %>
diff --git a/cgithub/views/wiki.eta b/cgithub/views/wiki.eta
index d6047e1..781caff 100644
--- a/cgithub/views/wiki.eta
+++ b/cgithub/views/wiki.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta"); it.path = "wiki/" + it.title %>
+<% layout("/layouts/repo.eta"); it.path = "wiki/" + it.title %>
<%~ include("./_wikiNav.eta", it) %>
diff --git a/cgithub/views/wikiPages.eta b/cgithub/views/wikiPages.eta
index 58d6d21..eb90781 100644
--- a/cgithub/views/wikiPages.eta
+++ b/cgithub/views/wikiPages.eta
@@ -1,4 +1,4 @@
-<% layout("./layout.eta"); it.path = "wiki/_pages" %>
+<% layout("/layouts/repo.eta"); it.path = "wiki/_pages" %>
<%~ include("./_wikiNav.eta", it) %>