Change index.ts to a mithril template

4a9f3a0954d6e0879474f0429b1bce727309174d

Tucker McKnight | Mon Jan 12 2026

Change index.ts to a mithril template

Adds needed mithril packages and changes the big string in index.ts
to use mithril. Nothing needs to be changed in main.ts.
js_templates/index.ts: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
export default async (eleventyConfig: any) => {
  return (data: any) => {
    return `
      <!doctype html>
      &lt;html lang="en">
        &lt;head&gt;
          &lt;meta charset="utf-8">
          &lt;meta name="viewport" content="width=device-width, initial-scale=1">
          &lt;title&gt;Repositories&lt;/title&gt;
          &lt;link rel="stylesheet" href="/css/design-board.css">
          &lt;script src=&quot;${data.reposPath}/frontend/top.js"></script>
        </head>
        &lt;body&gt;
          &lt;div class="container">
            &lt;div class="row d-flex justify-content-end">
              &lt;div class="col-auto pt-2">
                &lt;div class="dropdown">
                  &lt;button class="dropdown-toggle btn btn-bg" id="dark-mode-switch" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                    &lt;span&gt;&#xFE0F;&lt;/span>
                  &lt;/button&gt;
                  <ul class="dropdown-menu">
                    &lt;li&gt;&lt;button class="btn shadow-none" data-theme-pref="light" onclick="toggleDarkMode(this)"&gt;&lt;span class="me-1"&gt;&#x1F31E;&lt;/span&gt;Light&lt;/button></li>
                    &lt;li&gt;&lt;button class="btn shadow-none" data-theme-pref="dark" onclick="toggleDarkMode(this)"&gt;&lt;span class="me-1"&gt;&#x1F319;&lt;/span&gt;Dark&lt;/button></li>
                    &lt;li&gt;&lt;button class="btn shadow-none" data-theme-pref="auto" onclick="toggleDarkMode(this)"&gt;&lt;span class="me-1"&gt;&#x1F5A5;&#xFE0F;&lt;/span&gt;Match OS&lt;/button></li>
                  </ul>
                </div>
              </div>
            </div>
            &lt;div class="row my-3">
              &lt;div class="col">
                &lt;h1&gt;${data.reposConfig.defaultTemplateConfiguration?.allRepositoriesPageTitle || "All Repositories"}</h1>
              </div>
            </div>
            &lt;div class="row">
              &lt;div class="col d-flex flex-wrap">
                ${data.repos.map((repo) => {
                  return `
                    &lt;div class="m-2 card bezel-gray flex-grow-1" style="flex-basis: 20rem;">
                      &lt;div class="card-header">
                        &lt;a class="card-title fs-5" href="${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}">${repo.name}</a>
                      </div>
                      &lt;div class="card-body">
                        ${repo.description ? `&lt;p class="card-text">${repo.description}</p>` : ''}
                      </div>
                      <div class="card-footer">
                        &lt;a href=&quot;${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}" class="mx-1 my-2 btn btn-primary text-white"&gt;Go to site&lt;/a>
                        &lt;button class="mx-1 my-2 btn btn-outline-secondary shadow-none dropdown-toggle clone-popover-btn" data-copy-text=&quot;${repo.cloneUrl}&quot;>Clone&lt;/button>
                        ${(data.reposConfig.repos[repo.name].defaultTemplateConfiguration?.homepageButtons || []).map((button) => {
                          return `&lt;a class="mx-1 my-2 btn btn-outline-secondary shadow-none" href="${button.url}" ${button.newTab ? 'target="_blank&quot;&#39; : ''}>${button.text}${button.newTab ? ' &lt;span>&#x29C9;</span>&#39; : ''}</a>`
                        }).join('')}
                      </div>
                    </div>
                  `
                }).join('')}
              </div>
            </div>
          </div>
        </div>
        &lt;script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
        &lt;script src=&quot;${data.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
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
import m from 'mithril'
import render from 'mithril-node-render'

export default (eleventyConfig: any) => {
  return async (data: any) => {
    return render([
      m.trust(&#39;&lt;!doctype html>'),
      m(&#39;html', {lang: "en"}, [
        m(&#39;head&#39;, [
          m(&#39;meta', {charset:"utf-8"}),
          m(&#39;meta', {name: "viewport", content: "width=device-width, initial-scale=1"}),
          m(&#39;title&#39;, &#39;Repositories&#39;),
          m(&#39;link', {rel: "stylesheet", href: "/css/design-board.css"}),
          m(&#39;script&#39;, {src: `${data.reposPath}/frontend/top.js`}),
        ]),
        m(&#39;body&#39;, [
          m(&#39;div', {class: "container"}, [
            m(&#39;div', {class: "row d-flex justify-content-end"}, [
              m(&#39;div', {class: "col-auto pt-2"}, [
                m(&#39;div', {class: "dropdown"}, [
                  m(&#39;button', {
                    class: "dropdown-toggle btn btn-bg",
                    id: "dark-mode-switch",
                    type: "button",
                    'data-bs-toggle&#39;: &quot;dropdown",
                    'aria-expanded&#39;: &quot;false"
                  }, m(&#39;span&#39;, m.trust(&#39;&amp;#xFE0F;&#39;))),
                  m(&#39;ul&#39;, {class: "dropdown-menu"}, [
                    m(&#39;li&#39;,
                      m(&#39;button', {class: "btn shadow-none", 'data-theme-pref&#39;: &quot;light", onclick: "toggleDarkMode(this)"},
                        m(&#39;span&#39;, {class: "me-1"}, m.trust(&#39;&#x1F31E;&#39;)),
                        &#39;Light&#39;
                      )
                    ),
                    m(&#39;li&#39;,
                      m(&#39;button', {class: "btn shadow-none", 'data-theme-pref&#39;: &quot;dark", onclick: "toggleDarkMode(this)"},
                        m(&#39;span&#39;, {class: "me-1"}, m.trust(&#39;&#x1F319;&#39;)),
                        &#39;Dark&#39;
                      )
                    ),
                    m(&#39;li&#39;,
                      m(&#39;button', {class: "btn shadow-none", 'data-theme-pref&#39;: &quot;auto", onclick: "toggleDarkMode(this)"},
                        m(&#39;span&#39;, {class: "me-1"}, m.trust(&#39;&#x1F5A5;&#xFE0F;&#39;)),
                        &#39;Match OS&#39;
                      )
                    )
                  ])
                ])
              ])
            ]),
            m(&#39;div', {class: "row my-3"},
              m(&#39;div', {class: "col"},
                m(&#39;h1&#39;, data.reposConfig.defaultTemplateConfiguration?.allRepositoriesPageTitle || "All Repositories")
              )
            ),
            m(&#39;div', {class: "row"},
              m(&#39;div', {class: "col d-flex flex-wrap"},
                data.repos.map((repo) => {
                  return (
                    m(&#39;div', {class: "m-2 card bezel-gray flex-grow-1", style: "flex-basis: 20rem;"},
                      m(&#39;div', {class: "card-header"},
                        m(&#39;a', {class: "card-title fs-5", href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`}, repo.name)
                      ),
                      m(&#39;div', {class: "card-body"},
                        repo.description ? m(&#39;p', {class: "card-text"}, repo.description) : null
                      ),
                      m('div', {class: "card-footer"}, [
                        m(&#39;a&#39;, {
                          href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`,
                          class: "mx-1 my-2 btn btn-primary text-white"
                        }, &#39;Go to site&#39;),
                        m(&#39;button', {
                          class: "mx-1 my-2 btn btn-outline-secondary shadow-none dropdown-toggle clone-popover-btn",
                          'data-copy-text&#39;: repo.cloneUrl
                        }, &#39;Clone&#39;),
                        (data.reposConfig.repos[repo.name].defaultTemplateConfiguration?.homepageButtons || []).map((button) => {
                          return m(&#39;a', {
                            class: "mx-1 my-2 btn btn-outline-secondary shadow-none",
                            href: button.url,
                            target: button.newTab ? '_blank' : '_self'
                          }, [button.text, button.newTab ? [' ', m('span', m.trust('&amp;#x29C9;&#39;))] : null])
                        })
                      ])
                    )
                  )
                })
              )
            )
          ])
        ]),
        m(&#39;script', {
          src: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js",
          integrity: "sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI",
          crossorigin: "anonymous"
        }),
        m(&#39;script&#39;, {src: `${data.reposPath}/frontend/main-frontend.bundle.js`}),
      ])
    ])
package-lock.json:12
Before
12
        "lodash": "^4.17.21"
After
12
        "lodash": "^4.17.21",
        "mithril": "^2.3.8",
        "mithril-node-render": "^3.0.2"
package-lock.json:1864
Before
1864
After
1864
    "node_modules/mithril": {
      "version": "2.3.8",
      "resolved": "https://registry.npmjs.org/mithril/-/mithril-2.3.8.tgz",
      "integrity": "sha512-za/Yo7qXEckjm5syrSfaaI9Utf4tCUT3T1IOIYqH6Lrj7G0OZuYYLAY9SV4ygoaAf0+CNqU92MBt+7pmo53JVQ=="
    },
    "node_modules/mithril-node-render": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/mithril-node-render/-/mithril-node-render-3.0.2.tgz",
      "integrity": "sha512-8GZfFWW7h1YjO8s9fe+vHpWG3zacGIytQ/FBKxlynHlwknp1KLRHM6MtrtbMy72dVdQOiYw7wyfZXD0IrvpQOQ==",
      "peerDependencies": {
        "mithril": "^2.0.4"
      }
    },
package.json:30
Before
30
    "lodash": "^4.17.21"
After
30
    "lodash": "^4.17.21",
    "mithril": "^2.3.8",
    "mithril-node-render": "^3.0.2"