Tucker McKnight <tmcknight@instructure.com> | Sat Jun 20 2026
DRY cleanup of branchesAndTagsResults function Also fix bug where I was calling ref.type, which is undefined. It's data.currentRefType on that page.
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
export const branchesAndTagsResults = (
rels: {
branches: Array<{name: string, href: string, date: string}>,
tags: Array<{name: string, href: string, date: string}>,
},
defaultBranch: string,
currentRef: string,
currentRefType: "branch" | "tag",
sortBy: 'name' | 'date',
): string => {
return `<div class="branch">` + rels.branches.sort((a, b) => {
let comparison = 0
if (a[sortBy] < b[sortBy]) { comparison = -1 }
if (a[sortBy] > b[sortBy]) { comparison = 1 }
// we want reverse order if sorting by date (making newest first)
if (sortBy === 'date') { comparison = comparison * -1 }
return comparison
}).map((branch) => {
const currentBadge = currentRef === branch.name && currentRefType === "branch"
? '<div class="badge rounded-pill bg-secondary mx-1">current</div>'
: ''
const defaultBadge = defaultBranch === branch.name
? '<div class="badge rounded-pill bg-info text-dark mx-1">default</div>'
: ''
return `
<a href='${branch.href}' class='dropdown-item my-1'>
<span class="branch-dropdown-branch-name me-1">
${branch.name}
</span>${currentBadge}${defaultBadge}
<span class="text-body d-block ms-2">
updated ${new Date(branch.date).toDateString()}
</span>
</a>
`
}).join('') + `</div>
<div class="tag">` + rels.tags.sort((a, b) => {
let comparison = 0
if (a[sortBy] < b[sortBy]) { comparison = -1 }
if (a[sortBy] > b[sortBy]) { comparison = 1 }
// we want reverse order if sorting by date (making newest first)
if (sortBy === 'date') { comparison = comparison * -1 }
return comparison
}).map((tag) => {
const currentBadge = currentRef === tag.name && currentRefType === "tag"
? '<div class="badge rounded-pill bg-secondary mx-1">current</div>'
: ''
return `
<a href='${tag.href}' class='dropdown-item my-1'>
<span class="branch-dropdown-branch-name me-1">
${tag.name}
</span>${currentBadge}
<span class="text-body d-block ms-2">
updated ${new Date(tag.date).toDateString()}
</span>
</a>
`
}).join('') + `</div>`
}
export default (
rels: {
branches: Array<{name: string, href: string, date: string}>,
tags: Array<{name: string, href: string, date: string}>,
},
defaultBranch: string,
currentRef: string,
currentRefType: "branch" | "tag",
sortBy: 'name' | 'date',
): string => {
return `<div class="rel-dropdown" data-selected="${currentRefType}">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
<
mark>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) => {
const currentBadge = currentPageRef === ref.name && currentPageRefType === refType
? '<div class="badge rounded-pill bg-secondary mx-1">current</div>'
: ''
const defaultBadge = defaultBranch === ref.name && refType === 'branch'
? '<div class="badge rounded-pill bg-info text-dark mx-1">default</div>'
: ''
return `
<a href='${ref.href}' class='dropdown-item my-1'>
<span class="branch-dropdown-branch-name me-1">
${ref.name}
</span>${currentBadge}${defaultBadge}
<span class="text-body d-block ms-2">
updated ${new Date(ref.date).toDateString()}
</span>
</a>
`
}
const sortFunction = (a, b, sortBy) => {
let comparison = 0
if (a[sortBy] < b[sortBy]) { comparison = -1 }
if (a[sortBy] > b[sortBy]) { comparison = 1 }
// we want reverse order if sorting by date (making newest first)
if (sortBy === 'date') { comparison = comparison * -1 }
return comparison
}
// This is the full html for the contents of the ref: dropdown menu.
export const branchesAndTagsResults = (
refs: {
branches: Array<Ref>,
tags: Array<Ref>,
},
defaultBranch: string,
currentRef: string,
currentRefType: RefType,
sortBy: 'name' | 'date',
): string => {
const branchItemsHtml = refs.branches.sort((a, b) => sortFunction(a, b, sortBy))
.map(branch => htmlForRef(branch, 'branch', currentRef, currentRefType, defaultBranch))
.join('')
const tagItemsHtml = refs.tags.sort((a, b) => sortFunction(a, b, sortBy))
.map(tag => htmlForRef(tag, 'tag', currentRef, currentRefType, defaultBranch))
.join('')
return `<div class="branch">${branchItemsHtml}</div><div class="tag">${tagItemsHtml}</div>`
}
// Note: this function returns a plain string of HTML, instead of using mithril, because
// it is called directly by both the backend *and* the frontend, and the frontend does not
// include mithril. Ideally, the frontend should not need mithril; there are very few
// dynamic pieces on the frontend.
export default (
refs: {
branches: Array<Ref>,
tags: Array<Ref>,
},
defaultBranch: string,
currentRef: string,
currentRefType: RefType,
sortBy: 'name' | 'date',
): string => {
return `<div class="rel-dropdown" data-selected="${currentRefType}">81 82 83 84 85 86
</li>
</ul>
<div id="branches-and-tags-list">
${branchesAndTagsResults(rels, defaultBranch, currentRef, currentRefType, sortBy)}
</div>
</div>`
}81 82 83 84 85 86
</li>
</ul>
<div id="branches-and-tags-list">
${branchesAndTagsResults(refs, defaultBranch, currentRef, currentRefType, sortBy)}
</div>
</div>`
}46 47 48 49 50 51
window.branchesWithHrefs = ${JSON.stringify(branchesWithHrefs)};
window.defaultBranch = "${repo.defaultBranch}";
window.currentRef = "${ref.name}";
window.currentRefType = "${ref.type}";
window.cloneUrl = "${repo.cloneUrl}";
`)),
m('link', {46 47 48 49 50 51
window.branchesWithHrefs = ${JSON.stringify(branchesWithHrefs)};
window.defaultBranch = "${repo.defaultBranch}";
window.currentRef = "${ref.name}";
window.currentRefType = "${data.currentRefType}";
window.cloneUrl = "${repo.cloneUrl}";
`)),
m('link', {