Timothy J. Baek 8 tháng trước cách đây
mục cha
commit
4ef042e966

+ 8 - 0
src/lib/components/chat/Messages/MarkdownInlineTokens.svelte

@@ -45,6 +45,14 @@
 		{#if token.text}
 			<KatexRenderer content={revertSanitizedResponseContent(token.text)} displayMode={false} />
 		{/if}
+	{:else if token.type === 'iframe'}
+		<iframe
+			src="{WEBUI_BASE_URL}/api/v1/files/{token.fileId}/content"
+			title={token.fileId}
+			width="100%"
+			frameborder="0"
+			onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"
+		></iframe>
 	{:else if token.type === 'text'}
 		{token.raw}
 	{/if}

+ 9 - 0
src/lib/components/chat/Messages/MarkdownTokens.svelte

@@ -7,6 +7,7 @@
 	import CodeBlock from '$lib/components/chat/Messages/CodeBlock.svelte';
 	import MarkdownInlineTokens from '$lib/components/chat/Messages/MarkdownInlineTokens.svelte';
 	import KatexRenderer from './KatexRenderer.svelte';
+	import { WEBUI_BASE_URL } from '$lib/constants';
 
 	export let id: string;
 	export let tokens: Token[];
@@ -98,6 +99,14 @@
 		{:else}
 			{token.text}
 		{/if}
+	{:else if token.type === 'iframe'}
+		<iframe
+			src="{WEBUI_BASE_URL}/api/v1/files/{token.fileId}/content"
+			title={token.fileId}
+			width="100%"
+			frameborder="0"
+			onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"
+		></iframe>
 	{:else if token.type === 'paragraph'}
 		<p>
 			<MarkdownInlineTokens id={`${id}-${tokenIdx}-p`} tokens={token.tokens ?? []} />

+ 3 - 1
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -76,13 +76,15 @@
 
 	import 'katex/dist/katex.min.css';
 
-	import markedKatex from '$lib/utils/katex-extension';
+	import markedKatex from '$lib/utils/marked/katex-extension';
+	import markedToken from '$lib/utils/marked/token-extension';
 
 	const options = {
 		throwOnError: false
 	};
 
 	marked.use(markedKatex(options));
+	marked.use(markedToken({ WEBUI_BASE_URL }));
 
 	$: (async () => {
 		if (message?.content) {

+ 0 - 7
src/lib/utils/index.ts

@@ -27,7 +27,6 @@ export const replaceTokens = (content, char, user) => {
 	const charToken = /{{char}}/gi;
 	const userToken = /{{user}}/gi;
 	const videoIdToken = /{{VIDEO_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the video ID
-	const htmlIdToken = /{{HTML_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the HTML ID
 
 	// Replace {{char}} if char is provided
 	if (char !== undefined && char !== null) {
@@ -45,12 +44,6 @@ export const replaceTokens = (content, char, user) => {
 		return `<video src="${videoUrl}" controls></video>`;
 	});
 
-	// Replace HTML ID tags with corresponding HTML content
-	content = content.replace(htmlIdToken, (match, fileId) => {
-		const htmlUrl = `${WEBUI_BASE_URL}/api/v1/files/${fileId}/content`;
-		return `<iframe src="${htmlUrl}" width="100%" frameborder="0" onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"></iframe>`;
-	});
-
 	return content;
 };
 

+ 0 - 0
src/lib/utils/katex-extension.ts → src/lib/utils/marked/katex-extension.ts


+ 57 - 0
src/lib/utils/marked/token-extension.ts

@@ -0,0 +1,57 @@
+export default function (options = {}) {
+	return {
+		extensions: [inlineIframeToken(options), blockIframeToken(options)]
+	};
+}
+
+const inlineIframeToken = (options = {}) => {
+	const WEBUI_BASE_URL = options.WEBUI_BASE_URL || '';
+	const htmlIdToken = /{{HTML_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the HTML ID
+	function tokenizer(src) {
+		const match = htmlIdToken.exec(src);
+		if (match) {
+			return {
+				type: 'iframe',
+				raw: match[0],
+				fileId: match[1]
+			};
+		}
+	}
+	function renderer(token) {
+		const htmlUrl = `${WEBUI_BASE_URL}/api/v1/files/${token.fileId}/content`;
+		const iframeElement = `<iframe src="${htmlUrl}" width="100%" frameborder="0" onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"></iframe>`;
+		return iframeElement;
+	}
+	return {
+		name: 'iframe',
+		level: 'inline',
+		tokenizer,
+		renderer
+	};
+};
+
+const blockIframeToken = (options = {}) => {
+	const WEBUI_BASE_URL = options.WEBUI_BASE_URL || '';
+	const htmlIdToken = /{{HTML_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the HTML ID
+	function tokenizer(src) {
+		const match = htmlIdToken.exec(src);
+		if (match) {
+			return {
+				type: 'iframe',
+				raw: match[0],
+				fileId: match[1]
+			};
+		}
+	}
+	function renderer(token) {
+		const htmlUrl = `${WEBUI_BASE_URL}/api/v1/files/${token.fileId}/content`;
+		const iframeElement = `<iframe src="${htmlUrl}" width="100%" frameborder="0" onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"></iframe>`;
+		return iframeElement;
+	}
+	return {
+		name: 'iframe',
+		level: 'block',
+		tokenizer,
+		renderer
+	};
+};