feat: add 5 lines context around search matches in accessibilitySnapshot, getCleanHTML, getLatestLogs

This commit is contained in:
Tommy D. Rossi
2026-01-12 15:36:51 +01:00
parent 2498b523a3
commit 7e7edac856
3 changed files with 94 additions and 18 deletions
+29 -6
View File
@@ -104,9 +104,10 @@ export async function getCleanHTML(options: GetCleanHTMLOptions): Promise<string
// Handle search
if (search) {
const lines = htmlStr.split('\n')
const matches: string[] = []
const matchIndices: number[] = []
for (const line of lines) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
let isMatch = false
if (isRegExp(search)) {
isMatch = search.test(line)
@@ -115,16 +116,38 @@ export async function getCleanHTML(options: GetCleanHTMLOptions): Promise<string
}
if (isMatch) {
matches.push(line)
if (matches.length >= 10) break
matchIndices.push(i)
if (matchIndices.length >= 10) break
}
}
if (matches.length === 0) {
if (matchIndices.length === 0) {
return 'No matches found'
}
return matches.join('\n')
// Collect lines with 5 lines of context above and below each match
const CONTEXT_LINES = 5
const includedLines = new Set<number>()
for (const idx of matchIndices) {
const start = Math.max(0, idx - CONTEXT_LINES)
const end = Math.min(lines.length - 1, idx + CONTEXT_LINES)
for (let i = start; i <= end; i++) {
includedLines.add(i)
}
}
// Build result with separators between non-contiguous sections
const sortedIndices = [...includedLines].sort((a, b) => a - b)
const result: string[] = []
for (let i = 0; i < sortedIndices.length; i++) {
const lineIdx = sortedIndices[i]
if (i > 0 && sortedIndices[i - 1] !== lineIdx - 1) {
result.push('---')
}
result.push(lines[lineIdx])
}
return result.join('\n')
}
return htmlStr
+2 -1
View File
@@ -979,7 +979,8 @@ describe('MCP Server Tests', () => {
const errorOutput = (errorLogsResult as any).content[0].text
expect(errorOutput).toContain('[error] Test error 67890')
expect(errorOutput).not.toContain('[log] Test log 12345')
// With context lines (5 above/below), nearby logs are also included
expect(errorOutput).toContain('[log] Test log 12345')
// Test that logs are cleared on page reload
await client.callTool({
+63 -11
View File
@@ -747,9 +747,10 @@ server.tool(
}
const lines = snapshotStr.split('\n')
const matches: string[] = []
const matchIndices: number[] = []
for (const line of lines) {
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
let isMatch = false
if (isRegExp(search)) {
isMatch = search.test(line)
@@ -758,16 +759,38 @@ server.tool(
}
if (isMatch) {
matches.push(line)
if (matches.length >= 10) break
matchIndices.push(i)
if (matchIndices.length >= 10) break
}
}
if (matches.length === 0) {
if (matchIndices.length === 0) {
return 'No matches found'
}
return matches.join('\n')
// Collect lines with 5 lines of context above and below each match
const CONTEXT_LINES = 5
const includedLines = new Set<number>()
for (const idx of matchIndices) {
const start = Math.max(0, idx - CONTEXT_LINES)
const end = Math.min(lines.length - 1, idx + CONTEXT_LINES)
for (let i = start; i <= end; i++) {
includedLines.add(i)
}
}
// Build result with separators between non-contiguous sections
const sortedIndices = [...includedLines].sort((a, b) => a - b)
const result: string[] = []
for (let i = 0; i < sortedIndices.length; i++) {
const lineIdx = sortedIndices[i]
if (i > 0 && sortedIndices[i - 1] !== lineIdx - 1) {
result.push('---')
}
result.push(lines[lineIdx])
}
return result.join('\n')
}
throw new Error('accessibilitySnapshot is not available on this page')
}
@@ -812,14 +835,43 @@ server.tool(
}
if (search) {
allLogs = allLogs.filter((log) => {
const matchIndices: number[] = []
for (let i = 0; i < allLogs.length; i++) {
const log = allLogs[i]
let isMatch = false
if (typeof search === 'string') {
return log.includes(search)
isMatch = log.includes(search)
} else if (isRegExp(search)) {
return search.test(log)
isMatch = search.test(log)
}
return false
})
if (isMatch) {
matchIndices.push(i)
}
}
// Collect logs with 5 lines of context above and below each match
const CONTEXT_LINES = 5
const includedIndices = new Set<number>()
for (const idx of matchIndices) {
const start = Math.max(0, idx - CONTEXT_LINES)
const end = Math.min(allLogs.length - 1, idx + CONTEXT_LINES)
for (let i = start; i <= end; i++) {
includedIndices.add(i)
}
}
// Build result with separators between non-contiguous sections
const sortedIndices = [...includedIndices].sort((a, b) => a - b)
const result: string[] = []
for (let i = 0; i < sortedIndices.length; i++) {
const logIdx = sortedIndices[i]
if (i > 0 && sortedIndices[i - 1] !== logIdx - 1) {
result.push('---')
}
result.push(allLogs[logIdx])
}
allLogs = result
}
return count !== undefined ? allLogs.slice(-count) : allLogs