feat(comments): 集中 Giscus 加载逻辑并支持主题切换

- 将 Giscus 评论脚本从文章页面移至全局布局
- 添加动态脚本加载函数,防止重复加载
- 通过 MutationObserver 监听主题变化并实时更新 Giscus 主题
- 集成 Swup 页面导航事件,确保页面切换后评论正确加载
- 简化文章页面中的 Giscus 容器,仅保留数据属性
This commit is contained in:
二叉树树
2026-01-24 10:30:44 +08:00
parent 28ffdb4205
commit 935d2ffa78
2 changed files with 80 additions and 68 deletions

View File

@@ -636,6 +636,73 @@ if (window.swup) {
}
</script>
<script is:inline>
// Giscus Loader
function loadGiscus() {
const container = document.getElementById('giscus-container');
if (!container) return;
// Prevent double loading if script is already there
if (container.querySelector('script[src*="giscus"]')) return;
const script = document.createElement('script');
script.src = "https://giscus.app/client.js";
script.async = true;
script.crossOrigin = "anonymous";
// Required attributes
const requiredAttrs = [
'repo', 'repoId', 'category', 'categoryId',
'mapping', 'strict', 'reactionsEnabled',
'emitMetadata', 'inputPosition', 'lang', 'loading'
];
requiredAttrs.forEach(attr => {
if (container.dataset[attr]) {
const kebab = attr.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
script.setAttribute(`data-${kebab}`, container.dataset[attr]);
}
});
// Theme handling
const theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
script.setAttribute('data-theme', theme);
container.appendChild(script);
}
function initGiscus() {
loadGiscus();
// Listen for Swup navigation
if (window.swup) {
window.swup.hooks.on('page:view', loadGiscus);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initGiscus);
} else {
initGiscus();
}
// Global theme observer
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
const iframe = document.querySelector('iframe.giscus-frame');
if (iframe) {
const theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
iframe.contentWindow.postMessage({
giscus: { setConfig: { theme: theme } }
}, 'https://giscus.app');
}
}
});
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
</script>
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" aria-hidden="true">
<defs>
<filter id="liquid-glass">