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

76 lines
2.1 KiB
Svelte
Raw Normal View History

2025-11-23 23:27:57 +00:00
<script lang="ts">
import { LinkPreview } from 'bits-ui';
2025-11-28 07:44:36 +00:00
import { decodeString } from '$lib/utils';
2025-11-23 23:27:57 +00:00
import Source from './Source.svelte';
export let id;
export let token;
export let sourceIds = [];
export let onClick: Function = () => {};
let containerElement;
2025-11-23 23:31:59 +00:00
let openPreview = false;
2025-11-23 23:27:57 +00:00
// Helper function to return only the domain from a URL
function getDomain(url: string): string {
const domain = url.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if (domain.startsWith('www.')) {
return domain.slice(4);
}
return domain;
}
// Helper function to check if text is a URL and return the domain
function formattedTitle(title: string): string {
if (title.startsWith('http')) {
return getDomain(title);
}
return title;
}
const getDisplayTitle = (title: string) => {
if (!title) return 'N/A';
if (title.length > 30) {
return title.slice(0, 15) + '...' + title.slice(-10);
}
return title;
};
</script>
{#if (token?.ids ?? []).length == 1}
<Source id={token.ids[0] - 1} title={sourceIds[token.ids[0] - 1]} {onClick} />
{:else}
2025-11-23 23:31:59 +00:00
<LinkPreview.Root openDelay={0} bind:open={openPreview}>
2025-11-23 23:27:57 +00:00
<LinkPreview.Trigger>
<button
class="text-[10px] w-fit translate-y-[2px] px-2 py-0.5 dark:bg-white/5 dark:text-white/80 dark:hover:text-white bg-gray-50 text-black/80 hover:text-black transition rounded-xl"
2025-11-23 23:31:59 +00:00
on:click={() => {
openPreview = !openPreview;
}}
2025-11-23 23:27:57 +00:00
>
<span class="line-clamp-1">
2025-11-28 07:44:36 +00:00
{getDisplayTitle(formattedTitle(decodeString(sourceIds[token.ids[0] - 1])))}
2025-11-23 23:27:57 +00:00
<span class="dark:text-white/50 text-black/50">+{(token?.ids ?? []).length - 1}</span>
</span>
</button>
</LinkPreview.Trigger>
<LinkPreview.Content
class="z-[999]"
align="start"
strategy="fixed"
sideOffset={6}
el={containerElement}
>
<div class="bg-gray-50 dark:bg-gray-850 rounded-xl p-1 cursor-pointer">
{#each token.ids as sourceId}
<div class="">
<Source id={sourceId - 1} title={sourceIds[sourceId - 1]} {onClick} />
</div>
{/each}
</div>
</LinkPreview.Content>
</LinkPreview.Root>
{/if}