将代码高亮改为astro集成配置,mermaid改为客户端生成,优化导航栏样式,将地图数据动态导入
This commit is contained in:
parent
af0dee8d1d
commit
d3e0eddff7
@ -14,7 +14,6 @@ import { SITE_URL } from "./src/consts";
|
||||
import compressor from "astro-compressor";
|
||||
import vercel from "@astrojs/vercel";
|
||||
import { articleIndexerIntegration } from "./src/plugins/build-article-index.js";
|
||||
import customCodeBlocksIntegration from "./src/plugins/custom-code-blocks.js";
|
||||
|
||||
function getArticleDate(articleId) {
|
||||
try {
|
||||
@ -52,21 +51,15 @@ export default defineConfig({
|
||||
},
|
||||
|
||||
integrations: [
|
||||
// 使用我们自己的代码块集成替代expressiveCode
|
||||
customCodeBlocksIntegration(),
|
||||
|
||||
// MDX 集成配置
|
||||
// 使用Astro官方的MDX支持
|
||||
mdx(),
|
||||
swup({
|
||||
cache: true,
|
||||
preload: true,
|
||||
}
|
||||
|
||||
),
|
||||
}),
|
||||
react(),
|
||||
// 使用我们自己的文章索引生成器(替换pagefind)
|
||||
// 使用文章索引生成器
|
||||
articleIndexerIntegration(),
|
||||
|
||||
sitemap({
|
||||
filter: (page) => !page.includes("/api/"),
|
||||
serialize(item) {
|
||||
@ -109,9 +102,24 @@ export default defineConfig({
|
||||
compressor()
|
||||
],
|
||||
|
||||
// Markdown 配置
|
||||
// Markdown 配置 - 使用官方语法高亮
|
||||
markdown: {
|
||||
syntaxHighlight: false, // 禁用默认的语法高亮,使用我们自定义的高亮
|
||||
// 配置语法高亮
|
||||
syntaxHighlight: {
|
||||
// 使用shiki作为高亮器
|
||||
type: 'shiki',
|
||||
// 排除mermaid语言,不进行高亮处理
|
||||
excludeLangs: ['mermaid']
|
||||
},
|
||||
// Shiki主题配置
|
||||
shikiConfig: {
|
||||
theme: 'github-light',
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark'
|
||||
},
|
||||
wrap: true
|
||||
},
|
||||
remarkPlugins: [
|
||||
[remarkEmoji, { emoticon: false, padded: true }]
|
||||
],
|
||||
@ -119,13 +127,6 @@ export default defineConfig({
|
||||
[rehypeExternalLinks, { target: '_blank', rel: ['nofollow', 'noopener', 'noreferrer'] }]
|
||||
],
|
||||
gfm: true,
|
||||
// 设置 remark-rehype 选项,以控制HTML处理
|
||||
remarkRehype: {
|
||||
// 保留原始HTML格式,但仅在非代码块区域
|
||||
allowDangerousHtml: true,
|
||||
// 确保代码块内容不被解析
|
||||
passThrough: ['code']
|
||||
},
|
||||
},
|
||||
|
||||
adapter: vercel(),
|
||||
|
11
package-lock.json
generated
11
package-lock.json
generated
@ -25,7 +25,7 @@
|
||||
"astro": "^5.7.5",
|
||||
"astro-expressive-code": "^0.41.2",
|
||||
"cheerio": "^1.0.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"mermaid": "^11.6.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"octokit": "^4.1.3",
|
||||
"puppeteer": "^23.11.1",
|
||||
@ -9955,15 +9955,6 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/highlight.js": {
|
||||
"version": "11.11.1",
|
||||
"resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.11.1.tgz",
|
||||
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/html-escaper/-/html-escaper-3.0.3.tgz",
|
||||
|
@ -26,7 +26,7 @@
|
||||
"astro": "^5.7.5",
|
||||
"astro-expressive-code": "^0.41.2",
|
||||
"cheerio": "^1.0.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"mermaid": "^11.6.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"octokit": "^4.1.3",
|
||||
"puppeteer": "^23.11.1",
|
||||
|
@ -29,7 +29,7 @@ const breadcrumbs: Breadcrumb[] = pathSegments
|
||||
});
|
||||
---
|
||||
|
||||
<div class="flex items-center justify-between w-full flex-wrap sm:flex-nowrap" transition:persist transition:name="breadcrumb">
|
||||
<div class="flex items-center justify-between w-full flex-wrap sm:flex-nowrap">
|
||||
<div class="flex items-center text-sm overflow-hidden">
|
||||
<!-- 文章列表链接 - 根据当前页面类型决定链接 -->
|
||||
<a href={'/articles/'} class="text-secondary-600 dark:text-secondary-400 hover:text-primary-600 dark:hover:text-primary-400 flex items-center flex-shrink-0">
|
||||
|
@ -57,7 +57,7 @@ let secondaryHighlightStyle = activeSubItem ? "opacity: 1;" : "opacity: 0;";
|
||||
const activeClass = "font-medium";
|
||||
const itemClass = "px-4 py-2 text-sm font-medium";
|
||||
const primaryHighlightClass = "bg-primary-100 dark:bg-primary-800/30 rounded-xl shadow-md backdrop-blur-sm";
|
||||
const secondaryHighlightClass = "bg-primary-300/80 dark:bg-primary-700/60 rounded-md shadow-md backdrop-blur-sm";
|
||||
const secondaryHighlightClass = "bg-primary-300/80 dark:bg-primary-700/60 rounded-xl shadow-md backdrop-blur-sm";
|
||||
const transitionDuration = 300;
|
||||
const navSelectorClassName = "mr-4";
|
||||
---
|
||||
@ -98,7 +98,7 @@ const navSelectorClassName = "mr-4";
|
||||
class={`absolute z-0 hover:shadow-lg rounded-xl ${primaryHighlightClass}`}
|
||||
style={primaryHighlightStyle}></div>
|
||||
<div id="nav-secondary-highlight"
|
||||
class={`absolute z-10 hover:shadow-lg rounded-md ${secondaryHighlightClass}`}
|
||||
class={`absolute z-10 hover:shadow-lg rounded-xl ${secondaryHighlightClass}`}
|
||||
style={secondaryHighlightStyle}></div>
|
||||
|
||||
<!-- 导航菜单项 -->
|
||||
@ -130,7 +130,7 @@ const navSelectorClassName = "mr-4";
|
||||
|
||||
<!-- 二级菜单容器 -->
|
||||
<div class={`nav-group-items relative min-w-full ${activeGroupId === item.id ? 'menu-visible' : 'hidden'}`}>
|
||||
<div class="flex flex-row flex-wrap gap-2 justify-center items-center">
|
||||
<div class="flex flex-row flex-wrap justify-center items-center">
|
||||
{item.items.map((subItem) => (
|
||||
<a
|
||||
href={subItem.href}
|
||||
|
@ -165,9 +165,7 @@ const {
|
||||
|
||||
// 立即设置文档主题,在DOM渲染前应用,避免闪烁
|
||||
document.documentElement.dataset.theme = theme;
|
||||
// 确保同步classList,提高兼容性
|
||||
document.documentElement.classList.toggle('dark', theme === 'dark');
|
||||
|
||||
|
||||
// 监听系统主题变化(只有当主题设为跟随系统时才响应)
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
@ -176,7 +174,6 @@ const {
|
||||
if (!localStorage.getItem("theme")) {
|
||||
const newTheme = e.matches ? "dark" : "light";
|
||||
document.documentElement.dataset.theme = newTheme;
|
||||
document.documentElement.classList.toggle('dark', e.matches);
|
||||
}
|
||||
};
|
||||
|
||||
@ -191,11 +188,9 @@ const {
|
||||
// 重新初始化主题
|
||||
if (storedTheme) {
|
||||
document.documentElement.dataset.theme = storedTheme;
|
||||
document.documentElement.classList.toggle('dark', storedTheme === 'dark');
|
||||
} else {
|
||||
const systemTheme = getSystemTheme();
|
||||
document.documentElement.dataset.theme = systemTheme;
|
||||
document.documentElement.classList.toggle('dark', systemTheme === 'dark');
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,7 +201,6 @@ const {
|
||||
} catch (error) {
|
||||
// 出错时应用默认浅色主题,确保页面正常显示
|
||||
document.documentElement.dataset.theme = "light";
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
@ -454,7 +454,7 @@ const {
|
||||
callback();
|
||||
|
||||
// 确保DOM已更新
|
||||
document.documentElement.classList.toggle('dark', toTheme === 'dark');
|
||||
document.documentElement.dataset.theme = toTheme;
|
||||
});
|
||||
|
||||
// 生成动画需要的SVG资源
|
||||
@ -632,10 +632,6 @@ const {
|
||||
} else {
|
||||
document.documentElement.dataset.theme = "light";
|
||||
}
|
||||
|
||||
// 确保同步类名
|
||||
document.documentElement.classList.toggle('dark',
|
||||
document.documentElement.dataset.theme === 'dark');
|
||||
};
|
||||
|
||||
// 切换主题
|
||||
@ -714,7 +710,6 @@ const {
|
||||
if (!localStorage.getItem("theme")) {
|
||||
const newTheme = e.matches ? "dark" : "light";
|
||||
document.documentElement.dataset.theme = newTheme;
|
||||
document.documentElement.classList.toggle('dark', e.matches);
|
||||
}
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,10 @@ tags: []
|
||||
3. 如果变量没有使用可以前置下划线,消除警告
|
||||
4. 强制类型转换
|
||||
|
||||
```rust
|
||||
let a = 3.1;let b = a as i32
|
||||
```
|
||||
|
||||
5. 打印变量
|
||||
|
||||
```rust
|
||||
|
@ -4,7 +4,7 @@ import { getSpecialPath } from "@/content.config";
|
||||
import Layout from "@/components/Layout.astro";
|
||||
import Breadcrumb from "@/components/Breadcrumb.astro";
|
||||
import { ARTICLE_EXPIRY_CONFIG } from "@/consts";
|
||||
import "@/styles/content-styles.css";
|
||||
import "@/styles/articles.css";
|
||||
|
||||
// 定义文章类型
|
||||
interface ArticleEntry {
|
||||
@ -499,106 +499,197 @@ const tableOfContents = generateTableOfContents(headings);
|
||||
|
||||
listeners.length = 0;
|
||||
}
|
||||
|
||||
// 1. 应用高亮代码
|
||||
function applyCodeHighlighting() {
|
||||
const codeElements = document.querySelectorAll('code[data-highlighted]');
|
||||
|
||||
codeElements.forEach(codeElement => {
|
||||
const highlightedCode = codeElement.getAttribute('data-highlighted');
|
||||
if (highlightedCode) {
|
||||
codeElement.innerHTML = highlightedCode;
|
||||
codeElement.removeAttribute('data-highlighted');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 加载Mermaid SVG内容
|
||||
function loadMermaidSvg() {
|
||||
const mermaidContainers = document.querySelectorAll('.mermaid-figure [data-mermaid-src], .mermaid-svg-container[data-mermaid-src]');
|
||||
// 1. 增强代码块功能 - 添加标题栏、语言显示和复制按钮
|
||||
function enhanceCodeBlocks() {
|
||||
// 查找所有代码块元素
|
||||
const codeBlocks = document.querySelectorAll('pre > code');
|
||||
if (codeBlocks.length === 0) return;
|
||||
|
||||
mermaidContainers.forEach(container => {
|
||||
const svgSrc = container.getAttribute('data-mermaid-src');
|
||||
if (svgSrc) {
|
||||
fetch(svgSrc)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('SVG加载失败: ' + response.status);
|
||||
}
|
||||
return response.text();
|
||||
})
|
||||
.then(svgContent => {
|
||||
// 直接插入SVG内容,而不是作为图像
|
||||
container.innerHTML = svgContent;
|
||||
|
||||
// 确保SVG元素正确应用样式
|
||||
const svgElement = container.querySelector('svg');
|
||||
if (svgElement) {
|
||||
// 设置高度为auto以允许CSS控制
|
||||
svgElement.setAttribute('height', 'auto');
|
||||
|
||||
// 确保viewBox属性存在并正确设置
|
||||
if (!svgElement.hasAttribute('viewBox') ||
|
||||
!svgElement.getAttribute('viewBox')?.match(/^\d+\s+\d+\s+\d+\s+\d+$/)) {
|
||||
// 如果没有有效的viewBox,尝试从宽高创建一个
|
||||
const width = svgElement.getAttribute('width');
|
||||
const height = svgElement.getAttribute('height');
|
||||
if (width && height && !isNaN(parseFloat(width)) && !isNaN(parseFloat(height))) {
|
||||
svgElement.setAttribute('viewBox', `0 0 ${parseFloat(width)} ${parseFloat(height)}`);
|
||||
} else {
|
||||
// 使用默认viewBox
|
||||
svgElement.setAttribute('viewBox', '0 0 100 100');
|
||||
}
|
||||
}
|
||||
|
||||
// 确保具有mermaid-svg类
|
||||
svgElement.classList.add('mermaid-svg');
|
||||
}
|
||||
|
||||
// 移除data属性避免重复加载
|
||||
container.removeAttribute('data-mermaid-src');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('加载SVG失败:', error);
|
||||
container.innerHTML = '<div class="mermaid-error-message">图表加载失败</div>';
|
||||
});
|
||||
codeBlocks.forEach(codeBlock => {
|
||||
const pre = codeBlock.parentElement;
|
||||
// 如果已经处理过,跳过
|
||||
if (pre.parentElement.classList.contains('code-block-container')) return;
|
||||
|
||||
// 获取语言类 - 简化语言提取逻辑
|
||||
let language = '';
|
||||
|
||||
// 从data-language属性中提取(最常见的方式)
|
||||
language = pre.getAttribute('data-language') || codeBlock.getAttribute('data-language') || '';
|
||||
|
||||
// 如果没有找到语言,则默认为 'text'
|
||||
if (!language || language === 'mermaid') {
|
||||
// 跳过 mermaid 图表
|
||||
if (language === 'mermaid') return;
|
||||
language = 'text';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. 处理代码复制功能
|
||||
function setupCodeCopy() {
|
||||
const handleCopyClick = (e) => {
|
||||
const target = e.target;
|
||||
const copyButton = target.closest('[data-copy]');
|
||||
if (!copyButton) return;
|
||||
|
||||
const container = copyButton.closest('.code-block-container');
|
||||
if (!container) return;
|
||||
// 获取原始代码文本,保留换行和格式
|
||||
let originalCode = '';
|
||||
const hasLineElements = codeBlock.querySelectorAll('.line').length > 0 ||
|
||||
codeBlock.innerHTML.includes('<span class="line">');
|
||||
|
||||
const codeElement = container.querySelector('pre code');
|
||||
if (!codeElement) return;
|
||||
if (hasLineElements) {
|
||||
// 从行元素中提取文本
|
||||
const lines = codeBlock.querySelectorAll('.line');
|
||||
if (lines.length > 0) {
|
||||
originalCode = Array.from(lines)
|
||||
.map(line => line.textContent)
|
||||
.join('\n');
|
||||
} else {
|
||||
// 尝试解析HTML中的行
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = codeBlock.innerHTML;
|
||||
const lineSpans = tempDiv.querySelectorAll('.line');
|
||||
originalCode = Array.from(lineSpans)
|
||||
.map(span => span.textContent)
|
||||
.join('\n');
|
||||
}
|
||||
} else {
|
||||
// 直接使用textContent (这种情况下可能没有特殊格式化)
|
||||
originalCode = codeBlock.textContent || '';
|
||||
}
|
||||
|
||||
const code = codeElement.textContent || '';
|
||||
// 创建代码块容器
|
||||
const container = document.createElement('div');
|
||||
container.className = 'code-block-container';
|
||||
|
||||
navigator.clipboard.writeText(code)
|
||||
.then(() => {
|
||||
const originalText = copyButton.textContent || '';
|
||||
copyButton.textContent = '已复制!';
|
||||
copyButton.disabled = true;
|
||||
// 创建标题栏
|
||||
const header = document.createElement('div');
|
||||
header.className = 'code-block-header';
|
||||
|
||||
// 语言标签
|
||||
const langDiv = document.createElement('div');
|
||||
langDiv.className = 'code-block-lang';
|
||||
langDiv.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="16 18 22 12 16 6"></polyline>
|
||||
<polyline points="8 6 2 12 8 18"></polyline>
|
||||
</svg>
|
||||
${language.toUpperCase()}
|
||||
`;
|
||||
|
||||
// 复制按钮
|
||||
const copyButton = document.createElement('button');
|
||||
copyButton.className = 'code-block-copy';
|
||||
copyButton.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
复制
|
||||
`;
|
||||
|
||||
// 代码内容容器
|
||||
const codeContent = document.createElement('div');
|
||||
codeContent.className = 'code-block-content';
|
||||
|
||||
// 添加复制功能
|
||||
addListener(copyButton, 'click', async () => {
|
||||
try {
|
||||
// 使用优化后的方法获取代码文本
|
||||
await navigator.clipboard.writeText(originalCode);
|
||||
copyButton.classList.add('copied');
|
||||
copyButton.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
|
||||
<path d="M20 6L9 17l-5-5"></path>
|
||||
</svg>
|
||||
已复制
|
||||
`;
|
||||
|
||||
setTimeout(() => {
|
||||
copyButton.textContent = originalText;
|
||||
copyButton.disabled = false;
|
||||
copyButton.classList.remove('copied');
|
||||
copyButton.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
复制
|
||||
`;
|
||||
}, 2000);
|
||||
})
|
||||
.catch(err => {
|
||||
} catch (err) {
|
||||
console.error('复制失败:', err);
|
||||
alert('复制失败,请手动复制');
|
||||
});
|
||||
};
|
||||
|
||||
addListener(document, 'click', handleCopyClick);
|
||||
copyButton.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="8" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
||||
</svg>
|
||||
失败
|
||||
`;
|
||||
setTimeout(() => {
|
||||
copyButton.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
复制
|
||||
`;
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// 组装标题栏
|
||||
header.appendChild(langDiv);
|
||||
header.appendChild(copyButton);
|
||||
|
||||
// 添加行号
|
||||
const preHasLineNumbers = pre.classList.contains('line-numbers') || pre.classList.contains('has-line-numbers');
|
||||
|
||||
// 不改变原有结构,只在外层包装
|
||||
// 保留原有的代码块,将其移入新容器
|
||||
pre.parentNode.insertBefore(container, pre);
|
||||
container.appendChild(header);
|
||||
container.appendChild(codeContent);
|
||||
codeContent.appendChild(pre);
|
||||
|
||||
// 始终添加行号 - 修改此部分,确保所有代码块都有行号
|
||||
if (!preHasLineNumbers) {
|
||||
pre.classList.add('line-numbers');
|
||||
|
||||
// 如果代码块内部没有行号结构,则添加
|
||||
const hasLineElements = codeBlock.querySelectorAll('.line').length > 0 ||
|
||||
codeBlock.innerHTML.includes('<span class="line">');
|
||||
|
||||
if (!hasLineElements) {
|
||||
// 特殊处理已经高亮的代码,防止破坏高亮效果
|
||||
const isPreHighlighted = codeBlock.innerHTML.includes('span style=') ||
|
||||
pre.classList.contains('shiki') ||
|
||||
pre.classList.contains('astro-code');
|
||||
|
||||
if (isPreHighlighted) {
|
||||
// 已经高亮的代码,只添加行号类,不修改结构
|
||||
// 在这种情况下依赖CSS来显示行号,而不是修改DOM结构
|
||||
return;
|
||||
}
|
||||
|
||||
// 只处理未高亮的代码块
|
||||
// 将代码按行分割
|
||||
const lines = originalCode.split('\n');
|
||||
let newHtml = '';
|
||||
|
||||
// 优化行处理,确保正确处理行内容
|
||||
lines.forEach((line, index) => {
|
||||
// 避免末尾空行
|
||||
if (index === lines.length - 1 && line.trim() === '') return;
|
||||
|
||||
// 处理HTML实体,防止XSS并保留格式
|
||||
const escapedLine = line
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
|
||||
// 添加行标记(不添加换行符)
|
||||
newHtml += `<span class="line">${escapedLine}</span>`;
|
||||
});
|
||||
|
||||
// 更新代码块内容,仅在有内容时更新
|
||||
if (newHtml) {
|
||||
codeBlock.innerHTML = newHtml;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 4. 设置阅读进度条
|
||||
@ -655,7 +746,7 @@ const tableOfContents = generateTableOfContents(headings);
|
||||
|
||||
updateReadingProgress();
|
||||
}
|
||||
|
||||
|
||||
// 5. 管理目录交互
|
||||
function setupTableOfContents() {
|
||||
const tocContent = document.getElementById("toc-content");
|
||||
@ -773,24 +864,137 @@ const tableOfContents = generateTableOfContents(headings);
|
||||
updateActiveHeading();
|
||||
}
|
||||
|
||||
// 6. 处理Mermaid图表渲染
|
||||
function setupMermaid() {
|
||||
// 查找所有mermaid代码块 - 支持多种可能的类名和选择器
|
||||
const mermaidBlocks = document.querySelectorAll(
|
||||
'pre.language-mermaid, pre > code.language-mermaid, .mermaid'
|
||||
);
|
||||
|
||||
if (mermaidBlocks.length === 0) return;
|
||||
|
||||
console.log('找到Mermaid代码块:', mermaidBlocks.length);
|
||||
|
||||
// 动态加载mermaid库
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js';
|
||||
|
||||
script.onload = function() {
|
||||
console.log('Mermaid库加载完成,开始渲染图表');
|
||||
|
||||
// 初始化mermaid配置 - 始终使用默认主题,通过CSS控制样式
|
||||
window.mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
theme: 'default',
|
||||
securityLevel: 'loose'
|
||||
});
|
||||
|
||||
// 将所有mermaid代码块转换为可渲染的格式
|
||||
mermaidBlocks.forEach((block, index) => {
|
||||
// 获取mermaid代码
|
||||
let code = '';
|
||||
|
||||
// 检查元素类型并相应处理
|
||||
if (block.tagName === 'CODE' && block.classList.contains('language-mermaid')) {
|
||||
// 处理 code.language-mermaid 元素
|
||||
code = block.textContent || '';
|
||||
const pre = block.closest('pre');
|
||||
if (pre) {
|
||||
// 创建新的div元素替换整个pre
|
||||
const div = document.createElement('div');
|
||||
div.className = 'mermaid';
|
||||
div.id = 'mermaid-diagram-' + index;
|
||||
div.textContent = code;
|
||||
pre.parentNode.replaceChild(div, pre);
|
||||
}
|
||||
} else if (block.tagName === 'PRE' && block.classList.contains('language-mermaid')) {
|
||||
// 处理 pre.language-mermaid 元素
|
||||
code = block.textContent || '';
|
||||
const div = document.createElement('div');
|
||||
div.className = 'mermaid';
|
||||
div.id = 'mermaid-diagram-' + index;
|
||||
div.textContent = code;
|
||||
block.parentNode.replaceChild(div, block);
|
||||
} else if (block.classList.contains('mermaid') && block.tagName !== 'DIV') {
|
||||
// 如果是其他带mermaid类的元素但不是div,转换为div
|
||||
code = block.textContent || '';
|
||||
const div = document.createElement('div');
|
||||
div.className = 'mermaid';
|
||||
div.id = 'mermaid-diagram-' + index;
|
||||
div.textContent = code;
|
||||
block.parentNode.replaceChild(div, block);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化渲染
|
||||
try {
|
||||
console.log('开始渲染Mermaid图表');
|
||||
window.mermaid.run().catch(err => {
|
||||
console.error('Mermaid渲染出错:', err);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('初始化Mermaid渲染失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
script.onerror = function() {
|
||||
console.error('加载Mermaid库失败');
|
||||
// 显示错误信息
|
||||
mermaidBlocks.forEach(block => {
|
||||
if (block.tagName === 'CODE') block = block.closest('pre');
|
||||
if (block) {
|
||||
block.innerHTML = '<div class="mermaid-error-message">无法加载Mermaid图表库</div>';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
document.head.appendChild(script);
|
||||
|
||||
// 添加到清理列表,确保后续页面跳转时能删除脚本
|
||||
listeners.push({
|
||||
element: script,
|
||||
eventType: 'remove',
|
||||
handler: () => {
|
||||
if (script.parentNode) {
|
||||
script.parentNode.removeChild(script);
|
||||
}
|
||||
|
||||
// 清除全局mermaid对象
|
||||
if (window.mermaid) {
|
||||
window.mermaid = undefined;
|
||||
}
|
||||
|
||||
// 移除页面上可能留下的mermaid相关元素
|
||||
try {
|
||||
// 移除所有可能的mermaid样式和元素
|
||||
const mermaidElements = [
|
||||
'#mermaid-style',
|
||||
'#mermaid-cloned-styles',
|
||||
'.mermaid-svg-reference',
|
||||
'style[id^="mermaid-"]'
|
||||
];
|
||||
|
||||
document.querySelectorAll(mermaidElements.join(', ')).forEach(el => {
|
||||
if (el && el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('清理Mermaid元素时出错:', e);
|
||||
}
|
||||
},
|
||||
options: null
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化所有功能
|
||||
function init() {
|
||||
if (!document.querySelector("article")) return;
|
||||
|
||||
// 应用代码高亮
|
||||
applyCodeHighlighting();
|
||||
|
||||
// 加载Mermaid SVG图表
|
||||
loadMermaidSvg();
|
||||
|
||||
// 设置代码复制功能
|
||||
setupCodeCopy();
|
||||
|
||||
// 设置阅读进度条
|
||||
enhanceCodeBlocks(); // 添加新的代码块增强函数
|
||||
setupProgressBar();
|
||||
|
||||
// 设置目录交互
|
||||
setupTableOfContents();
|
||||
setupMermaid();
|
||||
}
|
||||
|
||||
// 注册清理函数
|
||||
|
File diff suppressed because it is too large
Load Diff
200
src/styles/articles-code.css
Normal file
200
src/styles/articles-code.css
Normal file
@ -0,0 +1,200 @@
|
||||
/* 代码块容器样式 - 简化背景和阴影 */
|
||||
.code-block-container {
|
||||
margin: 1rem 0;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e2e8f0;
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 代码块标题栏 */
|
||||
.code-block-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.4rem 0.8rem;
|
||||
background-color: #f1f5f9;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* 代码语言标签 */
|
||||
.code-block-lang {
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.code-block-lang svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
/* 复制按钮 */
|
||||
.code-block-copy {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #475569;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.code-block-copy:hover {
|
||||
background-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.code-block-copy.copied {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
/* 代码内容容器 - 移除背景 */
|
||||
.code-block-content {
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 基础代码块样式 - 减小内边距 */
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0.2rem 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.5rem;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 行号样式 - 缩小间距 */
|
||||
.line-numbers {
|
||||
counter-reset: line;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 行号背景条 - 减小宽度 */
|
||||
.line-numbers::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 3rem;
|
||||
background-color: #f1f5f9;
|
||||
border-right: 1px solid #e2e8f0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 行样式 - 进一步减小行间距和缩进 */
|
||||
.line-numbers .line {
|
||||
position: relative;
|
||||
counter-increment: line;
|
||||
padding-left: 3.5rem;
|
||||
padding-right: 0.5rem;
|
||||
min-height: 1.5rem;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* 行号 - 调整位置 */
|
||||
.line-numbers .line::before {
|
||||
content: counter(line);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 3rem;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
color: #94a3b8;
|
||||
font-size: 0.95rem;
|
||||
user-select: none;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 暗色模式 */
|
||||
[data-theme='dark'] .code-block-container {
|
||||
border-color: #334155;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .code-block-header {
|
||||
background-color: #1e293b;
|
||||
border-bottom-color: #334155;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .code-block-lang {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .code-block-copy {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .code-block-copy:hover {
|
||||
background-color: #334155;
|
||||
}
|
||||
|
||||
/* 移除代码内容区域的黑暗模式背景 */
|
||||
[data-theme='dark'] .code-block-content {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 暗色模式行号样式 */
|
||||
[data-theme='dark'] .line-numbers::before {
|
||||
background-color: #1e293b;
|
||||
border-right-color: #334155;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .line-numbers .line::before {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
/* 兼容原有高亮 - 确保不添加背景 */
|
||||
[data-theme='dark'] .shiki,
|
||||
[data-theme='dark'] .shiki span {
|
||||
color: var(--shiki-dark) !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .astro-code,
|
||||
[data-theme='dark'] .astro-code span {
|
||||
color: var(--shiki-dark) !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 确保所有代码元素没有背景 */
|
||||
code, pre, .code-block-content,
|
||||
.code-block-content pre.shiki,
|
||||
.code-block-content pre.astro-code,
|
||||
.code-block-content pre code,
|
||||
.code-block-content pre code span,
|
||||
pre.shiki, pre.astro-code,
|
||||
.line, .line span {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 高亮行样式 - 仅保留边框而不添加背景 */
|
||||
.line.highlighted {
|
||||
border-left: 2px solid #eab308;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .line.highlighted {
|
||||
border-left: 2px solid #fbbf24;
|
||||
background-color: transparent !important;
|
||||
}
|
150
src/styles/articles-mermaid.css
Normal file
150
src/styles/articles-mermaid.css
Normal file
@ -0,0 +1,150 @@
|
||||
:root {
|
||||
--mermaid-text-color: #1e293b;
|
||||
--mermaid-bg-color: #ffffff;
|
||||
--mermaid-primary-color: #4f46e5;
|
||||
--mermaid-secondary-color: #6366f1;
|
||||
--mermaid-border-color: #9ca3af;
|
||||
--mermaid-line-color: #4b5563;
|
||||
--mermaid-edge-label-bg: #ffffff;
|
||||
--mermaid-title-color: #0f172a;
|
||||
--mermaid-section-bg: #f8fafc;
|
||||
--mermaid-node-bg: #f1f5f9;
|
||||
}
|
||||
|
||||
/* 暗色模式样式变量 */
|
||||
[data-theme='dark'], .dark {
|
||||
--mermaid-text-color: #e2e8f0;
|
||||
--mermaid-bg-color: #1e293b;
|
||||
--mermaid-primary-color: #818cf8;
|
||||
--mermaid-secondary-color: #a5b4fc;
|
||||
--mermaid-border-color: #64748b;
|
||||
--mermaid-line-color: #94a3b8;
|
||||
--mermaid-edge-label-bg: #1e293b;
|
||||
--mermaid-title-color: #f8fafc;
|
||||
--mermaid-section-bg: #334155;
|
||||
--mermaid-node-bg: #475569;
|
||||
}
|
||||
|
||||
/* 基础Mermaid样式覆盖 */
|
||||
.mermaid {
|
||||
background-color: transparent !important;
|
||||
transition: color 0.3s ease, fill 0.3s ease, stroke 0.3s ease;
|
||||
}
|
||||
|
||||
/* Mermaid文本颜色统一 */
|
||||
.mermaid .label,
|
||||
.mermaid text,
|
||||
.mermaid span,
|
||||
.mermaid .messageText,
|
||||
.mermaid .loopText,
|
||||
.mermaid .noteText,
|
||||
.mermaid .taskText {
|
||||
color: var(--mermaid-text-color) !important;
|
||||
fill: var(--mermaid-text-color) !important;
|
||||
font-family: inherit !important;
|
||||
transition: color 0.3s ease, fill 0.3s ease;
|
||||
}
|
||||
|
||||
/* 节点样式设置 */
|
||||
.mermaid .node rect,
|
||||
.mermaid .node circle,
|
||||
.mermaid .node ellipse,
|
||||
.mermaid .node polygon,
|
||||
.mermaid .node path {
|
||||
fill: var(--mermaid-node-bg) !important;
|
||||
stroke: var(--mermaid-border-color) !important;
|
||||
stroke-width: 1px !important;
|
||||
transition: fill 0.3s ease, stroke 0.3s ease;
|
||||
}
|
||||
|
||||
/* 连接线样式 */
|
||||
.mermaid .edgePath .path,
|
||||
.mermaid .flowchart-link,
|
||||
.mermaid line,
|
||||
.mermaid .messageLine0,
|
||||
.mermaid .messageLine1 {
|
||||
stroke: var(--mermaid-line-color) !important;
|
||||
stroke-width: 1px !important;
|
||||
transition: stroke 0.3s ease;
|
||||
}
|
||||
|
||||
/* 箭头填充 */
|
||||
.mermaid .arrowheadPath,
|
||||
.mermaid marker path {
|
||||
fill: var(--mermaid-line-color) !important;
|
||||
stroke: none !important;
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
/* 文本标签背景 */
|
||||
.mermaid .edgeLabel rect,
|
||||
.mermaid .labelBox {
|
||||
fill: var(--mermaid-edge-label-bg) !important;
|
||||
background-color: var(--mermaid-edge-label-bg) !important;
|
||||
transition: fill 0.3s ease, background-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* 标题样式 */
|
||||
.mermaid .titleText,
|
||||
.mermaid .classTitle,
|
||||
.mermaid .cluster-label text {
|
||||
fill: var(--mermaid-title-color) !important;
|
||||
color: var(--mermaid-title-color) !important;
|
||||
font-weight: bold !important;
|
||||
transition: fill 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* 集群/子图样式 */
|
||||
.mermaid .cluster rect,
|
||||
.mermaid .cluster polygon {
|
||||
fill: var(--mermaid-section-bg) !important;
|
||||
stroke: var(--mermaid-border-color) !important;
|
||||
stroke-width: 1px !important;
|
||||
opacity: 0.8 !important;
|
||||
transition: fill 0.3s ease, stroke 0.3s ease;
|
||||
}
|
||||
|
||||
/* 序列图特殊样式 */
|
||||
.mermaid .actor {
|
||||
fill: var(--mermaid-node-bg) !important;
|
||||
stroke: var(--mermaid-border-color) !important;
|
||||
stroke-width: 1px !important;
|
||||
transition: fill 0.3s ease, stroke 0.3s ease;
|
||||
}
|
||||
|
||||
.mermaid .note {
|
||||
fill: var(--mermaid-secondary-color) !important;
|
||||
opacity: 0.7 !important;
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
/* 甘特图特殊样式 */
|
||||
.mermaid .section0,
|
||||
.mermaid .section2 {
|
||||
fill: var(--mermaid-section-bg) !important;
|
||||
opacity: 0.5 !important;
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
.mermaid .section1,
|
||||
.mermaid .section3 {
|
||||
fill: var(--mermaid-node-bg) !important;
|
||||
opacity: 0.4 !important;
|
||||
transition: fill 0.3s ease;
|
||||
}
|
||||
|
||||
.mermaid .task0,
|
||||
.mermaid .task1,
|
||||
.mermaid .task2,
|
||||
.mermaid .task3 {
|
||||
fill: var(--mermaid-primary-color) !important;
|
||||
stroke: var(--mermaid-border-color) !important;
|
||||
transition: fill 0.3s ease, stroke 0.3s ease;
|
||||
}
|
||||
|
||||
/* 类图特殊样式 */
|
||||
.mermaid .classLabel .label {
|
||||
fill: var(--mermaid-text-color) !important;
|
||||
color: var(--mermaid-text-color) !important;
|
||||
transition: fill 0.3s ease, color 0.3s ease;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
@import "./table-styles.css";
|
||||
@import "./code-blocks.css";
|
||||
@import "./mermaid-themes.css";
|
||||
@import "./articles-table.css";
|
||||
@import "./articles-mermaid.css";
|
||||
@import "./articles-code.css";
|
||||
|
||||
/* 增强列表样式 */
|
||||
.prose ul {
|
||||
@ -42,41 +42,6 @@
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* 行内代码样式 */
|
||||
.prose :not(pre) > code {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
color: var(--color-primary-700);
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 0.375em;
|
||||
font-weight: 500;
|
||||
font-family: "JetBrains Mono", Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
font-size: 0.875em;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
letter-spacing: -0.025em;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.prose :not(pre) > code:hover {
|
||||
background-color: rgba(var(--color-primary-600-rgb), 0.08);
|
||||
border-color: rgba(var(--color-primary-400-rgb), 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .prose :not(pre) > code {
|
||||
background-color: rgba(255, 255, 255, 0.07);
|
||||
color: var(--color-primary-300);
|
||||
border-color: rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .prose :not(pre) > code:hover {
|
||||
background-color: rgba(var(--color-primary-500-rgb), 0.15);
|
||||
border-color: rgba(var(--color-primary-300-rgb), 0.3);
|
||||
}
|
||||
|
||||
/* 标题样式 */
|
||||
.prose h1 {
|
||||
font-size: 2.25rem;
|
||||
@ -294,8 +259,7 @@
|
||||
.prose details > p,
|
||||
.prose details > ul,
|
||||
.prose details > ol,
|
||||
.prose details > div,
|
||||
.prose details > pre {
|
||||
.prose details > div {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
@ -1,537 +0,0 @@
|
||||
/* 代码块容器 */
|
||||
.code-block-container {
|
||||
margin: 1.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-block-container {
|
||||
background-color: #282a36;
|
||||
border-color: rgba(255,255,255,0.1);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* 标题栏 */
|
||||
.code-block-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #e2e8f0;
|
||||
border-bottom: 1px solid #cbd5e0;
|
||||
font-family: 'JetBrains Mono', Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-block-title {
|
||||
background-color: #343746;
|
||||
border-bottom: 1px solid #44475a;
|
||||
color: #f8f8f2;
|
||||
}
|
||||
|
||||
/* 标题栏左侧 */
|
||||
.code-title-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* 标题栏右侧 */
|
||||
.code-title-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 语言标识 */
|
||||
.code-language {
|
||||
text-transform: uppercase;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-language {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* 文件名 */
|
||||
.code-filename {
|
||||
margin-left: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
color: #4a5568;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-filename {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* 复制按钮 */
|
||||
.copy-button {
|
||||
background: transparent;
|
||||
border: 1px solid #a0aec0;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
cursor: pointer;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
background: #edf2f7;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .copy-button {
|
||||
border-color: #44475a;
|
||||
color: #f8f8f2;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .copy-button:hover {
|
||||
background: #44475a;
|
||||
}
|
||||
|
||||
/* 代码内容区 */
|
||||
.code-block-content {
|
||||
padding: 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.code-block-content pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
overflow: visible;
|
||||
font-family: 'JetBrains Mono', Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.code-block-content code {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* ----------------------- */
|
||||
/* 终端样式 */
|
||||
/* ----------------------- */
|
||||
|
||||
.terminal-container {
|
||||
background-color: #f8fafc;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid #adc2ff;
|
||||
box-shadow: 0 8px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
[data-theme="dark"] .terminal-container {
|
||||
background-color: #1a1e2a;
|
||||
border-color: rgba(255,255,255,0.1);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 终端标题栏 */
|
||||
.terminal-container .code-block-title {
|
||||
background-color: #f1f5f9;
|
||||
border-bottom: 1px solid #adc2ff;
|
||||
padding: 0.4rem 1rem;
|
||||
color: #334155;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .code-block-title {
|
||||
background-color: #111827;
|
||||
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||
color: #f8fafc;
|
||||
}
|
||||
|
||||
/* 终端控制按钮 */
|
||||
.terminal-controls {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.terminal-control {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.terminal-close {
|
||||
background-color: #f87171;
|
||||
}
|
||||
|
||||
.terminal-minimize {
|
||||
background-color: #fbbf24;
|
||||
}
|
||||
|
||||
.terminal-maximize {
|
||||
background-color: #34d399;
|
||||
}
|
||||
|
||||
/* 终端内容区 */
|
||||
.terminal-container .code-block-content {
|
||||
background-color: #f8fafc;
|
||||
color: #334155;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .code-block-content {
|
||||
background-color: #1a1e2a;
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.terminal-pre {
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-pre {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
/* 语言标签在终端样式中的颜色 */
|
||||
.terminal-container .code-language {
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .code-language {
|
||||
color: #a0aec0;
|
||||
}
|
||||
|
||||
/* 终端中的复制按钮 */
|
||||
.terminal-container .copy-button {
|
||||
border-color: #adc2ff;
|
||||
color: #4a5568;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-container .copy-button:hover {
|
||||
background: #ebf0ff;
|
||||
color: #4b6bff;
|
||||
border-color: #4b6bff;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .copy-button {
|
||||
border-color: rgba(255,255,255,0.3);
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .copy-button:hover {
|
||||
background: rgba(255,255,255,0.15);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* ----------------------- */
|
||||
/* Mermaid 图表样式 */
|
||||
/* ----------------------- */
|
||||
|
||||
.mermaid-figure {
|
||||
margin: 2rem auto;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mermaid-figure img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
/* 亮色主题图表 */
|
||||
.light-theme-diagram {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .light-theme-diagram {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 暗色主题图表 */
|
||||
.dark-theme-diagram {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .dark-theme-diagram {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Mermaid 错误样式 */
|
||||
.mermaid-error {
|
||||
border: 1px solid #e53e3e;
|
||||
background-color: #fff5f5;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-error {
|
||||
background-color: #3b1a1a;
|
||||
border-color: #fc8181;
|
||||
}
|
||||
|
||||
.mermaid-error-message {
|
||||
color: #c53030;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-error-message {
|
||||
color: #fc8181;
|
||||
}
|
||||
|
||||
/* ----------------------- */
|
||||
/* Highlight.js 主题样式 */
|
||||
/* ----------------------- */
|
||||
|
||||
/* 基本颜色方案 - 亮色 */
|
||||
.hljs {
|
||||
color: #1a202c;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs {
|
||||
color: #f8f8f2;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* 注释 */
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #718096;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-comment,
|
||||
[data-theme="dark"] .hljs-quote {
|
||||
color: #6272a4;
|
||||
}
|
||||
|
||||
/* 关键字 */
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-addition {
|
||||
color: #805ad5;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-keyword,
|
||||
[data-theme="dark"] .hljs-selector-tag,
|
||||
[data-theme="dark"] .hljs-addition {
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* 变量名和属性 */
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-literal,
|
||||
.hljs-attr,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-meta {
|
||||
color: #dd6b20;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-variable,
|
||||
[data-theme="dark"] .hljs-template-variable,
|
||||
[data-theme="dark"] .hljs-literal,
|
||||
[data-theme="dark"] .hljs-attr,
|
||||
[data-theme="dark"] .hljs-selector-attr,
|
||||
[data-theme="dark"] .hljs-selector-pseudo,
|
||||
[data-theme="dark"] .hljs-meta {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* 函数名 */
|
||||
.hljs-title,
|
||||
.hljs-function .hljs-title,
|
||||
.hljs-section {
|
||||
color: #3182ce;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-title,
|
||||
[data-theme="dark"] .hljs-function .hljs-title,
|
||||
[data-theme="dark"] .hljs-section {
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
/* 类名和ID */
|
||||
.hljs-title.class_,
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d53f8c;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-title.class_,
|
||||
[data-theme="dark"] .hljs-type,
|
||||
[data-theme="dark"] .hljs-class .hljs-title,
|
||||
[data-theme="dark"] .hljs-selector-id,
|
||||
[data-theme="dark"] .hljs-selector-class {
|
||||
color: #8be9fd;
|
||||
}
|
||||
|
||||
/* 字符串 */
|
||||
.hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-attribute,
|
||||
.hljs-doctag {
|
||||
color: #38a169;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-string,
|
||||
[data-theme="dark"] .hljs-regexp,
|
||||
[data-theme="dark"] .hljs-attribute,
|
||||
[data-theme="dark"] .hljs-doctag {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
/* 数字 */
|
||||
.hljs-number,
|
||||
.hljs-deletion,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-formula {
|
||||
color: #e53e3e;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-number,
|
||||
[data-theme="dark"] .hljs-deletion,
|
||||
[data-theme="dark"] .hljs-symbol,
|
||||
[data-theme="dark"] .hljs-bullet,
|
||||
[data-theme="dark"] .hljs-link,
|
||||
[data-theme="dark"] .hljs-formula {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
/* HTML标签 */
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-selector-tag {
|
||||
color: #2b6cb0;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-tag,
|
||||
[data-theme="dark"] .hljs-name,
|
||||
[data-theme="dark"] .hljs-selector-tag {
|
||||
color: #ff79c6;
|
||||
}
|
||||
|
||||
/* 内置对象 */
|
||||
.hljs-built_in {
|
||||
color: #c05621;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .hljs-built_in {
|
||||
color: #8be9fd;
|
||||
}
|
||||
|
||||
/* 高亮代码行 */
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 终端命令特殊着色 */
|
||||
.terminal-container .hljs-built_in,
|
||||
.terminal-container .hljs-keyword {
|
||||
color: #4b6bff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .hljs-built_in,
|
||||
[data-theme="dark"] .terminal-container .hljs-keyword {
|
||||
color: #9ae6b4;
|
||||
}
|
||||
|
||||
/* 终端中的字符串 */
|
||||
.terminal-container .hljs-string {
|
||||
color: #ea580c;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .hljs-string {
|
||||
color: #fbd38d;
|
||||
}
|
||||
|
||||
/* 终端中的变量 */
|
||||
.terminal-container .hljs-variable {
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .hljs-variable {
|
||||
color: #b794f4;
|
||||
}
|
||||
|
||||
/* 终端中的参数 */
|
||||
.terminal-container .hljs-params {
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .hljs-params {
|
||||
color: #cbd5e0;
|
||||
}
|
||||
|
||||
/* 终端中的注释 */
|
||||
.terminal-container .hljs-comment {
|
||||
color: #64748b;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .terminal-container .hljs-comment {
|
||||
color: #a0aec0;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.code-block-content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.code-block-content::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.code-block-content::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.code-block-content::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-block-content::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-block-content::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .code-block-content::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
/* Mermaid图表主题样式
|
||||
* 支持亮色/暗色主题切换
|
||||
*/
|
||||
|
||||
/* 图表容器样式 */
|
||||
.mermaid-figure {
|
||||
margin: 2rem auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.mermaid-svg-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-height: 80vh; /* 限制容器最大高度为视窗高度的80% */
|
||||
}
|
||||
|
||||
/* 错误信息样式 */
|
||||
.mermaid-error-message {
|
||||
color: #e53e3e;
|
||||
padding: 1rem;
|
||||
border: 1px dashed #e53e3e;
|
||||
border-radius: 0.5rem;
|
||||
margin: 1rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 基础样式 - 亮色主题 */
|
||||
.mermaid-svg {
|
||||
/* 全局图表容器样式 */
|
||||
max-width: 100%;
|
||||
height: auto !important; /* 强制高度为自动,覆盖内联样式 */
|
||||
max-height: 80vh; /* 限制最大高度为视窗高度的80% */
|
||||
width: auto; /* 允许宽度自适应内容 */
|
||||
overflow: visible;
|
||||
/* 移除背景色,使用透明背景 */
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 节点样式 */
|
||||
.mermaid-svg .node rect,
|
||||
.mermaid-svg .node circle,
|
||||
.mermaid-svg .node ellipse,
|
||||
.mermaid-svg .node polygon,
|
||||
.mermaid-svg .node path {
|
||||
fill: #f8fafc;
|
||||
stroke: #94a3b8;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
/* 基本填充和背景色 */
|
||||
.mermaid-svg .basic {
|
||||
fill: #f8fafc;
|
||||
stroke: #94a3b8;
|
||||
}
|
||||
|
||||
.mermaid-svg .labelBkg {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 集群样式 */
|
||||
.mermaid-svg .cluster rect {
|
||||
fill: #f1f5f9;
|
||||
stroke: #cbd5e1;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
/* 边标签样式 */
|
||||
.mermaid-svg .edgeLabel rect {
|
||||
fill: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* 文本样式 */
|
||||
.mermaid-svg text {
|
||||
fill: #334155;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.mermaid-svg .label {
|
||||
color: #334155;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.mermaid-svg .nodeLabel {
|
||||
color: #334155;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.mermaid-svg .cluster text {
|
||||
fill: #475569;
|
||||
}
|
||||
|
||||
/* 连线样式 */
|
||||
.mermaid-svg .edgePath .path {
|
||||
stroke: #94a3b8;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.mermaid-svg .flowchart-link {
|
||||
stroke: #94a3b8;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.mermaid-svg marker {
|
||||
fill: #94a3b8;
|
||||
}
|
||||
|
||||
/* 箭头路径 */
|
||||
.mermaid-svg .arrowMarkerPath {
|
||||
fill: #94a3b8;
|
||||
stroke: #94a3b8;
|
||||
}
|
||||
|
||||
/* 特殊节点样式 */
|
||||
.mermaid-svg .node.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mermaid-svg .node.clickable:hover rect,
|
||||
.mermaid-svg .node.clickable:hover circle,
|
||||
.mermaid-svg .node.clickable:hover ellipse,
|
||||
.mermaid-svg .node.clickable:hover polygon {
|
||||
stroke-width: 2px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* ======= 暗色主题样式 ======= */
|
||||
[data-theme="dark"] .mermaid-svg {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .node rect,
|
||||
[data-theme="dark"] .mermaid-svg .node circle,
|
||||
[data-theme="dark"] .mermaid-svg .node ellipse,
|
||||
[data-theme="dark"] .mermaid-svg .node polygon,
|
||||
[data-theme="dark"] .mermaid-svg .node path {
|
||||
fill: #1e293b;
|
||||
stroke: #475569;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .basic {
|
||||
fill: #1e293b;
|
||||
stroke: #475569;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .labelBkg {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .cluster rect {
|
||||
fill: #0f172a;
|
||||
stroke: #334155;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .edgeLabel rect {
|
||||
fill: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg text {
|
||||
fill: #e2e8f0;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .label {
|
||||
color: #e2e8f0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .nodeLabel {
|
||||
color: #e2e8f0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .cluster text {
|
||||
fill: #cbd5e1;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .edgePath .path {
|
||||
stroke: #64748b;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .flowchart-link {
|
||||
stroke: #64748b;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg marker {
|
||||
fill: #64748b;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .arrowMarkerPath {
|
||||
fill: #64748b;
|
||||
stroke: #64748b;
|
||||
}
|
||||
|
||||
/* 序列图特殊样式 */
|
||||
[data-theme="dark"] .mermaid-svg .actor {
|
||||
fill: #334155 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .messageLine0 {
|
||||
stroke: #94a3b8 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .messageLine1 {
|
||||
stroke: #94a3b8 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg #arrowhead path {
|
||||
fill: #94a3b8 !important;
|
||||
}
|
||||
|
||||
/* 甘特图特殊样式 */
|
||||
[data-theme="dark"] .mermaid-svg .section0 {
|
||||
fill: rgba(255, 255, 255, 0.1) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .section1,
|
||||
[data-theme="dark"] .mermaid-svg .section2 {
|
||||
fill: rgba(255, 255, 255, 0.07) !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .mermaid-svg .task0,
|
||||
[data-theme="dark"] .mermaid-svg .task1,
|
||||
[data-theme="dark"] .mermaid-svg .task2,
|
||||
[data-theme="dark"] .mermaid-svg .task3 {
|
||||
fill: #1e3a8a !important;
|
||||
}
|
Loading…
Reference in New Issue
Block a user