feat: code block dark mode
This commit is contained in:
		@@ -1,9 +1,11 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { computed, onMounted } from 'vue';
 | 
			
		||||
import { computed, onMounted, ref, watch } from 'vue';
 | 
			
		||||
import { marked } from 'marked';
 | 
			
		||||
import hljs from 'highlight.js';
 | 
			
		||||
// 导入默认样式 - 选择一个适合你的主题
 | 
			
		||||
import 'highlight.js/styles/github-dark.css';
 | 
			
		||||
// 导入亮色主题样式
 | 
			
		||||
import 'highlight.js/styles/github.css'; // 亮色主题
 | 
			
		||||
// 导入主题存储
 | 
			
		||||
import { useThemeStore } from '@/stores/theme';
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
    content: {
 | 
			
		||||
@@ -16,6 +18,24 @@ const props = defineProps({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 使用主题存储
 | 
			
		||||
const themeStore = useThemeStore();
 | 
			
		||||
// 使用 isDarkTheme 函数来检查当前是否为暗色主题
 | 
			
		||||
const isDarkMode = computed(() => themeStore.isDarkTheme());
 | 
			
		||||
 | 
			
		||||
// 监听主题变化
 | 
			
		||||
watch(() => themeStore.currentTheme, () => {
 | 
			
		||||
    // 主题变化时更新代码高亮样式
 | 
			
		||||
    updateCodeBlocksTheme();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 更新代码块主题样式
 | 
			
		||||
const updateCodeBlocksTheme = () => {
 | 
			
		||||
    // 这个函数可以在需要时手动更新代码块的样式
 | 
			
		||||
    // 由于我们使用CSS变量控制样式,可能不需要特定实现
 | 
			
		||||
    // 但如果需要,可以在这里添加额外逻辑
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const renderedContent = computed(() => {
 | 
			
		||||
    if (!props.content) return '<p>没有内容</p>';
 | 
			
		||||
    
 | 
			
		||||
@@ -57,15 +77,14 @@ const renderedContent = computed(() => {
 | 
			
		||||
    return marked(processedContent);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 页面挂载后,对已渲染的代码块应用高亮效果
 | 
			
		||||
// 页面挂载后,确保应用正确的主题样式
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
    // 如果需要在客户端重新高亮(通常不需要,因为我们已经在服务端高亮)
 | 
			
		||||
    // hljs.highlightAll();
 | 
			
		||||
    updateCodeBlocksTheme();
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="markdown-content" v-html="renderedContent"></div>
 | 
			
		||||
    <div class="markdown-content" :data-theme="themeStore.currentTheme" v-html="renderedContent"></div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style scoped>
 | 
			
		||||
@@ -208,9 +227,9 @@ onMounted(() => {
 | 
			
		||||
  color: hsl(var(--s));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 代码块样式增强 */
 | 
			
		||||
/* 代码块样式增强 - 响应主题 */
 | 
			
		||||
.markdown-content :deep(pre) {
 | 
			
		||||
  background-color: hsl(var(--b3));
 | 
			
		||||
  background-color: var(--code-bg, hsl(var(--b2)));
 | 
			
		||||
  padding: 1rem;
 | 
			
		||||
  border-radius: 0.5rem;
 | 
			
		||||
  overflow-x: auto;
 | 
			
		||||
@@ -218,6 +237,7 @@ onMounted(() => {
 | 
			
		||||
  margin: 1.5rem 0;
 | 
			
		||||
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
 | 
			
		||||
  position: relative;
 | 
			
		||||
  color: var(--code-color, hsl(var(--bc)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(pre::before) {
 | 
			
		||||
@@ -233,14 +253,13 @@ onMounted(() => {
 | 
			
		||||
 | 
			
		||||
/* 代码语言标签 */
 | 
			
		||||
.markdown-content :deep(pre.hljs::after) {
 | 
			
		||||
  content: attr(class);
 | 
			
		||||
  content: attr(data-language);
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  color: hsl(var(--bc) / 0.7);
 | 
			
		||||
  color: var(--code-label-color, hsl(var(--bc) / 0.7));
 | 
			
		||||
  font-size: 0.75rem;
 | 
			
		||||
  background-color: hsl(var(--b2));
 | 
			
		||||
  background-color: var(--code-label-bg, hsl(var(--b3)));
 | 
			
		||||
  padding: 0.2rem 0.5rem;
 | 
			
		||||
  border-radius: 0 0.3rem 0 0.3rem;
 | 
			
		||||
  opacity: 0.8;
 | 
			
		||||
@@ -249,11 +268,11 @@ onMounted(() => {
 | 
			
		||||
/* 内联代码样式 */
 | 
			
		||||
.markdown-content :deep(code) {
 | 
			
		||||
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
 | 
			
		||||
  background-color: hsl(var(--b3) / 0.7);
 | 
			
		||||
  background-color: var(--inline-code-bg, hsl(var(--b3) / 0.7));
 | 
			
		||||
  padding: 0.2rem 0.5rem;
 | 
			
		||||
  border-radius: 0.25rem;
 | 
			
		||||
  font-size: 0.9em;
 | 
			
		||||
  color: hsl(var(--p));
 | 
			
		||||
  color: var(--inline-code-color, hsl(var(--p)));
 | 
			
		||||
  border: 1px solid hsl(var(--b2) / 0.5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -389,6 +408,235 @@ onMounted(() => {
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 亮色主题下的代码样式 */
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs) {
 | 
			
		||||
  --code-bg: #f5f7ff;
 | 
			
		||||
  --code-color: #333;
 | 
			
		||||
  --inline-code-bg: #f0f2fa;
 | 
			
		||||
  --inline-code-color: #d32f2f;
 | 
			
		||||
  --code-label-bg: #e6e9f5;
 | 
			
		||||
  --code-label-color: #666;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 亮色主题下的语法高亮 */
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-keyword),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-keyword),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-keyword),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-tag),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-tag),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-tag),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-selector-tag),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-selector-tag),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-selector-tag) {
 | 
			
		||||
  color: #8959a8; /* 紫色,用于关键字 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-string),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-string),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-string),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-regexp),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-regexp),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-regexp) {
 | 
			
		||||
  color: #2e7d32; /* 绿色,用于字符串 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-number),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-number),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-number),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-literal),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-literal),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-literal) {
 | 
			
		||||
  color: #f5871f; /* 橙色,用于数字 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-comment),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-comment),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-comment) {
 | 
			
		||||
  color: #8e908c; /* 灰色,用于注释 */
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-built_in),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-built_in),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-built_in) {
 | 
			
		||||
  color: #3e999f; /* 青色,用于内置函数 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-title),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-title),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-title),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-function),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-function),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-function) {
 | 
			
		||||
  color: #4271ae; /* 蓝色,用于函数名 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-name),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-name),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-name),
 | 
			
		||||
:root[data-theme="winter"] .markdown-content :deep(.hljs-attribute),
 | 
			
		||||
.markdown-content[data-theme="winter"] :deep(.hljs-attribute),
 | 
			
		||||
[data-theme="winter"] .markdown-content :deep(.hljs-attribute) {
 | 
			
		||||
  color: #c82829; /* 红色,用于HTML标签和属性 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 暗黑主题下的代码样式 */
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs) {
 | 
			
		||||
  --code-bg: #1e1e2e;
 | 
			
		||||
  --code-color: #f8f8f2;
 | 
			
		||||
  --inline-code-bg: #282a36;
 | 
			
		||||
  --inline-code-color: #ff79c6;
 | 
			
		||||
  --code-label-bg: #282a36;
 | 
			
		||||
  --code-label-color: #bd93f9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 暗黑主题下的语法高亮 */
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-keyword),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-keyword),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-keyword),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-tag),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-tag),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-tag),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-selector-tag),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-selector-tag),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-selector-tag) {
 | 
			
		||||
  color: #cc99cd; /* 紫色,用于关键字 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-string),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-string),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-string),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-regexp),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-regexp),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-regexp) {
 | 
			
		||||
  color: #7ec699; /* 绿色,用于字符串 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-number),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-number),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-number),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-literal),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-literal),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-literal) {
 | 
			
		||||
  color: #f08d49; /* 橙色,用于数字 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-comment),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-comment),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-comment) {
 | 
			
		||||
  color: #999999; /* 灰色,用于注释 */
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-built_in),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-built_in),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-built_in) {
 | 
			
		||||
  color: #6196cc; /* 蓝色,用于内置函数 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-title),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-title),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-title),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-function),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-function),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-function) {
 | 
			
		||||
  color: #f8c555; /* 金色,用于函数名 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-name),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-name),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-name),
 | 
			
		||||
:root[data-theme="night"] .markdown-content :deep(.hljs-attribute),
 | 
			
		||||
.markdown-content[data-theme="night"] :deep(.hljs-attribute),
 | 
			
		||||
[data-theme="night"] .markdown-content :deep(.hljs-attribute) {
 | 
			
		||||
  color: #e2777a; /* 红色,用于HTML标签和属性 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(table) {
 | 
			
		||||
  border-collapse: separate;
 | 
			
		||||
  border-spacing: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin: 1.5rem 0;
 | 
			
		||||
  background-color: hsl(var(--b1));
 | 
			
		||||
  border-radius: 0.5rem;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
 | 
			
		||||
  border: 1px solid hsl(var(--b2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(th),
 | 
			
		||||
.markdown-content :deep(td) {
 | 
			
		||||
  border: 1px solid hsl(var(--b2));
 | 
			
		||||
  padding: 0.75rem 1rem;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(th) {
 | 
			
		||||
  background-color: hsl(var(--p) / 0.15);
 | 
			
		||||
  font-weight: 600;
 | 
			
		||||
  color: hsl(var(--bc));
 | 
			
		||||
  border-bottom: 2px solid hsl(var(--p) / 0.5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(tr:nth-child(even)) {
 | 
			
		||||
  background-color: hsl(var(--b2) / 0.3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(tr:hover) {
 | 
			
		||||
  background-color: hsl(var(--b2) / 0.5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(td) {
 | 
			
		||||
  color: hsl(var(--bc) / 0.8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(blockquote) {
 | 
			
		||||
  margin: 1.5rem 0;
 | 
			
		||||
  padding: 1rem 1.5rem;
 | 
			
		||||
  border-left: 4px solid hsl(var(--p));
 | 
			
		||||
  background-color: hsl(var(--b2) / 0.3);
 | 
			
		||||
  color: hsl(var(--bc) / 0.9);
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
  border-radius: 0 0.5rem 0.5rem 0;
 | 
			
		||||
  box-shadow: 0 2px 5px rgba(0,0,0,0.03);
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(blockquote::before) {
 | 
			
		||||
  content: '"';
 | 
			
		||||
  font-size: 2rem;
 | 
			
		||||
  color: hsl(var(--p) / 0.3);
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 0.5rem;
 | 
			
		||||
  left: 0.5rem;
 | 
			
		||||
  font-family: serif;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(blockquote p) {
 | 
			
		||||
  margin-top: 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(hr) {
 | 
			
		||||
  border: none;
 | 
			
		||||
  border-top: 1px solid hsl(var(--b2));
 | 
			
		||||
  margin: 1.5rem 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(a) {
 | 
			
		||||
  color: hsl(var(--p));
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
  transition: color 0.2s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.markdown-content :deep(a:hover) {
 | 
			
		||||
  color: hsl(var(--pf));
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 暗黑模式下的代码高亮调整 */
 | 
			
		||||
@media (prefers-color-scheme: dark) {
 | 
			
		||||
  .markdown-content :deep(pre) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user