feat: astro built-ins — news pagination, prefetch, RSS, OG/SEO meta, TOC scrollspy (Starlight-pattern)

This commit is contained in:
ctao
2026-07-25 06:57:58 +02:00
parent 2de0cf148e
commit 4ace039233
13 changed files with 283 additions and 46 deletions
+14 -2
View File
@@ -7,6 +7,15 @@
const status = document.getElementById(opts.status);
let index = null;
let timer;
// First title match wrapped in <mark> (Starlight search pattern) — built
// from text nodes, never innerHTML.
function highlight(text, q) {
const i = text.toLowerCase().indexOf(q);
if (i < 0) return [text];
const mark = document.createElement('mark');
mark.textContent = text.slice(i, i + q.length);
return [text.slice(0, i), mark, text.slice(i + q.length)];
}
async function run() {
const q = input.value.trim().toLowerCase();
list.innerHTML = '';
@@ -15,12 +24,15 @@
const hits = index
.filter((p) => (p.title + ' ' + p.description + ' ' + p.category).toLowerCase().includes(q))
.slice(0, opts.limit);
status.textContent = hits.length ? hits.length + ' ' + (opts.unit || 'result(s)') : 'No results.';
const unit = opts.unit || 'result';
status.textContent = hits.length
? hits.length + ' ' + unit + (hits.length === 1 ? '' : 's') + ' for “' + input.value.trim() + '”'
: 'No results for “' + input.value.trim() + '” — try a shorter or different term.';
for (const p of hits) {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = '/news/' + encodeURIComponent(p.slug);
a.textContent = p.title;
a.append(...highlight(p.title, q));
const small = document.createElement('small');
small.textContent = p.date;
li.append(a, small);