Tucker McKnight <tmcknight@instructure.com> | Wed Feb 11 2026
Add a temporary commonPage.ts to eventually replace htmlPage.ts This new commonPage.ts should include everything that overlaps between what was previously in js_templates/index.ts and js_templates/common/htmlPage.ts. The goal is to have *one* htmlPage.ts that is used on all pages. For now, js_templates/index.ts uses this new commonPage.ts. commonPage.ts should be updated to allow other content from htmlPage.ts to be inserted into parts of the page.
0
0
import m from 'mithril'
import render from 'mithril-node-render'
export default async (rootPath: string, pageContent: Function) => {
return render([
m.trust('<!doctype html>'),
m('html', {lang: "en"}, [
m('head', [
m('meta', {charset: "utf-8"}),
m('meta', {name: "viewport", content: "width=device-width, initial-scale=1"}),
// CUSTOMIZEABLE TITLE
m('title', 'Repositories'),
m('link', {rel: "stylesheet", href: "/css/design-board.css"}),
// ADDITIONAL SCRIPT CONTENT HERE
m('script', {src: `${rootPath}frontend/top.js`}),
// ADDITIONAL LINK CONTENT FOR PRISM THEME HERE
]),
m('body', [
m('div', {class: "container-fluid container-lg"}, [
m('div', {class: "row"}, [
m('div', {class: "col"}, [
// INSERT NAVBAR CONTENT HERE
]),
m('div', {class: "col-auto pt-2"}, [
m('div', {class: "dropdown"}, [
m('button', {class: "dropdown-toggle btn btn-bg", id: "dark-mode-switch", type: "button", 'data-bs-toggle': "dropdown", 'aria-expanded': 'false'},
m('span', m.trust('️'))
),
m('ul', {class: "dropdown-menu"}, [
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "light", onclick: "toggleDarkMode(this)"}, [
m('span', {class: "me-1"}, m.trust('🌞')),
'Light'
])
),
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "dark", onclick: "toggleDarkMode(this)"}, [
m('span', {class: "me-1"}, m.trust('🌙')),
'Dark'
])
),
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "auto", onclick: "toggleDarkMode(this)"}, [
m('span', {class: "me-1"}, m.trust('🖥️')),
'Match OS'
])
)
])
])
])
]),
await pageContent,
]),
m('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('script', {src: `${rootPath}frontend/main-frontend.bundle.js`})
])
])
])
}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
return render([
m.trust('<!doctype html>'),
m('html', {lang: "en"}, [
m('head', [
m('meta', {charset:"utf-8"}),
m('meta', {name: "viewport", content: "width=device-width, initial-scale=1"}),
m('title', 'Repositories'),
m('link', {rel: "stylesheet", href: "/css/design-board.css"}),
m('script', {src: `${data.reposPath}/frontend/top.js`}),
]),
m('body', [
m('div', {class: "container"}, [
m('div', {class: "row d-flex justify-content-end"}, [
m('div', {class: "col-auto pt-2"}, [
m('div', {class: "dropdown"}, [
class: "dropdown-toggle btn btn-bg",
id: "dark-mode-switch",
type: "button",
'data-bs-toggle': "dropdown",
'aria-expanded': "false"
}, m('span', m.trust('️'))),
m('ul', {class: "dropdown-menu"}, [
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "light", onclick: "toggleDarkMode(this)"},
m('span', {class: "me-1"}, m.trust('🌞')),
'Light'
)
),
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "dark", onclick: "toggleDarkMode(this)"},
m('span', {class: "me-1"}, m.trust('🌙')),
'Dark'
)
),
m('li',
m('button', {class: "btn shadow-none", 'data-theme-pref': "auto", onclick: "toggleDarkMode(this)"},
m('span', {class: "me-1"}, m.trust('🖥️')),
'Match OS'
)
)
])
])
]),
m('div', {class: "row my-3"},
m('div', {class: "col"},
m('h1', data.reposConfig.defaultTemplateConfiguration?.allRepositoriesPageTitle || "All Repositories")
)
),
m('div', {class: "row"},
m('div', {class: "col d-flex flex-wrap"},
data.repos.map((repo) => {
return (
m('div', {class: "m-2 card bezel-gray flex-grow-1", style: "flex-basis: 20rem;"},
m('div', {class: "card-header"},
m('a', {class: "card-title fs-5", href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`}, repo.name)
),
m('div', {class: "card-body"},
repo.description ? m('p', {class: "card-text"}, repo.description) : null
),
m('div', {class: "card-footer"}, [
m('a', {
href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`,
class: "ms-0 me-2 my-2 btn btn-primary text-white"
}, 'Go to site'),
m('button', {
class: "mx-1 my-2 btn btn-outline-secondary shadow-none dropdown-toggle clone-popover-btn",
'data-copy-text': repo.cloneUrl
}, 'Clone'),
(data.reposConfig.repos[repo.name].defaultTemplateConfiguration?.homepageButtons || []).map((button) => {
return m('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('⧉'))] : null])
})
])
)
)
})
])
]),
m('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('script', {src: `${data.reposPath}/frontend/main-frontend.bundle.js`}),
])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
import commonPage from './common/commonPage.ts'
const pageContent = m('div', {class: "container"}, [
m('div', {class: "row my-3"},
m('div', {class: "col"},
m('h1', data.reposConfig.defaultTemplateConfiguration?.allRepositoriesPageTitle || "All Repositories")
)
),
m('div', {class: "row"},
m('div', {class: "col d-flex flex-wrap"},
data.repos.map((repo) => {
return (
m('div', {class: "m-2 card bezel-gray flex-grow-1", style: "flex-basis: 20rem;"},
m('div', {class: "card-header"},
m('a', {class: "card-title fs-5", href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`}, repo.name)
),
m('div', {class: "card-body"},
repo.description ? m('p', {class: "card-text"}, repo.description) : null
),
m('div', {class: "card-footer"}, [
m('a', {
href: `${data.reposPath}/${slugify(repo.name)}/branches/${repo.defaultBranch}`,
class: "ms-0 me-2 my-2 btn btn-primary text-white"
}, 'Go to site'),
class: "mx-1 my-2 btn btn-outline-secondary shadow-none dropdown-toggle clone-popover-btn",
'data-copy-text': repo.cloneUrl
}, 'Clone'),
(data.reposConfig.repos[repo.name].defaultTemplateConfiguration?.homepageButtons || []).map((button) => {
return m('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('⧉'))] : null])
})
})
)
)
return commonPage(`${data.reposPath}/`, pageContent)