11/* global document */
2-
32const 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
104function 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 */
2116module . 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 )
0 commit comments