Change the before hook to an exported function

2ecee51488bef605eff051f8a03644ef2b74e81d

Tucker McKnight <tucker@pangolin.lan> | Sun Jan 11 2026

Change the before hook to an exported function

Also pass in the site output directory to the getLocation function,
since all calls to git now check in the cloned copy of the repo
in the _site dir (or whatever the output dir is) instead of checking
the user's original, local copy of the repo.

This also means that remote URLs can be used in your eleventy config.

An explanation for the before hook change is in wiki/projects/clone-early.md.
Basically, it seems like a plugin can't actually have a before hook run
before the site generation happens. So instead, I'm exporting the before hook
function so that the user can manually add it as a before hook in the
eleventy config for their main site.
main.ts:26
Before
After
main.ts:35
Before
34
35
36
37
38
39

  eleventyConfig.addTemplateFormats("js")

  const reposData = await repos(reposConfiguration)
  // TODO: make a better way of making this default to "" so that it doesn't have to
  // be done again in src/repos.ts.
  const reposPath = reposConfiguration.path || ""
After
34
35
36
37
38
39

  eleventyConfig.addTemplateFormats("js")

  const reposData = await repos(reposConfiguration, eleventyConfig.dir.output)
  // TODO: make a better way of making this default to "" so that it doesn't have to
  // be done again in src/repos.ts.
  const reposPath = reposConfiguration.path || ""
main.ts:62
Before
After
main.ts:222
Before
221
222
223
224
225
226
      return ""
    }

    const location = getLocation(reposConfiguration, repo)
    return operations.getFileLastTouchInfo(branch, filename, location)
  })
After
221
222
223
224
225
226
      return ""
    }

    const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repo)
    return operations.getFileLastTouchInfo(branch, filename, location)
  })
main.ts:236
Before
235
236
237
238
239
240
  })

  eleventyConfig.addAsyncFilter("getFileContents", async (repo: string, branch: string, filename: string) => {
    const location = getLocation(reposConfiguration, repo)
    const command = `git -C ${location} show ${branch}:${filename}`
    const res = await exec(command)
    return res.stdout
After
235
236
237
238
239
240
  })

  eleventyConfig.addAsyncFilter("getFileContents", async (repo: string, branch: string, filename: string) => {
    const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repo)
    const command = `git -C ${location} show ${branch}:${filename}`
    const res = await exec(command)
    return res.stdout
main.ts:255
Before
254
255
256
257
258
259
  })

  eleventyConfig.addAsyncFilter("getReadMe", async (repoName: string, branchName: string) => {
    const location = getLocation(reposConfiguration, repoName)
    const command = `git -C ${location} show ${branchName}:README.md`
    try {
      const res = await exec(command)
After
254
255
256
257
258
259
  })

  eleventyConfig.addAsyncFilter("getReadMe", async (repoName: string, branchName: string) => {
    const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repoName)
    const command = `git -C ${location} show ${branchName}:README.md`
    try {
      const res = await exec(command)
src/helpers.ts:70
Before
69
70
71
72
73
74
75
76
  return hunks
}

const getLocation = (reposConfig: ReposConfiguration, repoName: string): string => {
  const config = reposConfig.repos[repoName]
  return config.location
}

export {
After
69
70
71
72

73
74
75
  return hunks
}

const getLocation = (reposConfig: ReposConfiguration, outputDir: string, repoName: string): string => {
⁣
  return outputDir + (reposConfig.path || "") + "/" + repoName + ".git"
}

export {
src/repos.ts:26
Before
25
26
27
28
29
30

let cachedRepos: Array<Repository> | null = null

const repos: (reposConfig: ReposConfiguration) => Promise<Array<Repository>> = async (reposConfig) => {
  if (cachedRepos !== null) { return cachedRepos }

  const repoNames = Object.keys(reposConfig.repos)
After
25
26
27
28
29
30

let cachedRepos: Array<Repository> | null = null

const repos: (reposConfig: ReposConfiguration, outputDir: string) => Promise<Array<Repository>> = async (reposConfig, outputDir) => {
  if (cachedRepos !== null) { return cachedRepos }

  const repoNames = Object.keys(reposConfig.repos)
src/repos.ts:36
Before
35
36
37
38
39
40
41
42
43
44
45
    const branchNames = getBranchNames(reposConfig.repos[repoName])
    const commits: Repository['commits'] = new Map()
    for (const branchName of branchNames) {
      const repoLocation = getLocation(reposConfig, repoName)
      await addBranchToCommitsMap(branchName, repoLocation, commits)
    }

    const branches = await Promise.all(branchNames.map(async (branchName) => {
      const repoLocation = getLocation(reposConfig, repoName)
      const branchHeadRes = await exec(`git -C ${repoLocation} show-ref refs/heads/${branchName}`)
      const branchHead = branchHeadRes.stdout.split(" ")[0]
      return {
After
35
36
37
38
39
40
41
42
43
44
45
    const branchNames = getBranchNames(reposConfig.repos[repoName])
    const commits: Repository['commits'] = new Map()
    for (const branchName of branchNames) {
      const repoLocation = getLocation(reposConfig, outputDir, repoName)
      await addBranchToCommitsMap(branchName, repoLocation, commits)
    }

    const branches = await Promise.all(branchNames.map(async (branchName) => {
      const repoLocation = getLocation(reposConfig, outputDir, repoName)
      const branchHeadRes = await exec(`git -C ${repoLocation} show-ref refs/heads/${branchName}`)
      const branchHead = branchHeadRes.stdout.split(" ")[0]
      return {