diff --git a/newsfragments/fix-ANSI-garbage-output-in-builds-steps-logs.bugfix b/newsfragments/fix-ANSI-garbage-output-in-builds-steps-logs.bugfix new file mode 100644 index 00000000000..dc469978e44 --- /dev/null +++ b/newsfragments/fix-ANSI-garbage-output-in-builds-steps-logs.bugfix @@ -0,0 +1 @@ +Fix garbage output of ANSI escape codes sequences in builds steps logs (:bug:`7852`) diff --git a/www/base/src/util/LogChunkParsing.test.ts b/www/base/src/util/LogChunkParsing.test.ts index d10e89d9c6c..4fca3ef7450 100644 --- a/www/base/src/util/LogChunkParsing.test.ts +++ b/www/base/src/util/LogChunkParsing.test.ts @@ -76,19 +76,19 @@ describe('LogChunkParsing', () => { const chunkCssClasses = parseCssClassesForChunk(chunk, 20, 23); expect(chunkCssClasses).toEqual({ - 20: ["DEBUG [plugin]: Loading plugin karma-jasmine.", + 0: ["DEBUG [plugin]: Loading plugin karma-jasmine.", [ {cssClasses: "ansi36", firstPos: 0, lastPos: 16}, {cssClasses: "", firstPos: 16, lastPos: 45}, ], ], - 21: [".F", + 1: [".F", [ {cssClasses: "ansi32", firstPos: 0, lastPos: 1}, {cssClasses: "ansi31", firstPos: 1, lastPos: 2}, ], ], - 22: ["..", + 2: ["..", [ {cssClasses: "ansi32", firstPos: 0, lastPos: 1}, {cssClasses: "ansi32", firstPos: 1, lastPos: 2}, diff --git a/www/base/src/util/LogChunkParsing.tsx b/www/base/src/util/LogChunkParsing.tsx index 45d9f1bd239..5254b20b2f5 100644 --- a/www/base/src/util/LogChunkParsing.tsx +++ b/www/base/src/util/LogChunkParsing.tsx @@ -210,10 +210,10 @@ export function mergeChunks(chunk1: ParsedLogChunk, chunk2: ParsedLogChunk): Par export type ChunkCssClasses = {[globalLine: number]: [string, LineCssClasses[]]}; // Parses ansi escape code information for a span of lines in a particular chunk. Returns a map -// containing key-value pairs, where each key-value pair represents a line with at least on escape -// code. The key is line number and value is a tuple containing the line text with escape -// sequences removed and a list of CSS classes to style the line. The line text and the -// text positions in the list exclude any trailing newlines. +// containing key-value pairs, where each key-value pair represents a line with at least one escape +// code. The key is line index relative to beginning of a specific chunk and value is a tuple +// containing the line text with escape sequences removed and a list of CSS classes to style the +// line. The line text and the text positions in the list exclude any trailing newlines. export function parseCssClassesForChunk(chunk: ParsedLogChunk, firstLine: number, lastLine: number) { const cssClasses: ChunkCssClasses = {}; @@ -227,11 +227,11 @@ export function parseCssClassesForChunk(chunk: ParsedLogChunk, if (lastLine > chunk.lastLine) { lastLine = chunk.lastLine; } + const chunkFirstLine = firstLine - chunk.firstLine; + const chunkLastLine = lastLine - chunk.firstLine; if (chunk.linesWithEscapes !== null) { // small number of escaped lines - const chunkFirstLine = firstLine - chunk.firstLine; - const chunkLastLine = lastLine - chunk.firstLine; for (const chunkLineI of chunk.linesWithEscapes) { if (chunkLineI < chunkFirstLine) { // It probably makes sense to use binary search in this loop @@ -250,10 +250,9 @@ export function parseCssClassesForChunk(chunk: ParsedLogChunk, } } else { // large number of escape sequences - for (let lineI = firstLine; lineI < lastLine; ++lineI) { - const chunkLineI = lineI - chunk.firstLine; + for (let lineI = chunkFirstLine; lineI < chunkLastLine; ++lineI) { const chunkLine = chunk.text.slice( - chunk.textLineBounds[chunkLineI], chunk.textLineBounds[chunkLineI + 1] - 1); + chunk.textLineBounds[lineI], chunk.textLineBounds[lineI + 1] - 1); const [strippedLine, lineCssClasses] = parseEscapeCodesToClasses(chunkLine); if (lineCssClasses !== null) {