mirror of
https://github.com/HananoshikaYomaru/openfreebooks.git
synced 2026-11-12 20:45:52 +00:00
150 lines
4.3 KiB
TypeScript
150 lines
4.3 KiB
TypeScript
import { render } from "solid-js/web";
|
|
import { SiteHeader } from "./components/site-header";
|
|
import { Marquee } from "./components/marquee";
|
|
import { ContributorsDialogBootstrap } from "./components/contributors-dialog";
|
|
import { ScrollRevealBootstrap } from "./components/scroll-reveal";
|
|
import { initTheme } from "./theme";
|
|
|
|
function readConfig() {
|
|
const el = document.getElementById("site-config");
|
|
if (!el?.textContent) {
|
|
return {
|
|
brand: "Open Free Books",
|
|
homeUrl: "/",
|
|
browseUrl: "/catalog/",
|
|
aboutUrl: "/about/",
|
|
faqUrl: "/faq/",
|
|
searchUrl: "/search/",
|
|
contributingUrl: "/contributing/",
|
|
githubUrl: "https://github.com/openfreebooks/openfreebooks",
|
|
};
|
|
}
|
|
return JSON.parse(el.textContent) as {
|
|
brand: string;
|
|
homeUrl: string;
|
|
browseUrl: string;
|
|
aboutUrl: string;
|
|
faqUrl: string;
|
|
searchUrl: string;
|
|
contributingUrl: string;
|
|
githubUrl: string;
|
|
};
|
|
}
|
|
|
|
function mountFooterYear() {
|
|
const yearEl = document.getElementById("footer-year");
|
|
if (yearEl) {
|
|
yearEl.textContent = String(new Date().getFullYear());
|
|
}
|
|
}
|
|
|
|
function scheduleChapterMath() {
|
|
void import("./lib/render-math").then(({ renderBookMath }) => {
|
|
requestAnimationFrame(() => renderBookMath());
|
|
});
|
|
}
|
|
|
|
function mountChapterWidgets() {
|
|
const article = document.querySelector<HTMLElement>("[data-chapter]");
|
|
const chapterKey = article?.dataset.chapter;
|
|
const mounts = document.querySelectorAll<HTMLElement>("[data-widget]");
|
|
if (!article || !chapterKey) return;
|
|
|
|
// KaTeX must run on widget-less chapters too (renderBookMath was only chained after widgets).
|
|
if (mounts.length === 0) {
|
|
scheduleChapterMath();
|
|
return;
|
|
}
|
|
|
|
void import("./generated/chapter-widgets").then(({ chapterWidgetLoaders }) => {
|
|
const loadPromises: Promise<void>[] = [];
|
|
|
|
for (const el of mounts) {
|
|
const widget = el.dataset.widget;
|
|
if (!widget) continue;
|
|
const loaderKey = `${chapterKey}/${widget}`;
|
|
const loader = chapterWidgetLoaders[loaderKey];
|
|
if (!loader) {
|
|
console.warn(`No widget loader registered for ${loaderKey}`);
|
|
continue;
|
|
}
|
|
loadPromises.push(
|
|
loader().then((mod) => {
|
|
render(() => mod.default(), el);
|
|
})
|
|
);
|
|
}
|
|
|
|
void Promise.all(loadPromises).then(() => {
|
|
scheduleChapterMath();
|
|
});
|
|
});
|
|
}
|
|
|
|
initTheme();
|
|
|
|
const config = readConfig();
|
|
const navLinks = [
|
|
{ label: "Browse", href: config.browseUrl },
|
|
{ label: "Search", href: config.searchUrl },
|
|
{ label: "About", href: config.aboutUrl },
|
|
{ label: "FAQ", href: config.faqUrl },
|
|
{ label: "GitHub", href: config.githubUrl },
|
|
];
|
|
|
|
const headerRoot = document.getElementById("site-header");
|
|
if (headerRoot) {
|
|
render(
|
|
() => (
|
|
<SiteHeader brand={config.brand} homeUrl={config.homeUrl} links={navLinks} />
|
|
),
|
|
headerRoot
|
|
);
|
|
}
|
|
|
|
const marqueeRoot = document.getElementById("marquee");
|
|
if (marqueeRoot) {
|
|
render(() => <Marquee />, marqueeRoot);
|
|
}
|
|
|
|
render(() => <ScrollRevealBootstrap />, document.body);
|
|
render(() => <ContributorsDialogBootstrap />, document.body);
|
|
|
|
const particleRoot = document.getElementById("webgl-background");
|
|
if (particleRoot && !window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
void import("./lib/particle-background").then(({ initParticleBackground }) => {
|
|
initParticleBackground(particleRoot);
|
|
});
|
|
}
|
|
|
|
const copyPageRoot = document.getElementById("copy-page-button");
|
|
if (copyPageRoot) {
|
|
void import("./components/copy-page-button").then(({ CopyPageButton }) => {
|
|
render(() => <CopyPageButton />, copyPageRoot);
|
|
});
|
|
}
|
|
|
|
const chapterNavRoot = document.getElementById("chapter-heading-nav");
|
|
if (chapterNavRoot) {
|
|
void import("./components/chapter-heading-nav").then(({ ChapterHeadingNav }) => {
|
|
render(() => <ChapterHeadingNav />, chapterNavRoot);
|
|
});
|
|
}
|
|
|
|
mountChapterWidgets();
|
|
|
|
const catalogRoot = document.getElementById("catalog-app");
|
|
if (catalogRoot) {
|
|
void import("./components/catalog-app").then(({ CatalogApp }) => {
|
|
catalogRoot.replaceChildren();
|
|
render(() => <CatalogApp />, catalogRoot);
|
|
});
|
|
}
|
|
|
|
if (document.getElementById("contributing-demo-graph") || document.getElementById("contributing-demo-views")) {
|
|
void import("./components/contributing-demos").then(({ mountContributingDemos }) => {
|
|
mountContributingDemos();
|
|
});
|
|
}
|
|
|
|
mountFooterYear();
|