Make new repo page use the new languageGraph function

597f8cf24269908265910ad17eabc91baa531a86

Tucker McKnight <tmcknight@instructure.com> | Sun Aug 09 2026

Make new repo page use the new languageGraph function
js_templates/repo.ts:1
Before
0

1
2
3
4
5




6
7
8
import m from 'mithril'
⁣
import { type Repository } from '../src/dataTypes.ts'
import { NavHelper } from './helpers/nav.ts'
import htmlPage from './common/htmlPage.ts'
import { colorAndPercentMap } from '../src/languageGraph.ts'

⁣
⁣
⁣
⁣
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
  const repo: Repository = data.currentRepo
  const ref: Repository['branches'][0] | Repository['tags'][0] = data.currentRef
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
After
0
1
2
3
4
5
6
7
8
9
10
11
12
13
import m from 'mithril'
import { ReposConfigurationWithDefaultsApplied } from '../src/configTypes.ts'
import { type Repository } from '../src/dataTypes.ts'
import { NavHelper } from './helpers/nav.ts'
import htmlPage from './common/htmlPage.ts'
import { colorAndPercentMap } from '../src/languageGraph.ts'

export default async (
  reposConfig: ReposConfigurationWithDefaultsApplied,
  eleventyConfig: any,
  data: any
) => {
  const repo: Repository = data.currentRepo
  const ref: Repository['branches'][0] | Repository['tags'][0] = data.currentRef
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
js_templates/repo.ts:27
Before
26
27
28






29
30

  const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, ref.name), ref.name)

⁣
⁣
⁣
⁣
⁣
⁣
  const pageContent = [
    m('div', {class: "row"}, [
      m('div', {class: "col"}, [
After
26
27
28
29
30
31
32
33
34
35
36

  const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, ref.name), ref.name)

  const languageColors = []
  const colorsAndPercentages = await colorAndPercentMap(reposConfig, ref, repo.files)
  for (const language in colorsAndPercentages) {
    languageColors.push({language, values: colorsAndPercentages[language]})
  }

  const pageContent = [
    m('div', {class: "row"}, [
      m('div', {class: "col"}, [
js_templates/repo.ts:88
Before
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
                  ])
                ]),
                m('div', {class: "col-12 col-sm-6 d-flex"}, [
                  m('div', {class: "d-flex flex-column"}, [
                    topLanguagePercentages.map((percentTuple) => {
⁣
                      return m('div', {class: 'language-name me-1 d-flex justify-content-end align-items-end small text-white font-monospace flex-grow-1'}, percentTuple[0])
                    }),
                    otherLanguagePercent > 0
                    ? m('div', {class: 'language-name me-1 d-flex justify-content-end align-items-end small text-white font-monospace flex-grow-1'}, 'other')
                    : null
                  ]),
                  m('div', {class: "flex-grow-1 d-flex flex-column"}, [
                    topLanguagePercentages.map((percentTuple, index) => {
                      const color = colors[index % (colors.length - 1)].light
                      return m('div', {
                        class: 'language-col flex-grow-1',
                        style: `width: ${percentTuple[1] / largestPercent * 100}%; background-color: ${color};`
                      })
                    }),
                    otherLanguagePercent > 0
                      ? m('div', {
                        class: 'language-col flex-grow-1',
                        style: `width: ${otherLanguagePercent / largestPercent * 100}%; background-color: ${colors[colors.length - 1].light};`
                      })
                      : null
                  ])
                ]),
              ]),
After
87
88
89

90
91
92


93

94
95
96
97
98
99
100
101
102






103
104
                  ])
                ]),
                m('div', {class: "col-12 col-sm-6 d-flex"}, [
⁣
                  m('div', {class: "d-flex flex-column"}, languageColors.map((languageInfo) => {
                    return m('div', {
                      class: 'language-name me-1 d-flex justify-content-end align-items-end small text-white font-monospace flex-grow-1'
⁣
⁣
                    }, languageInfo.language)
⁣
                  })),
                  m('div', {class: "flex-grow-1 d-flex flex-column"}, [
                    languageColors.map((languageInfo) => {
                      const values = languageInfo.values
                      return m('div', {
                        class: 'language-col flex-grow-1',
                        style: `width: ${values.percentOfTotal * 100}%; background-color: ${values.color};`
                      })
                    }),
⁣
⁣
⁣
⁣
⁣
⁣
                  ])
                ]),
              ]),
src/dataTypes.ts:23
Before
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
  }>
}

⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
export type Repository = {
  name: string,
  description?: string,
  cloneUrl: string,
  defaultBranch: string,
  branches: Array<{
    name: string,
    description?: string,
    ahead: number,
    behind: number,
    compareTo: string,
    sha: string,
    fileList: Set<string>,
  }>,
  files: (filename: string, sha: string) => Promise<FileInfo>,
  tags?: Array<{
    name: string,
    sha: string,
    fileList: Set<string>,
  }>,
  commits?: Map<string, Commit>,
}
After
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
  }>
}

// A "ref" is a branch or tag. Branches have some fields that tags
// don't have, but both are a base type of Ref.
export type Ref = {
  name: string,
  sha: string,
  fileList: Set<string>,
}

export type Repository = {
  name: string,
  description?: string,
  cloneUrl: string,
  defaultBranch: string,
  branches: Array<Ref & {
⁣
    description?: string,
    ahead: number,
    behind: number,
    compareTo: string,
⁣
⁣
  }>,
  files: (filename: string, sha: string) => Promise<FileInfo>,
⁣
⁣
⁣
  tags?: Array<Ref>,
⁣
  commits?: Map<string, Commit>,
}
src/languageGraph.ts:1
Before






0
1
2
⁣
⁣
⁣
⁣
⁣
⁣
⁣
export const colorAndPercentMap = () => {
  const languageCounts = new Map<string, number>()
  const countPromises = Array.from(ref.fileList.keys()).map(async (currentFile) => {
    return new Promise<void>(async (resolve) => {
After
0
1
2
3
4
5
6
7
8
9
import { ReposConfigurationWithDefaultsApplied } from './configTypes.ts'
import { Ref, FileInfo } from './dataTypes.ts'

export const colorAndPercentMap = async (
  reposConfig: ReposConfigurationWithDefaultsApplied,
  ref: Ref,
  files: (filename: string, sha: string) => Promise<FileInfo>,
) => {
  const languageCounts = new Map<string, number>()
  const countPromises = Array.from(ref.fileList.keys()).map(async (currentFile) => {
    return new Promise<void>(async (resolve) => {
src/languageGraph.ts:10
Before
9
10
11
12
13
14
        resolve()
      }

      const fileLineCount = (await repo.files(currentFile, data.currentRef.sha)).contents.split('\n').length
      languageCounts.set(fileExtension, (languageCounts.get(fileExtension) + fileLineCount) || fileLineCount)
      resolve()
    })
After
9
10
11
12
13
14
        resolve()
      }

      const fileLineCount = (await files(currentFile, ref.sha)).contents.split('\n').length
      languageCounts.set(fileExtension, (languageCounts.get(fileExtension) + fileLineCount) || fileLineCount)
      resolve()
    })
src/languageGraph.ts:50
Before
49
50
51







52
    }
  })

⁣
⁣
⁣
⁣
⁣
⁣
⁣
  return colorAndPercentMap
}
After
49
50
51
52
53
54
55
56
57
58
59
    }
  })

  if (otherLanguagePercent > 0) {
    colorAndPercentMap['other'] = {
      color: colors[colors.length - 1].light,
      percentOfTotal: otherLanguagePercent / largestPercent
    }
  }

  return colorAndPercentMap
}