Branch

Add patch.njk page

Mon Sep 01 2025

Tucker McKnight <tucker.mcknight@gmail.com>

Fix some references to static files that weren't using the
reposPath variable.

Put main.css in the vendors folder, which should be renamed at some
point, but for now it gets main.css into a dist/ location that can
be used by the virutal templates.

Change the way the light/dark theme switcher works; just replace
"prism.css" or "prism_dark.css" instead of replacing the full path.
This avoids having to know the reposPath variable in a JS file.

4ccb6eca9b4d6b4e497cc558eb73652a69989e4e

Side-by-side
Stacked
frontend/top.ts:32
Before
32 33
    const stylesheet = window['currentTheme'] === 'dark' || (window['currentTheme'] === 'auto' && preferred === 'dark') ? "/vendor/prism_dark.css" : "/vendor/prism.css"
    link.href = stylesheet
After
32 33
    const stylesheet = window['currentTheme'] === 'dark' || (window['currentTheme'] === 'auto' && preferred === 'dark') ? "prism_dark.css" : "prism.css"
    link.href = link.href.split("/").slice(0, -1).concat(stylesheet).join("/")
main.ts:4
Before
4
After
4
import flatPatches from './src/flatPatches.ts'
main.ts:34
Before
34 35
    [vendor]: "vendor",
    [frontend]: "frontend"
After
34 35
    [vendor]: `${reposPath}/vendor`,
    [frontend]: `${reposPath}/frontend`,
main.ts:177
Before
177 178 179
    console.log("getreadme")
    console.log(branchName)
    console.log(repoName)
After
177 178 179 180 181 182 183 184
  eleventyConfig.addFilter("pagesJustForBranch", (pages, repoName, branchName) => {
    return pages.filter(page => page.repoName === repoName && page.branchName === branchName)
  })

  eleventyConfig.addFilter("date", (dateString) => {
    return new Date(dateString).toDateString()
  })
main.ts:304
Before
304
      branches: branchesData,
After
304
main.ts:325
Before
325
    topLayoutPartial + repoTemplate + bottomLayoutPartial,
After
325
    topLayoutPartial + patchesTemplate + bottomLayoutPartial,
main.ts:336
Before
336
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/patches/page${data.patchPage.pageNumber}`
After
336
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/patches/page${data.patchPage.pageNumber}/`
main.ts:347
Before
347
After
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

  // PATCH.NJK
  const patchTemplate = fsImport.readFileSync(`${__dirname}/templates/patch.njk`).toString()
  const flatPatchesData = await flatPatches(reposConfiguration)
  eleventyConfig.addTemplate(
    `repos/patch.njk`,
    topLayoutPartial + patchTemplate + bottomLayoutPartial,
    {
      pagination: {
        data: "flatPatches",
        size: 1,
        alias: "patchInfo",
      },
      flatPatches: flatPatchesData,
      permalink: (data) => {
        const repoName = data.patchInfo.repoName
        const branchName = data.patchInfo.branchName
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/patches/${data.patchInfo.patch.hash}/`
      },
      eleventyComputed: {
        nav: {
          repoName: (data) => data.patchInfo.repoName,
          branchName: (data) => data.patchInfo.branchName,
        }
      },
      width: "full",
      navTab: "patches",
    }
  )
partial_templates/main_bottom.njk:21
Before
21 22
        window.location = `/repos/${values[0]}/branches/${values[1]}/${values[2]}`
    <script src="/frontend/main.js"></script>
After
21 22
        window.location = `{{reposPath}}/${values[0]}/branches/${values[1]}/${values[2]}`
    <script src="{{reposPath}}/frontend/main.js"></script>
partial_templates/main_top.njk:29
Before
29 30 31
    <script src="/frontend/top.js"></script>
    <link rel="stylesheet" id="prism-theme" type="text/css" href="/vendor/prism.css" />
    <link rel="stylesheet" type="text/css" href="/static/main.css" />
After
29 30 31
    <script src="{{reposPath}}/frontend/top.js"></script>
    <link rel="stylesheet" id="prism-theme" type="text/css" href="{{reposPath}}/vendor/prism.css" />
    <link rel="stylesheet" type="text/css" href="{{reposPath}}/vendor/main.css" />
src/helpers.ts:137
Before
137
  console.log(repoName)
After
137
templates/patch.njk:0
Before
0
After
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
<div class="container-lg">
  <div class="row">
    <div class="col-auto">
      <h1>{{patchInfo.patch.name}}</h2>
      <p>{{patchInfo.patch.date | date }}</p>
      <p>{{patchInfo.patch.author }}</p>
      <pre>{{patchInfo.patch.description}}</pre>
    </div>
  </div>
  <div class="row">
    <div class="col-auto">
      <p class="font-monospace fw-bold text-secondary">{{patchInfo.patch.hash}}</p>
      {% if reposConfig.repos[patchInfo.repoName]._type == "darcs" %}
      <div class="input-group mb-3 d-flex flex-nowrap">
        <span id="clone-command" class="clone input-group-text overflow-hidden">
          {% set url = [reposConfig.baseUrl, "/repos/", patchInfo.repoName | slugify, "/branches/", patchInfo.branchName | slugify] | join | url %}
          darcs pull {{ url }} -h {{patchInfo.patch.hash}}
        </span>
        <button class="btn btn-primary" id="clone-button" onclick="copyCommand()">Copy</button>
      </div>
      {% endif %}
    </div>
  </div>
</div>
<div class="container-fluid border-top">
  <div class="row my-2">
    <div class="col-auto d-flex align-items-center fs-4">
      <i class="bi bi-layout-split"></i><span class="fs-6 mx-1">Side-by-side</span>
      <div class="form-check form-switch mb-1 px-2">
        <input class="form-check-input mx-0" type="checkbox" id="unifiedModeSwitch" value="unified" onchange="toggleUnifiedMode(this)" aria-label="Toggle switch for stacked or side by side diff view">
      </div>
      <i class="bi bi-hr"></i><span class="fs-6 mx-1">Stacked</span>
    </div>
  </div>
  <div class="row" id="diffs">
  {% set patchHunks = patchInfo.patch.diffs %}
  {% for hunk in patchHunks %}
    <div class=hunk>
      <span class="font-monospace fw-bold"><a href="/repos/{{patchInfo.repoName | slugify}}/branches/{{patchInfo.branchName | slugify}}/files/{{ hunk.file | slugify}}.html">{{ hunk.file }}:{{ hunk.lineNumber }}</a></span>
      <div class="diff d-flex">
        <div class="flex-grow-1 diff-left pe-2">
          <span class='font-monospace text-secondary'>Before</span>
          <div class="row">
            <div class="col-auto border-end">
              <code>
{%- for lineNumber in hunk.previousText | lineNumbers -%}
{{ lineNumber + hunk.lineNumber - 1}}
{% endfor -%}
              </code>
            </div>
            <div class="col overflow-scroll">
              <pre data-start="{{hunk.lineNumber}}"><code data-type="before" class="line-numbers language-{{hunk.file | languageExtension(patchInfo.repoName)}}">{{hunk.previousText | safe}}</code></pre>
            </div>
          </div>
        </div>
        <div class="diff-right flex-grow-1 ps-2 border-start">
          <span class='font-monospace text-secondary'>After</span>
          <div class="row">
            <div class="col-auto border-end">
              <code>
{%- for lineNumber in hunk.afterText | lineNumbers -%}
{{ lineNumber + hunk.lineNumber - 1}}
{% endfor -%}
              </code>
            </div>
            <div class="col overflow-scroll">
              <pre data-start="{{hunk.lineNumber}}"><code data-type="after" class="line-numbers language-{{hunk.file | languageExtension(patchInfo.repoName)}}">{{ hunk.afterText | safe}}</code></pre>
            </div>
          </div>
        </div>
      </div>
    </div>
  {% endfor %}
  </div>
</div>

<script>
  const copyCommand = () => {
    const text = document.getElementById("clone-command").innerText
    const button = document.getElementById("clone-button")
    navigator.clipboard.writeText(text).then(() => {
      button.innerText = "Copied"
    })
  }
</script>
templates/patches.njk:12
Before
12
        <span class="patch-name"><a href="/repos/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName | slugify}}/patches/{{patch.hash}}">{{patch.name}}</a></span>
After
12
        <span class="patch-name"><a href="{{reposPath}}/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName | slugify}}/patches/{{patch.hash}}">{{patch.name}}</a></span>
templates/patches.njk:27
Before
27
      <a class="page-link {% if pageObj.pageNumber == patchPage.pageNumber %}active{% endif %}" href="/repos/{{patchPage.repoName | slugify}}/branches/{{patchPage.branchName}}/patches/page{{pageObj.pageNumber}}">{{ pageObj.pageNumber }}</a>
After
27
      <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>
vendor/main.css:0
Before
0
After
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
pre {
  font-size: 14px !important;
}
code {
  white-space: pre;
}
blockquote {
  margin-left: 0.25rem;
  padding-left: 0.5rem;
  border-left: 3px solid royalblue;
  background: rgba(125, 125, 125, 0.07);
  overflow: hidden;
}
blockquote p {
  margin: 0.5rem;
}
.hunk {
  box-sizing: border-box;
  margin-bottom: 25px;
}
[data-type=before] mark {
  background-color: rgba(252, 78, 78, .15);
}
[data-type=after] mark {
  background-color: rgba(151, 247, 203, .4);
}
[data-bs-theme=dark] [data-type=after] mark {
  background-color: rgba(51, 247, 160, .1); /* different green for dark mode; looks better */
}
.unified .diff {
  flex-wrap: wrap;
}
.diff-left, .diff-right {
  flex: 1;
  overflow: hidden;
}
.unified .diff-left, .unified .diff-right {
  flex-basis: 100%;
}
.patch {
  margin: 12px 0;
}
.patch-name {
  font-size: 18px;
  font-weight: bold;
}
.patch-hash {
  font-size: 14px;
  margin: 6px 0;
}
.clone {
  font-family: monospace;
  font-size: 12px;
}
.popover {
  max-width: 100%;
}