@projectwallace/css-code-coverage 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # CSS Code Coverage
2
2
 
3
+ > [!WARNING]
4
+ > This is a very experimental approach to calculating CSS Code Coverage and currently very much a work in progress.
5
+
3
6
  Takes your generated coverage files and turns them into something actually usable. Accepts coverage reports generated by browsers (Edge/Chrome/chromium), Puppeteer, Playwright.
4
7
 
5
8
  Features include:
@@ -17,59 +20,93 @@ npm install @projectwallace/css-code-coverage
17
20
 
18
21
  ## Usage
19
22
 
20
- ### Prerequisites
23
+ ```ts
24
+ import { calculate_coverage } from '@projectwallace/css-code-coverage'
25
+
26
+ function parse_html(html) {
27
+ return new DOMParser().parseFromString(html, 'text/html')
28
+ }
21
29
 
22
- 1. You have collected browser coverage data of your CSS. There are several ways to do this:
30
+ let report = calculcate_coverage(coverage_data, parse_html)
31
+ ```
23
32
 
24
- 1. in the browser devtools in [Edge](https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/coverage/)/[Chrome](https://developer.chrome.com/docs/devtools/coverage/)/chromium
25
- 1. Via the `coverage.startCSSCoverage()` API that headless browsers like [Playwright](https://playwright.dev/docs/api/class-coverage#coverage-start-css-coverage) or [Puppeteer](https://pptr.dev/api/puppeteer.coverage.startcsscoverage/) provide.
33
+ See [src/index.ts](https://github.com/projectwallace/css-code-coverage/blob/main/src/index.ts) for the data that's returned.
26
34
 
27
- Either way you end up with one or more JSON files that contain coverage data.
35
+ ## Collecting CSS Coverage
28
36
 
29
- ```ts
30
- // Read a single JSON or a folder full of JSON files with coverage data
31
- // Coverage data looks like this:
32
- // {
33
- // url: 'https://www.projectwallace.com/style.css',
34
- // text: 'a { color: blue; text-decoration: underline; }', etc.
35
- // ranges: [
36
- // { start: 0, end: 46 }
37
- // ]
38
- // }
39
- import { parse_coverage } from '@projectwallace/css-code-coverage'
37
+ There are two principal ways of collecting CSS Coverage data:
40
38
 
41
- let files = await fs.glob('./css-coverage/**/*.json')
42
- let coverage_data = []
39
+ ### Browser devtools
43
40
 
44
- for (let file of files) {
45
- let json_content = await fs.readFile(file, 'urf-8')
46
- coverage_data.push(...parse_coverage(json_content))
47
- }
48
- ```
41
+ In Edge, Chrome or chromium you can manually collect coverage in the browser's DevTools. In all cases you'll generate coverage data manually and the browser will let you export the data to a JSON file. Note that this JSON contains both JS coverage as well as the CSS coverage. Learn how it works:
49
42
 
50
- 1. You provide a HTML parser that we use to 'scrape' the HTML in case the browser gives us not just plain CSS contents. Depending on where you run this analysis you can use:
43
+ - Collect coverage in Microsoft Edge: https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/coverage/
44
+ - Collect coevrage in Google Chrome: https://developer.chrome.com/docs/devtools/coverage/
51
45
 
52
- 1. Browser:
53
- ```ts
54
- function parse_html(html) {
55
- return new DOMParser().parseFromString(html, 'text/html')
56
- }
57
- ```
58
- 1. Node (using [linkedom](https://github.com/WebReflection/linkedom) in this example):
46
+ Additionally, DevTools Tips writes about it in their [explainer](https://devtoolstips.org/tips/en/detect-unused-code/).
59
47
 
60
- ```ts
61
- // $ npm install linkedom
62
- import { DOMParser } from 'linkedom'
48
+ You end up with one or more JSON files that contain coverage data. We provide a helper `parse_coverage()` that both parses the JSON and validates it so you can pass it directly into `calculate_coverage()`.
49
+
50
+ ```ts
51
+ // Read a single JSON or a folder full of JSON files with coverage data
52
+ // Coverage data looks like this:
53
+ // {
54
+ // url: 'https://www.projectwallace.com/style.css',
55
+ // text: 'a { color: blue; text-decoration: underline; }', etc.
56
+ // ranges: [
57
+ // { start: 0, end: 46 }
58
+ // ]
59
+ // }
60
+ import { parse_coverage } from '@projectwallace/css-code-coverage'
61
+
62
+ let files = await fs.glob('./css-coverage/**/*.json')
63
+ let coverage_data = []
64
+
65
+ for (let file of files) {
66
+ let json_content = await fs.readFile(file, 'urf-8')
67
+ coverage_data.push(...parse_coverage(json_content))
68
+ }
69
+ ```
63
70
 
64
- function parse_html(html: string) {
65
- return new DOMParser().parseFromString(html, 'text/html')
66
- }
67
- ```
71
+ ### Coverage API
68
72
 
69
- ### Bringing it together
73
+ Both Puppeteer and Playwright provide an API to programmatically get the coverage data, allowing you to put that directly into this library. Here is the gist:
70
74
 
71
75
  ```ts
76
+ // Start collecting coverage
77
+ await page.coverage.startCSSCoverage()
78
+ // Load the page, do all sorts of interactions to increase coverage, etc.
79
+ await page.goto('http://example.com')
80
+ // Stop the coverage and store the result in a variable to pass along
81
+ let coverage = await page.coverage.stopCSSCoverage()
82
+
83
+ // Now we can process it
72
84
  import { calculate_coverage } from '@projectwallace/css-code-coverage'
73
85
 
74
- let report = calculcate_coverage(coverage_data, parse_html)
86
+ function parse_html(html) {
87
+ return new DOMParser().parseFromString(html, 'text/html')
88
+ }
89
+
90
+ let report = calculcate_coverage(coverage, parse_html)
75
91
  ```
92
+
93
+ ### Optional: coverage from `<style>` blocks
94
+
95
+ Coverage generators also create coverage ranges for `<style>` blocks in HTML. If this applies to your code you should provide a HTML parser that we use to 'scrape' the HTML in case the browser gives us not just plain CSS contents. Depending on where you run this analysis you can use:
96
+
97
+ 1. Browser:
98
+ ```ts
99
+ function parse_html(html) {
100
+ return new DOMParser().parseFromString(html, 'text/html')
101
+ }
102
+ ```
103
+ 1. Node (using [linkedom](https://github.com/WebReflection/linkedom) in this example, but other parsers could work, too):
104
+
105
+ ```ts
106
+ // $ npm install linkedom
107
+ import { DOMParser } from 'linkedom'
108
+
109
+ function parse_html(html: string) {
110
+ return new DOMParser().parseFromString(html, 'text/html')
111
+ }
112
+ ```
@@ -134,6 +134,8 @@ function G(t, e) {
134
134
  continue;
135
135
  }
136
136
  if (D(n.text)) {
137
+ if (!e)
138
+ continue;
137
139
  let { css: u, ranges: o } = R(e, n.text, n.ranges);
138
140
  l.push({
139
141
  url: n.url,
@@ -1,3 +1,3 @@
1
1
  import { Coverage } from './parse-coverage.ts';
2
2
  import { Parser } from './types.ts';
3
- export declare function filter_coverage(coverage: Coverage[], parse_html: Parser): Coverage[];
3
+ export declare function filter_coverage(coverage: Coverage[], parse_html?: Parser): Coverage[];
@@ -32,7 +32,7 @@ export type CoverageResult = CoverageData & {
32
32
  * 4. Calculate used/unused CSS bytes (fastest path, no inspection of the actual CSS needed)
33
33
  * 5. Calculate line-coverage, byte-coverage per stylesheet
34
34
  */
35
- export declare function calculate_coverage(coverage: Coverage[], parse_html: Parser): CoverageResult;
35
+ export declare function calculate_coverage(coverage: Coverage[], parse_html?: Parser): CoverageResult;
36
36
  export type { Coverage, Range } from './parse-coverage.ts';
37
37
  export { parse_coverage } from './parse-coverage.ts';
38
38
  export type { Parser } from './types.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectwallace/css-code-coverage",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "author": "Bart Veneman <bart@projectwallace.com>",
6
6
  "repository": {