Put commit pages as a single permalink, not per-branch or per-tag

b1c07138709eb2fcdeeb331bceff15e87341c047

Tucker McKnight <tucker@pangolin.lan> | Sat Jul 04 2026

Put commit pages as a single permalink, not per-branch or per-tag

Commit pages will be a special case where there isn't one on each
/branch/branch-name or /tags/tag-name URL. Instead, commit pages
are their own thing, detached from branches and tags.

So the currentRef for a commit page is just the hash of the commit.
There can be a 'commit' refType on the nav helper now.

Commit pages will have their nav links just go back to the default branch.

Additionally, this change makes pages use the nav helper for determining
their permalinks, and uses the nav helper in other places where it wasn't
being used before, to DRY things up and avoid broken links.

Also, the URL scheme on the default branch for all pages will now omit
the /branches/main part of the URL. Instead, default branch pages are
just at the repo root path. E.g. /repos/my-repo/files for the default
branch, but still /repos/my-repo/branches/development/files for the
development branch.
js_templates/commit.ts:1
Before
0
1
2

3
import m from 'mithril'
import htmlPage from './common/htmlPage.ts'

⁣
export default async (
  reposConfig: any,
After
0
1
2
3
4
import m from 'mithril'
import htmlPage from './common/htmlPage.ts'
import { NavHelper } from './helpers/nav.ts'

export default async (
  reposConfig: any,
js_templates/commit.ts:10
Before
9
10
11
12







13
  const slugify = eleventyConfig.getFilter("slugify")
  const lineNumbers = eleventyConfig.getFilter("lineNumbers")
  const languageExtension = eleventyConfig.getFilter("languageExtension")

⁣
⁣
⁣
⁣
⁣
⁣
⁣
  return await htmlPage(reposConfig, eleventyConfig, data, [
    m('div', {class: "row"},
After
9
10
11
12
13
14
15
16
17
18
19
20
  const slugify = eleventyConfig.getFilter("slugify")
  const lineNumbers = eleventyConfig.getFilter("lineNumbers")
  const languageExtension = eleventyConfig.getFilter("languageExtension")
  const nav = NavHelper({
    reposConfig,
    slugify,
    currentRepoName: data.currentRepo.name,
    currentRefName: data.currentRef.name,
    currentRefType: data.currentRefType,
  })

  return await htmlPage(reposConfig, eleventyConfig, data, [
    m('div', {class: "row"},
js_templates/commit.ts:56
Before
55
56
57
58
59
60
      return m('div', {class: 'hunk'}, [
        m('span', {class: "font-monospace fw-bold"},
          m('a', {
            href: `${data.reposPath}/${slugify(data.patchInfo.repoName)}/${data.patchInfo.type}/${slugify(data.patchInfo.refName)}/files/${hunk.fileName.split('/').map((filePart) => { return filePart.split('.').map((subpart) => { return slugify(subpart)}).join('.')}).join('/')}.html`
          }, `${hunk.fileName}:${hunk.lineNumber}`)
        ),
        m('div', {class: "diff d-flex"}, [
After
55
56
57
58
59
60
      return m('div', {class: 'hunk'}, [
        m('span', {class: "font-monospace fw-bold"},
          m('a', {
            href: nav.file(hunk.fileName)
          }, `${hunk.fileName}:${hunk.lineNumber}`)
        ),
        m('div', {class: "diff d-flex"}, [
js_templates/commits.ts:49
Before
48
49
50
51
52
53
          return m('li', {class: "page-item"},
            m('a', {
              class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
              href: `${nav.commits()}/page${pageObj.pageNumber}`,
            }, pageObj.pageNumber)
          )
        })
After
48
49
50
51
52
53
          return m('li', {class: "page-item"},
            m('a', {
              class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
              href: `${nav.commits(pageObj.pageNumber)}`,
            }, pageObj.pageNumber)
          )
        })
js_templates/commits.ts:83
Before
82
83
84
85
86
87
          return m('li', {class: "page-item"},
            m('a', {
              class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
              href: `${nav.commits()}/page${pageObj.pageNumber}`,
            }, pageObj.pageNumber)
          )
        })
After
82
83
84
85
86
87
          return m('li', {class: "page-item"},
            m('a', {
              class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
              href: `${nav.commits(pageObj.pageNumber)}`,
            }, pageObj.pageNumber)
          )
        })
js_templates/common/branchesListItems.ts:1
Before
0
1
2
3
type Ref = { name: string, href: string, date: string }
type RefType = 'branch' | 'tag'

// These are the menu items that show up in the ref: dropdown menu.
const htmlForRef = (ref: Ref, refType: RefType, currentPageRef: string, currentPageRefType: RefType, defaultBranch: string) => {
After
0
1
2
3
type Ref = { name: string, href: string, date: string }
type RefType = 'branch' | 'tag' | 'commit'

// These are the menu items that show up in the ref: dropdown menu.
const htmlForRef = (ref: Ref, refType: RefType, currentPageRef: string, currentPageRefType: RefType, defaultBranch: string) => {
js_templates/common/htmlPage.ts:69
Before
68
69
70
71
72
73
        ),
        m('li', {class: "nav-item me-4 mb-1"}, [
          m('span', {class: "nav-link d-inline-block"}, 'ref:'),
          relDropDown(ref, data.currentRefType, repo, branchesWithHrefs),
        ]),
        m('ul', {class: "main-nav navbar-nav flex-wrap"}, [
          m('li', {class: "nav-item"},
After
68
69
70
71
72
73
        ),
        m('li', {class: "nav-item me-4 mb-1"}, [
          m('span', {class: "nav-link d-inline-block"}, 'ref:'),
          relDropDown(ref.name, data.currentRefType, repo, branchesWithHrefs),
        ]),
        m('ul', {class: "main-nav navbar-nav flex-wrap"}, [
          m('li', {class: "nav-item"},
js_templates/common/htmlPage.ts:79
Before
78
79
80
81
82
83
            m('a', {class: `nav-link ${data.navTab === 'files' ? 'active' : ''}`, href: nav.files()}, 'Files')
          ),
          m('li', {class: "nav-item"},
            m('a', {class: `nav-link ${data.navTab === 'commits' ? 'active' : ''}`, href: nav.commits()}, 'Commits')
          ),
          m('li', {class: "nav-item"},
            m('a', {class: `nav-link ${data.navTab === 'branches' ? 'active' : ''}`, href: nav.branches()}, 'Branches')
After
78
79
80
81
82
83
            m('a', {class: `nav-link ${data.navTab === 'files' ? 'active' : ''}`, href: nav.files()}, 'Files')
          ),
          m('li', {class: "nav-item"},
            m('a', {class: `nav-link ${data.navTab === 'commits' ? 'active' : ''}`, href: nav.commits(1)}, 'Commits')
          ),
          m('li', {class: "nav-item"},
            m('a', {class: `nav-link ${data.navTab === 'branches' ? 'active' : ''}`, href: nav.branches()}, 'Branches')
js_templates/common/relDropDown.ts:35
Before
34
35
36
37
38
39
      ]),
      m('div', {class: "dropdown-divider"}),
      m('div', {id: "dropdown-branches-results", class: "dropdown-branches"},
        m.trust(branchesListItems(branchesWithHrefs, repo.defaultBranch, ref.name, refType, 'date'))
      )
    ])
  ])
After
34
35
36
37
38
39
      ]),
      m('div', {class: "dropdown-divider"}),
      m('div', {id: "dropdown-branches-results", class: "dropdown-branches"},
        m.trust(branchesListItems(branchesWithHrefs, repo.defaultBranch, refName, refType, 'date'))
      )
    ])
  ])
js_templates/feed.ts:3
Before
2
3
4
5
6
7
import { type Repository } from '../src/dataTypes.ts'
import getFlatRefs from '../src/flatRefs.ts'
import { dateToRfc3339 } from '@11ty/eleventy-plugin-rss'
import flatPatches from '../src/flatPatches.ts'

export default async (
  eleventyConfig: any,
After
2
3
4
5
6
7
import { type Repository } from '../src/dataTypes.ts'
import getFlatRefs from '../src/flatRefs.ts'
import { dateToRfc3339 } from '@11ty/eleventy-plugin-rss'
import { flatPatches } from '../src/flatPatches.ts'

export default async (
  eleventyConfig: any,
js_templates/file.ts:2
Before
1
2
3

4
5
import htmlPage from './common/htmlPage.ts'
import { type Repository } from '../src/dataTypes.ts'
import { type FlatFileEntry } from '../src/flatFiles.ts'
⁣
type Branch = Repository['branches'][0]

export default async (reposConfig: any, eleventyConfig: any, data: any) => {
After
1
2
3
4
5
6
import htmlPage from './common/htmlPage.ts'
import { type Repository } from '../src/dataTypes.ts'
import { type FlatFileEntry } from '../src/flatFiles.ts'
import { NavHelper } from './helpers/nav.ts'
type Branch = Repository['branches'][0]

export default async (reposConfig: any, eleventyConfig: any, data: any) => {
js_templates/file.ts:14
Before
13
14
15
16
17
18
19
20








21
22
  const highlightCode = eleventyConfig.getFilter("highlightCode")
  const languageExtension = eleventyConfig.getFilter("languageExtension")
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")

  const currentRef: Branch = data.currentRef
  const currentRepo: Repository = data.currentRepo
  const fileInfo: FlatFileEntry = data.fileInfo

⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
  const pageContent = [  
    m('div', {class: "row mt-3 mb-1"},
      m('div', {class: "col"},
After
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
  const highlightCode = eleventyConfig.getFilter("highlightCode")
  const languageExtension = eleventyConfig.getFilter("languageExtension")
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
⁣
  const currentRef: Branch = data.currentRef
  const currentRepo: Repository = data.currentRepo
  const fileInfo: FlatFileEntry = data.fileInfo

  const nav = NavHelper({
    reposConfig,
    slugify,
    currentRepoName: currentRepo.name,
    currentRefName: currentRef.name,
    currentRefType: data.currentRefType,
  })

  const pageContent = [  
    m('div', {class: "row mt-3 mb-1"},
      m('div', {class: "col"},
js_templates/file.ts:56
Before
55
56
57
58
59
60
61
62
63
64
              return m('li', {class: 'list-group-item'}, [
                dir.isDirectory ? m('span', m.trust('&#x1F4C1;&nbsp;')) : null,
                m('a', {
                  href: `${data.reposPath}/${slugify(fileInfo.repoName)}/${fileInfo.type}/${slugify(fileInfo.refName)}/files/${dir.fullPath.split('/').map((pathPart) => {
                    return pathPart.split('.').map((subPart) => {
                      return slugify(subPart)
                    }).join('.')
                  }).join('/')}`},
                  getRelativePath(fileInfo.file, dir.name)
                )
              ])
After
55
56
57




58
59
60
              return m('li', {class: 'list-group-item'}, [
                dir.isDirectory ? m('span', m.trust('&#x1F4C1;&nbsp;')) : null,
                m('a', {
⁣
⁣
⁣
⁣
                  href: nav.file(dir.fullPath)},
                  getRelativePath(fileInfo.file, dir.name)
                )
              ])
js_templates/file.ts:72
Before
71
72
73
74
75
76
        m('div', {class: "row my-3"},
          m('div', {class: "col"},
            m('span', m('a', {
              href: `${data.reposPath}/${slugify(fileInfo.repoName)}/${fileInfo.type}/${slugify(fileInfo.refName)}/raw/${fileInfo.file.split('.').map(filePart => slugify(filePart)).join('.')}`}, 'View raw file'))
          )
        ),
        (fileInfo.file.endsWith(".md") ?
After
71
72
73
74
75
76
        m('div', {class: "row my-3"},
          m('div', {class: "col"},
            m('span', m('a', {
              href: nav.raw(fileInfo.file)}, 'View raw file'))
          )
        ),
        (fileInfo.file.endsWith(".md") ?
js_templates/file.ts:127
Before
126
127
128
129
130
131
                m('code', {style: "white-space: pre;"}, [
                  m('pre', {class: "language-text"}, m.trust(
                    (await currentRepo.files(fileInfo.file, currentRef.sha)).blameLines.map((annotation) => {
                      return `<a href="${data.reposPath}/${slugify(fileInfo.repoName)}/${fileInfo.type}/${slugify(fileInfo.refName)}/commits/${annotation.sha}">${annotation.sha.substr(0, 6)}</a> ${annotation.author}`
                    }).join('\n')))
                ])
              ),
After
126
127
128
129
130
131
                m('code', {style: "white-space: pre;"}, [
                  m('pre', {class: "language-text"}, m.trust(
                    (await currentRepo.files(fileInfo.file, currentRef.sha)).blameLines.map((annotation) => {
                      return `<a href="${nav.commit(annotation.sha)}">${annotation.sha.substr(0, 6)}</a> ${annotation.author}`
                    }).join('\n')))
                ])
              ),
js_templates/files.ts:36
Before
35
36
37
38
39
40
      return m('li', {class: 'list-group-item'}, [
        file.isDirectory ? m.trust('<span>&#x1F4C1;&nbsp;</span>') : null,
        m('a', {
          href: nav.file(file)
        }, file.name)
      ])
    }))
After
35
36
37
38
39
40
      return m('li', {class: 'list-group-item'}, [
        file.isDirectory ? m.trust('<span>&#x1F4C1;&nbsp;</span>') : null,
        m('a', {
          href: nav.file(file.fullPath)
        }, file.name)
      ])
    }))
js_templates/helpers/nav.ts:1
Before
0
1
2
import { type SortedFileList } from '../../src/dataTypes.ts'
import { type ReposConfiguration } from "../../src/configTypes.ts"

/**
After
0
1
i⁣
mport { type ReposConfiguration } from "../../src/configTypes.ts"

/**
js_templates/helpers/nav.ts:14
Before
13
14
15
16
17
18
  slugify: Function,
  currentRepoName: string,
  currentRefName: string,
  currentRefType: 'branch' | 'tag'
}
export const NavHelper = (args: CurrentRefArgs) => {
  const reposPath = args.reposConfig.path || ""
After
13
14
15
16
17
18
  slugify: Function,
  currentRepoName: string,
  currentRefName: string,
  currentRefType: 'branch' | 'tag' | 'commit'
}
export const NavHelper = (args: CurrentRefArgs) => {
  const reposPath = args.reposConfig.path || ""
js_templates/helpers/nav.ts:24
Before
23
24
25





26
27

28
  // or 'repos/my-repo-name/branches.'
  const repoBasePath = `${reposPath}/${args.slugify(args.currentRepoName)}`

⁣
⁣
⁣
⁣
⁣
  const refPath = (refName, refType) => `${repoBasePath}/${refType}/${args.slugify(refName)}`

⁣
  type RefArgument = {
    refName: string,
After
23
24
25
26
27
28
29
30
31
32
33
34
  // or 'repos/my-repo-name/branches.'
  const repoBasePath = `${reposPath}/${args.slugify(args.currentRepoName)}`

  const refPath = (refName, refType) => {
    if (refType === 'commit'
        || (refType === 'branch' && refName === args.reposConfig.repos[args.currentRepoName].defaultBranch)) {
      return repoBasePath
    }
    return `${repoBasePath}/${refType}/${args.slugify(refName)}`
  }

  type RefArgument = {
    refName: string,
main.ts:4
Before
3
4
5
6
7
8
import {repos, getBranchesAndTags} from './src/repos.ts'
import getFlatRefs from './src/flatRefs.ts'
import { flatFiles, flatDirectories } from './src/flatFiles.ts'
import flatPatches from './src/flatPatches.ts'
import paginatedPatches, {type PatchPage} from './src/paginatedPatches.ts'
import {getLocation} from './src/helpers.ts'
import {ReposConfiguration} from './src/configTypes.ts'
After
3
4
5
6
7
8
import {repos, getBranchesAndTags} from './src/repos.ts'
import getFlatRefs from './src/flatRefs.ts'
import { flatFiles, flatDirectories } from './src/flatFiles.ts'
import { flatPatches, commitsInRepo } from './src/flatPatches.ts'
import paginatedPatches, {type PatchPage} from './src/paginatedPatches.ts'
import {getLocation} from './src/helpers.ts'
import {ReposConfiguration} from './src/configTypes.ts'
main.ts:22
Before
21
22
23
24

25
import tagsJsTemplate from './js_templates/tags.ts'
import rawJsTemplate from './js_templates/raw.ts'
import feedJsTemplate from './js_templates/feed.ts'

⁣
const ajv = new Ajv()
const exec = util.promisify(childProcess.exec)
After
21
22
23
24
25
26
import tagsJsTemplate from './js_templates/tags.ts'
import rawJsTemplate from './js_templates/raw.ts'
import feedJsTemplate from './js_templates/feed.ts'
import { NavHelper } from './js_templates/helpers/nav.ts'

const ajv = new Ajv()
const exec = util.promisify(childProcess.exec)
main.ts:308
Before
307
308
309



310
311
312


313
314
315
        alias: "flatRef",
      },
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.flatRef.repoName
        const refName = data.flatRef.refName
        const refType = data.flatRef.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/branches/`
      },
      eleventyComputed: {
        nav: {
After
307
308
309
310
311
312
313
314
315
316
317
318
319
320
        alias: "flatRef",
      },
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.flatRef.repoName,
          currentRefName: data.flatRef.refName,
          currentRefType: data.flatRef.type,
        })

        return nav.branches() + '/'
      },
      eleventyComputed: {
        nav: {
main.ts:348
Before
347
348
349



350
351
352


353
354
355
        alias: "flatRef",
      },
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.flatRef.repoName
        const refName = data.flatRef.refName
        const refType = data.flatRef.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/tags/`
      },
      eleventyComputed: {
        nav: {
After
347
348
349
350
351
352
353
354
355
356
357
358
359
360
        alias: "flatRef",
      },
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.flatRef.repoName,
          currentRefName: data.flatRef.refName,
          currentRefType: data.flatRef.type,
        })

        return nav.tags() + '/'
      },
      eleventyComputed: {
        nav: {
main.ts:392
Before
391
392
393



394
395
396


397
398
399
      },
      flatFiles: flatFilesData.concat(flatDirectoriesData),
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.fileInfo.repoName
        const refName = data.fileInfo.refName
        const refType = data.fileInfo.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/files/${data.fileInfo.file.split('/').map((filePart) => filePart.split('.').map((subPart) => eleventyConfig.getFilter("slugify")(subPart)).join('.')).join('/')}.html`
      },
      eleventyComputed: {
        nav: {
After
391
392
393
394
395
396
397
398
399
400
401
402
403
404
      },
      flatFiles: flatFilesData.concat(flatDirectoriesData),
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.fileInfo.repoName,
          currentRefName: data.fileInfo.refName,
          currentRefType: data.fileInfo.type,
        })

        return nav.file(data.fileInfo.file)
      },
      eleventyComputed: {
        nav: {
main.ts:434
Before
433
434
435



436
437
438


439
440
441
      eleventyAllowMissingExtension: true,
      flatFiles: flatFilesData,
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.fileInfo.repoName
        const refName = data.fileInfo.refName
        const refType = data.fileInfo.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/raw/${data.fileInfo.file.split('/').map((filePart) => filePart.split('.').map((subPart) => eleventyConfig.getFilter("slugify")(subPart)).join('.')).join('/')}`
      },
      eleventyComputed: {
        currentRepo: (data) => reposData.find(repo => {
After
433
434
435
436
437
438
439
440
441
442
443
444
445
446
      eleventyAllowMissingExtension: true,
      flatFiles: flatFilesData,
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.fileInfo.repoName,
          currentRefName: data.fileInfo.refName,
          currentRefType: data.fileInfo.type,
        })

        return nav.raw(data.fileInfo.file)
      },
      eleventyComputed: {
        currentRepo: (data) => reposData.find(repo => {
main.ts:468
Before
467
468
469



470
471
472


473
474
475
        alias: "flatRef",
      },
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.flatRef.repoName
        const refName = data.flatRef.refName
        const refType = data.flatRef.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/files/`
      },
      eleventyComputed: {
        nav: {
After
467
468
469
470
471
472
473
474
475
476
477
478
479
480
        alias: "flatRef",
      },
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.flatRef.repoName,
          currentRefName: data.flatRef.refName,
          currentRefType: data.flatRef.type,
        })

        return nav.files() + '/'
      },
      eleventyComputed: {
        nav: {
main.ts:507
Before
506
507
508



509
510
511
512
513
514
515
516
517
518
519
        alias: "flatRef",
      },
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.flatRef.repoName
        const refName = data.flatRef.refName
        const refType = data.flatRef.type
        if (refType === "branch" && refName === reposConfiguration.repos[repoName].defaultBranch) {
          return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/`
        }
        else {
          return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/`
        }
      },
      eleventyComputed: {
        nav: {
After
506
507
508
509
510
511
512
513
514

515
516

517

518
519
        alias: "flatRef",
      },
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.flatRef.repoName,
          currentRefName: data.flatRef.refName,
          currentRefType: data.flatRef.type,
⁣
        })

⁣
        return nav.refHome() + '/'
⁣
      },
      eleventyComputed: {
        nav: {
main.ts:553
Before
552
553
554



555
556
557


558
559
560
      },
      paginatedPatches: paginatedPatchesData,
      permalink: (data) => {
⁣
⁣
⁣
        const repoName = data.patchPage.repoName
        const refName = data.patchPage.refName
        const refType = data.patchPage.type
⁣
⁣
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/commits/page${data.patchPage.pageNumber}/`
      },
      eleventyComputed: {
        nav: {
After
552
553
554
555
556
557
558
559
560
561
562
563
564
565
      },
      paginatedPatches: paginatedPatchesData,
      permalink: (data) => {
        const nav = NavHelper({
          reposConfig: reposConfiguration,
          slugify,
          currentRepoName: data.patchPage.repoName,
          currentRefName: data.patchPage.refName,
          currentRefType: data.patchPage.type,
        })

        return nav.commits(data.patchPage.pageNumber) + '/'
      },
      eleventyComputed: {
        nav: {
main.ts:582
Before
After
scss/design-board.scss:191
Before
190
191
192








193
194
195
196
197
198
  max-width: 100%;
}

⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
.branch-selector .dropdown-menu {
  min-width: 220px;
  max-height: 80vh;
  overflow-y: scroll;
}

⁣
.badge {
After
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  max-width: 100%;
}

.branch-selector {
  /* Special purple box to draw user's attention to the fact that
   * commit pages are a special case. */
  .current-ref-commit {
    background: $purple;
    color: white;
  }

  .dropdown-menu {
    min-width: 220px;
    max-height: 80vh;
    overflow-y: scroll;
  }
}

.badge {
src/flatPatches.ts:1
Before
0
1
2


3
4
5
6
7
8
9
10




11
12
13
14
import { type Repository } from "./dataTypes.ts"

type FlatPatchRecord = {
⁣
⁣
  commit: ReturnType<Repository['commits']['get']>,
  repoName: string,
  refName: string,
  type: "branch" | "tag",
}

let cachedFlatPatches: Array<FlatPatchRecord> | null = null

⁣
⁣
⁣
⁣
export default async (repos: Array<Repository>)
  : Promise<Array<FlatPatchRecord>> => {
  if (cachedFlatPatches !== null) { return cachedFlatPatches }

  const itemsForRef: (
After
0
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { type Repository } from "./dataTypes.ts"

⁣
type Commit = ReturnType<Repository['commits']['get']>
type FlatPatchRecord = {
  commit: Commit,
  repoName: string,
  refName: string,
  type: "branch" | "tag",
}

let cachedFlatPatches: Array<FlatPatchRecord> | null = null
let cachedRepoCommits: Array<{
  repoName: string,
  commit: Commit,
}> | null = null

const flatPatches = (repos: Array<Repository>)
  : Array<FlatPatchRecord> => {
  if (cachedFlatPatches !== null) { return cachedFlatPatches }

  const itemsForRef: (
src/flatPatches.ts:47
Before
46
47




















  return cachedFlatPatches
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
}
After
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

  return cachedFlatPatches
}

const commitsInRepo = (repos: Array<Repository>) : Array<{repoName: string, commit: Commit}> => {
  if (cachedRepoCommits !== null) { return cachedRepoCommits }

  cachedRepoCommits = repos.flatMap((repo) => {
    return Array.from(repo.commits.values()).map((commit) => {
      return {
        repoName: repo.name,
        commit,
      }
    })
  })

  return cachedRepoCommits
}

export {
  flatPatches,
  commitsInRepo,
}
src/paginatedPatches.ts:1
Before
0
1
2
3
import { type Repository } from './dataTypes.ts'
import flatPatchesFunc from './flatPatches.js'

export type PatchPage = {
  repoName: string,
After
0
1
2
3
import { type Repository } from './dataTypes.ts'
import { flatPatches as flatPatchesFunc } from './flatPatches.js'

export type PatchPage = {
  repoName: string,
wiki/index.md:13
Before
12
13
14
15

16
## Works in Progress

- [ ] Clean up the template views, create mithril components for rows and columns

⁣
## Ideas and Todos
After
12
13
14
15
16
17
## Works in Progress

- [ ] Clean up the template views, create mithril components for rows and columns
- [ ] [Make it only generate one page per commit](./projects/one-page-per-commit.md.html)

## Ideas and Todos