mirror of
https://github.com/open-webui/open-webui
synced 2024-11-16 05:24:02 +00:00
refac
This commit is contained in:
parent
7cbc94592e
commit
e6b3de310b
@ -2,14 +2,20 @@
|
||||
import { marked } from 'marked';
|
||||
import type { Token } from 'marked';
|
||||
import { revertSanitizedResponseContent, unescapeHtml } from '$lib/utils';
|
||||
import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import Image from '$lib/components/common/Image.svelte';
|
||||
import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
|
||||
|
||||
import MarkdownInlineTokens from '$lib/components/chat/Messages/MarkdownInlineTokens.svelte';
|
||||
|
||||
export let id: string;
|
||||
export let tokens: Token[];
|
||||
export let top = true;
|
||||
|
||||
let containerElement;
|
||||
|
||||
const headerComponent = (depth: number) => {
|
||||
return 'h' + depth;
|
||||
};
|
||||
@ -20,8 +26,61 @@
|
||||
return `<code class="codespan">${code.replaceAll('&', '&')}</code>`;
|
||||
};
|
||||
|
||||
let codes = [];
|
||||
renderer.code = (code, lang) => {
|
||||
return `<pre><code class="language-${lang}">${code}</code></pre>`;
|
||||
codes.push({
|
||||
code: code,
|
||||
lang: lang
|
||||
});
|
||||
codes = codes;
|
||||
const codeId = `${id}-${codes.length}`;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (document.getElementById(`code-${codeId}`)) {
|
||||
clearInterval(interval);
|
||||
|
||||
new CodeBlock({
|
||||
target: document.getElementById(`code-${codeId}`),
|
||||
props: {
|
||||
id: `${id}-${codes.length}`,
|
||||
lang: lang,
|
||||
code: revertSanitizedResponseContent(code)
|
||||
},
|
||||
hydrate: true,
|
||||
$$inline: true
|
||||
});
|
||||
}
|
||||
}, 10);
|
||||
|
||||
return `<div id="code-${id}-${codes.length}" />`;
|
||||
};
|
||||
|
||||
let images = [];
|
||||
renderer.image = (href, title, text) => {
|
||||
images.push({
|
||||
href: href,
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
images = images;
|
||||
|
||||
const imageId = `${id}-${images.length}`;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (document.getElementById(`image-${imageId}`)) {
|
||||
clearInterval(interval);
|
||||
new Image({
|
||||
target: document.getElementById(`image-${imageId}`),
|
||||
props: {
|
||||
src: href,
|
||||
alt: text
|
||||
},
|
||||
hydrate: true
|
||||
});
|
||||
}
|
||||
}, 10);
|
||||
|
||||
return `<div id="image-${id}-${images.length}" />`;
|
||||
};
|
||||
|
||||
// Open all links in a new tab/window (from https://github.com/markedjs/marked/issues/655#issuecomment-383226346)
|
||||
@ -30,24 +89,31 @@
|
||||
const html = origLinkRenderer.call(renderer, href, title, text);
|
||||
return html.replace(/^<a /, '<a target="_blank" rel="nofollow" ');
|
||||
};
|
||||
|
||||
const { extensions, ...defaults } = marked.getDefaults() as marked.MarkedOptions & {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
extensions: any;
|
||||
};
|
||||
|
||||
$: if (tokens) {
|
||||
images = [];
|
||||
codes = [];
|
||||
}
|
||||
</script>
|
||||
|
||||
{#each tokens as token, tokenIdx (`${id}-${tokenIdx}`)}
|
||||
{#if token.type === 'code'}
|
||||
{#if token.lang === 'mermaid'}
|
||||
<pre class="mermaid">{revertSanitizedResponseContent(token.text)}</pre>
|
||||
{:else}
|
||||
<CodeBlock
|
||||
id={`${id}-${tokenIdx}`}
|
||||
lang={token?.lang ?? ''}
|
||||
code={revertSanitizedResponseContent(token?.text ?? '')}
|
||||
/>
|
||||
{/if}
|
||||
<!-- {:else if token.type === 'heading'}
|
||||
<div bind:this={containerElement} class="flex flex-col">
|
||||
{#each tokens as token, tokenIdx (`${id}-${tokenIdx}`)}
|
||||
{#if token.type === 'code'}
|
||||
{#if token.lang === 'mermaid'}
|
||||
<pre class="mermaid">{revertSanitizedResponseContent(token.text)}</pre>
|
||||
{:else}
|
||||
<CodeBlock
|
||||
id={`${id}-${tokenIdx}`}
|
||||
lang={token?.lang ?? ''}
|
||||
code={revertSanitizedResponseContent(token?.text ?? '')}
|
||||
/>
|
||||
{/if}
|
||||
<!-- {:else if token.type === 'heading'}
|
||||
<svelte:element this={headerComponent(token.depth)}>
|
||||
<MarkdownInlineTokens id={`${id}-${tokenIdx}-h`} tokens={token.tokens} />
|
||||
</svelte:element>
|
||||
@ -119,7 +185,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
{:else if token.type === 'text'} -->
|
||||
<!-- {#if top}
|
||||
<!-- {#if top}
|
||||
<p>
|
||||
{#if token.tokens}
|
||||
<MarkdownInlineTokens id={`${id}-${tokenIdx}-t`} tokens={token.tokens} />
|
||||
@ -132,12 +198,13 @@
|
||||
{:else}
|
||||
{unescapeHtml(token.text)}
|
||||
{/if} -->
|
||||
{:else}
|
||||
{@html marked.parse(token.raw, {
|
||||
...defaults,
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
renderer
|
||||
})}
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
{@html marked.parse(token.raw, {
|
||||
...defaults,
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
renderer
|
||||
})}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -13,18 +13,13 @@
|
||||
let showImagePreview = false;
|
||||
</script>
|
||||
|
||||
<div class={className}>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<img
|
||||
on:click={() => {
|
||||
showImagePreview = true;
|
||||
}}
|
||||
src={_src}
|
||||
{alt}
|
||||
class=" rounded-lg cursor-pointer"
|
||||
draggable="false"
|
||||
data-cy="image"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class={className}
|
||||
on:click={() => {
|
||||
showImagePreview = true;
|
||||
}}
|
||||
>
|
||||
<img src={_src} {alt} class=" rounded-lg cursor-pointer" draggable="false" data-cy="image" />
|
||||
</button>
|
||||
|
||||
<ImagePreview bind:show={showImagePreview} src={_src} {alt} />
|
||||
|
Loading…
Reference in New Issue
Block a user