mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-10-16 06:58:51 +08:00
feat(chatui): reuse Shiki for workspace code previews
This commit is contained in:
@@ -152,6 +152,11 @@
|
||||
<div v-else-if="fileError" class="workspace-preview-state">
|
||||
{{ fileError }}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="highlightedContent"
|
||||
class="workspace-preview-content"
|
||||
v-html="highlightedContent"
|
||||
/>
|
||||
<pre
|
||||
v-else
|
||||
class="workspace-preview-content"
|
||||
@@ -194,6 +199,11 @@
|
||||
<div v-else-if="fileError" class="workspace-preview-state">
|
||||
{{ fileError }}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="highlightedContent"
|
||||
class="workspace-preview-content workspace-dialog-preview-content"
|
||||
v-html="highlightedContent"
|
||||
/>
|
||||
<pre
|
||||
v-else
|
||||
class="workspace-preview-content workspace-dialog-preview-content"
|
||||
@@ -207,6 +217,7 @@
|
||||
<script setup lang="ts">
|
||||
import "@/components/chat/chatPanelTransition.css";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useTheme } from "vuetify";
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
@@ -244,6 +255,7 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const { tm } = useModuleI18n("features/chat");
|
||||
const theme = useTheme();
|
||||
const rootEntries = ref<WorkspaceEntry[]>([]);
|
||||
const loadedProjectId = ref("");
|
||||
const rootLoading = ref(false);
|
||||
@@ -251,6 +263,7 @@ const treeError = ref("");
|
||||
const filterQuery = ref("");
|
||||
const selectedFilePath = ref("");
|
||||
const fileContent = ref("");
|
||||
const highlightedContent = ref("");
|
||||
const fileLoading = ref(false);
|
||||
const fileError = ref("");
|
||||
const fileDownloading = ref(false);
|
||||
@@ -297,6 +310,39 @@ watch(
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
[fileContent, selectedFilePath, () => theme.global.current.value.dark],
|
||||
async ([content, path, dark], _, onCleanup) => {
|
||||
let cancelled = false;
|
||||
onCleanup(() => {
|
||||
cancelled = true;
|
||||
});
|
||||
highlightedContent.value = "";
|
||||
if (!content || !path) return;
|
||||
|
||||
try {
|
||||
const { getShikiHighlighter, renderShikiCode } = await import(
|
||||
"@/utils/shiki"
|
||||
);
|
||||
const highlighter = await getShikiHighlighter();
|
||||
if (cancelled) return;
|
||||
|
||||
const name = path.split("/").pop()?.toLowerCase() || "";
|
||||
const language = name.startsWith("dockerfile.")
|
||||
? "dockerfile"
|
||||
: name.split(".").pop();
|
||||
highlightedContent.value = renderShikiCode(
|
||||
highlighter,
|
||||
content,
|
||||
language,
|
||||
dark ? "dark" : "light",
|
||||
);
|
||||
} catch (error) {
|
||||
if (!cancelled) console.warn("Failed to highlight workspace file", error);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function close() {
|
||||
emit("update:modelValue", false);
|
||||
}
|
||||
@@ -682,6 +728,15 @@ function formatSize(size: number) {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.workspace-preview-content :deep(pre),
|
||||
.workspace-preview-content :deep(code) {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
tab-size: inherit;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.workspace-dialog-preview {
|
||||
height: min(78vh, 760px);
|
||||
background: var(--chat-page-bg, rgb(var(--v-theme-surface)));
|
||||
|
||||
Reference in New Issue
Block a user