diff --git a/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte b/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte new file mode 100644 index 000000000..82090d7bb --- /dev/null +++ b/src/lib/components/chat/Messages/MarkdownInlineTokens.svelte @@ -0,0 +1,44 @@ + + +{#each tokens as token} + {#if token.type === 'escape'} + {unescapeHtml(token.text)} + {:else if token.type === 'html'} + {@html token.text} + {:else if token.type === 'link'} + {token.text} + {:else if token.type === 'image'} + {token.text} + {:else if token.type === 'strong'} + + + + {:else if token.type === 'em'} + + + + {:else if token.type === 'codespan'} + {unescapeHtml(token.text.replaceAll('&', '&'))} + {:else if token.type === 'br'} +
+ {:else if token.type === 'del'} + + + + {:else if token.type === 'text'} + {unescapeHtml(token.text)} + {/if} +{/each} diff --git a/src/lib/components/chat/Messages/MarkdownTokens.svelte b/src/lib/components/chat/Messages/MarkdownTokens.svelte new file mode 100644 index 000000000..fd86a586c --- /dev/null +++ b/src/lib/components/chat/Messages/MarkdownTokens.svelte @@ -0,0 +1,118 @@ + + +{#each tokens as token, tokenIdx} + {#if token.type === 'hr'} +
+ {:else if token.type === 'heading'} + + + + {:else if token.type === 'code'} + + {:else if token.type === 'table'} + + + + {#each token.header as header, headerIdx} + + {/each} + + + + {#each token.rows as row, rowIdx} + + {#each row ?? [] as cell, cellIdx} + + {/each} + + {/each} + +
+ +
+ +
+ {:else if token.type === 'blockquote'} +
+ +
+ {:else if token.type === 'list'} + {#if token.ordered} +
    + {#each token.items as item, itemIdx} +
  1. + +
  2. + {/each} +
+ {:else} + + {/if} + {:else if token.type === 'html'} + {@html token.text} + {:else if token.type === 'paragraph'} +

+ +

+ {:else if token.type === 'text'} + {#if top} +

+ {#if token.tokens} + + {:else} + {unescapeHtml(token.text)} + {/if} +

+ {:else if token.tokens} + + {:else} + {unescapeHtml(token.text)} + {/if} + {:else if token.type === 'space'} + {''} + {:else} + {console.log('Unknown token', token)} + {/if} +{/each} diff --git a/src/lib/components/chat/Messages/ResponseMessage.svelte b/src/lib/components/chat/Messages/ResponseMessage.svelte index 5cb0cbeef..9924c0931 100644 --- a/src/lib/components/chat/Messages/ResponseMessage.svelte +++ b/src/lib/components/chat/Messages/ResponseMessage.svelte @@ -38,7 +38,7 @@ import Spinner from '$lib/components/common/Spinner.svelte'; import WebSearchResults from './ResponseMessage/WebSearchResults.svelte'; import Sparkles from '$lib/components/icons/Sparkles.svelte'; - import TokenRenderer from './TokenRenderer.svelte'; + import MarkdownTokens from './MarkdownTokens.svelte'; export let message; export let siblings; @@ -77,9 +77,7 @@ let selectedCitation = null; - $: tokens = marked.lexer( - replaceTokens(sanitizeResponseContent(message?.content), model?.name, $user?.name) - ); + $: tokens = marked.lexer(sanitizeResponseContent(message?.content)); $: if (message) { renderStyling(); @@ -413,7 +411,7 @@ {/if}
{#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0} @@ -499,9 +497,7 @@ {:else if message.content && message.error !== true} - {#each tokens as token, tokenIdx} - - {/each} + {/if} {#if message.error} diff --git a/src/lib/components/chat/Messages/TokenRenderer.svelte b/src/lib/components/chat/Messages/TokenRenderer.svelte deleted file mode 100644 index ce0c38d41..000000000 --- a/src/lib/components/chat/Messages/TokenRenderer.svelte +++ /dev/null @@ -1,97 +0,0 @@ - - -
- {#if token.type === 'code'} - {#if token.lang === 'mermaid'} -
{revertSanitizedResponseContent(token.text)}
- {:else} - - {/if} - {:else if token.type === 'image'} - {token.text} - {:else} - {#each content as part} - {@html part.startsWith('{{@IMAGE ') || part.startsWith('{{@CODE ') ? '' : part} - - {#if images.length > 0 && part.startsWith('{{@IMAGE ')} - {@const img = images[parseInt(part.match(/{{@IMAGE (\d+)}}/)[1])]} - -
- -
- {:else if codes.length > 0 && part.startsWith('{{@CODE ')} - {@const _code = codes[parseInt(part.match(/{{@CODE (\d+)}}/)[1])]} -
- -
- {/if} - {/each} - {/if} -
diff --git a/src/lib/components/common/Image.svelte b/src/lib/components/common/Image.svelte index 425b9bc4f..020e016e8 100644 --- a/src/lib/components/common/Image.svelte +++ b/src/lib/components/common/Image.svelte @@ -5,21 +5,26 @@ export let src = ''; export let alt = ''; - let _src = ''; + export let className = ''; + let _src = ''; $: _src = src.startsWith('/') ? `${WEBUI_BASE_URL}${src}` : src; let showImagePreview = false; -
- + src={_src} + {alt} + class=" rounded-lg" + draggable="false" + data-cy="image" + />
diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 9200de968..385b006ab 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -90,6 +90,11 @@ export const revertSanitizedResponseContent = (content: string) => { return content.replaceAll('<', '<').replaceAll('>', '>'); }; +export function unescapeHtml(html: string) { + const doc = new DOMParser().parseFromString(html, 'text/html'); + return doc.documentElement.textContent; +} + export const capitalizeFirstLetter = (string) => { return string.charAt(0).toUpperCase() + string.slice(1); };