Fix page meta not updating on client-side post navigation
When a card was clicked, history.pushState changed the URL but left document.title, description, og:*, and canonical pointing at the overview page. navigate() also only updated document.title, not meta. Add setMeta/syncHeadMeta helpers; update title+meta from POSTS data on card open, and sync all head meta from the fetched document in navigate(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,36 @@
|
|||||||
return esc(text).replace(re, '<mark class="hl">$1</mark>');
|
return esc(text).replace(re, '<mark class="hl">$1</mark>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setMeta(attr, key, val) {
|
||||||
|
let el = document.querySelector(`meta[${attr}="${key}"]`);
|
||||||
|
if (val !== null && val !== undefined && val !== '') {
|
||||||
|
if (!el) { el = document.createElement('meta'); el.setAttribute(attr, key); document.head.appendChild(el); }
|
||||||
|
el.setAttribute('content', val);
|
||||||
|
} else if (el) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncHeadMeta(doc) {
|
||||||
|
const canon = doc.querySelector('link[rel="canonical"]');
|
||||||
|
const curCanon = document.querySelector('link[rel="canonical"]');
|
||||||
|
if (canon && curCanon) curCanon.href = canon.href;
|
||||||
|
[
|
||||||
|
['name', 'description'],
|
||||||
|
['property', 'og:title'],
|
||||||
|
['property', 'og:description'],
|
||||||
|
['property', 'og:url'],
|
||||||
|
['property', 'og:image'],
|
||||||
|
['property', 'og:image:width'],
|
||||||
|
['property', 'og:image:height'],
|
||||||
|
['name', 'twitter:card'],
|
||||||
|
['name', 'twitter:image'],
|
||||||
|
].forEach(([attr, key]) => {
|
||||||
|
const src = doc.querySelector(`meta[${attr}="${key}"]`);
|
||||||
|
setMeta(attr, key, src ? src.getAttribute('content') : null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ── Inverted search index
|
// ── Inverted search index
|
||||||
const INDEX = (() => {
|
const INDEX = (() => {
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
@@ -377,6 +407,17 @@
|
|||||||
const scopedList = issueId ? POSTS.filter(p => p.issue === issueId) : POSTS;
|
const scopedList = issueId ? POSTS.filter(p => p.issue === issueId) : POSTS;
|
||||||
lbReferrer = location.href;
|
lbReferrer = location.href;
|
||||||
history.pushState({ slug }, '', card.href);
|
history.pushState({ slug }, '', card.href);
|
||||||
|
if (clicked) {
|
||||||
|
const postTitle = clicked.title + ' — Roux';
|
||||||
|
const postUrl = new URL(clicked.url, location.origin).href;
|
||||||
|
document.title = postTitle;
|
||||||
|
setMeta('name', 'description', clicked.description || null);
|
||||||
|
setMeta('property', 'og:title', postTitle);
|
||||||
|
setMeta('property', 'og:description', clicked.description || null);
|
||||||
|
setMeta('property', 'og:url', postUrl);
|
||||||
|
const canon = document.querySelector('link[rel="canonical"]');
|
||||||
|
if (canon) canon.href = postUrl;
|
||||||
|
}
|
||||||
lbOpen(slug, scopedList.length ? scopedList : POSTS);
|
lbOpen(slug, scopedList.length ? scopedList : POSTS);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -431,6 +472,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.title = doc.title;
|
document.title = doc.title;
|
||||||
|
syncHeadMeta(doc);
|
||||||
history.pushState({}, '', url);
|
history.pushState({}, '', url);
|
||||||
|
|
||||||
// Re-init page state
|
// Re-init page state
|
||||||
|
|||||||
Reference in New Issue
Block a user