Skip to content

Commit

Permalink
Merge pull request #1245 from solliancenet/sc-user-portal-markdown-re…
Browse files Browse the repository at this point in the history
…ndering

User portal markdown rendering
  • Loading branch information
ciprianjichici authored Jul 21, 2024
2 parents 16b5f85 + 42cab42 commit e1e6484
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 27 deletions.
60 changes: 43 additions & 17 deletions src/ui/UserPortal/components/ChatMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<template v-if="message.sender === 'Assistant' && message.type === 'LoadingMessage'">
<i class="pi pi-spin pi-spinner"></i>
</template>
<span v-else>{{ displayText }}</span>
<div v-html="displayHtml"></div>
</div>

<div v-if="message.sender !== 'User'" class="message__footer">
Expand Down Expand Up @@ -128,6 +128,22 @@ import type { PropType } from 'vue';
import type { Message, CompletionPrompt } from '@/js/types';
import api from '@/js/api';
import hljs from 'highlight.js';
import 'highlight.js/styles/github-dark-dimmed.css';
import { marked } from 'marked';
import { markedHighlight } from 'marked-highlight';
import truncate from 'truncate-html';
import DOMPurify from 'dompurify';
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
const validLanguage = !!(language && hljs.getLanguage(language));
const highlighted = validLanguage ? hljs.highlight(code, { language }).value : hljs.highlightAuto(code).value;
const languageClass = validLanguage ? `hljs language-${language}` : 'hljs';
return `<pre><code class="${languageClass}">${highlighted}</code></pre>`;
};
marked.use({ renderer });
export default {
name: 'ChatMessage',
Expand All @@ -149,34 +165,44 @@ export default {
return {
prompt: {} as CompletionPrompt,
viewPrompt: false,
displayText: '',
displayHtml: '',
currentWordIndex: 0,
primaryButtonBg: this.$appConfigStore.primaryButtonBg,
primaryButtonText: this.$appConfigStore.primaryButtonText
primaryButtonText: this.$appConfigStore.primaryButtonText,
};
},
computed: {
compiledMarkdown() {
return DOMPurify.sanitize(marked(this.message.text));
}
},
created() {
if (this.showWordAnimation) {
this.displayWordByWord();
} else {
this.displayText = this.message.text;
this.displayHtml = this.compiledMarkdown;
}
},
methods: {
displayWordByWord() {
const words = this.message.text.split(' ');
let index = 0;
const displayNextWord = () => {
if (index < words.length) {
this.displayText += words[index] + ' ';
index++;
setTimeout(displayNextWord, 10);
}
};
displayNextWord();
if (this.currentWordIndex >= this.compiledMarkdown.split(/\s+/).length) return;
this.currentWordIndex += 1;
this.displayHtml = truncate(this.compiledMarkdown, this.currentWordIndex, {
byWords: true,
stripTags: false,
ellipsis: '',
decodeEntities: false,
keepWhitespaces: true,
excludes: '',
reserveLastWord: false,
keepWhitespaces: true
});
setTimeout(this.displayWordByWord, 10);
},
formatTimeStamp(timeStamp: string) {
Expand Down Expand Up @@ -260,7 +286,7 @@ export default {
}
.message__body {
white-space: pre-wrap;
// white-space: pre-wrap;
overflow-wrap: break-word;
padding-left: 12px;
padding-right: 12px;
Expand Down
132 changes: 123 additions & 9 deletions src/ui/UserPortal/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/ui/UserPortal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@
"@azure/app-configuration": "^1.4.1",
"@azure/msal-browser": "^3.2.0",
"@pinia/nuxt": "^0.5.1",
"dompurify": "^3.1.6",
"highlight.js": "^11.10.0",
"javascript-time-ago": "^2.5.9",
"marked": "^13.0.2",
"marked-highlight": "^2.1.3",
"pinia": "^2.1.7",
"primeicons": "^6.0.1",
"primevue": "^3.35.0",
"truncate-html": "^1.1.1",
"vue-mention": "^2.0.0-alpha.3"
}
}
1 change: 0 additions & 1 deletion src/ui/UserPortal/plugins/primevue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import OverlayPanel from 'primevue/overlaypanel';
import Badge from 'primevue/badge';
import BadgeDirective from 'primevue/badgedirective';


import { defineNuxtPlugin } from '#app';

export default defineNuxtPlugin((nuxtApp) => {
Expand Down

0 comments on commit e1e6484

Please sign in to comment.