(text: string, query: string, contextChars: number)
| 89 | return chalk.dim(before) + highlightColor(match) + chalk.dim(after); |
| 90 | } |
| 91 | function extractSnippet(text: string, query: string, contextChars: number): Snippet | null { |
| 92 | // Find exact query occurrence (case-insensitive). |
| 93 | // Note: Fuse does fuzzy matching, so this may miss some fuzzy matches. |
| 94 | // This is acceptable for now - in the future we could use Fuse's includeMatches |
| 95 | // option and work with the match indices directly. |
| 96 | const matchIndex = text.toLowerCase().indexOf(query.toLowerCase()); |
| 97 | if (matchIndex === -1) return null; |
| 98 | const matchEnd = matchIndex + query.length; |
| 99 | const snippetStart = Math.max(0, matchIndex - contextChars); |
| 100 | const snippetEnd = Math.min(text.length, matchEnd + contextChars); |
| 101 | const beforeRaw = text.slice(snippetStart, matchIndex); |
| 102 | const matchText = text.slice(matchIndex, matchEnd); |
| 103 | const afterRaw = text.slice(matchEnd, snippetEnd); |
| 104 | return { |
| 105 | before: (snippetStart > 0 ? '…' : '') + beforeRaw.replace(/\s+/g, ' ').trimStart(), |
| 106 | match: matchText.trim(), |
| 107 | after: afterRaw.replace(/\s+/g, ' ').trimEnd() + (snippetEnd < text.length ? '…' : '') |
| 108 | }; |
| 109 | } |
| 110 | function buildLogLabel(log: LogOption, maxLabelWidth: number, options?: { |
| 111 | isGroupHeader?: boolean; |
| 112 | isChild?: boolean; |
no test coverage detected