feat: code block dark mode
This commit is contained in:
parent
6d640e8049
commit
cc83133a6c
|
@ -1,9 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted } from 'vue';
|
import { computed, onMounted, ref, watch } from 'vue';
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked';
|
||||||
import hljs from 'highlight.js';
|
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({
|
const props = defineProps({
|
||||||
content: {
|
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(() => {
|
const renderedContent = computed(() => {
|
||||||
if (!props.content) return '<p>没有内容</p>';
|
if (!props.content) return '<p>没有内容</p>';
|
||||||
|
|
||||||
|
@ -57,15 +77,14 @@ const renderedContent = computed(() => {
|
||||||
return marked(processedContent);
|
return marked(processedContent);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面挂载后,对已渲染的代码块应用高亮效果
|
// 页面挂载后,确保应用正确的主题样式
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 如果需要在客户端重新高亮(通常不需要,因为我们已经在服务端高亮)
|
updateCodeBlocksTheme();
|
||||||
// hljs.highlightAll();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="markdown-content" v-html="renderedContent"></div>
|
<div class="markdown-content" :data-theme="themeStore.currentTheme" v-html="renderedContent"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -208,9 +227,9 @@ onMounted(() => {
|
||||||
color: hsl(var(--s));
|
color: hsl(var(--s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 代码块样式增强 */
|
/* 代码块样式增强 - 响应主题 */
|
||||||
.markdown-content :deep(pre) {
|
.markdown-content :deep(pre) {
|
||||||
background-color: hsl(var(--b3));
|
background-color: var(--code-bg, hsl(var(--b2)));
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
@ -218,6 +237,7 @@ onMounted(() => {
|
||||||
margin: 1.5rem 0;
|
margin: 1.5rem 0;
|
||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
color: var(--code-color, hsl(var(--bc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
.markdown-content :deep(pre::before) {
|
.markdown-content :deep(pre::before) {
|
||||||
|
@ -233,14 +253,13 @@ onMounted(() => {
|
||||||
|
|
||||||
/* 代码语言标签 */
|
/* 代码语言标签 */
|
||||||
.markdown-content :deep(pre.hljs::after) {
|
.markdown-content :deep(pre.hljs::after) {
|
||||||
content: attr(class);
|
|
||||||
content: attr(data-language);
|
content: attr(data-language);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
color: hsl(var(--bc) / 0.7);
|
color: var(--code-label-color, hsl(var(--bc) / 0.7));
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
background-color: hsl(var(--b2));
|
background-color: var(--code-label-bg, hsl(var(--b3)));
|
||||||
padding: 0.2rem 0.5rem;
|
padding: 0.2rem 0.5rem;
|
||||||
border-radius: 0 0.3rem 0 0.3rem;
|
border-radius: 0 0.3rem 0 0.3rem;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
|
@ -249,11 +268,11 @@ onMounted(() => {
|
||||||
/* 内联代码样式 */
|
/* 内联代码样式 */
|
||||||
.markdown-content :deep(code) {
|
.markdown-content :deep(code) {
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
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;
|
padding: 0.2rem 0.5rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: hsl(var(--p));
|
color: var(--inline-code-color, hsl(var(--p)));
|
||||||
border: 1px solid hsl(var(--b2) / 0.5);
|
border: 1px solid hsl(var(--b2) / 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,6 +408,235 @@ onMounted(() => {
|
||||||
text-decoration: underline;
|
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) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.markdown-content :deep(pre) {
|
.markdown-content :deep(pre) {
|
||||||
|
|
Loading…
Reference in New Issue