From 1e4d66cbe4a6fd0dc4bac3b9f6005111512ee1a6 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Wed, 18 Mar 2026 11:23:06 -0700 Subject: [PATCH] Fix log search filtering to match against plain text instead of ANSI escape codes Move styles array outside the parse loop in ansiToHtml so styles accumulate across sequences, and use stripAnsi when filtering live logs so search matches visible text. --- src/client/ansi.ts | 2 +- src/client/components/LogsSection.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/ansi.ts b/src/client/ansi.ts index 8a770c2..dadff9d 100644 --- a/src/client/ansi.ts +++ b/src/client/ansi.ts @@ -34,6 +34,7 @@ export function ansiToHtml(text: string): string { let result = '' let last = 0 let open = false + const styles: string[] = [] let match: RegExpExecArray | null while ((match = ESC.exec(text)) !== null) { @@ -41,7 +42,6 @@ export function ansiToHtml(text: string): string { last = match.index + match[0].length const codes = match[1] ? match[1].split(';').map(Number) : [0] - const styles: string[] = [] for (const code of codes) { if (code === 0) { diff --git a/src/client/components/LogsSection.tsx b/src/client/components/LogsSection.tsx index effac3d..1ee90f3 100644 --- a/src/client/components/LogsSection.tsx +++ b/src/client/components/LogsSection.tsx @@ -1,6 +1,6 @@ import { define } from '@because/forge' import type { App, LogLine as LogLineType } from '../../shared/types' -import { ansiToHtml } from '../ansi' +import { ansiToHtml, stripAnsi } from '../ansi' import { getLogDates, getLogsForDate } from '../api' import { isNarrow } from '../state' import { LogLine, LogsContainer, LogsHeader, LogTime, Section, SectionTitle } from '../styles' @@ -92,7 +92,7 @@ function LogsContent() { const state = getState(currentApp.name) const isLive = state.selectedDate === 'live' - const filteredLiveLogs = filterLogs(currentApp.logs ?? [], state.searchFilter, l => l.text) + const filteredLiveLogs = filterLogs(currentApp.logs ?? [], state.searchFilter, l => stripAnsi(l.text)) const filteredHistoricalLogs = filterLogs(state.historicalLogs, state.searchFilter, l => l) return (