Skip to content

Commit 284fc11

Browse files
committed
move calculate_styleshete_coverage out of main fn
1 parent 88a40af commit 284fc11

File tree

1 file changed

+109
-109
lines changed

1 file changed

+109
-109
lines changed

src/lib/index.ts

Lines changed: 109 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,114 @@ function ratio(fraction: number, total: number) {
3838
return fraction / total
3939
}
4040

41+
function calculate_stylesheet_coverage({ text, url, ranges }: Coverage) {
42+
function is_line_covered(line: string, start_offset: number) {
43+
let end = start_offset + line.length
44+
let next_offset = end + 1 // account for newline character
45+
let is_empty = /^\s*$/.test(line)
46+
let is_closing_brace = line.endsWith('}')
47+
48+
if (!is_empty && !is_closing_brace) {
49+
for (let range of ranges) {
50+
if (range.start > end || range.end < start_offset) {
51+
continue
52+
}
53+
if (range.start <= start_offset && range.end >= end) {
54+
return true
55+
} else if (line.startsWith('@') && range.start > start_offset && range.start < next_offset) {
56+
return true
57+
}
58+
}
59+
}
60+
return false
61+
}
62+
63+
let lines = text.split('\n')
64+
let total_file_lines = lines.length
65+
let line_coverage = new Uint8Array(total_file_lines)
66+
let file_lines_covered = 0
67+
let file_total_bytes = text.length
68+
let file_bytes_covered = 0
69+
let offset = 0
70+
71+
for (let index = 0; index < lines.length; index++) {
72+
let line = lines[index]!
73+
let start = offset
74+
let end = offset + line.length
75+
let next_offset = end + 1 // +1 for the newline character
76+
let is_empty = /^\s*$/.test(line)
77+
let is_closing_brace = line.endsWith('}')
78+
let is_in_range = is_line_covered(line, start)
79+
let is_covered = false
80+
81+
let prev_is_covered = index > 0 && line_coverage[index - 1] === 1
82+
83+
if (is_in_range && !is_closing_brace && !is_empty) {
84+
is_covered = true
85+
} else if ((is_empty || is_closing_brace) && prev_is_covered) {
86+
is_covered = true
87+
} else if (is_empty && !prev_is_covered && is_line_covered(lines[index + 1]!, next_offset)) {
88+
// If the next line is covered, mark this empty line as covered
89+
is_covered = true
90+
}
91+
92+
line_coverage[index] = is_covered ? 1 : 0
93+
94+
if (is_covered) {
95+
file_lines_covered++
96+
file_bytes_covered += line.length + 1
97+
}
98+
99+
offset = next_offset
100+
}
101+
102+
// Create "chunks" of covered/uncovered lines for easier rendering later on
103+
let chunks = [
104+
{
105+
start_line: 1,
106+
is_covered: line_coverage[0] === 1,
107+
end_line: 1,
108+
total_lines: 1,
109+
},
110+
]
111+
112+
for (let index = 1; index < line_coverage.length; index++) {
113+
let is_covered = line_coverage.at(index)
114+
if (is_covered !== line_coverage.at(index - 1)) {
115+
let last_chunk = chunks.at(-1)!
116+
last_chunk.end_line = index
117+
last_chunk.total_lines = index - last_chunk.start_line + 1
118+
119+
chunks.push({
120+
start_line: index + 1,
121+
is_covered: is_covered === 1,
122+
end_line: index,
123+
total_lines: 0,
124+
})
125+
}
126+
}
127+
128+
let last_chunk = chunks.at(-1)!
129+
last_chunk.total_lines = line_coverage.length + 1 - last_chunk.start_line
130+
last_chunk.end_line = line_coverage.length
131+
132+
return {
133+
url,
134+
text,
135+
ranges,
136+
unused_bytes: file_total_bytes - file_bytes_covered,
137+
used_bytes: file_bytes_covered,
138+
total_bytes: file_total_bytes,
139+
line_coverage_ratio: ratio(file_lines_covered, total_file_lines),
140+
byte_coverage_ratio: ratio(file_bytes_covered, file_total_bytes),
141+
line_coverage,
142+
total_lines: total_file_lines,
143+
covered_lines: file_lines_covered,
144+
uncovered_lines: total_file_lines - file_lines_covered,
145+
chunks,
146+
}
147+
}
148+
41149
/**
42150
* @description
43151
* CSS Code Coverage calculation
@@ -55,115 +163,7 @@ export async function calculate_coverage(coverage: Coverage[]): Promise<Coverage
55163
let filtered_coverage: Coverage[] = await filter_coverage(coverage)
56164
let prettified_coverage: Coverage[] = prettify(filtered_coverage)
57165
let deduplicated: Coverage[] = deduplicate_entries(prettified_coverage)
58-
59-
// Calculate coverage for each individual stylesheet we found
60-
let coverage_per_stylesheet = deduplicated.map(({ text, url, ranges }) => {
61-
function is_line_covered(line: string, start_offset: number) {
62-
let end = start_offset + line.length
63-
let next_offset = end + 1 // account for newline character
64-
let is_empty = /^\s*$/.test(line)
65-
let is_closing_brace = line.endsWith('}')
66-
67-
if (!is_empty && !is_closing_brace) {
68-
for (let range of ranges) {
69-
if (range.start > end || range.end < start_offset) {
70-
continue
71-
}
72-
if (range.start <= start_offset && range.end >= end) {
73-
return true
74-
} else if (line.startsWith('@') && range.start > start_offset && range.start < next_offset) {
75-
return true
76-
}
77-
}
78-
}
79-
return false
80-
}
81-
82-
let lines = text.split('\n')
83-
let total_file_lines = lines.length
84-
let line_coverage = new Uint8Array(total_file_lines)
85-
let file_lines_covered = 0
86-
let file_total_bytes = text.length
87-
let file_bytes_covered = 0
88-
let offset = 0
89-
90-
for (let index = 0; index < lines.length; index++) {
91-
let line = lines[index]!
92-
let start = offset
93-
let end = offset + line.length
94-
let next_offset = end + 1 // +1 for the newline character
95-
let is_empty = /^\s*$/.test(line)
96-
let is_closing_brace = line.endsWith('}')
97-
let is_in_range = is_line_covered(line, start)
98-
let is_covered = false
99-
100-
let prev_is_covered = index > 0 && line_coverage[index - 1] === 1
101-
102-
if (is_in_range && !is_closing_brace && !is_empty) {
103-
is_covered = true
104-
} else if ((is_empty || is_closing_brace) && prev_is_covered) {
105-
is_covered = true
106-
} else if (is_empty && !prev_is_covered && is_line_covered(lines[index + 1]!, next_offset)) {
107-
// If the next line is covered, mark this empty line as covered
108-
is_covered = true
109-
}
110-
111-
line_coverage[index] = is_covered ? 1 : 0
112-
113-
if (is_covered) {
114-
file_lines_covered++
115-
file_bytes_covered += line.length + 1
116-
}
117-
118-
offset = next_offset
119-
}
120-
121-
// Create "chunks" of covered/uncovered lines for easier rendering later on
122-
let chunks = [
123-
{
124-
start_line: 1,
125-
is_covered: line_coverage[0] === 1,
126-
end_line: 1,
127-
total_lines: 1,
128-
},
129-
]
130-
131-
for (let index = 1; index < line_coverage.length; index++) {
132-
let is_covered = line_coverage.at(index)
133-
if (is_covered !== line_coverage.at(index - 1)) {
134-
let last_chunk = chunks.at(-1)!
135-
last_chunk.end_line = index
136-
last_chunk.total_lines = index - last_chunk.start_line + 1
137-
138-
chunks.push({
139-
start_line: index + 1,
140-
is_covered: is_covered === 1,
141-
end_line: index,
142-
total_lines: 0,
143-
})
144-
}
145-
}
146-
147-
let last_chunk = chunks.at(-1)!
148-
last_chunk.total_lines = line_coverage.length + 1 - last_chunk.start_line
149-
last_chunk.end_line = line_coverage.length
150-
151-
return {
152-
url,
153-
text,
154-
ranges,
155-
unused_bytes: file_total_bytes - file_bytes_covered,
156-
used_bytes: file_bytes_covered,
157-
total_bytes: file_total_bytes,
158-
line_coverage_ratio: ratio(file_lines_covered, total_file_lines),
159-
byte_coverage_ratio: ratio(file_bytes_covered, file_total_bytes),
160-
line_coverage,
161-
total_lines: total_file_lines,
162-
covered_lines: file_lines_covered,
163-
uncovered_lines: total_file_lines - file_lines_covered,
164-
chunks,
165-
}
166-
})
166+
let coverage_per_stylesheet = deduplicated.map((stylesheet) => calculate_stylesheet_coverage(stylesheet))
167167

168168
// Calculate total coverage for all stylesheets combined
169169
let { total_lines, total_covered_lines, total_uncovered_lines, total_bytes, total_used_bytes, total_unused_bytes } =

0 commit comments

Comments
 (0)