brewlog/templates/base.html
Jon Seager 5c75c39883
perf(build): add release profile, lld linker, and defer script tags
- Add [profile.release] with thin LTO and symbol stripping
- Configure lld linker via .cargo/config.toml for faster linking
- Add clang and lld to Nix devShell
- Add defer attribute to component script tags to unblock HTML parsing
2026-02-06 18:05:16 +00:00

111 lines
5 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-star-root>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block title %}Brewlog{% endblock %}</title>
<link rel="stylesheet" href="/styles.css" />
<link rel="icon" id="favicon" type="image/svg+xml" href="/favicon-light.svg" />
<script>
(() => {
const stored = localStorage.getItem("theme");
const isDark = stored === "dark" || (!stored && matchMedia("(prefers-color-scheme: dark)").matches);
if (isDark) {
document.documentElement.setAttribute("data-theme", "dark");
document.getElementById("favicon").href = "/favicon-dark.svg";
}
})();
</script>
<script
type="module"
src="https://cdn.jsdelivr.net/gh/starfederation/datastar@1.0.0-RC.6/bundles/datastar.js"
></script>
<script defer src="/components/photo-capture.js"></script>
<script defer src="/components/searchable-select.js"></script>
{% block head %}{% endblock %}
<script>
document.addEventListener("DOMContentLoaded", () => {
const mobileQuery = window.matchMedia("(max-width: 767px)");
if (!mobileQuery.matches) return;
const setupInfiniteScroll = () => {
document.querySelectorAll("[data-infinite-scroll]").forEach((container) => {
const sentinel = container.querySelector(".infinite-scroll-sentinel");
if (!sentinel || sentinel.dataset.observed) return;
sentinel.dataset.observed = "true";
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const nextUrl = container.getAttribute("data-next-url");
const targetSelector = container.getAttribute("data-target");
if (!nextUrl || !targetSelector) {
observer.disconnect();
return;
}
observer.disconnect();
sentinel.remove();
fetch(nextUrl, {
headers: { "datastar-request": "true" },
})
.then((res) => res.text())
.then((html) => {
const doc = new DOMParser().parseFromString(html, "text/html");
const newTarget = doc.querySelector(targetSelector);
if (!newTarget) return;
// Append new rows to existing tbody
const existingTbody = container.querySelector("tbody");
const newTbody = newTarget.querySelector("tbody");
if (existingTbody && newTbody) {
Array.from(newTbody.children).forEach((row) => {
existingTbody.appendChild(document.adoptNode(row));
});
}
// Check if there are more pages
const newContainer = newTarget.querySelector("[data-infinite-scroll]");
const newNextUrl = newContainer && newContainer.getAttribute("data-next-url");
if (newNextUrl) {
container.setAttribute("data-next-url", newNextUrl);
const newSentinel = document.createElement("div");
newSentinel.className = "infinite-scroll-sentinel h-4 md:hidden";
newSentinel.setAttribute("aria-hidden", "true");
container.appendChild(newSentinel);
setupInfiniteScroll();
} else {
container.removeAttribute("data-next-url");
container.removeAttribute("data-infinite-scroll");
}
});
});
},
{ rootMargin: "200px" }
);
observer.observe(sentinel);
});
};
setupInfiniteScroll();
const bodyObserver = new MutationObserver(() => {
setupInfiniteScroll();
});
bodyObserver.observe(document.body, { childList: true, subtree: true });
});
</script>
</head>
<body class="min-h-screen bg-page text-text">
<main class="mx-auto flex w-full max-w-5xl flex-col gap-8 px-6 py-10">
{% include "partials/nav.html" %} {% block content %}{% endblock %}
<footer class="mt-8 text-center text-xs tracking-widest text-text-muted" style="font-variant: small-caps">
<p>B{rew}log by <a href="https://jnsgr.uk" class="text-text-muted hover:text-accent transition" target="_blank" rel="noreferrer noopener">jnsgruk</a> · {{ version_info.version }} · <a href="https://github.com/jnsgruk/brewlog/commit/{{ version_info.commit }}" class="text-text-muted hover:text-accent transition" target="_blank" rel="noreferrer noopener">{{ version_info.commit }}</a></p>
</footer>
</main>
</body>
</html>