feat: 新增代码块增强组件(支持复制与语言标签)
This commit is contained in:
parent
d79e66facc
commit
5e9220302c
71
src/components/CodeBlockHelper.astro
Normal file
71
src/components/CodeBlockHelper.astro
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
// 此组件不渲染任何 HTML,仅注入全局客户端脚本
|
||||||
|
---
|
||||||
|
<script>
|
||||||
|
function upgradeCodeBlocks() {
|
||||||
|
const codeBlocks = document.querySelectorAll('pre');
|
||||||
|
|
||||||
|
codeBlocks.forEach((pre) => {
|
||||||
|
// 防止重复注入
|
||||||
|
if (pre.querySelector('.copy-button')) return;
|
||||||
|
|
||||||
|
// 1. 获取语言名称 (从 rehype-pretty-code 自动生成的属性中获取)
|
||||||
|
const lang = pre.getAttribute('data-language') || 'code';
|
||||||
|
|
||||||
|
// 2. 创建包裹容器并调整 pre 样式
|
||||||
|
pre.classList.add('relative', 'group');
|
||||||
|
|
||||||
|
// 3. 创建顶栏 (语言标签 + 复制按钮)
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.className = "absolute top-0 right-0 left-0 flex justify-between items-center px-4 py-1.5 text-[10px] font-mono font-bold uppercase tracking-widest text-gray-400 bg-gray-800/50 border-b border-gray-700/50 rounded-t-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300";
|
||||||
|
header.innerHTML = `
|
||||||
|
<span class="flex items-center gap-1.5"><span class="w-2 h-2 rounded-full bg-blue-500"></span>${lang}</span>
|
||||||
|
<button class="copy-button hover:text-white transition-colors cursor-pointer flex items-center gap-1">
|
||||||
|
<span class="btn-text">COPY</span>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 4. 注入到 pre 头部
|
||||||
|
pre.prepend(header);
|
||||||
|
// 增加 padding 给 header 留位
|
||||||
|
pre.style.paddingTop = '2.5rem';
|
||||||
|
|
||||||
|
// 5. 绑定点击事件
|
||||||
|
const btn = header.querySelector('.copy-button');
|
||||||
|
const btnText = header.querySelector('.btn-text');
|
||||||
|
|
||||||
|
btn?.addEventListener('click', async () => {
|
||||||
|
const code = pre.querySelector('code')?.innerText || "";
|
||||||
|
await navigator.clipboard.writeText(code);
|
||||||
|
|
||||||
|
if (btnText) {
|
||||||
|
btnText.innerText = "COPIED!";
|
||||||
|
btn.classList.add('text-green-400');
|
||||||
|
setTimeout(() => {
|
||||||
|
btnText.innerText = "COPY";
|
||||||
|
btn.classList.remove('text-green-400');
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
document.addEventListener('astro:page-load', upgradeCodeBlocks);
|
||||||
|
upgradeCodeBlocks();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
/* 优化代码块圆角与阴影 */
|
||||||
|
pre {
|
||||||
|
@apply rounded-xl shadow-2xl border border-gray-800/50 !important;
|
||||||
|
}
|
||||||
|
/* 隐藏原有的滚动条,美化自定义滚动条 */
|
||||||
|
pre::-webkit-scrollbar {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
pre::-webkit-scrollbar-thumb {
|
||||||
|
background: #374151;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user