Skip to content

Commit fa4fe7f

Browse files
committed
WIP feat: syntax highlight css in pretty reporter
1 parent 2650792 commit fa4fe7f

File tree

2 files changed

+82
-29
lines changed

2 files changed

+82
-29
lines changed

src/cli/reporters/pretty.test.ts

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ test.describe('with --min-file-line-coverage', () => {
249249
expect(lines[4]).toEqual(lines[0])
250250
})
251251
test('shows file name', () => {
252-
expect(lines[1]).toEqual('example.com')
252+
expect(lines[1]).toEqual('File: example.com')
253253
})
254254
test('shows coverage info', () => {
255255
expect(lines[2]).toEqual('Coverage: 42.11%, 8/19 lines covered')
@@ -262,29 +262,31 @@ test.describe('with --min-file-line-coverage', () => {
262262
expect(snapshot).toEqual(
263263
`
264264
────────────────────────────────────────────────────────────
265-
example.com
265+
File: example.com
266266
Coverage: 42.11%, 8/19 lines covered
267267
Tip: cover 11 more lines to meet the file threshold of 100%
268268
────────────────────────────────────────────────────────────
269-
1 ━ a {
270-
2 ━ color: red;
271-
3 ━ }
272-
4 │
273-
5 │ a1 {
274-
6 │ color: blue;
275-
7 │ }
276-
8 │
277-
9 ━ b {
278-
10 ━ color: red;
279-
11 ━ }
280-
12 │
281-
13 │ b1 {
282-
14 │ color: blue;
283-
15 │ }
284-
16 │
285-
17 ━ c {
286-
18 ━ color: red;
287-
19 ━ }`.trim(),
269+
▌ 1 │ a {
270+
▌ 2 │ color: red;
271+
▌ 3 │ }
272+
4 │
273+
5 │ a1 {
274+
6 │ color: blue;
275+
276+
6 │ color: blue;
277+
7 │ }
278+
8 │
279+
▌ 9 │ b {
280+
▌ 10 │ color: red;
281+
▌ 11 │ }
282+
12 │
283+
13 │ b1 {
284+
14 │ color: blue;
285+
15 │ }
286+
16 │
287+
▌ 17 │ c {
288+
▌ 18 │ color: red;
289+
▌ 19 │ }`.trim(),
288290
)
289291
})
290292
})

src/cli/reporters/pretty.ts

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,24 @@ function indent(line?: string): string {
88
return (line || '').replace(/^\t+/, (tabs) => ' '.repeat(tabs.length * 4))
99
}
1010

11-
let line_number = (num: number, covered: boolean = true) => `${num.toString().padStart(5, ' ')} ${covered ? '│' : '━'} `
11+
let line_number = (num: number) => `${num.toString().padStart(5, ' ')} `
1212

1313
function percentage(ratio: number, decimals: number = 2): string {
1414
return `${(ratio * 100).toFixed(ratio === 1 ? 0 : decimals)}%`
1515
}
1616

17-
export type TextStyle = 'bold' | 'red' | 'dim' | 'green'
17+
export type TextStyle =
18+
| 'bold'
19+
| 'red'
20+
| 'dim'
21+
| 'green'
22+
| 'magenta'
23+
| 'cyan'
24+
| 'blue'
25+
| 'blueBright'
26+
| 'magentaBright'
27+
| 'cyanBright'
28+
| 'greenBright'
1829

1930
type StyleTextFn = (style: TextStyle | TextStyle[], input: string) => string
2031

@@ -23,6 +34,46 @@ export type PrintLinesDependencies = {
2334
print_width?: number
2435
}
2536

37+
function highlight(css: string, styleText: StyleTextFn): string {
38+
// atrule
39+
if (css.trim().startsWith('@')) {
40+
let at_pos = css.indexOf('@')
41+
let space_pos = css.indexOf(' ', at_pos)
42+
let name = css.slice(0, space_pos)
43+
let is_empty = css.endsWith('{}')
44+
let prelude = css.slice(space_pos, is_empty ? -2 : -1)
45+
return [styleText('blueBright', name), styleText('magentaBright', prelude), is_empty ? '{}' : '{'].join('')
46+
}
47+
48+
// declaration
49+
if (css.includes(':') && css.endsWith(';')) {
50+
return [styleText('cyanBright', css.slice(0, css.indexOf(':'))), ':', css.slice(css.indexOf(':') + 1, css.length - 1), ';'].join('')
51+
}
52+
53+
// Empty rule
54+
if (css.endsWith('{}')) {
55+
return [styleText('greenBright', css.slice(0, -2)), '{}'].join('')
56+
}
57+
58+
// Closing }
59+
if (css.endsWith('}')) {
60+
return css
61+
}
62+
63+
// empty line
64+
if (css.trim() === '') {
65+
return css
66+
}
67+
68+
// selector,
69+
if (css.endsWith(',')) {
70+
return [styleText('greenBright', css.slice(0, -1)), ','].join('')
71+
}
72+
73+
// selector {
74+
return [styleText('greenBright', css.slice(0, -1)), '{'].join('')
75+
}
76+
2677
export function print_lines({ report, context }: Report, params: CliArguments, { styleText, print_width }: PrintLinesDependencies) {
2778
let output: (string | undefined)[] = []
2879

@@ -78,7 +129,7 @@ export function print_lines({ report, context }: Report, params: CliArguments, {
78129
) {
79130
output.push()
80131
output.push(styleText('dim', '─'.repeat(print_width)))
81-
output.push(sheet.url)
132+
output.push(`File: ${sheet.url}`)
82133
output.push(`Coverage: ${percentage(sheet.line_coverage_ratio)}, ${sheet.covered_lines}/${sheet.total_lines} lines covered`)
83134

84135
if (min_file_line_coverage && min_file_line_coverage !== 0 && sheet.line_coverage_ratio < min_file_line_coverage) {
@@ -96,18 +147,18 @@ export function print_lines({ report, context }: Report, params: CliArguments, {
96147
for (let chunk of sheet.chunks.filter((chunk) => !chunk.is_covered)) {
97148
// Render N leading lines
98149
for (let x = Math.max(chunk.start_line - NUM_LEADING_LINES, 1); x < chunk.start_line; x++) {
99-
output.push([styleText('dim', line_number(x)), styleText('dim', indent(lines[x - 1]))].join(''))
150+
output.push([' ', styleText('dim', line_number(x)), styleText('dim', indent(lines[x - 1]))].join(''))
100151
}
101152
// Render the uncovered chunk
102153
for (let i = chunk.start_line; i <= chunk.end_line; i++) {
103-
output.push([styleText('red', line_number(i, false)), indent(lines[i - 1])].join(''))
154+
output.push([styleText('red', '▌'), styleText('dim', line_number(i)), highlight(indent(lines[i - 1]), styleText)].join(''))
104155
}
105156
// Render N trailing lines
106-
for (let y = chunk.end_line + 1; y < Math.min(chunk.end_line + NUM_TRAILING_LINES, lines.length); y++) {
107-
output.push([styleText('dim', line_number(y)), styleText('dim', indent(lines[y - 1]))].join(''))
157+
for (let y = chunk.end_line + 1; y < Math.min(chunk.end_line + NUM_TRAILING_LINES + 1, lines.length); y++) {
158+
output.push([' ', styleText('dim', line_number(y)), styleText('dim', indent(lines[y - 1]))].join(''))
108159
}
109160
// Show empty line between blocks
110-
output.push()
161+
output.push('')
111162
}
112163
}
113164
}

0 commit comments

Comments
 (0)