summaryrefslogtreecommitdiff
path: root/cgithub/public
diff options
context:
space:
mode:
authorJoe Mou <dev@mou.fo>2026-09-18 07:27:21 +0100
committerJoe Mou <dev@mou.fo>2026-09-18 07:27:21 +0100
commit9659525bf2387af6deab9d401784b94b1f44d395 (patch)
treec67dc1dd05bf2a8fa48dc123d6353d255a658ef1 /cgithub/public
parent9819d8e5504d6f03d27ec6b8786eec8fe5a752a5 (diff)
parent01494e6fa1345a509560e5e19a7f08cb2aac5cc8 (diff)
Merge commit 'FILTERED_HEAD'HEADmain
Diffstat (limited to 'cgithub/public')
-rw-r--r--cgithub/public/static/icons/eye.svg1
-rw-r--r--cgithub/public/static/icons/file.svg1
-rw-r--r--cgithub/public/static/icons/folder-simple.svg1
-rw-r--r--cgithub/public/static/icons/git-branch.svg1
-rw-r--r--cgithub/public/static/icons/git-fork.svg1
-rw-r--r--cgithub/public/static/icons/link.svg1
-rw-r--r--cgithub/public/static/icons/star.svg1
-rw-r--r--cgithub/public/static/refs.js71
-rw-r--r--cgithub/public/static/style.css407
9 files changed, 485 insertions, 0 deletions
diff --git a/cgithub/public/static/icons/eye.svg b/cgithub/public/static/icons/eye.svg
new file mode 100644
index 0000000..f6f8230
--- /dev/null
+++ b/cgithub/public/static/icons/eye.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M247.31,124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57,61.26,162.88,48,128,48S61.43,61.26,36.34,86.35C17.51,105.18,9,124,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208s66.57-13.26,91.66-38.34c18.83-18.83,27.3-37.61,27.65-38.4A8,8,0,0,0,247.31,124.76ZM128,192c-30.78,0-57.67-11.19-79.93-33.25A133.47,133.47,0,0,1,25,128,133.33,133.33,0,0,1,48.07,97.25C70.33,75.19,97.22,64,128,64s57.67,11.19,79.93,33.25A133.46,133.46,0,0,1,231.05,128C223.84,141.46,192.43,192,128,192Zm0-112a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/file.svg b/cgithub/public/static/icons/file.svg
new file mode 100644
index 0000000..f2e7629
--- /dev/null
+++ b/cgithub/public/static/icons/file.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/folder-simple.svg b/cgithub/public/static/icons/folder-simple.svg
new file mode 100644
index 0000000..36acab2
--- /dev/null
+++ b/cgithub/public/static/icons/folder-simple.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M216,72H130.67L102.93,51.2a16.12,16.12,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V200a16,16,0,0,0,16,16H216.89A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72Zm0,128H40V64H93.33L123.2,86.4A8,8,0,0,0,128,88h88Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/git-branch.svg b/cgithub/public/static/icons/git-branch.svg
new file mode 100644
index 0000000..4b442e2
--- /dev/null
+++ b/cgithub/public/static/icons/git-branch.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M232,64a32,32,0,1,0-40,31v17a8,8,0,0,1-8,8H96a23.84,23.84,0,0,0-8,1.38V95a32,32,0,1,0-16,0v66a32,32,0,1,0,16,0V144a8,8,0,0,1,8-8h88a24,24,0,0,0,24-24V95A32.06,32.06,0,0,0,232,64ZM64,64A16,16,0,1,1,80,80,16,16,0,0,1,64,64ZM96,192a16,16,0,1,1-16-16A16,16,0,0,1,96,192ZM200,80a16,16,0,1,1,16-16A16,16,0,0,1,200,80Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/git-fork.svg b/cgithub/public/static/icons/git-fork.svg
new file mode 100644
index 0000000..ca318b2
--- /dev/null
+++ b/cgithub/public/static/icons/git-fork.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M224,64a32,32,0,1,0-40,31v17a8,8,0,0,1-8,8H80a8,8,0,0,1-8-8V95a32,32,0,1,0-16,0v17a24,24,0,0,0,24,24h40v25a32,32,0,1,0,16,0V136h40a24,24,0,0,0,24-24V95A32.06,32.06,0,0,0,224,64ZM48,64A16,16,0,1,1,64,80,16,16,0,0,1,48,64Zm96,128a16,16,0,1,1-16-16A16,16,0,0,1,144,192ZM192,80a16,16,0,1,1,16-16A16,16,0,0,1,192,80Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/link.svg b/cgithub/public/static/icons/link.svg
new file mode 100644
index 0000000..25ffe17
--- /dev/null
+++ b/cgithub/public/static/icons/link.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M240,88.23a54.43,54.43,0,0,1-16,37L189.25,160a54.27,54.27,0,0,1-38.63,16h-.05A54.63,54.63,0,0,1,96,119.84a8,8,0,0,1,16,.45A38.62,38.62,0,0,0,150.58,160h0a38.39,38.39,0,0,0,27.31-11.31l34.75-34.75a38.63,38.63,0,0,0-54.63-54.63l-11,11A8,8,0,0,1,135.7,59l11-11A54.65,54.65,0,0,1,224,48,54.86,54.86,0,0,1,240,88.23ZM109,185.66l-11,11A38.41,38.41,0,0,1,70.6,208h0a38.63,38.63,0,0,1-27.29-65.94L78,107.31A38.63,38.63,0,0,1,144,135.71a8,8,0,0,0,16,.45A54.86,54.86,0,0,0,144,96a54.65,54.65,0,0,0-77.27,0L32,130.75A54.62,54.62,0,0,0,70.56,224h0a54.28,54.28,0,0,0,38.64-16l11-11A8,8,0,0,0,109,185.66Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/icons/star.svg b/cgithub/public/static/icons/star.svg
new file mode 100644
index 0000000..4e640f4
--- /dev/null
+++ b/cgithub/public/static/icons/star.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M239.18,97.26A16.38,16.38,0,0,0,224.92,86l-59-4.76L143.14,26.15a16.36,16.36,0,0,0-30.27,0L90.11,81.23,31.08,86a16.46,16.46,0,0,0-9.37,28.86l45,38.83L53,211.75a16.38,16.38,0,0,0,24.5,17.82L128,198.49l50.53,31.08A16.4,16.4,0,0,0,203,211.75l-13.76-58.07,45-38.83A16.43,16.43,0,0,0,239.18,97.26Zm-15.34,5.47-48.7,42a8,8,0,0,0-2.56,7.91l14.88,62.8a.37.37,0,0,1-.17.48c-.18.14-.23.11-.38,0l-54.72-33.65a8,8,0,0,0-8.38,0L69.09,215.94c-.15.09-.19.12-.38,0a.37.37,0,0,1-.17-.48l14.88-62.8a8,8,0,0,0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16A8,8,0,0,0,103,91.86l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153,91.86a8,8,0,0,0,6.75,4.92l63.92,5.16c.15,0,.24,0,.33.29S224,102.63,223.84,102.73Z"/></svg> \ No newline at end of file
diff --git a/cgithub/public/static/refs.js b/cgithub/public/static/refs.js
new file mode 100644
index 0000000..1035593
--- /dev/null
+++ b/cgithub/public/static/refs.js
@@ -0,0 +1,71 @@
+// Progressive enhancement for the bits of data GitHub itself loads lazily:
+// the branch/tag dropdown, the latest-commit bar above a file listing, and the
+// language breakdown. All degrade gracefully without JS: the button's
+// command/commandfor still opens the (empty) dialog natively; the placeholders
+// just never fill in.
+document.addEventListener("DOMContentLoaded", () => {
+ const dialog = document.querySelector(".ref-selector-menu");
+ if (dialog) {
+ const list = dialog.querySelector(".ref-selector-list");
+ // The view and path let the picker link to the same place on another ref
+ // rather than to the repository root.
+ const { owner, repo, view, path = "" } = dialog.dataset;
+ const cache = {};
+
+ async function load(type) {
+ if (Object.prototype.hasOwnProperty.call(cache, type)) {
+ list.innerHTML = cache[type];
+ return;
+ }
+ list.textContent = "Loading…";
+ try {
+ const res = await fetch(`/api/${owner}/${repo}/refs/${type}/${view}/${path}`);
+ const html = res.ok ? await res.text() : "";
+ cache[type] = html || "Failed to load.";
+ list.innerHTML = cache[type];
+ } catch {
+ list.textContent = "Failed to load.";
+ }
+ }
+
+ let opened = false;
+ dialog.addEventListener("toggle", () => {
+ if (dialog.open && !opened) {
+ opened = true;
+ load("branches");
+ }
+ });
+
+ for (const tab of dialog.querySelectorAll("[data-ref-type]")) {
+ tab.addEventListener("click", () => {
+ for (const other of dialog.querySelectorAll("[data-ref-type]")) {
+ other.classList.toggle("active", other === tab);
+ }
+ load(tab.dataset.refType);
+ });
+ }
+ }
+
+ for (const placeholder of document.querySelectorAll(".placeholder[data-src]")) {
+ fetch(placeholder.dataset.src)
+ .then((res) => (res.ok ? res.text() : ""))
+ .then((html) => {
+ if (html.trim()) {
+ placeholder.outerHTML = html;
+ relocate();
+ } else {
+ placeholder.remove();
+ }
+ })
+ .catch(() => placeholder.remove());
+ }
+
+ // A fragment may carry a node that belongs elsewhere on the page, where an
+ // empty element of that id holds its spot: the sidebar's latest release
+ // reads as part of the release count, far from the languages it arrives with.
+ function relocate() {
+ for (const node of document.querySelectorAll("[data-target]")) {
+ document.getElementById(node.dataset.target)?.replaceWith(node);
+ }
+ }
+});
diff --git a/cgithub/public/static/style.css b/cgithub/public/static/style.css
new file mode 100644
index 0000000..1d277b7
--- /dev/null
+++ b/cgithub/public/static/style.css
@@ -0,0 +1,407 @@
+:root {
+ color-scheme: light dark;
+ scrollbar-color: var(--border-color) var(--body-background);
+
+ --body-background: light-dark(
+ oklch(95% 0.01 250),
+ oklch(20% 0.01 250)
+ );
+
+ --text-color: light-dark(
+ oklch(5% 0.01 250),
+ oklch(90% 0.01 250)
+ );
+
+ --border-color: light-dark(
+ oklch(80% 0.01 250),
+ oklch(40% 0.01 250)
+ );
+
+ --shade-background: light-dark(
+ oklch(90% 0.01 250),
+ oklch(30% 0.01 250)
+ );
+
+ --link-color: light-dark(
+ oklch(50% 0.15 250),
+ oklch(60% 0.15 250)
+ );
+
+ --pl-c: light-dark(#6e7781, #8b949e);
+ --pl-c1: light-dark(#0550ae, #79c0ff);
+ --pl-e: light-dark(#6639ba, #d2a8ff);
+ --pl-en: light-dark(#0550ae, #d2a8ff);
+ --pl-k: light-dark(#cf222e, #ff7b72);
+ --pl-s: light-dark(#0a3069, #a5d6ff);
+ --pl-v: light-dark(#953800, #ffa657);
+}
+
+body {
+ margin: 1rem;
+ font-family: Helvetica, Arial, sans-serif;
+ background: var(--body-background);
+ color: var(--text-color);
+}
+
+a {
+ text-decoration: none;
+ color: var(--link-color);
+}
+
+h1, h2, h3, h4, h5, h6,
+p, pre, ul, ol {
+ margin: .5em 0;
+}
+
+input, select, button {
+ background-color: var(--body-background);
+ color: var(--text-color);
+ border: 1px solid var(--border-color);
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+tr {
+ border: 1px solid var(--border-color);
+}
+
+td {
+ padding: .25rem;
+ vertical-align: top;
+ &:first-child {
+ padding-left: .5rem;
+ }
+ &:last-child {
+ padding-right: .5rem;
+ }
+}
+
+nav {
+ display: flex;
+ margin: .5em 0;
+ > a {
+ display: block;
+ padding-right: .5rem;
+ + a {
+ padding-left: .5rem;
+ border-left: 1px solid var(--border-color);
+ }
+ &:last-child {
+ padding-right: 0;
+ }
+ }
+}
+
+section {
+ margin: 1rem 0;
+}
+
+.box {
+ --box-padding: .5rem;
+
+ margin: 1rem 0;
+ border: 1px solid var(--border-color);
+ padding: var(--box-padding);
+
+ > *:first-child {
+ margin-top: 0;
+ }
+ > *:last-child {
+ margin-bottom: 0;
+ }
+
+ > header:first-child {
+ margin: calc(-1 * var(--box-padding));
+ margin-bottom: 0;
+ padding: .5rem;
+ border-bottom: 1px solid var(--border-color);
+ }
+
+ > footer:last-child {
+ margin: 0 calc(-1 * var(--box-padding));
+ padding: .5rem;
+ border-top: 1px solid var(--border-color);
+ }
+}
+
+body > footer {
+ margin-top: 1rem;
+ text-align: center;
+}
+
+.icon {
+ height: 1lh;
+ vertical-align: text-bottom;
+}
+
+@media (prefers-color-scheme: dark) {
+ .icon {
+ filter: brightness(0) invert(1);
+ }
+}
+
+.repo {
+ font-size: 120%;
+ font-weight: bold;
+}
+
+.avatar {
+ float: right;
+ clip-path: circle();
+}
+
+.branch {
+ display: inline-block;
+ margin-right: 1rem;
+ padding: .2rem;
+ border: 1px solid var(--border-color);
+}
+
+.ref-selector-button {
+ anchor-name: --ref-selector-anchor;
+}
+
+.ref-selector-menu {
+ position: absolute;
+ position-anchor: --ref-selector-anchor;
+ position-area: bottom span-right;
+ width: 16rem;
+ max-height: 20rem;
+ overflow-y: auto;
+ overflow-wrap: break-word;
+ background: var(--body-background);
+ border: 1px solid var(--border-color);
+ padding: 0.5rem;
+
+ &::backdrop {
+ background: transparent;
+ }
+}
+
+.ref-selector-tabs {
+ display: flex;
+ margin-bottom: 0.5rem;
+
+ button {
+ flex: 1;
+ padding: 0.25rem;
+ cursor: pointer;
+ &.active {
+ font-weight: bold;
+ border-bottom: 2px solid var(--link-color);
+ }
+ }
+}
+
+.ref-selector-items {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+
+ li {
+ padding: 0.2rem 0;
+ }
+}
+
+.ref-selector-badge {
+ margin-left: 0.3rem;
+ font-size: 0.75rem;
+ opacity: 0.7;
+}
+
+.ref-selector-empty,
+.ref-selector-more {
+ padding: 0.2rem 0;
+ font-size: 0.85rem;
+}
+
+.placeholder {
+ opacity: 0.7;
+}
+
+.languages {
+ .language-bar {
+ display: flex;
+ height: .5rem;
+ border-radius: .25rem;
+ overflow: hidden;
+
+ span {
+ /* Keep slivers of tiny languages visible. */
+ min-width: 1px;
+ }
+ }
+
+ .language-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: .2rem 1rem;
+ list-style: none;
+ margin: .5rem 0 0;
+ padding: 0;
+ font-size: 0.85rem;
+ }
+
+ .language-dot {
+ display: inline-block;
+ width: .6rem;
+ height: .6rem;
+ border-radius: 50%;
+ }
+
+ .language-percentage {
+ opacity: 0.7;
+ }
+}
+
+.repo-info {
+ .description {
+ margin-bottom: .2rem;
+ }
+
+ .detail {
+ white-space: nowrap;
+ }
+
+ div.detail {
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ }
+
+ span.detail + span.detail {
+ margin-left: 1rem;
+ }
+}
+
+object.pdf {
+ display: block;
+ width: 100%;
+ height: 80vh;
+ padding: 0;
+}
+
+pre.box {
+ /* Instead of scrolling overflow for long lines, grow the box. */
+ width: fit-content;
+
+ span:target {
+ background: var(--shade-background);
+ }
+}
+
+.overview, .release, .wiki {
+ overflow-wrap: break-word;
+
+ /* This is a bit convoluted: we want the effect of padding but using margins
+ * vertically so we get margin collapsing. */
+ --box-padding: 1rem;
+ padding-top: 0;
+ padding-bottom: 0;
+ > header:first-child {
+ margin-top: 0;
+ }
+ > :first-child, > header:first-child + * {
+ margin-top: 1rem;
+ }
+ > :last-child {
+ margin-bottom: 1rem;
+ }
+
+ a {
+ text-decoration: underline;
+ }
+
+ h1, h2 {
+ border-bottom: 1px solid var(--border-color);
+ }
+
+ img, video {
+ max-width: 100%;
+ }
+
+ code, pre {
+ background: var(--shade-background);
+ }
+
+ pre {
+ overflow-x: auto;
+ scrollbar-color: var(--border-color) var(--shade-background);
+ }
+}
+
+.overview > header {
+ font-weight: bold;
+}
+
+.release > header, .wiki > header {
+ display: flex;
+ align-items: baseline;
+ > :first-child {
+ flex-grow: 1;
+ font-weight: bold;
+ }
+}
+
+.wiki > footer {
+ /* The wiki's _Footer page is rendered content, not a caption for the page. */
+ font-size: .9rem;
+}
+
+.wiki-pages {
+ summary {
+ cursor: pointer;
+ }
+
+ ul {
+ columns: 16rem;
+ list-style: none;
+ padding: 0;
+ }
+}
+
+.timestamp {
+ white-space: nowrap;
+ font-size: .8rem;
+}
+
+.commit {
+ display: flex;
+ justify-content: space-between;
+ padding: 0.5rem;
+ border: 1px solid var(--border-color);
+ + .commit {
+ border-top: none;
+ }
+}
+
+.commit-author {
+ font-size: 0.8rem;
+ margin-top: 0.2rem;
+}
+
+.commit-sha {
+ align-self: center;
+ font-size: 0.8rem;
+}
+
+/* TODO Strip permalinks? */
+svg.octicon-link {
+ display: none;
+}
+
+.pl-c { color: var(--pl-c); }
+.pl-c1 { color: var(--pl-c1); }
+.pl-e { color: var(--pl-e); }
+.pl-en { color: var(--pl-en); }
+.pl-k { color: var(--pl-k); }
+.pl-s { color: var(--pl-s); }
+.pl-v { color: var(--pl-v); }
+.pl-ent { color: var(--pl-k); }
+.pl-mh { font-weight: bold; color: var(--pl-en); }
+.pl-bu { color: var(--pl-k); }
+.pl-ii { color: var(--text-color); background-color: var(--pl-k); }
+.pl-pds { color: var(--pl-s); }
+.pl-smi { color: var(--text-color); }