Skip to content

Commit 776e315

Browse files
authored
Improve tests and coverage of extracting (#25)
* rewrite extracting logic to ditch coverage API * oopsie * oopsie * omg * improve cssfinding * fix tests Co-authored-by: Bart Veneman <[email protected]>
1 parent 796c88a commit 776e315

22 files changed

+174
-153
lines changed

package-lock.json

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
"@bartveneman/eslint-config-bv": "0.0.2",
2828
"ava": "^2.4.0",
2929
"create-test-server": "^3.0.1",
30-
"eslint": "^6.7.2"
30+
"eslint": "^6.7.2",
31+
"sirv": "^0.4.2"
3132
},
3233
"dependencies": {
3334
"puppeteer": "^2.0.0"

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ String.
5757

5858
Type: `Object`
5959

60-
Default: `null`
60+
Default: `{}`
6161

6262
#### waitUntil
6363

src/index.js

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
/* global document */
2-
32
const puppeteer = require('puppeteer')
4-
const crypto = require('crypto')
5-
6-
function hashString(str) {
7-
return crypto.createHash('md5').update(str, 'utf8').digest('hex')
8-
}
93

104
function InvalidUrlError({url, statusCode, statusText}) {
115
this.name = 'InvalidUrlError'
@@ -17,15 +11,14 @@ InvalidUrlError.prototype = Error.prototype
1711
/**
1812
* @param {string} url URL to get CSS from
1913
* @param {string} waitUntil https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagegotourl-options
14+
* @returns {string} All CSS that was found
2015
*/
2116
module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
2217
// Setup a browser instance
2318
const browser = await puppeteer.launch()
2419

2520
// Create a new page and navigate to it
2621
const page = await browser.newPage()
27-
28-
// Start CSS coverage. This is the meat and bones of this module
2922
await page.coverage.startCSSCoverage()
3023
const response = await page.goto(url, {waitUntil})
3124

@@ -43,22 +36,22 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
4336
)
4437
}
4538

46-
// Coverage contains a lot of <style> and <link> CSS,
47-
// but not all...
4839
const coverage = await page.coverage.stopCSSCoverage()
4940

5041
// Get all CSS generated with the CSSStyleSheet API
5142
// This is primarily for CSS-in-JS solutions
5243
// See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule/cssText
5344
const styleSheetsApiCss = await page.evaluate(() => {
5445
return [...document.styleSheets]
46+
// Only take the stylesheets without href (BUT WHY)
5547
.filter(stylesheet => stylesheet.href === null)
56-
.map(stylesheet =>
57-
[...stylesheet.cssRules]
58-
.map(cssStyleRule => cssStyleRule.cssText)
59-
.join('\n')
60-
)
61-
.join('\n')
48+
.map(stylesheet => {
49+
return {
50+
type: stylesheet.ownerNode.tagName.toLowerCase(),
51+
href: stylesheet.href || document.location.href,
52+
css: [...stylesheet.cssRules].map(({cssText}) => cssText).join('\n')
53+
}
54+
})
6255
})
6356

6457
// Get all inline styles: <element style="">
@@ -71,38 +64,36 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
7164
// <h1 style="color: red;">Text</h1>
7265
//
7366
// CSSRule:
74-
// [x-inline-style-237a7d] { color: red; }
75-
// ^^^^^^
67+
// [x-extract-css-inline-style] { color: red; }
7668
//
77-
// The 6-digit hash is based on the actual CSS, so it's not
78-
// necessarily unique!
7969
const inlineCssRules = await page.evaluate(() => {
8070
return [...document.querySelectorAll('[style]')]
8171
.map(element => element.getAttribute('style'))
72+
// Filter out empty style="" attributes
8273
.filter(Boolean)
8374
})
8475
const inlineCss = inlineCssRules
85-
.map(rule => {
86-
const hash = hashString(rule).slice(-6)
87-
return `[x-inline-style-${hash}] { ${rule} }`
88-
})
89-
.join('\n')
76+
.map(rule => `[x-extract-css-inline-style] { ${rule} }`)
77+
.map(css => ({type: 'inline', href: url, css}))
9078

91-
await browser.close()
92-
93-
// Turn the coverage Array into a single string of CSS
94-
const coverageCss = coverage
79+
const links = coverage
9580
// Filter out the <style> tags that were found in the coverage
9681
// report since we've conducted our own search for them.
9782
// A coverage CSS item with the same url as the url of the page
9883
// we requested is an indication that this was a <style> tag
99-
.filter(styles => styles.url !== url)
100-
// The `text` property contains the actual CSS
101-
.map(({text}) => text)
102-
.join('\n')
84+
.filter(entry => entry.url !== url)
85+
.map(entry => ({
86+
href: entry.url,
87+
css: entry.text,
88+
type: 'link-or-import'
89+
}))
90+
91+
await browser.close()
10392

104-
const css = [styleSheetsApiCss, coverageCss, inlineCss]
105-
.filter(Boolean)
93+
const css = links
94+
.concat(styleSheetsApiCss)
95+
.concat(inlineCss)
96+
.map(({css}) => css)
10697
.join('\n')
10798

10899
return Promise.resolve(css)

test/fixture.css

Lines changed: 0 additions & 2 deletions
This file was deleted.
File renamed without changes.

test/fixtures/import-in-css.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.css-imported-with-css {}

test/fixtures/import-in-js.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.css-imported-with-js {}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)