added DocsPage, improved navbar with dynamic height handling, MathJax integration, new TOC features, and extensive markdown processing
This commit is contained in:
1 parent
918534afb5
commit
1fadc42414
13 files changed
+707
-223
No files matched your search
@@ -45,7 +45,43 @@
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"
|
||||
/>
|
||||
<!-- MathJax v3 configuration and loader (replace KaTeX) -->
|
||||
<script>
|
||||
window.MathJax = {
|
||||
tex: {
|
||||
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
||||
displayMath: [['$$', '$$'], ['\\[', '\\]']],
|
||||
processEscapes: true
|
||||
},
|
||||
options: {
|
||||
skipHtmlTags: ['script','noscript','style','textarea','pre','code']
|
||||
},
|
||||
startup: {
|
||||
// We'll trigger typesetting manually from the app after markdown is mounted
|
||||
typeset: false
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
|
||||
<style>
|
||||
/* Reserve space for fixed navbar and ensure in-page anchors don't end up hidden under it */
|
||||
:root { --navbar-offset: 56px; }
|
||||
body {
|
||||
/* Fallback padding; JS will keep this equal to the real navbar height */
|
||||
padding-top: var(--navbar-offset);
|
||||
/* Make native hash jumps account for the fixed header */
|
||||
scroll-padding-top: calc(var(--navbar-offset) + 8px);
|
||||
}
|
||||
/* Also offset scroll for headings and any element targeted by an id */
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4,
|
||||
.markdown-body h5,
|
||||
.markdown-body h6,
|
||||
[id] {
|
||||
scroll-margin-top: calc(var(--navbar-offset) + 8px);
|
||||
}
|
||||
/* Unify markdown and page backgrounds with Bootstrap theme variables */
|
||||
.markdown-body {
|
||||
box-sizing: border-box;
|
||||
@@ -102,7 +138,70 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<!-- Fixed top navbar for the whole site -->
|
||||
<a href="#root" class="visually-hidden-focusable position-absolute top-0 start-0 m-2 px-2 py-1 bg-body border rounded">Skip to content</a>
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top border-bottom" role="navigation" aria-label="Primary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand d-flex align-items-center gap-2" href="#">
|
||||
<i class="bi bi-braces-asterisk"></i>
|
||||
Lyng
|
||||
</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#topbarNav"
|
||||
aria-controls="topbarNav"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="topbarNav">
|
||||
<!-- Left-aligned main menu -->
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#/docs/Iterator.md" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Documentation
|
||||
</a>
|
||||
<ul id="docsDropdownMenu" class="dropdown-menu">
|
||||
<!-- Will be populated at runtime -->
|
||||
<li><a class="dropdown-item" href="#/docs/tutorial.md" data-route="docs">tutorial</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#/reference" data-route="reference">Reference</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Right utilities: search, GitHub link -->
|
||||
<div class="ms-auto d-flex align-items-center gap-2" style="min-width: 240px;">
|
||||
<!-- Search widget with Bootstrap Icons magnifying glass -->
|
||||
<form class="d-flex" role="search" onsubmit="return false;">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-transparent border-end-0">
|
||||
<i class="bi bi-search"></i>
|
||||
</span>
|
||||
<input
|
||||
id="topSearch"
|
||||
class="form-control border-start-0"
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<a class="btn btn-sm btn-outline-secondary" href="https://github.com/sergeych/lyng" target="_blank" rel="noopener" aria-label="GitHub">
|
||||
<i class="bi bi-github"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- App root; extra top padding so content is not hidden behind fixed navbar -->
|
||||
<div id="root" class="pt-4" tabindex="-1" aria-live="polite" aria-atomic="false"></div>
|
||||
|
||||
<!-- App bundle (produced by Kotlin/JS). The Gradle config forces this name. -->
|
||||
<script src="site.js"></script>
|
||||
@@ -113,5 +212,51 @@
|
||||
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script>
|
||||
// Adjust body padding to account for fixed-top navbar height (handles dynamic font sizes)
|
||||
(function () {
|
||||
function adjustPadding() {
|
||||
var nav = document.querySelector('.navbar.fixed-top');
|
||||
if (!nav) return;
|
||||
var h = nav.getBoundingClientRect().height;
|
||||
var px = Math.ceil(h) + 'px';
|
||||
// Keep legacy inline padding for older browsers
|
||||
document.body.style.paddingTop = px;
|
||||
// And expose as a CSS variable used by scroll-padding/scroll-margin rules
|
||||
document.documentElement.style.setProperty('--navbar-offset', px);
|
||||
}
|
||||
window.addEventListener('load', adjustPadding);
|
||||
window.addEventListener('resize', adjustPadding);
|
||||
// Also listen to Bootstrap collapse events which may change navbar height on small screens
|
||||
document.addEventListener('shown.bs.collapse', adjustPadding);
|
||||
document.addEventListener('hidden.bs.collapse', adjustPadding);
|
||||
|
||||
// Basic active state management for topbar links
|
||||
function updateActive() {
|
||||
var hash = location.hash;
|
||||
// Clear previous actives
|
||||
document.querySelectorAll('#topbarNav .nav-link').forEach(function(a){
|
||||
a.classList.remove('active');
|
||||
a.removeAttribute('aria-current');
|
||||
});
|
||||
// Mark active for simple routes
|
||||
var activeLink = null;
|
||||
if (!hash || hash === '#' || hash === '#/') {
|
||||
activeLink = document.querySelector('#topbarNav .nav-link[data-route="home"]');
|
||||
} else if (hash.startsWith('#/docs/')) {
|
||||
// Mark Docs menu root as active
|
||||
activeLink = document.querySelector('#topbarNav .nav-link.dropdown-toggle');
|
||||
} else if (hash.startsWith('#/reference')) {
|
||||
activeLink = document.querySelector('#topbarNav .nav-link[data-route="reference"]');
|
||||
}
|
||||
if (activeLink) {
|
||||
activeLink.classList.add('active');
|
||||
activeLink.setAttribute('aria-current', 'page');
|
||||
}
|
||||
}
|
||||
window.addEventListener('hashchange', updateActive);
|
||||
window.addEventListener('load', updateActive);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user