]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/commitdiff
feat: render user content as markdown option (#16358)
authorPascal <redacted>
Sat, 11 Oct 2025 13:50:49 +0000 (15:50 +0200)
committerGitHub <redacted>
Sat, 11 Oct 2025 13:50:49 +0000 (15:50 +0200)
* feat: render user content as markdown option
- Add a persisted 'renderUserContentAsMarkdown' preference to the settings defaults and info metadata so the choice survives reloads like other options
- Surface the new 'Render user content as Markdown' checkbox in the General section of the chat settings dialog, beneath the PDF toggle
- Render user chat messages with 'MarkdownContent' when the new setting is enabled, matching assistant formatting while preserving the existing card styling otherwise
- chore: update webui build output

* chore: update webui build output

tools/server/public/index.html.gz
tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageUser.svelte
tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettingsDialog.svelte
tools/server/webui/src/lib/constants/settings-config.ts

index 5026edcebed37b7176eeaec592c60899b558a027..d0c44534efcb67291b81baa6f5d996dfd2e4d64e 100644 (file)
Binary files a/tools/server/public/index.html.gz and b/tools/server/public/index.html.gz differ
index 66369b2f1ce1094e42226a7cd8c5d8c948d611c9..cc2631b830c3eca2fa523b40c8116ee6e26bf05a 100644 (file)
@@ -2,8 +2,9 @@
        import { Check, X } from '@lucide/svelte';
        import { Card } from '$lib/components/ui/card';
        import { Button } from '$lib/components/ui/button';
-       import { ChatAttachmentsList } from '$lib/components/app';
+       import { ChatAttachmentsList, MarkdownContent } from '$lib/components/app';
        import { INPUT_CLASSES } from '$lib/constants/input-classes';
+       import { config } from '$lib/stores/settings.svelte';
        import ChatMessageActions from './ChatMessageActions.svelte';
 
        interface Props {
@@ -55,6 +56,7 @@
 
        let isMultiline = $state(false);
        let messageElement: HTMLElement | undefined = $state();
+       const currentConfig = config();
 
        $effect(() => {
                if (!messageElement || !message.content.trim()) return;
                                class="max-w-[80%] rounded-[1.125rem] bg-primary px-3.75 py-1.5 text-primary-foreground data-[multiline]:py-2.5"
                                data-multiline={isMultiline ? '' : undefined}
                        >
-                               <span bind:this={messageElement} class="text-md whitespace-pre-wrap">
-                                       {message.content}
-                               </span>
+                               {#if currentConfig.renderUserContentAsMarkdown}
+                                       <div bind:this={messageElement} class="text-md">
+                                               <MarkdownContent
+                                                       class="markdown-user-content text-primary-foreground"
+                                                       content={message.content}
+                                               />
+                                       </div>
+                               {:else}
+                                       <span bind:this={messageElement} class="text-md whitespace-pre-wrap">
+                                               {message.content}
+                                       </span>
+                               {/if}
                        </Card>
                {/if}
 
index 7c25e5925882961dfd5bef903004fe355200d941..dc617afdcd4cdc61bc20f9298d4fe0a702347c73 100644 (file)
                                        key: 'showModelInfo',
                                        label: 'Show model information',
                                        type: 'checkbox'
+                               },
+                               {
+                                       key: 'renderUserContentAsMarkdown',
+                                       label: 'Render user content as Markdown',
+                                       type: 'checkbox'
                                }
                        ]
                },
index 63e4364ae5656a4809d4d5a893f9e2edabb2474d..154ec888ce2dc7c9f2e2b517281c52c10ef497cc 100644 (file)
@@ -12,6 +12,7 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
        pasteLongTextToFileLen: 2500,
        pdfAsImage: false,
        showModelInfo: false,
+       renderUserContentAsMarkdown: false,
        // make sure these default values are in sync with `common.h`
        samplers: 'top_k;typ_p;top_p;min_p;temperature',
        temperature: 0.8,
@@ -84,6 +85,7 @@ export const SETTING_CONFIG_INFO: Record<string, string> = {
                'Ask for confirmation before automatically changing conversation title when editing the first message.',
        pdfAsImage: 'Parse PDF as image instead of text (requires vision-capable model).',
        showModelInfo: 'Display the model name used to generate each message below the message content.',
+       renderUserContentAsMarkdown: 'Render user messages using markdown formatting in the chat.',
        pyInterpreterEnabled:
                'Enable Python interpreter using Pyodide. Allows running Python code in markdown code blocks.'
 };