feat: 添加 Markdown 渲染组件,支持代码高亮和格式化
This commit is contained in:
parent
e876a4d88b
commit
8b87de67c1
@ -26,7 +26,10 @@ const props = defineProps({
|
||||
<span class="text-sm font-medium">{{ name }}</span>
|
||||
</div>
|
||||
<div class="rounded-lg bg-white/50 p-2 text-sm dark:bg-neutral-800/50">
|
||||
<span v-if="message">{{ message }}</span>
|
||||
<span v-if="message">
|
||||
<Markdown :source="message" />
|
||||
<!-- {{ message }} -->
|
||||
</span>
|
||||
<span v-else class="flex items-center gap-1.5">
|
||||
<UIcon name="svg-spinners:3-dots-scale" class="text-lg -mt-0.5" />
|
||||
<p class="text-xs">思考中</p>
|
||||
|
@ -38,7 +38,8 @@ defineProps({
|
||||
class="rounded-lg bg-white/50 p-2 text-sm dark:bg-neutral-800/50 break-all text-justify"
|
||||
>
|
||||
<div v-if="message.message" class="prose prose-sm">
|
||||
{{ message.message }}
|
||||
<!-- {{ message.message }} -->
|
||||
<Markdown :source="message.message" />
|
||||
</div>
|
||||
<span v-else class="flex items-center gap-1.5">
|
||||
<UIcon name="svg-spinners:3-dots-scale" class="text-lg -mt-0.5" />
|
||||
|
43
components/Markdown.vue
Normal file
43
components/Markdown.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<script setup lang="ts">
|
||||
import md from "markdown-it";
|
||||
import hljs from "highlight.js";
|
||||
import "highlight.js/styles/github-dark-dimmed.min.css";
|
||||
|
||||
const renderer = md({
|
||||
html: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
breaks: true,
|
||||
highlight: function (str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return `<pre class="hljs" style="overflow-x: auto"><code>${
|
||||
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value
|
||||
}</code></pre>`;
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
return (
|
||||
'<pre class="hljs"><code>' + md().utils.escapeHtml(str) + "</code></pre>"
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
source: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article
|
||||
class="prose dark:prose-invert max-w-none prose-sm prose-neutral"
|
||||
v-html="
|
||||
renderer.render(source.replaceAll('\t', ' '))
|
||||
"
|
||||
></article>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -15,6 +15,8 @@
|
||||
"@tailwindcss/vite": "^4.0.14",
|
||||
"@uniiem/uuid": "^0.2.1",
|
||||
"dotenv": "^16.4.7",
|
||||
"highlight.js": "^11.11.1",
|
||||
"markdown-it": "^14.1.0",
|
||||
"nuxt": "^3.16.0",
|
||||
"pinia": "^3.0.1",
|
||||
"tailwindcss": "^4.0.14",
|
||||
@ -23,6 +25,7 @@
|
||||
},
|
||||
"packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a",
|
||||
"devDependencies": {
|
||||
"@nuxt/ui": "^3.0.0"
|
||||
"@nuxt/ui": "^3.0.0",
|
||||
"@types/markdown-it": "^14.1.2"
|
||||
}
|
||||
}
|
||||
|
69
pnpm-lock.yaml
generated
69
pnpm-lock.yaml
generated
@ -23,6 +23,12 @@ importers:
|
||||
dotenv:
|
||||
specifier: ^16.4.7
|
||||
version: 16.4.7
|
||||
highlight.js:
|
||||
specifier: ^11.11.1
|
||||
version: 11.11.1
|
||||
markdown-it:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
nuxt:
|
||||
specifier: ^3.16.0
|
||||
version: 3.16.0(@parcel/watcher@2.5.1)(@types/node@22.13.10)(db0@0.3.1)(ioredis@5.6.0)(lightningcss@1.29.2)(magicast@0.3.5)(rollup@4.35.0)(terser@5.39.0)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.0))(yaml@2.7.0)
|
||||
@ -42,6 +48,9 @@ importers:
|
||||
'@nuxt/ui':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0(@babel/parser@7.26.9)(change-case@5.4.4)(db0@0.3.1)(embla-carousel@8.5.2)(ioredis@5.6.0)(magicast@0.3.5)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.0))
|
||||
'@types/markdown-it':
|
||||
specifier: ^14.1.2
|
||||
version: 14.1.2
|
||||
|
||||
packages:
|
||||
|
||||
@ -1064,6 +1073,15 @@ packages:
|
||||
'@types/http-proxy@1.17.16':
|
||||
resolution: {integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==}
|
||||
|
||||
'@types/linkify-it@5.0.0':
|
||||
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
|
||||
|
||||
'@types/markdown-it@14.1.2':
|
||||
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
|
||||
|
||||
'@types/mdurl@2.0.0':
|
||||
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
|
||||
|
||||
'@types/node@22.13.10':
|
||||
resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==}
|
||||
|
||||
@ -1981,6 +1999,10 @@ packages:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
highlight.js@11.11.1:
|
||||
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
hookable@5.5.3:
|
||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||
|
||||
@ -2273,6 +2295,9 @@ packages:
|
||||
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
linkify-it@5.0.0:
|
||||
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
|
||||
|
||||
listhen@1.9.0:
|
||||
resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==}
|
||||
hasBin: true
|
||||
@ -2324,6 +2349,10 @@ packages:
|
||||
magicast@0.3.5:
|
||||
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
|
||||
|
||||
markdown-it@14.1.0:
|
||||
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
|
||||
hasBin: true
|
||||
|
||||
mdn-data@2.0.28:
|
||||
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
|
||||
|
||||
@ -2333,6 +2362,9 @@ packages:
|
||||
mdn-data@2.12.2:
|
||||
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
|
||||
|
||||
mdurl@2.0.0:
|
||||
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
|
||||
|
||||
merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
|
||||
@ -2829,6 +2861,10 @@ packages:
|
||||
protocols@2.0.2:
|
||||
resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==}
|
||||
|
||||
punycode.js@2.3.1:
|
||||
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
quansync@0.2.8:
|
||||
resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==}
|
||||
|
||||
@ -3183,6 +3219,9 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
uc.micro@2.1.0:
|
||||
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
||||
|
||||
ufo@1.5.4:
|
||||
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
|
||||
|
||||
@ -4821,6 +4860,15 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@types/linkify-it@5.0.0': {}
|
||||
|
||||
'@types/markdown-it@14.1.2':
|
||||
dependencies:
|
||||
'@types/linkify-it': 5.0.0
|
||||
'@types/mdurl': 2.0.0
|
||||
|
||||
'@types/mdurl@2.0.0': {}
|
||||
|
||||
'@types/node@22.13.10':
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
@ -5799,6 +5847,8 @@ snapshots:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
highlight.js@11.11.1: {}
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
http-errors@2.0.0:
|
||||
@ -6033,6 +6083,10 @@ snapshots:
|
||||
|
||||
lilconfig@3.1.3: {}
|
||||
|
||||
linkify-it@5.0.0:
|
||||
dependencies:
|
||||
uc.micro: 2.1.0
|
||||
|
||||
listhen@1.9.0:
|
||||
dependencies:
|
||||
'@parcel/watcher': 2.5.1
|
||||
@ -6106,12 +6160,23 @@ snapshots:
|
||||
'@babel/types': 7.26.9
|
||||
source-map-js: 1.2.1
|
||||
|
||||
markdown-it@14.1.0:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
entities: 4.5.0
|
||||
linkify-it: 5.0.0
|
||||
mdurl: 2.0.0
|
||||
punycode.js: 2.3.1
|
||||
uc.micro: 2.1.0
|
||||
|
||||
mdn-data@2.0.28: {}
|
||||
|
||||
mdn-data@2.0.30: {}
|
||||
|
||||
mdn-data@2.12.2: {}
|
||||
|
||||
mdurl@2.0.0: {}
|
||||
|
||||
merge-stream@2.0.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
@ -6764,6 +6829,8 @@ snapshots:
|
||||
|
||||
protocols@2.0.2: {}
|
||||
|
||||
punycode.js@2.3.1: {}
|
||||
|
||||
quansync@0.2.8: {}
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
@ -7133,6 +7200,8 @@ snapshots:
|
||||
|
||||
typescript@5.8.2: {}
|
||||
|
||||
uc.micro@2.1.0: {}
|
||||
|
||||
ufo@1.5.4: {}
|
||||
|
||||
ultrahtml@1.5.3: {}
|
||||
|
Loading…
Reference in New Issue
Block a user