[WIP] move language colors to its own file for re-use elsewhere

e763b34a87ffc4960753980dfbecc285582215a9

Tucker McKnight <tmcknight@instructure.com> | Fri Aug 07 2026

[WIP] move language colors to its own file for re-use elsewhere
js_templates/repo.ts:2
Before
1
2
3
4

5
import { type Repository } from '../src/dataTypes.ts'
import { NavHelper } from './helpers/nav.ts'
import htmlPage from './common/htmlPage.ts'

⁣
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
  const repo: Repository = data.currentRepo
After
1
2
3
4
5
6
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
js_templates/repo.ts:24
Before
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
    currentRefType: data.flatRef.type,
  })

  const languageCounts = new Map<string, number>()

  const countPromises = Array.from(ref.fileList.keys()).map(async (currentFile) => {
    return new Promise<void>(async (resolve) => {
      const fileParts = currentFile.split(".")
      const fileExtension = fileParts[fileParts.length - 1]
// todo: add more ignoreable extensions or specific files
// (like package-lock.json). Allow glob patterns?
      if (fileExtension === 'gitignore') {
        resolve()
      }

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

  await Promise.all(countPromises)

  let languagePercentages: Array<[string, number]> = []
  const total = Array.from(ref.fileList.keys()).length

  for (const entry of languageCounts) {
    languagePercentages.push([entry[0], entry[1] / total])
  }
  languagePercentages.sort((a, b) => {
    return b[1] - a[1]
  })

  // Show graph for the top 5 languages, unless there are fewer than 5 total
  const numOfTopLanguages = Math.min(5, languagePercentages.length)
  const topLanguagePercentages = languagePercentages.slice(0, numOfTopLanguages)
  const otherLanguagePercent = languagePercentages.slice(numOfTopLanguages).reduce((sum, current) => {
    return sum + current[1]
  }, 0)

  const largestPercent = Math.max(...topLanguagePercentages.map(tuple => tuple[1]), otherLanguagePercent)

  const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, ref.name), ref.name)
  // TODO: make dark mode work here
  const colors = reposConfig.defaultTemplate.colors.languageGraph

  const pageContent = [
    m('div', {class: "row"}, [
After
23
24
25







































26
27


28
    currentRefType: data.flatRef.type,
  })

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

⁣
⁣
  const pageContent = [
    m('div', {class: "row"}, [
src/languageGraph.ts:0
Before



















































⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
After
-1
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
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) => {
      const fileParts = currentFile.split(".")
      const fileExtension = fileParts[fileParts.length - 1]
// todo: add more ignoreable extensions or specific files
// (like package-lock.json). Allow glob patterns?
      if (fileExtension === 'gitignore') {
        resolve()
      }

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

  await Promise.all(countPromises)

  let languagePercentages: Array<[string, number]> = []
  const total = Array.from(ref.fileList.keys()).length

  for (const entry of languageCounts) {
    languagePercentages.push([entry[0], entry[1] / total])
  }
  languagePercentages.sort((a, b) => {
    return b[1] - a[1]
  })

  // Show graph for the top 5 languages, unless there are fewer than 5 total
  const numOfTopLanguages = Math.min(5, languagePercentages.length)
  const topLanguagePercentages = languagePercentages.slice(0, numOfTopLanguages)
  const otherLanguagePercent = languagePercentages.slice(numOfTopLanguages).reduce((sum, current) => {
    return sum + current[1]
  }, 0)

  const largestPercent = Math.max(...topLanguagePercentages.map(tuple => tuple[1]), otherLanguagePercent)

  // TODO: make dark mode work here
  const colors = reposConfig.defaultTemplate.colors.languageGraph

  const colorAndPercentMap = {}

  topLanguagePercentages.forEach((percentTuple, index) => {
    const color = colors[index % (colors.length - 1)].light
    colorAndPercentMap[percentTuple[0]] = {
      color,
      percentOfTotal: percentTuple[1] / largestPercent
    }
  })

  return colorAndPercentMap
}