diff --git a/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte b/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte index 022bcfb2c..c2c7d81e6 100644 --- a/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte +++ b/src/lib/components/chat/Messages/Markdown/MarkdownInlineTokens.svelte @@ -18,6 +18,7 @@ import TextToken from './MarkdownInlineTokens/TextToken.svelte'; import CodespanToken from './MarkdownInlineTokens/CodespanToken.svelte'; import MentionToken from './MarkdownInlineTokens/MentionToken.svelte'; + import NoteLinkToken from './MarkdownInlineTokens/NoteLinkToken.svelte'; import SourceToken from './SourceToken.svelte'; export let id: string; @@ -26,6 +27,24 @@ export let sourceIds = []; export let onSourceClick: Function = () => {}; + /** + * Check if a URL is a same-origin note link and return the note ID if so. + */ + const getNoteIdFromHref = (href: string): string | null => { + try { + const url = new URL(href, window.location.origin); + if (url.origin === window.location.origin) { + const match = url.pathname.match(/^\/notes\/([^/]+)$/); + if (match) { + return match[1]; + } + } + } catch { + // Invalid URL + } + return null; + }; + /** * Handle link clicks - intercept same-origin app URLs for in-app navigation */ @@ -54,7 +73,10 @@ {:else if token.type === 'html'} {:else if token.type === 'link'} - {#if token.tokens} + {@const noteId = getNoteIdFromHref(token.href)} + {#if noteId} + + {:else if token.tokens} + import { onMount, getContext } from 'svelte'; + import { goto } from '$app/navigation'; + import { getNoteById } from '$lib/apis/notes'; + import { getUserInfoById } from '$lib/apis/users'; + import { capitalizeFirstLetter } from '$lib/utils'; + + const i18n = getContext('i18n'); + + export let noteId: string; + export let href: string; + + let title = ''; + let author = ''; + let loading = true; + + onMount(async () => { + try { + const note = await getNoteById(localStorage.token, noteId); + if (note) { + title = note.title || $i18n.t('Untitled'); + + if (note.user_id) { + try { + const userInfo = await getUserInfoById(localStorage.token, note.user_id); + if (userInfo) { + author = capitalizeFirstLetter(userInfo.name ?? userInfo.email ?? ''); + } + } catch { + // user lookup failed, skip author + } + } + } + } catch { + title = $i18n.t('Note'); + } finally { + loading = false; + } + }); + + + + +