mirror of
https://github.com/Chanzhaoyu/chatgpt-web.git
synced 2025-07-20 19:39:40 +00:00
79 lines
2.2 KiB
Vue
79 lines
2.2 KiB
Vue
<script lang="ts" setup>
|
|
import { computed, ref } from 'vue'
|
|
import MarkdownIt from 'markdown-it'
|
|
import mdKatex from '@traptitech/markdown-it-katex'
|
|
import hljs from 'highlight.js'
|
|
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
|
import { t } from '@/locales'
|
|
|
|
interface Props {
|
|
inversion?: boolean
|
|
error?: boolean
|
|
text?: string
|
|
loading?: boolean
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
|
|
const { isMobile } = useBasicLayout()
|
|
|
|
const textRef = ref<HTMLElement>()
|
|
|
|
const mdi = new MarkdownIt({
|
|
linkify: true,
|
|
highlight(code, language) {
|
|
const validLang = !!(language && hljs.getLanguage(language))
|
|
if (validLang) {
|
|
const lang = language ?? ''
|
|
return highlightBlock(hljs.highlight(code, { language: lang }).value, lang)
|
|
}
|
|
return highlightBlock(hljs.highlightAuto(code).value, '')
|
|
},
|
|
})
|
|
|
|
mdi.use(mdKatex, { blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000' })
|
|
|
|
const wrapClass = computed(() => {
|
|
return [
|
|
'text-wrap',
|
|
'min-w-[20px]',
|
|
'rounded-md',
|
|
isMobile.value ? 'p-2' : 'px-3 py-2',
|
|
props.inversion ? 'bg-[#d2f9d1]' : 'bg-[#f4f6f8]',
|
|
props.inversion ? 'dark:bg-[#a1dc95]' : 'dark:bg-[#1e1e20]',
|
|
{ 'text-red-500': props.error },
|
|
]
|
|
})
|
|
|
|
const text = computed(() => {
|
|
const value = props.text ?? ''
|
|
if (!props.inversion)
|
|
return mdi.render(value)
|
|
return value
|
|
})
|
|
|
|
function highlightBlock(str: string, lang?: string) {
|
|
return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t('chat.copyCode')}</span></div><code class="hljs code-block-body ${lang}">${str}</code></pre>`
|
|
}
|
|
|
|
defineExpose({ textRef })
|
|
</script>
|
|
|
|
<template>
|
|
<div class="text-black" :class="wrapClass">
|
|
<template v-if="loading">
|
|
<span class="dark:text-white w-[4px] h-[20px] block animate-blink" />
|
|
</template>
|
|
<template v-else>
|
|
<div ref="textRef" class="leading-relaxed break-words">
|
|
<div v-if="!inversion" class="markdown-body" v-html="text" />
|
|
<div v-else class="whitespace-pre-wrap" v-text="text" />
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="less">
|
|
@import url(./style.less);
|
|
</style>
|