Change feed.njk to a typescript template

14e3d38c967898d3811831bdf23b9108575439aa

Tucker McKnight | Sat Jan 03 2026

Change feed.njk to a typescript template

This is the last njk template that needed to be changed over.

Several changes have been made to this template. First, the RSS
plugin isn't expected to be provided by the parent 11ty site anymore.
Instead, this plugin will require the RSS plugin itself.

The dateToRfc3339 function is therefore being imported directly,
instead of being looked for as an eleventyConfig filter.

Some of the other functions dealing with absolute URLs are no longer
being used. This is using its own baseUrl value instead. (May want
to revisit this later, but let's just use baseUrl for now.)
js_templates/feed.ts:0
Before
0
After
0
import _ from 'lodash'
import { type Repository } from '../src/dataTypes.ts'
import branches from '../src/branches.ts'
import { dateToRfc3339 } from '@11ty/eleventy-plugin-rss'
import flatPatches from '../src/flatPatches.ts'

export default async (
  eleventyConfig: any,
) => {
  return (data) => {
    const branch: ReturnType<typeof branches>[0] = data.branch
    const currentRepo: Repository = data.currentRepo
    const currentBranch: Repository['branches'][0] = data.currentBranch
    const currentBranchCommits: Awaited<ReturnType<typeof flatPatches>> = data.currentBranchCommits

    const slugify = eleventyConfig.getFilter("slugify")

    return `<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Latest patches in ${branch.branchName}</title>
<link href="${ data.reposConfig.baseUrl + '/repos/' + slugify(branch.repoName) + '/branches/' + slugify(branch.branchName) + '/commits.xml'}" rel="self" />
<link href="${data.reposConfig.baseUrl + '/repos/' + slugify(branch.repoName) + '/branches/' + slugify(branch.branchName)}" />
<updated>${dateToRfc3339(currentRepo.commits.get(currentBranch.head).date)}</updated>
<id>${data.reposConfig.baseUrl}</id>
  <author>
    <name>${_.escape(currentRepo.name)} contributors</name>
  </author>
  ${currentBranchCommits.map((commit) => {
    const commitUrl = data.reposConfig.baseUrl + '/repos/' + slugify(branch.repoName) + '/branches/' + slugify(branch.branchName) + '/commits/' + commit.commit.hash
  return `<entry>
    <title>${_.escape(commit.commit.message.split('\n')[0])}</title>
    <author><name>${_.escape(commit.commit.author)}</name></author>
    <link href="${commitUrl}" />
    <updated>${dateToRfc3339(commit.commit.date)}</updated>
    <id>${commitUrl}</id>
    <content type="text">${_.escape(commit.commit.message)}</content>
  </entry>`
  })}
</feed>`
  }
}
main.ts:21
Before
21
After
21
import feedJsTemplate from './js_templates/feed.ts'
main.ts:498
Before
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  // FEED.NJK
  // htmlBaseUrl is a function defined by the 11ty RSS plugin.
  // Skip this virtual template if the 11ty RSS plugin is not being used.
  let rssAvailable = false
  // if (eleventyConfig?.javascript?.functions?.htmlBaseUrl) {
  //   rssAvailable = true
  //   const feedTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/feed.njk`).toString()
  //   eleventyConfig.addTemplate(
  //     `repos/feed.njk`,
  //     feedTemplate,
  //     {
  //       pagination: {
  //         data: "branches",
  //         size: 1,
  //         alias: "branch",
  //       },
  //       permalink: (data) => {
  //         const repoName = data.branch.repoName
  //         const branchName = data.branch.branchName
  //         return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/patches.xml`
  //       },
  //       eleventyComputed: {
  //         currentRepo: (data) => reposData.find(repo => {
  //           return repo.name === data.branch.repoName
  //         }),
  //         currentBranch: (data) => reposData.find(repo => {
  //           return repo.name === data.branch.repoName
  //         }).branches.find(branch => {
  //           return branch.name === data.branch.branchName
  //         }),
  //       },
  //       eleventyExcludeFromCollections: true,
  //     }
  //   )
  // }

  // This is used to show/hide the RSS feed link on the landing page.
  eleventyConfig.addGlobalData('rssAvailable', rssAvailable)
After
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  // FEED.TS
  eleventyConfig.addTemplate(
    `repos/feed.11ty.js`,
    feedJsTemplate(eleventyConfig),
    {
      pagination: {
        data: "branches",
        size: 1,
        alias: "branch",
      },
      permalink: (data) => {
        const repoName = data.branch.repoName
        const branchName = data.branch.branchName
        return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/commits.xml`
      },
      eleventyComputed: {
        currentRepo: (data) => reposData.find(repo => {
          return repo.name === data.branch.repoName
        }),
        currentBranch: (data) => reposData.find(repo => {
          return repo.name === data.branch.repoName
        }).branches.find(branch => {
          return branch.name === data.branch.branchName
        }),
        currentBranchCommits: (data) => {
          return flatPatchesData.filter((patch) => {
            return patch.branchName === data.branch.branchName
          })
        }
      },
      eleventyExcludeFromCollections: true,
    }
  )
make.sh:6
Before
6
7
cp templates/*.njk dist/templates
cp partial_templates/*.njk dist/partial_templates
After
6
7
package-lock.json:9
Before
9
After
9
        "@11ty/eleventy-plugin-rss": "^2.0.4",
package-lock.json:24
Before
24
After
24
    "node_modules/@11ty/eleventy-plugin-rss": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-rss/-/eleventy-plugin-rss-2.0.4.tgz",
      "integrity": "sha512-LF60sGVlxGTryQe3hTifuzrwF8R7XbrNsM2xfcDcNMSliLN4kmB+7zvoLRySRx0AQDjqhPTAeeeT0ra6/9zHUQ==",
      "dependencies": {
        "@11ty/eleventy-utils": "^2.0.0",
        "@11ty/posthtml-urls": "^1.0.1",
        "debug": "^4.4.0",
        "posthtml": "^0.16.6"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/11ty"
      }
    },
    "node_modules/@11ty/eleventy-utils": {
      "version": "2.0.7",
      "resolved": "https://registry.npmjs.org/@11ty/eleventy-utils/-/eleventy-utils-2.0.7.tgz",
      "integrity": "sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/11ty"
      }
    },
    "node_modules/@11ty/posthtml-urls": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/@11ty/posthtml-urls/-/posthtml-urls-1.0.2.tgz",
      "integrity": "sha512-0vaV3Wt0surZ+oS1VdKKe0axeeupuM+l7W/Z866WFQwF+dGg2Tc/nmhk/5l74/Y55P8KyImnLN9CdygNw2huHg==",
      "dependencies": {
        "evaluate-value": "^2.0.0",
        "http-equiv-refresh": "^2.0.1",
        "list-to-array": "^1.1.0",
        "parse-srcset": "^1.0.2"
      },
      "engines": {
        "node": ">= 6"
      }
    },
package-lock.json:1054
Before
1054
After
1054
    "node_modules/debug": {
      "version": "4.4.3",
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
      "dependencies": {
        "ms": "^2.1.3"
      },
      "engines": {
        "node": ">=6.0"
      },
      "peerDependenciesMeta": {
        "supports-color": {
          "optional": true
        }
      }
    },
package-lock.json:1076
Before
1076
After
1076
    "node_modules/dom-serializer": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
      "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
      "dependencies": {
        "domelementtype": "^2.0.1",
        "domhandler": "^4.2.0",
        "entities": "^2.0.0"
      },
      "funding": {
        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
      }
    },
    "node_modules/dom-serializer/node_modules/entities": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
      "funding": {
        "url": "https://github.com/fb55/entities?sponsor=1"
      }
    },
    "node_modules/domelementtype": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/fb55"
        }
      ]
    },
    "node_modules/domhandler": {
      "version": "4.3.1",
      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
      "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
      "dependencies": {
        "domelementtype": "^2.2.0"
      },
      "engines": {
        "node": ">= 4"
      },
      "funding": {
        "url": "https://github.com/fb55/domhandler?sponsor=1"
      }
    },
    "node_modules/domutils": {
      "version": "2.8.0",
      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
      "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
      "dependencies": {
        "dom-serializer": "^1.0.1",
        "domelementtype": "^2.2.0",
        "domhandler": "^4.2.0"
      },
      "funding": {
        "url": "https://github.com/fb55/domutils?sponsor=1"
      }
    },
package-lock.json:1192
Before
1192
After
1192
    "node_modules/evaluate-value": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/evaluate-value/-/evaluate-value-2.0.0.tgz",
      "integrity": "sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==",
      "engines": {
        "node": ">= 8"
      }
    },
package-lock.json:1355
Before
1355
After
1355
    "node_modules/htmlparser2": {
      "version": "7.2.0",
      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
      "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
      "funding": [
        "https://github.com/fb55/htmlparser2?sponsor=1",
        {
          "type": "github",
          "url": "https://github.com/sponsors/fb55"
        }
      ],
      "dependencies": {
        "domelementtype": "^2.0.1",
        "domhandler": "^4.2.2",
        "domutils": "^2.8.0",
        "entities": "^3.0.1"
      }
    },
    "node_modules/htmlparser2/node_modules/entities": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
      "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
      "engines": {
        "node": ">=0.12"
      },
      "funding": {
        "url": "https://github.com/fb55/entities?sponsor=1"
      }
    },
    "node_modules/http-equiv-refresh": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz",
      "integrity": "sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==",
      "engines": {
        "node": ">= 6"
      }
    },
package-lock.json:1440
Before
1440
After
1440
    "node_modules/is-json": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz",
      "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA=="
    },
package-lock.json:1554
Before
1554
After
1554
    "node_modules/list-to-array": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz",
      "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g=="
    },
package-lock.json:1692
Before
1692
After
1692
    "node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
    },
package-lock.json:1767
Before
1767
After
1767
    "node_modules/parse-srcset": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
      "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q=="
    },
package-lock.json:1843
Before
1843
After
1843
    "node_modules/posthtml": {
      "version": "0.16.7",
      "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.7.tgz",
      "integrity": "sha512-7Hc+IvlQ7hlaIfQFZnxlRl0jnpWq2qwibORBhQYIb0QbNtuicc5ZxvKkVT71HJ4Py1wSZ/3VR1r8LfkCtoCzhw==",
      "dependencies": {
        "posthtml-parser": "^0.11.0",
        "posthtml-render": "^3.0.0"
      },
      "engines": {
        "node": ">=12.0.0"
      }
    },
    "node_modules/posthtml-parser": {
      "version": "0.11.0",
      "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz",
      "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==",
      "dependencies": {
        "htmlparser2": "^7.1.1"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/posthtml-render": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz",
      "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==",
      "dependencies": {
        "is-json": "^2.0.1"
      },
      "engines": {
        "node": ">=12"
      }
    },
package.json:27
Before
27
After
27
    "@11ty/eleventy-plugin-rss": "^2.0.4",
partial_templates/main_bottom.njk:1
Before
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
        </div>
      </div>
    </div>
    <script>
      const toggleUnifiedMode = (e) => {
        const diffs = document.getElementById('diffs')
        const afterDiffs = document.querySelectorAll('.diff-right')
        if (e.checked) {
          diffs.classList.add("unified")
          afterDiffs.forEach((elem) => {
            elem.classList.remove('border-start', 'ps-2')
          })
        }
        else {
          diffs.classList.remove("unified")
          afterDiffs.forEach((elem) => {
            elem.classList.add('border-start', 'ps-2')
          })
        }
      }

      const selectBranch = (e) => {
        const values = e.value.split(",")
        window.location = `{{reposPath}}/${values[0]}/branches/${values[1]}/${values[2]}`
      }
    </script>
    <script src="{{reposPath}}/frontend/main-frontend.bundle.js"></script>
  </body>
</html>
After
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
partial_templates/main_top.njk:1
Before
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!DOCTYPE html>
<html>
  <head>
    <title>{% if nav.title %}{{nav.title}}{% else %}Repositories{% endif %}</title>
    <script>
      window.jsVars = {};
    
      {% if nav %}
        window.jsVars['baseUrl'] = `{{ repoConfig.repos[nav.repoName].baseUrl | jsonStringify | safe }}`;
    
        window.jsVars['nav'] = {{nav | jsonStringify | safe}};
    
        window.jsVars['cloneDiv'] = `<label class="form-label">HTTPS URL</label>
<div class="input-group d-flex flex-nowrap">
  <span class="clone overflow-hidden input-group-text">
    {% set url = currentRepo.cloneUrl %}
    {{ url }}
  </span>
  <button data-clone-url="{{url}}" class="btn btn-primary" id="clone-button">Copy</button>
</div>`;
    
      {% endif %}
    </script>
    <script src="{{reposPath}}/frontend/top.js"></script>
    <link rel="stylesheet" id="prism-theme" type="text/css" href="{{reposPath}}/vendor/prism.css" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-SgOJa3DmI69IUzQ2PVdRZhwQ+dy64/BUtbMJw1MZ8t5HZApcHrRKUc4W0kG879m7" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js" integrity="sha384-j1CDi7MgGQ12Z7Qab0qlWQ/Qqz24Gc6BM0thvEMVjHnfYGF0rmFCozFSxQBxwHKO" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="{{reposPath}}/vendor/main.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>

  <body>
    <div class="container-lg">
      <div class="row pt-5">
        <div class="col">
          <header>
            <div class="row d-flex justify-content-between pb-3">
              <div class="col-auto">
                <nav class="fs-4">
                  <a href="{% if reposPath == "" %}/{% else %}{{reposPath}}{% endif %}">Repositories</a>{% if nav.repoName %}<span class="text-secondary mx-2">&gt;</span><a href="{{reposPath}}/{{nav.repoName | slugify}}/branches/{{reposConfig.repos[nav.repoName].defaultBranch | slugify}}">{{nav.repoName}}</a>{% endif %}
                </nav>
              </div>
              <div class="col-auto d-flex align-items-center">
                <div class="dropdown">
                  <button class="dropdown-toggle btn" id="dark-mode-switch" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                    <i class="bi bi-brightness-high"></i>
                  </button>
                  <ul class="dropdown-menu">
                    <li><button class="btn" data-theme-pref="light" onclick="toggleDarkMode(this)"><i class="bi bi-brightness-high mx-1"></i>Light</button></li>
                    <li><button class="btn" data-theme-pref="dark" onclick="toggleDarkMode(this)"><i class="bi bi-moon mx-1"></i>Dark</button></li>
                    <li><button class="btn" data-theme-pref="auto" onclick="toggleDarkMode(this)"><i class="bi bi-yin-yang mx-1"></i>Auto</button></li>
                  </ul>
                </div>
              </div>
            </div>
            {% if nav.repoName %}
            <div class="row mb-4">
              <div class="col-12 col-md order-2 order-md-1 pe-0">
                <nav class="nav-tabs">
                  <ul class="nav">
                    <li class="nav-item">
                      <a class="nav-link {% if navTab == "landing" %}active{% endif %}" href="{{reposPath}}/{{nav.repoName | slugify}}/branches/{{nav.branchName | slugify}}">Landing Page</a>
                    </li>
                    <li class="nav-item">
                      <a class="nav-link {% if navTab == "files" %}active{% endif %}" href="{{reposPath}}/{{nav.repoName | slugify}}/branches/{{nav.branchName | slugify}}/files">Files</a>
                    </li>
                    <li class="nav-item">
                      <a class="nav-link {% if navTab == "patches" %}active{% endif %}" href="{{reposPath}}/{{nav.repoName | slugify}}/branches/{{nav.branchName | slugify}}/patches/page1">Changes</a>
                    </li>
                    <li class="nav-item">
                      <a class="nav-link {% if navTab == "branches" %}active{% endif %}" href="{{reposPath}}/{{nav.repoName | slugify}}/branches/{{nav.branchName | slugify}}/list">Branches</a>
                    </li>
                  </ul>
                </nav>
              </div>
              <div class="col-12 col-md-auto order-1 order-md-2 pb-2 pb-md-0 mb-2 mb-md-0 border-bottom">
                <div class="row">
                  <div class="col-auto px-2">
                    <button type="button" id="clone-popover-btn" class="btn btn-sm btn-primary" data-bs-toggle="popover" data-bs-placement="bottom">Clone <i class="bi bi-caret-down-fill"></i></button>
                  </div>
                  <div class="col-auto px-2">
                    <div class="input-group input-group-sm">
                      <span class="input-group-text">Branch</span>
                      <select class="form-select" onchange="selectBranch(this)" aria-label="Repository branch selector">
                        {% for branch in currentRepo.branches %}
                        <option value="{{currentRepo.name | slugify}},{{branch.name | slugify}},{{nav.path}}" {% if branch.name == nav.branchName %}selected{% endif %}>{{branch.name}}</option>
                        {% endfor %}
                      </select>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            {% endif %}
          </header>
        </div>
      </div>
    </div>
    <div class="container-{% if width == "full"%}fluid{% else %}lg{% endif %}">
      <div class="row">
        <div class="col">
After
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
templates/feed.njk:1
Before
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="{{ page.lang }}">
  <title>Latest patches in {{branch.branchName}}</title>
  <link href="{{ ('/repos/' + (branch.repoName | slugify) + '/branches/' + (branch.branchName | slugify) + '/patches.xml')| htmlBaseUrl(reposConfig.baseUrl) }}" rel="self" />
  <link href="{{ ('/repos/' + (branch.repoName | slugify) + '/branches/' + (branch.branchName | slugify)) | htmlBaseUrl(reposConfig.baseUrl) }}" />
  {% set lastPatch = repos[branch.repoName].branches[branch.branchName].patches | last %}
  <updated>{{ lastPatch.date | toDateObj | dateToRfc3339 }}</updated>
  <id>{{ reposConfig.baseUrl | addPathPrefixToFullUrl }}</id>
  <author>
    <name>{{branch.repoName}} contributors</name>
  </author>
  {%- for patch in repos[branch.repoName].branches[branch.branchName].patches | reverse %}
  {%- set absolutePostUrl %}{{ ('/repos/' + (branch.repoName | slugify) + '/branches/' + (branch.branchName | slugify) + '/patches/' + patch.hash) | htmlBaseUrl(reposConfig.baseUrl) }}{% endset %}
  <entry>
    <title>{{ patch.name }}</title>
    <author><name>{{ patch.author }}</name></author>
    <link href="{{ absolutePostUrl }}" />
    <updated>{{ patch.date | toDateObj | dateToRfc3339 }}</updated>
    <id>{{ absolutePostUrl }}</id>
    <content type="html">{{ patch.description | renderTransforms({}, reposConfig.baseUrl) }}</content>
  </entry>
  {%- endfor %}
</feed>
After
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23