From 48bb1064f521ee984a6ca0662257cba07ea0bb71 Mon Sep 17 00:00:00 2001 From: Bart Veneman Date: Sun, 16 Feb 2020 22:46:16 +0100 Subject: [PATCH] add support for fetching @import rules --- readme.md | 38 +++++++++++----------- src/index.js | 19 ++++++++--- test/fixture.css | 3 +- test/imported.css | 1 + test/index.js | 61 ++++++++++++++++++++++++++--------- test/kitchen-sink.html | 33 +++++++++++++++++++ test/link-tag-html.html | 1 + test/link-tag-js.html | 1 + test/snapshots/index.js.md | 45 +++++++++++++++++++++----- test/snapshots/index.js.snap | Bin 168 -> 305 bytes test/style-tag-html.html | 3 +- test/style-tag-js.html | 2 +- 12 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 test/imported.css create mode 100644 test/kitchen-sink.html diff --git a/readme.md b/readme.md index 6d4b474..a49b0bd 100644 --- a/readme.md +++ b/readme.md @@ -12,6 +12,22 @@ [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo) [![Project: Wallace](https://img.shields.io/badge/Project-Wallace-29c87d.svg)](https://www.projectwallace.com/oss) +## Usage + +```js +const extractCss = require('extract-css-core') + +const css = await extractCss('http://www.projectwallace.com') +``` + +## Installation + +```sh +npm install extract-css-core +# or +yarn add extract-css-core +``` + ## Problem, solution and shortcomings ### Problem @@ -28,23 +44,7 @@ This module uses an instance of Chromium to render a page. This has the benefit that most of the styles can be rendered, even when generated by JavaScript. The [Puppeteer CSSCoverage API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#coveragestartcsscoverageoptions) is the power behind finding most of the CSS. Additionally, the -`document.styleSheets` API is used to get CSS-inJS styling. - -## Installation - -```sh -npm install extract-css-core -# or -yarn add extract-css-core -``` - -## Usage - -```js -const extractCss = require('extract-css-core') - -const css = await extractCss('http://www.projectwallace.com') -``` +`document.styleSheets` API is used to get CSS-in-JS styling. ## API @@ -63,7 +63,7 @@ Default: `null` Type: `String` -Default: `networkidle2` +Default: `networkidle0` Can be any value as provided by the [Puppeteer docs](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagegotourl-options). @@ -72,4 +72,4 @@ Can be any value as provided by the - [Wallace CLI](https://github.com/bartveneman/wallace-cli) - Pretty CSS analytics in your terminal - [get-css](https://github.com/cssstats/cssstats/tree/master/packages/get-css) - - The original get-css + The original get-css from CSSStats diff --git a/src/index.js b/src/index.js index aa92a5d..03389bc 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,11 @@ function InvalidUrlError({url, statusCode, statusText}) { InvalidUrlError.prototype = Error.prototype -module.exports = async (url, {waitUntil = 'networkidle2'} = {}) => { +/** + * @param {string} url URL to get CSS from + * @param {string} waitUntil https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagegotourl-options + */ +module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => { // Setup a browser instance const browser = await puppeteer.launch() @@ -37,6 +41,7 @@ module.exports = async (url, {waitUntil = 'networkidle2'} = {}) => { const coverage = await page.coverage.stopCSSCoverage() // Get all CSS generated with the CSSStyleSheet API + // This is primarily for CSS-in-JS solutions // See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule/cssText const styleSheetsApiCss = await page.evaluate(() => { /* global document */ @@ -45,9 +50,9 @@ module.exports = async (url, {waitUntil = 'networkidle2'} = {}) => { .map(stylesheet => [...stylesheet.cssRules] .map(cssStyleRule => cssStyleRule.cssText) - .join('') + .join('\n') ) - .join('') + .join('\n') }) await browser.close() @@ -61,7 +66,11 @@ module.exports = async (url, {waitUntil = 'networkidle2'} = {}) => { .filter(styles => styles.url !== url) // The `text` property contains the actual CSS .map(({text}) => text) - .join('') + .join('\n') - return Promise.resolve(styleSheetsApiCss + coverageCss) + const css = [styleSheetsApiCss, coverageCss] + .filter(Boolean) + .join('\n') + + return Promise.resolve(css) } diff --git a/test/fixture.css b/test/fixture.css index 7c88d8e..ad12d88 100644 --- a/test/fixture.css +++ b/test/fixture.css @@ -1 +1,2 @@ -.fixture { color: red; } +@import url("imported.css"); +.fixture { color: red; } \ No newline at end of file diff --git a/test/imported.css b/test/imported.css new file mode 100644 index 0000000..7fd2bab --- /dev/null +++ b/test/imported.css @@ -0,0 +1 @@ +.imported { color: blue; } \ No newline at end of file diff --git a/test/index.js b/test/index.js index 462062d..1e0104c 100644 --- a/test/index.js +++ b/test/index.js @@ -6,9 +6,8 @@ const {resolve} = require('path') const extractCss = require('..') let server -const fixture = readFileSync(resolve(__dirname, 'fixture.css'), 'utf8') -function staticFile(req, res) { +function serveStatic(req, res) { const fileContents = readFileSync(resolve(__dirname, req.path.slice(1)), 'utf8') res.send(fileContents) } @@ -16,7 +15,8 @@ function staticFile(req, res) { test.before(async () => { server = await createTestServer() - server.get('/fixture.css', staticFile) + server.get('/fixture.css', serveStatic) + server.get('/imported.css', serveStatic) }) test.after(async () => { @@ -24,40 +24,69 @@ test.after(async () => { }) test('it finds css in a tag - HTML', async t => { - server.get('/link-tag-html.html', staticFile) + // @TODO: during tests, it doesn't find the imported CSS file contents + // but it does work outside of test scope + server.get('/link-tag-html.html', serveStatic) const actual = await extractCss(server.url + '/link-tag-html.html') - const expected = fixture - t.is(actual, expected) + + t.true(actual.includes('@import url("imported.css");')) + t.true(actual.includes('.fixture { color: red; }')) + t.snapshot(actual) }) test('it finds css in a tag - JS', async t => { - server.get('/link-tag-js.html', staticFile) + // @TODO: during tests, it doesn't find the imported CSS file contents + // but it does work outside of test scope + server.get('/link-tag-js.html', serveStatic) const actual = await extractCss(server.url + '/link-tag-js.html') - const expected = fixture - t.is(actual, expected) + + t.true(actual.includes('@import url("imported.css");')) + t.true(actual.includes('.fixture { color: red; }')) + t.snapshot(actual) }) test('it finds css in a + + + + + + + + + + \ No newline at end of file diff --git a/test/link-tag-html.html b/test/link-tag-html.html index 7f5fb70..bce5b55 100644 --- a/test/link-tag-html.html +++ b/test/link-tag-html.html @@ -8,5 +8,6 @@

<link> tag in HTML

+
imported
\ No newline at end of file diff --git a/test/link-tag-js.html b/test/link-tag-js.html index 1170980..7cfe5db 100644 --- a/test/link-tag-js.html +++ b/test/link-tag-js.html @@ -9,6 +9,7 @@

<link> tag in JS

+
imported