Tucker McKnight <tucker@pangolin.lan> | Sat Dec 27 2025
Change patch.njk to commit.ts, use new template Adds a "Copy" button for copying the hash of the commit. Made the "Commits" nav item get underlined when it's the active navTab. Some style tweaks, added a looping template for bezel-color classes. (The bezel-header class is a special case because it changes colors between light and dark mode -- not sure what to do about that one yet.)
6 7 8 9 10 11
const copyCommand = (event) => {
const elem = event.target
const cloneText = elem.dataset.cloneUrl
const originalInnerText = elem.innerText
navigator.clipboard.writeText(cloneText).then(() => {
elem.innerText = "Copied"6 7 8 9 10 11
const copyCommand = (event) => {
const elem = event.target
const cloneText = elem.dataset.copyText
const originalInnerText = elem.innerText
navigator.clipboard.writeText(cloneText).then(() => {
elem.innerText = "Copied"24 25 26 27 28 29 30 31
<label class='form-label'>HTTPS URL</label>
<div class='input-group d-flex flex-nowrap'>
<span class='clone overflow-hidden input-group-text'>${window.cloneUrl}</span>
<button data-clone-url='${window.cloneUrl}' class='btn btn-primary shadow-none text-white' id='clone-button'>Copy</button>
</div>`
const popoverBtn = document.getElementById("clone-popover-btn")
const bsPopover = new bootstrap.Popover(popoverBtn, {
sanitize: false,24 25 26 27 28 29 30 31 32 33
<label class='form-label'>HTTPS URL</label>
<div class='input-group d-flex flex-nowrap'>
<span class='clone overflow-hidden input-group-text'>${window.cloneUrl}</span>
<button data-copy-text='${window.cloneUrl}' class='btn btn-primary shadow-none text-white' id='copy-button'>Copy</button>
</div>`
div.querySelector("#copy-button").addEventListener('click', copyCommand)
const popoverBtn = document.getElementById("clone-popover-btn")
const bsPopover = new bootstrap.Popover(popoverBtn, {
sanitize: false,37 38 39 40 41 42 43
container: 'body',
})
div.querySelector("#clone-button").addEventListener('click', copyCommand)
document.body.addEventListener('click', (event) => {
const target = event.target
// If they didn't click the #clone-popover-btn or if we're not inside of37 38 39 40 41
container: 'body',
})
document.body.addEventListener('click', (event) => {
const target = event.target
// If they didn't click the #clone-popover-btn or if we're not inside of102 103
if (document.getElementById('clone-popover-btn')) {
createClonePopover()
}102 103 104 105
if (document.getElementById('clone-popover-btn')) {
createClonePopover()
}
document.querySelector("#copy-button").addEventListener('click', copyCommand)
117 118 119 120 121 122
<a class="nav-link ${data.navTab === 'files' ? 'active' : ''}" href="${nav.repoCurrentBranchFiles()}">Files</a>
</li>
<li class="nav-item">
<a class="nav-link" href="${nav.repoCurrentBranchCommits()}">Commits</a>
</li>
<li class="nav-item">
<a class="nav-link" href="${nav.repoCurrentBranchBranches()}">Branches</a>117 118 119 120 121 122
<a class="nav-link ${data.navTab === 'files' ? 'active' : ''}" href="${nav.repoCurrentBranchFiles()}">Files</a>
</li>
<li class="nav-item">
<a class="nav-link ${data.navTab === 'commits' ? 'active' : ''}" href="${nav.repoCurrentBranchCommits()}">Commits</a>
</li>
<li class="nav-item">
<a class="nav-link" href="${nav.repoCurrentBranchBranches()}">Branches</a>38 39 40 41 42 43
return `
<div class="row">
<div class="col">
<div class="px-4 pt-3 bezel">
<div class="row">
<div class="col-12 col-xl-6">
<h1 class="display-2 text-white"><em>${repo.name}</em></h1>38 39 40 41 42 43
return `
<div class="row">
<div class="col">
<div class="px-4 pt-3 bezel-header">
<div class="row">
<div class="col-12 col-xl-6">
<h1 class="display-2 text-white"><em>${repo.name}</em></h1>15 16 17 18 19
import repoJsTemplate from './js_templates/repo.ts'
import filesJsTemplate from './js_templates/files.ts'
import fileJsTemplate from './js_templates/file.ts'
const ajv = new Ajv()
const exec = util.promisify(childProcess.exec)15 16 17 18 19 20
import repoJsTemplate from './js_templates/repo.ts'
import filesJsTemplate from './js_templates/files.ts'
import fileJsTemplate from './js_templates/file.ts'
import commitJsTemplate from './js_templates/commit.ts'
const ajv = new Ajv()
const exec = util.promisify(childProcess.exec)419 420 421 422 423 424 425
}
)
// PATCHES.NJK
const patchesTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/patches.njk`).toString()
const paginatedPatchesData = await paginatedPatches(reposData)419 420 421 422 423
}
)
// PATCHES.NJK
const patchesTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/patches.njk`).toString()
const paginatedPatchesData = await paginatedPatches(reposData)458 459 460 461 462 463 464 465 466 467 468
}
)
// PATCH.NJK
const patchTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/patch.njk`).toString()
const flatPatchesData = await flatPatches(reposData)
eleventyConfig.addTemplate(
`repos/patch.njk`,
topLayoutPartial + patchTemplate + bottomLayoutPartial,
{
pagination: {
data: "flatPatches",458 459 460 461 462 463 464 465 466 467
}
)
// COMMIT.TS
const flatPatchesData = await flatPatches(reposData)
eleventyConfig.addTemplate(
`repos/commit.11ty.js`,
htmlPage(reposConfiguration, eleventyConfig, commitJsTemplate),
{
pagination: {
data: "flatPatches",491 492 493 494 495 496 497
return branch.name === data.patchInfo.branchName
}),
},
width: "full",
navTab: "patches",
}
)
491 492 493 494 495 496
return branch.name === data.patchInfo.branchName
}),
},
navTab: "commits",
}
)
35 36 37 38 39 40
--bs-list-group-border-color: #BAC1CA;
}
.bezel {
background-color: $lightblue;
border-top: 6px solid color.adjust($lightblue, $lightness: 15%);
border-left: 6px solid color.adjust($lightblue, $lightness: 13%);35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
--bs-list-group-border-color: #BAC1CA;
}
$bezel-colors: ("primary": $primary, "secondary": $secondary, "info": $info, "warning": $warning);
@each $color, $value in $bezel-colors {
.bezel-#{$color} {
background-color: $value;
border-top: 6px solid color.adjust($value, $lightness: 15%);
border-left: 6px solid color.adjust($value, $lightness: 13%);
border-bottom: 6px solid color.adjust($value, $lightness: -30%);
border-right: 6px solid color.adjust($value, $lightness: -40%);
}
}
@each $color, $value in map-remove($bezel-colors, "info") {
.bezel-#{$color} {
color: $body-color-dark;
}
}
.bezel-header {
background-color: $lightblue;
border-top: 6px solid color.adjust($lightblue, $lightness: 15%);
border-left: 6px solid color.adjust($lightblue, $lightness: 13%);46 47 48 49 50 51
@include color-mode(dark) {
$blue: #354BC6;
.bezel {
background-color: $blue;
border-top: 6px solid color.adjust($blue, $lightness: 10%);
border-left: 6px solid color.adjust($blue, $lightness: 7%);46 47 48 49 50 51
@include color-mode(dark) {
$blue: #354BC6;
.bezel-header {
background-color: $blue;
border-top: 6px solid color.adjust($blue, $lightness: 10%);
border-left: 6px solid color.adjust($blue, $lightness: 7%);237 238
margin: 10px 10px;
}
}237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
margin: 10px 10px;
}
}
/* Commit page */
.hunk {
box-sizing: border-box;
margin-bottom: 25px;
}
.unified .diff {
flex-wrap: wrap;
}
.diff-left, .diff-right {
flex: 1;
overflow: hidden;
}
.unified .diff-left, .unified .diff-right {
flex-basis: 100%;
}
[data-type=before] mark {
background-color: rgba(252, 78, 78, .15);
}
[data-type=after] mark, .token.inserted {
background-color: rgba(170, 227, 203, .35);
}
[data-bs-theme=dark] [data-type=after] mark, [data-bs-theme=dark] .token.inserted {
background-color: rgba(51, 247, 160, .1); /* different green for dark mode; looks better */
}1 2 3 4 5 6
<ul class="pagination">
{% for pageObj in (paginatedPatches | pagesJustForBranch(patchPage.repoName, patchPage.branchName)) %}
<li class="page-item">
<a class="page-link {% if pageObj.pageNumber == patchPage.pageNumber %}active{% endif %}" href="{{reposPath}}/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName}}/patches/page{{pageObj.pageNumber}}">{{ pageObj.pageNumber }}</a>
</li>
{% endfor %}
</ul>1 2 3 4 5 6
<ul class="pagination">
{% for pageObj in (paginatedPatches | pagesJustForBranch(patchPage.repoName, patchPage.branchName)) %}
<li class="page-item">
<a class="page-link {% if pageObj.pageNumber == patchPage.pageNumber %}active{% endif %}" href="{{reposPath}}/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName}}/commits/page{{pageObj.pageNumber}}">{{ pageObj.pageNumber }}</a>
</li>
{% endfor %}
</ul>11 12 13 14 15 16
{% for commit in patchPage.commits %}
<li class="patch">
<div>
<span class="patch-name"><a href="{{reposPath}}/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName | slugify}}/patches/{{commit.hash}}">{{commit.message}}</a></span>
<br />
<span>{{commit.date | date}}</span>
<br />11 12 13 14 15 16
{% for commit in patchPage.commits %}
<li class="patch">
<div>
<span class="patch-name"><a href="{{reposPath}}/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName | slugify}}/commits/{{commit.hash}}">{{commit.message}}</a></span>
<br />
<span>{{commit.date | date}}</span>
<br />