22 <template v-if =" isUserMessage " >
33 <v-row class =" justify-end pa-2 mb-0 mt-1 mx-1 ml-15" >
44 <v-sheet color =" green-accent-2" class =" pa-2" rounded >
5- <vue-markdown :source =" textMessage" :options = " options " />
5+ <Markdown :content =" textMessage" />
66
77 <!-- at the moment, only user messages can have attachments -->
88 <template v-for =" attachmentMeta of attachmentsMeta " :key =" attachmentMeta .Path " >
7373 <v-row class =" pa-2 mb-0 mt-1 mx-1" v-if =" textMessage" >
7474 <v-col >
7575 <v-sheet class =" pa-2" rounded >
76- <vue-markdown :source =" textMessage" :options = " options " />
76+ <Markdown :content =" textMessage" />
7777 <ChatMessageActions @toggleVisibility =" onToggleVisibility" :hide-edit =" hideEdit" @onEdit =" onEdit" />
7878 </v-sheet >
7979 </v-col >
8282 <template v-else >
8383 <v-row class =" pa-2 mb-0 mt-1 mx-1 mr-15" >
8484 <v-sheet color =" grey-lighten-2" class =" pa-2" rounded >
85- <vue-markdown :source =" textMessage" :options = " options " />
85+ <Markdown :content =" textMessage" />
8686 <small class =" d-flex justify-space-between align-center" >
8787 <ChatMessageActions @toggleVisibility =" onToggleVisibility" :hide-edit =" hideEdit" @on-edit =" onEdit" />
8888 <template v-if =" consumption " >
102102
103103<script lang="ts">
104104import { defineComponent , PropType } from ' vue'
105- import VueMarkdown from ' vue-markdown-render'
106105
107106import { GetAssetMeta } from ' ../../wailsjs/go/controller/Controller'
108107import { controller } from ' ../../wailsjs/go/models.ts'
109108import { PathSeparator } from ' ../common/platform.ts'
110109import AssetMeta = controller .AssetMeta
111110import LLMMessageContentPart = controller .LLMMessageContentPart
112111import LLMMessageCall = controller .LLMMessageCall
113- import hljs from ' highlight.js'
114- import { type Options as MarkdownItOptions } from ' markdown-it'
115- import { UseCodeStyle } from ' ./code-style.ts'
116- import { ClipboardSetText } from ' ../../wailsjs/runtime'
117112import GeneralToolCall from ' ./toolcall/GeneralToolCall.vue'
118113import BuiltinToolCallFileCreation from ' ./toolcall/BuiltinToolCallFileCreation.vue'
119114import BuiltinToolCallCommandExecution from ' ./toolcall/BuiltinToolCallCommandExecution.vue'
@@ -136,6 +131,7 @@ import { useConfigStore } from '../store/config.ts'
136131import McpToolCall from ' ./toolcall/McpToolCall.vue'
137132import { HistoryEntryConsumption } from ' ../store/history.ts'
138133import Consumption from ' ./Consumption.vue'
134+ import Markdown from ' ./Markdown.vue'
139135
140136export enum Role {
141137 System = ' system' ,
@@ -153,6 +149,7 @@ export enum ContentType {
153149export default defineComponent ({
154150 name: ' ChatMessage' ,
155151 components: {
152+ Markdown ,
156153 Consumption ,
157154 McpToolCall ,
158155 ChatMessageActions ,
@@ -172,7 +169,6 @@ export default defineComponent({
172169 GeneralToolCall ,
173170 BuiltinToolCallCommandExecution ,
174171 BuiltinToolCallFileCreation ,
175- VueMarkdown ,
176172 },
177173 emits: [' toggleVisibility' , ' onEdit' ],
178174 props: {
@@ -200,17 +196,6 @@ export default defineComponent({
200196 },
201197 data() {
202198 return {
203- options: {
204- highlight : (code : string , language : string ) => {
205- if (language && hljs .getLanguage (language )) {
206- try {
207- const result = hljs .highlight (code , { language })
208- return result .value
209- } catch (__ ) {}
210- }
211- return ' ' // use external default escaping
212- },
213- } as MarkdownItOptions ,
214199 attachmentsMeta: [] as AssetMeta [],
215200 showConsumption: false ,
216201 }
@@ -249,39 +234,6 @@ export default defineComponent({
249234 },
250235 },
251236 methods: {
252- enrichCopyButtons() {
253- const codeBlocks = document .querySelectorAll (' pre:not(.code-container pre)' ).values ()
254- for (const pre of codeBlocks ) {
255- const div = document .createElement (' div' )
256- div .className = ' code-container'
257-
258- const button = document .createElement (' button' )
259- button .className = ' copy-button mdi-clipboard-text-outline mdi v-icon notranslate v-icon--size-small'
260- button .addEventListener (' click' , this .onCopyButtonClicked )
261-
262- div .appendChild (button )
263- div .appendChild (pre .cloneNode (true ))
264- pre .replaceWith (div )
265- }
266- },
267- onCopyButtonClicked(event : MouseEvent ) {
268- const preElement = (event .target as HTMLButtonElement )?.nextElementSibling as HTMLElement
269- if (preElement && preElement .tagName === ' PRE' ) {
270- let code = preElement .innerText
271- const newlineCount = (code .match (/ \n / g ) || []).length
272- if (newlineCount === 1 ) {
273- // prevent that shell-code-statements will be executed directly
274- code = code .trim ()
275- }
276-
277- ClipboardSetText (code ).then (() => {
278- preElement .classList .add (' copied' )
279- setTimeout (() => {
280- preElement .classList .remove (' copied' )
281- }, 1000 )
282- })
283- }
284- },
285237 fileName(asset : AssetMeta ) {
286238 return asset .Path .split (PathSeparator ).pop () || ' '
287239 },
@@ -296,9 +248,6 @@ export default defineComponent({
296248 },
297249 },
298250 watch: {
299- textMessage() {
300- this .$nextTick (() => this .enrichCopyButtons ())
301- },
302251 attachments: {
303252 async handler() {
304253 const promises = this .attachments .map ((path ) => GetAssetMeta (path ))
@@ -311,99 +260,8 @@ export default defineComponent({
311260 immediate: true ,
312261 },
313262 },
314- mounted() {
315- UseCodeStyle (this .profile .UI .CodeStyle )
316-
317- this .$nextTick (() => this .enrichCopyButtons ())
318- },
319263})
320264 </script >
321265
322- <style >
323- pre code {
324- background-color : #f5f5f5 ;
325- border : 1px solid #ccc ;
326- margin : 0.5em 0 ;
327- padding : 0.5em 2em 0.5em 1em ;
328- border-radius : 5px ;
329- display : block ;
330- overflow-x : auto ;
331- position : relative ;
332- }
333-
334- /* blue block when hover over code-blocks */
335- pre code ::before {
336- content : ' ' ;
337- position : absolute ;
338- top : 0 ;
339- left : 0 ;
340- width : 0 ;
341- height : 100% ;
342- background-color : #007bff ;
343- transition : width 0.3s ;
344- }
345-
346- pre code :hover ::before {
347- width : 5px ;
348- }
349-
350- /* Add styles for the copy button */
351-
352- div .code-container {
353- position : relative ;
354- }
355-
356- .copy-button {
357- position : absolute ;
358- right : 1px ;
359- padding-top : 1em ;
360- padding-right : 0.5em ;
361- z-index : 1 ;
362- float : right ;
363- }
364-
365- pre .copied code {
366- border : 2px solid #4db6ac ;
367- border-radius : 5px ;
368- box-shadow : 0 4px 8px rgba (0 , 0 , 0 , 0.5 ); /* Add elevation effect */
369- }
370-
371- /* Inline code blocks inside text (not in headers) */
372- code :not (pre code ):not (h1 code ):not (h2 code ):not (h3 code ):not (h4 code ):not (h5 code ):not (h6 code ) {
373- background-color : #f5f5f5 ;
374- border : 1px solid #ccc ;
375- padding : 2px 4px ;
376- border-radius : 3px ;
377- }
378-
379- /* Quote-Blocks */
380-
381- blockquote {
382- border-left : 5px solid #ccc ;
383- margin : 0.5em 0 ;
384- padding : 0.5em 1em ;
385- color : #555 ;
386- background : none ;
387- border-radius : 0 ;
388- }
389-
390- blockquote :hover {
391- border-color : #007bff ;
392- }
393-
394- /* Header Padding increase */
395- h1 ,
396- h2 ,
397- h3 ,
398- h4 ,
399- h5 ,
400- h6 {
401- padding-top : 1em ;
402- }
403-
404- /* make list items visible */
405- ol ,
406- ul li {
407- margin-left : 2em ;
408- }
266+ <style scoped>
409267 </style >
0 commit comments