This commit is contained in:
2025-12-08 01:03:07 +08:00
commit 5c77d25b6d
334 changed files with 71475 additions and 0 deletions

View File

@@ -0,0 +1,370 @@
class CodeBlockCollapser {
constructor() {
this.processedBlocks = new WeakSet();
this.observer = null;
this.isThemeChanging = false;
this.debug = false; // 设置为 true 启用调试日志
this.init();
}
log(...args) {
if (this.debug) {
console.log("[CodeBlockCollapser]", ...args);
}
}
init() {
this.log("Initializing...");
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
this.log("DOMContentLoaded - setting up code blocks");
this.setupCodeBlocks();
});
} else {
this.log("Document already loaded - setting up code blocks");
this.setupCodeBlocks();
}
this.observePageChanges();
this.setupThemeChangeListener();
this.setupThemeOptimizerSync();
}
setupThemeOptimizerSync() {
// 与主题优化器同步,确保代码块的隐藏/显示行为一致
this.syncWithThemeOptimizer();
// 监听主题优化器初始化完成事件
document.addEventListener("themeOptimizerReady", () => {
this.log("Theme optimizer ready, syncing code block behavior");
this.syncWithThemeOptimizer();
});
// 监听页面切换事件,确保同步
document.addEventListener("swup:pageView", () => {
// 延迟同步,确保主题优化器已经处理完代码块
setTimeout(() => {
this.syncWithThemeOptimizer();
}, 150);
});
}
syncWithThemeOptimizer() {
// 检查主题优化器是否存在
if (window.themeOptimizer) {
// 获取当前主题优化器的设置
const shouldHideDuringTransition =
window.themeOptimizer.hideCodeBlocksDuringTransition;
// 应用相同的设置到代码块
const codeBlocks = document.querySelectorAll(".expressive-code");
codeBlocks.forEach((block) => {
if (shouldHideDuringTransition) {
block.classList.add("hide-during-transition");
} else {
block.classList.remove("hide-during-transition");
}
});
this.log(
`Synced with theme optimizer: hide code blocks during transition = ${shouldHideDuringTransition}`,
);
} else {
// 如果主题优化器不存在,应用默认行为
const codeBlocks = document.querySelectorAll(".expressive-code");
codeBlocks.forEach((block) => {
block.classList.add("hide-during-transition");
});
this.log("Theme optimizer not available, applied default behavior");
}
}
setupThemeChangeListener() {
// 监听主题切换,在切换期间暂停 observer 和优化性能
const themeObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (
mutation.type === "attributes" &&
(mutation.attributeName === "class" ||
mutation.attributeName === "data-theme")
) {
const isTransitioning = document.documentElement.classList.contains(
"is-theme-transitioning",
);
if (isTransitioning && !this.isThemeChanging) {
this.isThemeChanging = true;
// 断开 observer 以避免在主题切换时进行不必要的检查
if (this.observer) {
this.observer.disconnect();
}
// 性能优化:临时禁用代码块的动画和过渡
document.querySelectorAll(".expressive-code").forEach((block) => {
block.style.transition = "none";
});
} else if (!isTransitioning && this.isThemeChanging) {
this.isThemeChanging = false;
// 等待主题切换完全结束后再恢复
requestAnimationFrame(() => {
// 恢复代码块的过渡效果
document.querySelectorAll(".expressive-code").forEach((block) => {
block.style.transition = "";
});
// 重新连接 observer
setTimeout(() => {
this.observePageChanges();
}, 50);
});
}
break;
}
}
});
themeObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class", "data-theme"],
});
}
setupCodeBlocks() {
requestAnimationFrame(() => {
const codeBlocks = document.querySelectorAll(".expressive-code");
this.log(`Found ${codeBlocks.length} code blocks to process`);
codeBlocks.forEach((codeBlock, index) => {
if (!this.processedBlocks.has(codeBlock)) {
this.log(`Enhancing code block ${index + 1}`);
this.enhanceCodeBlock(codeBlock);
this.processedBlocks.add(codeBlock);
} else {
this.log(`Code block ${index + 1} already processed`);
}
});
});
}
enhanceCodeBlock(codeBlock) {
const frame = codeBlock.querySelector(".frame");
if (!frame) {
this.log("No frame found in code block, skipping");
return;
}
if (frame.classList.contains("has-title")) {
this.log("Code block has title, skipping collapse feature");
return;
}
this.log("Adding collapse feature to code block");
codeBlock.classList.add("collapsible", "expanded");
const toggleBtn = this.createToggleButton();
frame.appendChild(toggleBtn);
this.bindToggleEvents(codeBlock, toggleBtn);
}
createToggleButton() {
const button = document.createElement("button");
button.className = "collapse-toggle-btn";
button.type = "button";
button.setAttribute("aria-label", "折叠/展开代码块");
button.innerHTML = `
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none">
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
<path fill="currentColor" d="m12 16.172l-4.95-4.95a1 1 0 1 0-1.414 1.414l5.657 5.657a1 1 0 0 0 1.414 0l5.657-5.657a1 1 0 0 0-1.414-1.414z"></path>
</g>
</svg>
`;
return button;
}
bindToggleEvents(codeBlock, button) {
button.addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
this.toggleCollapse(codeBlock);
});
button.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
this.toggleCollapse(codeBlock);
}
});
}
toggleCollapse(codeBlock) {
const isCollapsed = codeBlock.classList.contains("collapsed");
requestAnimationFrame(() => {
if (isCollapsed) {
codeBlock.classList.remove("collapsed");
codeBlock.classList.add("expanded");
} else {
codeBlock.classList.remove("expanded");
codeBlock.classList.add("collapsed");
}
});
const event = new CustomEvent("codeBlockToggle", {
detail: { collapsed: !isCollapsed, element: codeBlock },
});
document.dispatchEvent(event);
}
observePageChanges() {
// 如果正在主题切换,不要重新连接
if (this.isThemeChanging) return;
// 断开现有的 observer
if (this.observer) {
this.observer.disconnect();
}
let debounceTimer = null;
this.observer = new MutationObserver((mutations) => {
// 如果正在主题切换,忽略所有变化
if (this.isThemeChanging) return;
let shouldReinit = false;
for (const mutation of mutations) {
if (mutation.type === "childList") {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
// 只检查添加的节点本身或其直接子节点
if (
node.classList &&
node.classList.contains("expressive-code")
) {
shouldReinit = true;
break;
}
// 避免深度查询,只检查一层
if (node.children && node.children.length > 0) {
for (let i = 0; i < Math.min(node.children.length, 10); i++) {
if (
node.children[i].classList &&
node.children[i].classList.contains("expressive-code")
) {
shouldReinit = true;
break;
}
}
}
}
if (shouldReinit) break;
}
}
if (shouldReinit) break;
}
if (shouldReinit) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => this.setupCodeBlocks(), 150);
}
});
this.observer.observe(document.body, {
childList: true,
subtree: true,
});
}
destroy() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
this.processedBlocks = new WeakSet();
}
// 公共API方法
collapseAll() {
const allBlocks = document.querySelectorAll(".expressive-code.expanded");
allBlocks.forEach((block) => {
this.toggleCollapse(block);
});
}
expandAll() {
const allBlocks = document.querySelectorAll(".expressive-code.collapsed");
allBlocks.forEach((block) => {
this.toggleCollapse(block);
});
}
}
const codeBlockCollapser = new CodeBlockCollapser();
window.CodeBlockCollapser = CodeBlockCollapser;
window.codeBlockCollapser = codeBlockCollapser;
// 设置 Swup 钩子的函数
function setupSwupHooks() {
if (window.swup) {
codeBlockCollapser.log("Setting up Swup hooks");
// 监听 page:view 事件
window.swup.hooks.on("page:view", () => {
codeBlockCollapser.log(
"Swup page:view event - reinitializing code blocks",
);
// 页面切换后重置 processedBlocks确保新页面的代码块被处理
codeBlockCollapser.processedBlocks = new WeakSet();
setTimeout(() => {
codeBlockCollapser.setupCodeBlocks();
}, 100);
});
// 监听 content:replace 事件(更早触发)
window.swup.hooks.on("content:replace", () => {
codeBlockCollapser.log(
"Swup content:replace event - preparing for reinitialization",
);
// 内容替换时也重置,确保不会因为缓存而跳过处理
codeBlockCollapser.processedBlocks = new WeakSet();
setTimeout(() => {
codeBlockCollapser.setupCodeBlocks();
}, 50);
});
return true;
}
return false;
}
// 尝试立即设置 Swup 钩子
if (!setupSwupHooks()) {
// 如果 Swup 尚未初始化,等待它加载
codeBlockCollapser.log("Swup not ready, waiting for initialization");
// 监听 swup:enable 事件
document.addEventListener("swup:enable", () => {
codeBlockCollapser.log("Swup enabled, setting up hooks");
setupSwupHooks();
});
// 额外的延迟重试机制,确保捕获到 Swup
const retryInterval = setInterval(() => {
if (setupSwupHooks()) {
codeBlockCollapser.log("Swup hooks set up successfully via retry");
clearInterval(retryInterval);
}
}, 100);
// 最多重试 20 次2 秒)
setTimeout(() => {
clearInterval(retryInterval);
}, 2000);
}

View File

@@ -0,0 +1,136 @@
// 右侧边栏布局管理器
// 用于在网格模式下隐藏右侧边栏
/**
* 初始化页面布局
* @param {string} pageType - 页面类型projects, skills等
*/
function initPageLayout(pageType) {
// 获取布局配置
const defaultPostListLayout =
localStorage.getItem("postListLayout") || "list";
// 如果默认布局是网格模式,则隐藏右侧边栏
if (defaultPostListLayout === "grid") {
hideRightSidebar();
} else {
showRightSidebar();
}
// 监听布局切换事件
window.addEventListener("layoutChange", (event) => {
const layout = event.detail.layout;
if (layout === "grid") {
hideRightSidebar();
} else {
showRightSidebar();
}
});
// 监听本地存储变化(用于跨标签页同步)
window.addEventListener('storage', (event) => {
if (event.key === 'postListLayout') {
if (event.newValue === 'grid') {
hideRightSidebar();
} else {
showRightSidebar();
}
}
});
// 监听页面导航事件
document.addEventListener("astro:page-load", () => {
setTimeout(() => {
const currentLayout = localStorage.getItem("postListLayout") || "list";
if (currentLayout === "grid") {
hideRightSidebar();
} else {
showRightSidebar();
}
}, 100);
});
// 监听SWUP导航事件
document.addEventListener("swup:contentReplaced", () => {
setTimeout(() => {
const currentLayout = localStorage.getItem("postListLayout") || "list";
if (currentLayout === "grid") {
hideRightSidebar();
} else {
showRightSidebar();
}
}, 100);
});
}
/**
* 隐藏右侧边栏
*/
function hideRightSidebar() {
const rightSidebar = document.querySelector(".right-sidebar-container");
if (rightSidebar) {
// 添加隐藏类
rightSidebar.classList.add("hidden-in-grid-mode");
// 设置显示为none以完全隐藏
rightSidebar.style.display = "none";
// 调整主网格布局
const mainGrid = document.getElementById("main-grid");
if (mainGrid) {
mainGrid.style.gridTemplateColumns = "17.5rem 1fr";
mainGrid.setAttribute("data-layout-mode", "grid");
}
}
}
/**
* 显示右侧边栏
*/
function showRightSidebar() {
const rightSidebar = document.querySelector(".right-sidebar-container");
if (rightSidebar) {
// 移除隐藏类
rightSidebar.classList.remove("hidden-in-grid-mode");
// 恢复显示
rightSidebar.style.display = "";
// 恢复主网格布局
const mainGrid = document.getElementById("main-grid");
if (mainGrid) {
mainGrid.style.gridTemplateColumns = "";
mainGrid.setAttribute("data-layout-mode", "list");
}
}
}
// 页面加载完成后初始化
function initialize() {
const pageType = document.documentElement.getAttribute("data-page-type") || "projects";
initPageLayout(pageType);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initialize);
} else {
initialize();
}
// 导出函数供其他脚本使用
if (typeof module !== "undefined" && module.exports) {
module.exports = {
initPageLayout,
hideRightSidebar,
showRightSidebar,
};
}
// 同时也挂载到 window 对象,以便在浏览器环境中直接调用
if (typeof window !== 'undefined') {
window.rightSidebarLayout = {
initPageLayout,
hideRightSidebar,
showRightSidebar
};
}

View File

@@ -0,0 +1,536 @@
/**
* 主题切换综合性能优化器
*
* 整合功能:
* 1. 代码块主题切换优化Intersection Observer + 分批更新)
* 2. 重型元素优化临时禁用动画、隐藏屏幕外元素、GPU 加速)
*
* 核心优化策略:
* - 只更新可见代码块,延迟屏幕外代码块
* - 主题切换期间临时禁用重型元素动画和过渡
* - 强制 GPU 合成层,减少重绘重排
* - 使用 content-visibility 隐藏屏幕外元素
*/
class ThemeOptimizer {
constructor() {
// 代码块优化相关
this.visibleBlocks = new Set();
this.pendingThemeUpdate = null;
this.codeBlockObserver = null;
// 从配置中获取是否在主题切换时隐藏代码块的设置
this.hideCodeBlocksDuringTransition = true; // 默认值为true
this.initFromConfig();
// 性能优化相关
this.isOptimizing = false;
this.heavySelectors = [
".float-panel",
"#navbar",
".music-player",
"#mobile-toc-panel",
"#nav-menu-panel",
"#search-panel",
".dropdown-content",
".widget",
".post-card",
".custom-md",
];
this.init();
}
init() {
// 从配置中初始化
this.initFromConfig();
// 初始化代码块优化
this.initCodeBlockOptimization();
// 初始化主题切换拦截
this.interceptThemeSwitch();
// 应用代码块过渡行为设置
this.applyCodeBlockTransitionBehavior();
// 设置 Swup 钩子以确保在页面切换时重新初始化
this.setupSwupHooks();
// 通知其他组件主题优化器已准备就绪
document.dispatchEvent(new CustomEvent("themeOptimizerReady"));
}
// ==================== Swup 钩子设置 ====================
setupSwupHooks() {
// 设置 Swup 钩子的函数
const setupHooks = () => {
if (window.swup) {
// 监听 page:view 事件
window.swup.hooks.on("page:view", () => {
// 页面切换后重新初始化代码块优化
setTimeout(() => {
this.observeCodeBlocks();
this.applyCodeBlockTransitionBehavior();
// 确保主题切换样式正确应用
this.forceApplyThemeTransitionStyles();
}, 100);
});
// 监听 content:replace 事件(更早触发)
window.swup.hooks.on("content:replace", () => {
// 内容替换时也重新应用代码块过渡行为
setTimeout(() => {
this.applyCodeBlockTransitionBehavior();
// 确保主题切换样式正确应用
this.forceApplyThemeTransitionStyles();
}, 50);
});
return true;
}
return false;
};
// 尝试立即设置 Swup 钩子
if (!setupHooks()) {
// 如果 Swup 尚未初始化,等待它加载
document.addEventListener("swup:enable", () => {
setupHooks();
});
// 额外的延迟重试机制,确保捕获到 Swup
const retryInterval = setInterval(() => {
if (setupHooks()) {
clearInterval(retryInterval);
}
}, 100);
// 最多重试 20 次2 秒)
setTimeout(() => {
clearInterval(retryInterval);
}, 2000);
}
}
forceApplyThemeTransitionStyles() {
// 强制应用主题切换样式,确保在页面切换后也能正确工作
const codeBlocks = document.querySelectorAll(".expressive-code");
codeBlocks.forEach((block) => {
// 确保代码块有正确的类
if (this.hideCodeBlocksDuringTransition) {
block.classList.add("hide-during-transition");
} else {
block.classList.remove("hide-during-transition");
}
// 强制重新计算样式
void block.offsetWidth;
});
// 检查当前是否处于主题切换状态
const isTransitioning = document.documentElement.classList.contains(
"is-theme-transitioning",
);
if (isTransitioning) {
// 如果正在切换主题,确保样式立即应用
codeBlocks.forEach((block) => {
if (block.classList.contains("hide-during-transition")) {
block.style.setProperty("content-visibility", "hidden", "important");
block.style.setProperty("opacity", "0.99", "important");
}
});
} else {
// 如果不在切换状态,确保样式恢复正常
codeBlocks.forEach((block) => {
block.style.removeProperty("content-visibility");
block.style.removeProperty("opacity");
});
}
}
// ==================== 配置初始化 ====================
initFromConfig() {
try {
// 尝试从配置中获取设置
// 检查是否已经有从配置中传递的设置
const configCarrier = document.getElementById("config-carrier");
if (
configCarrier &&
configCarrier.dataset.hideCodeBlocksDuringTransition !== undefined
) {
this.hideCodeBlocksDuringTransition =
configCarrier.dataset.hideCodeBlocksDuringTransition === "true";
}
} catch (error) {
this.hideCodeBlocksDuringTransition = true; // 默认启用隐藏
}
}
applyCodeBlockTransitionBehavior() {
// 应用代码块在主题切换期间的行为设置
const codeBlocks = document.querySelectorAll(".expressive-code");
codeBlocks.forEach((block) => {
if (this.hideCodeBlocksDuringTransition) {
// 默认行为:添加类以便在主题切换时隐藏
block.classList.add("hide-during-transition");
} else {
// 如果配置为不隐藏,移除类
block.classList.remove("hide-during-transition");
}
});
// 确保临时样式表中的规则与当前设置一致
this.updateTempStyleSheet();
}
updateTempStyleSheet() {
// 如果临时样式表存在,更新其内容以反映当前设置
if (this.tempStyleSheet) {
// 获取当前内容
let content = this.tempStyleSheet.textContent;
// 更新代码块隐藏规则
const hideRule = `.is-theme-transitioning .expressive-code {
content-visibility: hidden !important;
/* 避免闪烁 */
opacity: 0.99;
}`;
const showRule = `.is-theme-transitioning .expressive-code:not(.hide-during-transition) {
/* 保持代码块可见,但禁用过渡效果 */
content-visibility: visible !important;
opacity: 1 !important;
}`;
// 检查是否已存在这些规则,如果不存在则添加
if (!content.includes(".is-theme-transitioning .expressive-code")) {
content += "\n" + hideRule + "\n" + showRule;
this.tempStyleSheet.textContent = content;
}
}
}
// ==================== 代码块优化 ====================
initCodeBlockOptimization() {
// 创建 Intersection Observer 追踪可见代码块
this.codeBlockObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
this.visibleBlocks.add(entry.target);
// 如果有待处理的主题更新,立即应用
if (this.pendingThemeUpdate) {
this.applyThemeToBlock(entry.target, this.pendingThemeUpdate);
}
} else {
this.visibleBlocks.delete(entry.target);
}
});
},
{
rootMargin: "50px 0px",
threshold: 0.01,
},
);
// 观察所有代码块
this.observeCodeBlocks();
// 监听主题变化
this.setupThemeListener();
// 页面变化时重新观察
if (window.swup) {
window.swup.hooks.on("page:view", () => {
setTimeout(() => this.observeCodeBlocks(), 100);
});
}
}
observeCodeBlocks() {
this.visibleBlocks.clear();
requestAnimationFrame(() => {
const codeBlocks = document.querySelectorAll(".expressive-code");
codeBlocks.forEach((block) => {
this.codeBlockObserver.observe(block);
// 根据配置设置代码块在主题切换时的行为
if (this.hideCodeBlocksDuringTransition) {
block.classList.add("hide-during-transition");
} else {
block.classList.remove("hide-during-transition");
}
});
});
}
setupThemeListener() {
// 监听 data-theme 属性变化
const themeObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "data-theme"
) {
const newTheme = document.documentElement.getAttribute("data-theme");
this.handleThemeChange(newTheme);
break;
}
}
});
themeObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ["data-theme"],
});
}
handleThemeChange(newTheme) {
this.pendingThemeUpdate = newTheme;
const visibleBlocksArray = Array.from(this.visibleBlocks);
if (visibleBlocksArray.length === 0) return;
// 分批更新可见代码块
this.batchUpdateBlocks(visibleBlocksArray, newTheme);
}
batchUpdateBlocks(blocks, theme) {
const batchSize = 3;
let currentIndex = 0;
const processBatch = () => {
const batch = blocks.slice(currentIndex, currentIndex + batchSize);
requestAnimationFrame(() => {
batch.forEach((block) => {
this.applyThemeToBlock(block, theme);
});
currentIndex += batchSize;
if (currentIndex < blocks.length) {
setTimeout(processBatch, 0);
}
});
};
processBatch();
}
applyThemeToBlock(block, theme) {
// 标记该代码块已更新
block.dataset.themeUpdated = theme;
}
// ==================== 重型元素优化 ====================
interceptThemeSwitch() {
// 监听 class 变化来拦截主题切换
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "class" &&
mutation.target === document.documentElement
) {
const classList = document.documentElement.classList;
const isTransitioning = classList.contains("is-theme-transitioning");
const useViewTransition = classList.contains("use-view-transition");
if (isTransitioning && !this.isOptimizing) {
this.optimizeThemeSwitch(useViewTransition);
} else if (!isTransitioning && this.isOptimizing) {
this.restoreAfterThemeSwitch(useViewTransition);
}
}
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
});
}
optimizeThemeSwitch(useViewTransition = false) {
this.isOptimizing = true;
this.useViewTransition = useViewTransition;
// 如果使用 View Transitions不需要额外的优化让浏览器处理
if (useViewTransition) {
return;
}
// 1. 临时禁用重型元素动画
this.disableHeavyAnimations();
// 2. 隐藏视口外的重型元素
this.hideOffscreenHeavyElements();
// 3. 强制 GPU 合成层
this.forceCompositing();
}
disableHeavyAnimations() {
if (!this.tempStyleSheet) {
this.tempStyleSheet = document.createElement("style");
this.tempStyleSheet.id = "theme-optimizer-temp";
document.head.appendChild(this.tempStyleSheet);
}
this.tempStyleSheet.textContent = `
/* 临时禁用重型元素的过渡和动画 */
.is-theme-transitioning .float-panel:not(.float-panel-closed),
.is-theme-transitioning .music-player,
.is-theme-transitioning .widget,
.is-theme-transitioning .post-card,
.is-theme-transitioning #navbar *,
.is-theme-transitioning .dropdown-content,
.is-theme-transitioning .custom-md * {
transition: none !important;
animation: none !important;
}
/* 强制隔离渲染上下文 */
.is-theme-transitioning .float-panel,
.is-theme-transitioning .post-card,
.is-theme-transitioning .widget {
contain: layout style paint !important;
}
/* 隐藏装饰性元素 */
.is-theme-transitioning .gradient-overlay,
.is-theme-transitioning .decoration,
.is-theme-transitioning .animation-element {
visibility: hidden !important;
}
/* 在主题切换期间临时隐藏代码块以提升性能 */
/* 这个行为可以通过配置文件中的 expressiveCodeConfig.hideDuringThemeTransition 控制 */
.is-theme-transitioning .expressive-code {
content-visibility: hidden !important;
/* 避免闪烁 */
opacity: 0.99;
}
/* 当禁用隐藏代码块功能时通过JavaScript动态控制 */
.is-theme-transitioning .expressive-code:not(.hide-during-transition) {
/* 保持代码块可见,但禁用过渡效果 */
content-visibility: visible !important;
opacity: 1 !important;
}
/* 确保打开的TOC面板在主题切换期间保持可点击 */
.is-theme-transitioning .float-panel:not(.float-panel-closed) {
pointer-events: auto !important;
}
`;
}
hideOffscreenHeavyElements() {
const viewportHeight = window.innerHeight;
const scrollTop = window.scrollY;
this.hiddenElements = [];
this.heavySelectors.forEach((selector) => {
const elements = document.querySelectorAll(selector);
elements.forEach((element) => {
const rect = element.getBoundingClientRect();
const elementTop = rect.top + scrollTop;
const elementBottom = elementTop + rect.height;
// 完全在视口外增加200px边距
if (
elementBottom < scrollTop - 200 ||
elementTop > scrollTop + viewportHeight + 200
) {
const originalVisibility = element.style.contentVisibility;
element.style.contentVisibility = "hidden";
this.hiddenElements.push({ element, originalVisibility });
}
});
});
}
forceCompositing() {
const criticalElements = document.querySelectorAll(`
.expressive-code,
.post-card,
.widget,
#navbar
`);
this.compositedElements = [];
criticalElements.forEach((element) => {
const original = element.style.transform;
element.style.transform = "translateZ(0)";
element.style.willChange = "transform";
this.compositedElements.push({ element, original });
});
}
restoreAfterThemeSwitch(useViewTransition = false) {
this.isOptimizing = false;
// 如果使用 View Transitions直接清理即可
if (useViewTransition) {
this.useViewTransition = false;
return;
}
// 延迟恢复,确保主题切换完全完成
requestAnimationFrame(() => {
requestAnimationFrame(() => {
// 移除临时样式表
if (this.tempStyleSheet && this.tempStyleSheet.parentNode) {
this.tempStyleSheet.remove();
this.tempStyleSheet = null;
}
// 恢复隐藏的元素
if (this.hiddenElements) {
this.hiddenElements.forEach(({ element, originalVisibility }) => {
element.style.contentVisibility = originalVisibility || "";
});
this.hiddenElements = null;
}
// 恢复合成层设置
if (this.compositedElements) {
this.compositedElements.forEach(({ element, original }) => {
element.style.transform = original || "";
element.style.willChange = "";
});
this.compositedElements = null;
}
});
});
}
// 清理资源
destroy() {
if (this.codeBlockObserver) {
this.codeBlockObserver.disconnect();
}
this.visibleBlocks.clear();
}
}
// 初始化优化器
const themeOptimizer = new ThemeOptimizer();
// 导出到全局统一API
window.themeOptimizer = themeOptimizer;