WIP: placeholder for file content and blame lines

f7c4e59b2fe93b2a3973ca162b718eff33557247

Tucker McKnight <tmcknight@instructure.com> | Tue May 26 2026

WIP: placeholder for file content and blame lines
js_templates/file.ts:16
Before
15
16
17

18
19
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")

  const currentRef: Branch = data.currentRef
⁣
  const fileInfo: FlatFileEntry = data.fileInfo

  const pageContent = [  
After
15
16
17
18
19
20
  const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")

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

  const pageContent = [  
js_templates/file.ts:96
Before
95
96
97
98
99
100
            m('div', {class: "row rendered-content"},
              m('div', {class: "col"},
                m.trust(await renderContentIfAvailable(
                  currentRef.fileList.get(fileInfo.file).fileInfo.contents
                ))
              )
            )
After
95
96
97
98
99
100
            m('div', {class: "row rendered-content"},
              m('div', {class: "col"},
                m.trust(await renderContentIfAvailable(
                  (await currentRepo.files(fileInfo.file, currentRef.sha)).contents
                ))
              )
            )
js_templates/file.ts:116
Before
115
116
117
118
119
120
              m('div', {class: "col-auto p-0"},
                m('code', {style: "white-space: pre;"},
                  m('pre', {class: "language-text"},
                    lineNumbers(currentRef.fileList.get(fileInfo.file).fileInfo.contents).map((lineNumber) => {
                      return lineNumber
                    }).join('\n')
                  )
After
115
116
117
118
119
120
              m('div', {class: "col-auto p-0"},
                m('code', {style: "white-space: pre;"},
                  m('pre', {class: "language-text"},
                    lineNumbers((await currentRepo.files(fileInfo.file, currentRef.sha)).contents).map((lineNumber) => {
                      return lineNumber
                    }).join('\n')
                  )
js_templates/file.ts:125
Before
124
125
126
127
128
129
130
131
132
133
134
135
136
              m('div', {id: "annotations", class: "col-auto d-none p-0"},
                m('code', {style: "white-space: pre;"}, [
                  m('pre', {class: "language-text"}, m.trust(
                    currentRef.fileList.get(fileInfo.file).fileInfo.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')))
                ])
              ),
              m('div', {class: "col overflow-scroll p-0"},
                m('code', m.trust(highlightCode(
                  currentRef.fileList.get(fileInfo.file).fileInfo.contents,
                  languageExtension(
                    fileInfo.file,
                    fileInfo.repoName
After
124
125
126
127
128
129
130
131
132
133
134
135
136
              m('div', {id: "annotations", class: "col-auto d-none p-0"},
                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')))
                ])
              ),
              m('div', {class: "col overflow-scroll p-0"},
                m('code', m.trust(highlightCode(
                  (await currentRepo.files(fileInfo.file, currentRef.sha)).contents,
                  languageExtension(
                    fileInfo.file,
                    fileInfo.repoName
js_templates/raw.ts:1
Before
0
1
2

3
4
5
6
7
8
import { type Repository } from "../src/dataTypes.ts"
type Branch = Repository['branches'][0]

⁣
export default async (eleventyConfig: any) => {
  return async (data) => {
    const branch: Branch = data.currentRef

    return branch.fileList.get(data.fileInfo.file).fileInfo.contents
  }
}
After
0
1
2
3
4
5
6
7
8
9
import { type Repository } from "../src/dataTypes.ts"
type Branch = Repository['branches'][0]
type Tag = Repository['tags'][0]

export default async (eleventyConfig: any) => {
  return async (data) => {
    const branch: Branch | Tag = data.currentRef

    return (await data.currentRepo.files(data.fileInfo.file, branch.sha)).contents
  }
}
main.ts:436
Before
435
436
437



438
439
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/raw/${data.fileInfo.file.split('.').map(filePart => eleventyConfig.getFilter("slugify")(filePart)).join('.')}`
      },
      eleventyComputed: {
⁣
⁣
⁣
        currentRef: (data) => {
          const refKey = data.fileInfo.type === 'branch' ? 'branches' : 'tags'
After
435
436
437
438
439
440
441
442
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${refType}/${eleventyConfig.getFilter("slugify")(refName)}/raw/${data.fileInfo.file.split('.').map(filePart => eleventyConfig.getFilter("slugify")(filePart)).join('.')}`
      },
      eleventyComputed: {
        currentRepo: (data) => reposData.find(repo => {
          return repo.name === data.fileInfo.repoName
        }),
        currentRef: (data) => {
          const refKey = data.fileInfo.type === 'branch' ? 'branches' : 'tags'
src/dataTypes.ts:8
Before
7
8
9
10
11
12
13
14

export type Commit = {
  hash: string,
  // TODO: put cached files map in here. Save file as an object
  // so that it gets saved by reference.
  cachedFiles: Map<string, FileInfo>,
  message: string,
  isMerge: boolean,
  author: string,
After
7
8
9



10
11

export type Commit = {
  hash: string,
⁣
⁣
⁣
  message: string,
  isMerge: boolean,
  author: string,
src/dataTypes.ts:36
Before
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    behind: number,
    compareTo: string,
    sha: string,
    // instead of strings, make it point to a function that returns
    // the file contents. The first time, search in both directions for a commit
    // that has already cached this file before a diff in that commit mentions
    // this filename. If one is found, return the *object* in the cached file
    // map (so that it returns a reference). Also set that in a const inside
    // the function so that we don't have to compute it again.
    // If one is not found, then `cat` the file and save it in the commit
    // cache.
    // The FileInfo needs to know which commit it is looking at, then, in order
    // to query for the file contents or to search around the existing file list
    // to see if a copy is already available.
    fileList: Map<string, {fileInfo: FileInfo}>,
  }>,
  tags?: Array<{
    name: string,
    sha: string,
    fileList: Map<string, {fileInfo: FileInfo}>,
  }>,
  commits?: Map<string, Commit>,
}
After
35
36
37
38
39









40

41
42
43
44
45
46
    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>,
}
src/repos.ts:225
Before
224
225
226









227
228
      cloneUrl: cloneUrl.cloneUrl(reposConfig.baseUrl, repoName),
      defaultBranch: reposConfig.repos[repoName].defaultBranch,
      tags: tags,
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
      commits,
    })
  }
After
224
225
226
227
228
229
230
231
232
233
234
235
236
237
      cloneUrl: cloneUrl.cloneUrl(reposConfig.baseUrl, repoName),
      defaultBranch: reposConfig.repos[repoName].defaultBranch,
      tags: tags,
      files: async (filename: string, sha: string) => {
        return Promise.resolve({
          contents: "Pretend like this is the text of the file.",
          lastModified: new Date(),
          blameLines: [
            { sha: 'abc123', author: 'You Did This' }
          ]
        })
      },
      commits,
    })
  }
src/vcses/git/operations.ts:142
Before
141
142
143
144
145
146
                                             // js Date() exects milliseconds
      diffs,
      parent,
      cachedFiles: new Map(),
    })
  } while (gitLogSubset.length > 1)
}
After
141
142
143

144
145
                                             // js Date() exects milliseconds
      diffs,
      parent,
⁣
    })
  } while (gitLogSubset.length > 1)
}