Ver código fonte

feat: preview html

Timothy Jaeryang Baek 4 meses atrás
pai
commit
54dc24986f

+ 9 - 2
src/lib/components/chat/Artifacts.svelte

@@ -4,7 +4,7 @@
 	const i18n = getContext('i18n');
 	const dispatch = createEventDispatcher();
 
-	import { chatId, settings, showArtifacts, showControls } from '$lib/stores';
+	import { artifactCode, chatId, settings, showArtifacts, showControls } from '$lib/stores';
 	import XMark from '../icons/XMark.svelte';
 	import { copyToClipboard, createMessagesList } from '$lib/utils';
 	import ArrowsPointingOut from '../icons/ArrowsPointingOut.svelte';
@@ -180,7 +180,14 @@
 		}
 	};
 
-	onMount(() => {});
+	onMount(() => {
+		artifactCode.subscribe((value) => {
+			if (contents) {
+				const codeIdx = contents.findIndex((content) => content.content.includes(value));
+				selectedContentIdx = codeIdx !== -1 ? codeIdx : 0;
+			}
+		});
+	});
 </script>
 
 <div class=" w-full h-full relative flex flex-col bg-gray-50 dark:bg-gray-850">

+ 0 - 2
src/lib/components/chat/MessageInput.svelte

@@ -957,8 +957,6 @@
 																? (e.key === 'Enter' || e.keyCode === 13) && isCtrlPressed
 																: (e.key === 'Enter' || e.keyCode === 13) && !e.shiftKey;
 
-														console.log('Enter pressed:', enterPressed);
-
 														if (enterPressed) {
 															e.preventDefault();
 														}

+ 24 - 2
src/lib/components/chat/Messages/CodeBlock.svelte

@@ -17,6 +17,7 @@
 	import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
 	import ChevronUpDown from '$lib/components/icons/ChevronUpDown.svelte';
 	import CommandLine from '$lib/components/icons/CommandLine.svelte';
+	import Cube from '$lib/components/icons/Cube.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -24,9 +25,11 @@
 
 	export let onSave = (e) => {};
 	export let onCode = (e) => {};
+	export let onPreview = (e) => {};
 
 	export let save = false;
 	export let run = true;
+	export let preview = false;
 	export let collapsed = false;
 
 	export let token;
@@ -88,6 +91,10 @@
 		}, 1000);
 	};
 
+	const previewCode = () => {
+		onPreview(code);
+	};
+
 	const checkPythonCode = (str) => {
 		// Check if the string contains typical Python syntax characters
 		const pythonSyntax = [
@@ -430,7 +437,7 @@
 						class="flex gap-1 items-center bg-none border-none bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-md px-1.5 py-0.5"
 						on:click={collapseCodeBlock}
 					>
-						<div>
+						<div class=" -translate-y-[0.5px]">
 							<ChevronUpDown className="size-3" />
 						</div>
 
@@ -439,6 +446,21 @@
 						</div>
 					</button>
 
+					{#if preview && ['html', 'svg'].includes(lang)}
+						<button
+							class="flex gap-1 items-center run-code-button bg-none border-none bg-gray-50 hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition rounded-md px-1.5 py-0.5"
+							on:click={previewCode}
+						>
+							<div class=" -translate-y-[0.5px]">
+								<Cube className="size-3" />
+							</div>
+
+							<div>
+								{$i18n.t('Preview')}
+							</div>
+						</button>
+					{/if}
+
 					{#if ($config?.features?.enable_code_execution ?? true) && (lang.toLowerCase() === 'python' || lang.toLowerCase() === 'py' || (lang === '' && checkPythonCode(code)))}
 						{#if executing}
 							<div class="run-code-button bg-none border-none p-1 cursor-not-allowed">
@@ -453,7 +475,7 @@
 									executePython(code);
 								}}
 							>
-								<div>
+								<div class=" -translate-y-[0.5px]">
 									<CommandLine className="size-3" />
 								</div>
 

+ 19 - 5
src/lib/components/chat/Messages/ContentRenderer.svelte

@@ -1,10 +1,17 @@
 <script>
-	import { onDestroy, onMount, tick, getContext, createEventDispatcher } from 'svelte';
+	import { onDestroy, onMount, tick, getContext } from 'svelte';
 	const i18n = getContext('i18n');
-	const dispatch = createEventDispatcher();
 
 	import Markdown from './Markdown.svelte';
-	import { chatId, mobile, settings, showArtifacts, showControls, showOverview } from '$lib/stores';
+	import {
+		artifactCode,
+		chatId,
+		mobile,
+		settings,
+		showArtifacts,
+		showControls,
+		showOverview
+	} from '$lib/stores';
 	import FloatingButtons from '../ContentRenderer/FloatingButtons.svelte';
 	import { createMessagesList } from '$lib/utils';
 
@@ -15,8 +22,10 @@
 	export let sources = null;
 
 	export let save = false;
+	export let preview = false;
 	export let floatingButtons = true;
 
+	export let onUpdate = () => {};
 	export let onSourceClick = () => {};
 	export let onTaskClick = () => {};
 
@@ -122,6 +131,7 @@
 		{content}
 		{model}
 		{save}
+		{preview}
 		sourceIds={(sources ?? []).reduce((acc, s) => {
 			let ids = [];
 			s.document.forEach((document, index) => {
@@ -154,8 +164,12 @@
 		}, [])}
 		{onSourceClick}
 		{onTaskClick}
-		onUpdate={(value) => {
-			dispatch('update', value);
+		{onUpdate}
+		onPreview={async (value) => {
+			await artifactCode.set(value);
+			await showControls.set(true);
+			await showArtifacts.set(true);
+			await showOverview.set(false);
 		}}
 		onCode={(value) => {
 			const { lang, code } = value;

+ 13 - 1
src/lib/components/chat/Messages/Markdown.svelte

@@ -12,11 +12,13 @@
 	export let content;
 	export let model = null;
 	export let save = false;
+	export let preview = false;
 
 	export let sourceIds = [];
 
 	export let onUpdate = () => {};
 	export let onCode = () => {};
+	export let onPreview = () => {};
 
 	export let onSourceClick = () => {};
 	export let onTaskClick = () => {};
@@ -40,5 +42,15 @@
 </script>
 
 {#key id}
-	<MarkdownTokens {tokens} {id} {save} {onTaskClick} {onSourceClick} {onUpdate} {onCode} />
+	<MarkdownTokens
+		{tokens}
+		{id}
+		{save}
+		{preview}
+		{onTaskClick}
+		{onSourceClick}
+		{onUpdate}
+		{onCode}
+		{onPreview}
+	/>
 {/key}

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

@@ -29,9 +29,11 @@
 	export let attributes = {};
 
 	export let save = false;
+	export let preview = false;
 
 	export let onUpdate: Function = () => {};
 	export let onCode: Function = () => {};
+	export let onPreview: Function = () => {};
 
 	export let onTaskClick: Function = () => {};
 	export let onSourceClick: Function = () => {};
@@ -95,7 +97,9 @@
 				code={token?.text ?? ''}
 				{attributes}
 				{save}
+				{preview}
 				{onCode}
+				{onPreview}
 				onSave={(value) => {
 					onUpdate({
 						raw: token.raw,

+ 2 - 16
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -806,6 +806,7 @@
 										sources={message.sources}
 										floatingButtons={message?.done && !readOnly}
 										save={!readOnly}
+										preview={!readOnly}
 										{model}
 										onTaskClick={async (e) => {
 											console.log(e);
@@ -840,28 +841,13 @@
 										onAddMessages={({ modelId, parentId, messages }) => {
 											addMessages({ modelId, parentId, messages });
 										}}
-										on:update={(e) => {
-											const { raw, oldContent, newContent } = e.detail;
-
+										onUpdate={({ raw, oldContent, newContent }) => {
 											history.messages[message.id].content = history.messages[
 												message.id
 											].content.replace(raw, raw.replace(oldContent, newContent));
 
 											updateChat();
 										}}
-										on:select={(e) => {
-											const { type, content } = e.detail;
-
-											if (type === 'explain') {
-												submitMessage(
-													message.id,
-													`Explain this section to me in more detail\n\n\`\`\`\n${content}\n\`\`\``
-												);
-											} else if (type === 'ask') {
-												const input = e.detail?.input ?? '';
-												submitMessage(message.id, `\`\`\`\n${content}\n\`\`\`\n${input}`);
-											}
-										}}
 									/>
 								{/if}
 

+ 2 - 0
src/lib/stores/index.ts

@@ -74,6 +74,8 @@ export const showOverview = writable(false);
 export const showArtifacts = writable(false);
 export const showCallOverlay = writable(false);
 
+export const artifactCode = writable(null);
+
 export const temporaryChatEnabled = writable(false);
 export const scrollPaginationEnabled = writable(false);
 export const currentChatPage = writable(1);