open-webui/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte

88 lines
3 KiB
Svelte
Raw Normal View History

<script lang="ts">
import DOMPurify from 'dompurify';
2024-08-26 12:17:33 +00:00
import { toast } from 'svelte-sonner';
import type { Token } from 'marked';
2024-08-26 12:17:33 +00:00
import { getContext } from 'svelte';
const i18n = getContext('i18n');
2024-08-08 22:01:38 +00:00
2024-08-17 17:43:04 +00:00
import { WEBUI_BASE_URL } from '$lib/constants';
2025-01-08 08:59:03 +00:00
import { copyToClipboard, unescapeHtml } from '$lib/utils';
2024-08-26 12:17:33 +00:00
import Image from '$lib/components/common/Image.svelte';
import KatexRenderer from './KatexRenderer.svelte';
2024-11-22 01:58:29 +00:00
import Source from './Source.svelte';
2025-04-20 06:38:08 +00:00
import HtmlToken from './HTMLToken.svelte';
2025-07-18 12:38:43 +00:00
import TextToken from './MarkdownInlineTokens/TextToken.svelte';
2025-07-18 12:57:49 +00:00
import CodespanToken from './MarkdownInlineTokens/CodespanToken.svelte';
2025-09-14 22:49:01 +00:00
import MentionToken from './MarkdownInlineTokens/MentionToken.svelte';
2025-11-23 23:27:57 +00:00
import SourceToken from './SourceToken.svelte';
2024-08-08 22:01:38 +00:00
export let id: string;
2025-07-18 12:38:43 +00:00
export let done = true;
export let tokens: Token[];
2025-11-23 23:27:57 +00:00
export let sourceIds = [];
2024-11-22 01:58:29 +00:00
export let onSourceClick: Function = () => {};
</script>
2025-10-28 06:42:00 +00:00
{#each tokens as token, tokenIdx (tokenIdx)}
{#if token.type === 'escape'}
{unescapeHtml(token.text)}
{:else if token.type === 'html'}
2025-04-20 06:38:08 +00:00
<HtmlToken {id} {token} {onSourceClick} />
{:else if token.type === 'link'}
{#if token.tokens}
<a href={token.href} target="_blank" rel="nofollow" title={token.title}>
2025-07-18 12:57:49 +00:00
<svelte:self id={`${id}-a`} tokens={token.tokens} {onSourceClick} {done} />
</a>
{:else}
<a href={token.href} target="_blank" rel="nofollow" title={token.title}>{token.text}</a>
{/if}
{:else if token.type === 'image'}
<Image src={token.href} alt={token.text} />
{:else if token.type === 'strong'}
<strong><svelte:self id={`${id}-strong`} tokens={token.tokens} {onSourceClick} /></strong>
{:else if token.type === 'em'}
<em><svelte:self id={`${id}-em`} tokens={token.tokens} {onSourceClick} /></em>
{:else if token.type === 'codespan'}
2025-07-18 12:57:49 +00:00
<CodespanToken {token} {done} />
{:else if token.type === 'br'}
<br />
{:else if token.type === 'del'}
<del><svelte:self id={`${id}-del`} tokens={token.tokens} {onSourceClick} /></del>
2024-08-08 22:01:38 +00:00
{:else if token.type === 'inlineKatex'}
{#if token.text}
2025-01-08 07:59:58 +00:00
<KatexRenderer content={token.text} displayMode={false} />
2024-08-08 22:01:38 +00:00
{/if}
2024-08-16 13:33:14 +00:00
{:else if token.type === 'iframe'}
<iframe
src="{WEBUI_BASE_URL}/api/v1/files/{token.fileId}/content"
title={token.fileId}
width="100%"
frameborder="0"
2025-10-27 04:06:32 +00:00
on:load={(e) => {
try {
e.currentTarget.style.height =
e.currentTarget.contentWindow.document.body.scrollHeight + 20 + 'px';
} catch {}
}}
2024-08-16 13:33:14 +00:00
></iframe>
2025-09-14 22:49:01 +00:00
{:else if token.type === 'mention'}
<MentionToken {token} />
2025-11-23 23:27:57 +00:00
{:else if token.type === 'footnote'}
{@html DOMPurify.sanitize(
`<sup class="footnote-ref footnote-ref-text">${token.escapedText}</sup>`
) || ''}
{:else if token.type === 'citation'}
<SourceToken {id} {token} {sourceIds} onClick={onSourceClick} />
<!-- {#if token.ids && token.ids.length > 0}
{#each token.ids as sourceId}
<Source id={sourceId - 1} title={sourceIds[sourceId - 1]} onClick={onSourceClick} />
{/each}
{/if} -->
{:else if token.type === 'text'}
2025-07-18 12:38:43 +00:00
<TextToken {token} {done} />
{/if}
{/each}