fix: render bold and inline code formatting in list items

This commit is contained in:
shokollm
2026-04-10 13:14:17 +00:00
parent 36dcfdb6e2
commit 7795753aaa
2 changed files with 37 additions and 6 deletions

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { Bot } from '$lib/api'; import type { Bot } from '$lib/api';
import type { ChatMessage } from '$lib/stores/chatStore'; import type { ChatMessage } from '$lib/stores/chatStore';
import { parseMarkdown } from '$lib/utils/markdown'; import { parseMarkdown, parseInlineElements, type InlineSegment } from '$lib/utils/markdown';
interface Props { interface Props {
bot: Bot | null; bot: Bot | null;
@@ -62,6 +62,18 @@
function renderContent(content: string) { function renderContent(content: string) {
return parseMarkdown(content); return parseMarkdown(content);
} }
function renderInline(segments: InlineSegment[]): string {
return segments.map(seg => {
switch (seg.type) {
case 'bold': return `<strong>${seg.content}</strong>`;
case 'italic': return `<em>${seg.content}</em>`;
case 'code': return `<code class="inline-code">${seg.content}</code>`;
case 'link': return `<a href="${seg.href || '#'}" target="_blank" rel="noopener noreferrer">${seg.content}</a>`;
default: return seg.content;
}
}).join('');
}
</script> </script>
<div class="chat-interface"> <div class="chat-interface">
@@ -121,7 +133,7 @@
{:else if segment.type === 'list' && segment.items} {:else if segment.type === 'list' && segment.items}
<ul> <ul>
{#each segment.items as item} {#each segment.items as item}
<li>{item}</li> <li>{@html renderInline(parseInlineElements(item))}</li>
{/each} {/each}
</ul> </ul>
{:else if segment.type === 'table' && segment.headers && segment.rows} {:else if segment.type === 'table' && segment.headers && segment.rows}

View File

@@ -134,6 +134,19 @@ function parseInlineElements(text: string): InlineSegment[] {
return segments; return segments;
} }
// Render inline segments to HTML string
function renderInlineSegments(segments: InlineSegment[]): string {
return segments.map(seg => {
switch (seg.type) {
case 'bold': return `<strong>${seg.content}</strong>`;
case 'italic': return `<em>${seg.content}</em>`;
case 'code': return `<code class="inline-code">${seg.content}</code>`;
case 'link': return `<a href="${seg.href || '#'}" target="_blank" rel="noopener noreferrer">${seg.content}</a>`;
default: return seg.content;
}
}).join('');
}
function parseLines(text: string): ParsedSegment[] { function parseLines(text: string): ParsedSegment[] {
const segments: ParsedSegment[] = []; const segments: ParsedSegment[] = [];
@@ -160,12 +173,16 @@ function parseLines(text: string): ParsedSegment[] {
if (line.match(/^[\-\*]\s/)) { if (line.match(/^[\-\*]\s/)) {
const listMatch = line.match(/^([\-\*])\s(.*)/); const listMatch = line.match(/^([\-\*])\s(.*)/);
if (listMatch) { if (listMatch) {
// Parse inline formatting for list item
const itemContent = listMatch[2];
const inlineSegments = parseInlineElements(itemContent);
// Check if previous segment is a list // Check if previous segment is a list
const lastSeg = segments[segments.length - 1]; const lastSeg = segments[segments.length - 1];
if (lastSeg && lastSeg.type === 'list') { if (lastSeg && lastSeg.type === 'list') {
lastSeg.items?.push(listMatch[2]); lastSeg.items?.push(itemContent);
} else { } else {
segments.push({ type: 'list', content: '', items: [listMatch[2]] }); segments.push({ type: 'list', content: '', items: [itemContent] });
} }
} }
continue; continue;
@@ -175,11 +192,13 @@ function parseLines(text: string): ParsedSegment[] {
if (line.match(/^\d+\.\s/)) { if (line.match(/^\d+\.\s/)) {
const listMatch = line.match(/^\d+\.\s(.*)/); const listMatch = line.match(/^\d+\.\s(.*)/);
if (listMatch) { if (listMatch) {
const itemContent = listMatch[1];
const lastSeg = segments[segments.length - 1]; const lastSeg = segments[segments.length - 1];
if (lastSeg && lastSeg.type === 'list') { if (lastSeg && lastSeg.type === 'list') {
lastSeg.items?.push(listMatch[1]); lastSeg.items?.push(itemContent);
} else { } else {
segments.push({ type: 'list', content: '', items: [listMatch[1]] }); segments.push({ type: 'list', content: '', items: [itemContent] });
} }
} }
continue; continue;