From 43225293d08ba9e4f6a3859d776a16f2cd8952a6 Mon Sep 17 00:00:00 2001 From: Jimmycai Date: Fri, 6 Jun 2025 23:07:46 +0800 Subject: [PATCH 1/2] fix: TaskItem display and copy issues with HTML tags in task messages. * Display issue: HTML tags not displaying in HistoryView. * Copy issue: HTML tags in message are removed when clicking the copy button in TaskItem. --- webview-ui/src/components/history/CopyButton.tsx | 5 +---- webview-ui/src/components/history/TaskItem.tsx | 10 +++++++--- webview-ui/src/components/history/useTaskSearch.ts | 2 +- webview-ui/src/utils/highlight.ts | 14 +++++++++++++- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/webview-ui/src/components/history/CopyButton.tsx b/webview-ui/src/components/history/CopyButton.tsx index b6fff490a7..e9a2155a6f 100644 --- a/webview-ui/src/components/history/CopyButton.tsx +++ b/webview-ui/src/components/history/CopyButton.tsx @@ -16,12 +16,9 @@ export const CopyButton = ({ itemTask }: CopyButtonProps) => { const onCopy = useCallback( (e: React.MouseEvent) => { e.stopPropagation() - const tempDiv = document.createElement("div") - tempDiv.innerHTML = itemTask - const text = tempDiv.textContent || tempDiv.innerText || "" if (!isCopied) { - copy(text) + copy(itemTask) } }, [isCopied, copy, itemTask], diff --git a/webview-ui/src/components/history/TaskItem.tsx b/webview-ui/src/components/history/TaskItem.tsx index 635be2e351..9b07ca5d96 100644 --- a/webview-ui/src/components/history/TaskItem.tsx +++ b/webview-ui/src/components/history/TaskItem.tsx @@ -9,8 +9,12 @@ import { useAppTranslation } from "@/i18n/TranslationContext" import TaskItemHeader from "./TaskItemHeader" import TaskItemFooter from "./TaskItemFooter" +interface DisplayHistoryItem extends HistoryItem { + highlight?: string +} + interface TaskItemProps { - item: HistoryItem + item: DisplayHistoryItem variant: "compact" | "full" showWorkspace?: boolean isSelectionMode?: boolean @@ -103,8 +107,8 @@ const TaskItem = ({ overflowWrap: "anywhere", }} data-testid={isCompact ? undefined : "task-content"} - {...(isCompact ? {} : { dangerouslySetInnerHTML: { __html: item.task } })}> - {isCompact ? item.task : undefined} + {...(item.highlight ? { dangerouslySetInnerHTML: { __html: item.highlight } } : {})}> + {item.highlight ? undefined : item.task} {/* Task Item Footer */} diff --git a/webview-ui/src/components/history/useTaskSearch.ts b/webview-ui/src/components/history/useTaskSearch.ts index 47d5c3719c..3969985b98 100644 --- a/webview-ui/src/components/history/useTaskSearch.ts +++ b/webview-ui/src/components/history/useTaskSearch.ts @@ -48,7 +48,7 @@ export const useTaskSearch = () => { return { ...result.item, - task: highlightFzfMatch( + highlight: highlightFzfMatch( result.item.task, positions.filter((p) => p < taskEndIndex), ), diff --git a/webview-ui/src/utils/highlight.ts b/webview-ui/src/utils/highlight.ts index fe8f3c49a7..d781d60092 100644 --- a/webview-ui/src/utils/highlight.ts +++ b/webview-ui/src/utils/highlight.ts @@ -1,3 +1,12 @@ +function escapeHtml(text: string): string { + return text + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'") +} + export function highlightFzfMatch( text: string, positions: number[], @@ -39,6 +48,9 @@ export function highlightFzfMatch( // Build final string return parts - .map((part) => (part.highlight ? `${part.text}` : part.text)) + .map((part) => { + const escapedText = escapeHtml(part.text) + return part.highlight ? `${escapedText}` : escapedText + }) .join("") } From 37bd655c2a6eb05e87128cf1115e14051c316ed4 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Sat, 7 Jun 2025 23:11:30 -0500 Subject: [PATCH 2/2] perf(webview-ui): add LRU cache to escapeHtml function - Add LRU cache with 500 item limit for escapeHtml results - Improves performance by caching frequently escaped strings - Reduces redundant HTML escaping operations --- webview-ui/src/utils/highlight.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/webview-ui/src/utils/highlight.ts b/webview-ui/src/utils/highlight.ts index d781d60092..21c84f993a 100644 --- a/webview-ui/src/utils/highlight.ts +++ b/webview-ui/src/utils/highlight.ts @@ -1,10 +1,27 @@ +import { LRUCache } from "lru-cache" + +// LRU cache for escapeHtml with reasonable size limit +const escapeHtmlCache = new LRUCache({ max: 500 }) + function escapeHtml(text: string): string { - return text + // Check cache first + const cached = escapeHtmlCache.get(text) + if (cached !== undefined) { + return cached + } + + // Compute escaped text + const escaped = text .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'") + + // Cache the result + escapeHtmlCache.set(text, escaped) + + return escaped } export function highlightFzfMatch(