astro check restored: tsconfig excludes public/ (the 2 MB vendored CMS bundle was what exhausted the heap) and extends tsconfigs/strict; type annotations in template scripts, z from astro/zod; exact version pins; compressHTML true (lossless whitespace, no words glued to links) and explicit trailingSlash/build.format; README: upgrading section
This commit is contained in:
@@ -16,7 +16,7 @@ export async function getStaticPaths() {
|
||||
const chunks = [posts.slice(0, FIRST)];
|
||||
for (let i = FIRST; i < posts.length; i += REST) chunks.push(posts.slice(i, i + REST));
|
||||
const lastPage = chunks.length;
|
||||
const hrefOf = (n) => (n === 1 ? '/news' : `/news/${n}`);
|
||||
const hrefOf = (n: number) => (n === 1 ? '/news' : `/news/${n}`);
|
||||
return chunks.map((data, i) => {
|
||||
const n = i + 1;
|
||||
return {
|
||||
@@ -42,7 +42,7 @@ for (let n = 1; n <= page.lastPage; n++) {
|
||||
if (n === 1 || n === page.lastPage || Math.abs(n - page.currentPage) <= 1) nums.push(n);
|
||||
else if (nums.at(-1) !== 0) nums.push(0);
|
||||
}
|
||||
const hrefFor = (n) => (n === 1 ? '/news' : `/news/${n}`);
|
||||
const hrefFor = (n: number) => (n === 1 ? '/news' : `/news/${n}`);
|
||||
---
|
||||
<Base
|
||||
title={first ? 'CTAO Science Portal - News' : `CTAO Science Portal - News, page ${page.currentPage}`}
|
||||
|
||||
+11
-10
@@ -96,10 +96,10 @@ const readMin = readMinOf(post);
|
||||
// enters it is mapped back to its governing h2/h3, whose TOC link(s) get
|
||||
// aria-current="true" (set in BOTH renderings — inline <details> and rail).
|
||||
// Progressive enhancement: without JS the TOC is plain working anchors.
|
||||
const links = [...document.querySelectorAll('.toc a[href^="#"]')];
|
||||
const links = [...document.querySelectorAll<HTMLAnchorElement>('.toc a[href^="#"]')];
|
||||
if (links.length) {
|
||||
let current = [];
|
||||
const setCurrent = (id) => {
|
||||
let current: HTMLAnchorElement[] = [];
|
||||
const setCurrent = (id: string | null) => {
|
||||
const next = id ? links.filter((a) => decodeURIComponent(a.hash.slice(1)) === id) : [];
|
||||
if (next[0] === current[0]) return;
|
||||
for (const a of current) a.removeAttribute('aria-current');
|
||||
@@ -108,35 +108,36 @@ const readMin = readMinOf(post);
|
||||
};
|
||||
const blocks = [...document.querySelectorAll('.prose > *')];
|
||||
// Governing heading = the block itself or the nearest h2/h3[id] above it
|
||||
const headingFor = (el) => {
|
||||
const headingFor = (el: Element) => {
|
||||
for (let i = blocks.indexOf(el); i >= 0; i--) {
|
||||
if (blocks[i].matches('h2[id], h3[id]')) return blocks[i].id;
|
||||
}
|
||||
return null; // intro before the first heading — nothing highlighted
|
||||
};
|
||||
const onIntersect = (entries) => {
|
||||
const onIntersect = (entries: IntersectionObserverEntry[]) => {
|
||||
for (const e of entries) {
|
||||
if (e.isIntersecting) { setCurrent(headingFor(e.target)); break; }
|
||||
}
|
||||
};
|
||||
let observer;
|
||||
let observer: IntersectionObserver | undefined;
|
||||
const observe = () => {
|
||||
observer?.disconnect();
|
||||
// Narrow band below the sticky header (--header-h 56px + 12px slack;
|
||||
// JS can't read the token cheaply, keep in sync) — Starlight's rootMargin trick
|
||||
const top = 68, band = 64;
|
||||
observer = new IntersectionObserver(onIntersect, {
|
||||
const io = new IntersectionObserver(onIntersect, {
|
||||
rootMargin: `-${top}px 0px ${top + band - document.documentElement.clientHeight}px`,
|
||||
});
|
||||
blocks.forEach((b) => observer.observe(b));
|
||||
observer = io;
|
||||
blocks.forEach((b) => io.observe(b));
|
||||
};
|
||||
observe();
|
||||
let timer;
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
addEventListener('resize', () => { clearTimeout(timer); timer = setTimeout(observe, 200); });
|
||||
// Short final section: at page bottom, the last heading wins
|
||||
addEventListener('scroll', () => {
|
||||
if (innerHeight + scrollY >= document.documentElement.scrollHeight - 4) {
|
||||
setCurrent(headingFor(blocks.at(-1)));
|
||||
setCurrent(headingFor(blocks[blocks.length - 1]));
|
||||
}
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user