Skip to content

Commit 5f0178b

Browse files
authored
chore: switch dashboard code blocks highlight to shiki (#7497)
* fix: switch dashboard code blocks to shiki and sync theme rendering * fix: harden and optimize dashboard shiki highlighting
1 parent 6131386 commit 5f0178b

19 files changed

Lines changed: 362 additions & 263 deletions

dashboard/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
1515
},
1616
"dependencies": {
17-
"qrcode": "^1.5.4",
1817
"@guolao/vue-monaco-editor": "^1.5.4",
1918
"@tiptap/starter-kit": "2.1.7",
2019
"@tiptap/vue-3": "2.1.7",
@@ -25,7 +24,6 @@
2524
"date-fns": "2.30.0",
2625
"dompurify": "^3.3.2",
2726
"event-source-polyfill": "^1.0.31",
28-
"highlight.js": "^11.11.1",
2927
"js-md5": "^0.8.3",
3028
"katex": "^0.16.27",
3129
"lodash": "4.17.23",
@@ -35,6 +33,7 @@
3533
"monaco-editor": "^0.52.2",
3634
"pinia": "2.1.6",
3735
"pinyin-pro": "^3.26.0",
36+
"qrcode": "^1.5.4",
3837
"shiki": "^3.20.0",
3938
"stream-markdown": "^0.0.13",
4039
"vee-validate": "4.11.3",

dashboard/pnpm-lock.yaml

Lines changed: 0 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dashboard/src/assets/mdi-subset/materialdesignicons-subset.css

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Auto-generated MDI subset – 248 icons */
1+
/* Auto-generated MDI subset – 247 icons */
22
/* Do not edit manually. Run: pnpm run subset-icons */
33

44
@font-face {
@@ -236,10 +236,6 @@
236236
content: "\F0167";
237237
}
238238

239-
.mdi-code-braces::before {
240-
content: "\F0169";
241-
}
242-
243239
.mdi-code-json::before {
244240
content: "\F0626";
245241
}
Binary file not shown.
Binary file not shown.

dashboard/src/components/chat/Chat.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ import {
678678
import { useRoute, useRouter } from "vue-router";
679679
import { useDisplay } from "vuetify";
680680
import axios from "axios";
681-
import { MarkdownCodeBlockNode, setCustomComponents } from "markstream-vue";
681+
import { setCustomComponents } from "markstream-vue";
682682
import "markstream-vue/index.css";
683683
import StyledMenu from "@/components/shared/StyledMenu.vue";
684684
import ProviderConfigDialog from "@/components/chat/ProviderConfigDialog.vue";
@@ -696,6 +696,7 @@ import RefsSidebar from "@/components/chat/message_list_comps/RefsSidebar.vue";
696696
import RefNode from "@/components/chat/message_list_comps/RefNode.vue";
697697
import ActionRef from "@/components/chat/message_list_comps/ActionRef.vue";
698698
import MarkdownMessagePart from "@/components/chat/message_list_comps/MarkdownMessagePart.vue";
699+
import ThemeAwareMarkdownCodeBlock from "@/components/shared/ThemeAwareMarkdownCodeBlock.vue";
699700
import { useSessions, type Session } from "@/composables/useSessions";
700701
import {
701702
useMessages,
@@ -720,7 +721,7 @@ const props = withDefaults(defineProps<{ chatboxMode?: boolean }>(), {
720721
721722
setCustomComponents("chat-message", {
722723
ref: RefNode,
723-
code_block: MarkdownCodeBlockNode,
724+
code_block: ThemeAwareMarkdownCodeBlock,
724725
});
725726
726727
const route = useRoute();

dashboard/src/components/chat/MessageList.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@
237237
<script setup lang="ts">
238238
import { computed, nextTick, reactive, ref } from "vue";
239239
import axios from "axios";
240-
import { MarkdownCodeBlockNode, setCustomComponents } from "markstream-vue";
240+
import { setCustomComponents } from "markstream-vue";
241241
import "markstream-vue/index.css";
242242
import IPythonToolBlock from "@/components/chat/message_list_comps/IPythonToolBlock.vue";
243243
import MarkdownMessagePart from "@/components/chat/message_list_comps/MarkdownMessagePart.vue";
@@ -247,6 +247,7 @@ import RefsSidebar from "@/components/chat/message_list_comps/RefsSidebar.vue";
247247
import ToolCallCard from "@/components/chat/message_list_comps/ToolCallCard.vue";
248248
import ToolCallItem from "@/components/chat/message_list_comps/ToolCallItem.vue";
249249
import ActionRef from "@/components/chat/message_list_comps/ActionRef.vue";
250+
import ThemeAwareMarkdownCodeBlock from "@/components/shared/ThemeAwareMarkdownCodeBlock.vue";
250251
import type {
251252
ChatContent,
252253
ChatRecord,
@@ -270,7 +271,7 @@ const props = withDefaults(
270271
271272
setCustomComponents("chat-message", {
272273
ref: RefNode,
273-
code_block: MarkdownCodeBlockNode,
274+
code_block: ThemeAwareMarkdownCodeBlock,
274275
});
275276
276277
const { tm } = useModuleI18n("features/chat");

dashboard/src/components/chat/MessageListDEPRECATED.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ import { useI18n, useModuleI18n } from '@/i18n/composables';
183183
import { enableKatex, enableMermaid, MarkdownCodeBlockNode, setCustomComponents } from 'markstream-vue'
184184
import 'markstream-vue/index.css'
185185
import 'katex/dist/katex.min.css'
186-
import 'highlight.js/styles/github.css';
187186
import axios from 'axios';
188187
import { useToast } from '@/utils/toast'
189188
import ReasoningBlock from './message_list_comps/ReasoningBlock.vue';

dashboard/src/components/chat/StandaloneChat.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ import {
174174
ref,
175175
} from "vue";
176176
import axios from "axios";
177-
import { MarkdownCodeBlockNode, setCustomComponents } from "markstream-vue";
177+
import { setCustomComponents } from "markstream-vue";
178178
import "markstream-vue/index.css";
179179
import ChatInput from "@/components/chat/ChatInput.vue";
180180
import IPythonToolBlock from "@/components/chat/message_list_comps/IPythonToolBlock.vue";
@@ -183,6 +183,7 @@ import ReasoningBlock from "@/components/chat/message_list_comps/ReasoningBlock.
183183
import RefNode from "@/components/chat/message_list_comps/RefNode.vue";
184184
import ToolCallCard from "@/components/chat/message_list_comps/ToolCallCard.vue";
185185
import ToolCallItem from "@/components/chat/message_list_comps/ToolCallItem.vue";
186+
import ThemeAwareMarkdownCodeBlock from "@/components/shared/ThemeAwareMarkdownCodeBlock.vue";
186187
import { useMediaHandling } from "@/composables/useMediaHandling";
187188
import {
188189
useMessages,
@@ -201,7 +202,7 @@ const props = withDefaults(defineProps<{ configId?: string | null }>(), {
201202
202203
setCustomComponents("chat-message", {
203204
ref: RefNode,
204-
code_block: MarkdownCodeBlockNode,
205+
code_block: ThemeAwareMarkdownCodeBlock,
205206
});
206207
207208
const { tm } = useModuleI18n("features/chat");

dashboard/src/components/chat/message_list_comps/IPythonToolBlock.vue

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<script setup>
2525
import { ref, computed, onMounted } from 'vue';
2626
import { useModuleI18n } from '@/i18n/composables';
27-
import { createHighlighter } from 'shiki';
27+
import { ensureShikiLanguages, escapeHtml, renderShikiCode } from '@/utils/shiki';
2828
2929
const props = defineProps({
3030
toolCall: {
@@ -82,13 +82,15 @@ const highlightedCode = computed(() => {
8282
return '';
8383
}
8484
try {
85-
return shikiHighlighter.value.codeToHtml(code.value, {
86-
lang: 'python',
87-
theme: props.isDark ? 'min-dark' : 'github-light'
88-
});
85+
return renderShikiCode(
86+
shikiHighlighter.value,
87+
code.value,
88+
'python',
89+
props.isDark ? 'dark' : 'light'
90+
);
8991
} catch (err) {
9092
console.error('Failed to highlight code:', err);
91-
return `<pre><code>${code.value}</code></pre>`;
93+
return `<pre><code>${escapeHtml(code.value)}</code></pre>`;
9294
}
9395
});
9496
@@ -101,10 +103,7 @@ const displayExpanded = computed(() => {
101103
102104
onMounted(async () => {
103105
try {
104-
shikiHighlighter.value = await createHighlighter({
105-
themes: ['min-dark', 'github-light'],
106-
langs: ['python']
107-
});
106+
shikiHighlighter.value = await ensureShikiLanguages(['python']);
108107
shikiReady.value = true;
109108
} catch (err) {
110109
console.error('Failed to initialize Shiki:', err);
@@ -139,6 +138,20 @@ onMounted(async () => {
139138
overflow-x: auto;
140139
}
141140
141+
:deep(.code-highlighted pre.shiki) {
142+
margin: 0;
143+
padding: 16px;
144+
border-radius: 6px;
145+
overflow: auto;
146+
}
147+
148+
:deep(.code-highlighted pre.shiki code) {
149+
display: block;
150+
padding: 0;
151+
background: transparent;
152+
border-radius: 0;
153+
}
154+
142155
.code-fallback {
143156
margin: 0;
144157
padding: 12px;

0 commit comments

Comments
 (0)