diff --git a/src/index.js b/src/index.js index 03389bc..ae45075 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,11 @@ +/* global document */ + const puppeteer = require('puppeteer') +const crypto = require('crypto') + +function hashString(str) { + return crypto.createHash('md5').update(str, 'utf8').digest('hex') +} function InvalidUrlError({url, statusCode, statusText}) { this.name = 'InvalidUrlError' @@ -44,7 +51,6 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => { // 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 */ return [...document.styleSheets] .filter(stylesheet => stylesheet.href === null) .map(stylesheet => @@ -55,6 +61,33 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => { .join('\n') }) + // Get all inline styles: + // This creates a new CSSRule for every inline style + // attribute it encounters. + // + // Example: + // + // HTML: + //

Text

+ // + // CSSRule: + // [x-inline-style-237a7d] { color: red; } + // ^^^^^^ + // + // The 6-digit hash is based on the actual CSS, so it's not + // necessarily unique! + const inlineCssRules = await page.evaluate(() => { + return [...document.querySelectorAll('[style]')] + .map(element => element.getAttribute('style')) + .filter(Boolean) + }) + const inlineCss = inlineCssRules + .map(rule => { + const hash = hashString(rule).slice(-6) + return `[x-inline-style-${hash}] { ${rule} }` + }) + .join('\n') + await browser.close() // Turn the coverage Array into a single string of CSS @@ -68,7 +101,7 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => { .map(({text}) => text) .join('\n') - const css = [styleSheetsApiCss, coverageCss] + const css = [styleSheetsApiCss, coverageCss, inlineCss] .filter(Boolean) .join('\n') diff --git a/test/index.js b/test/index.js index 1e0104c..8eb3619 100644 --- a/test/index.js +++ b/test/index.js @@ -83,10 +83,30 @@ test('it does not report the same CSS twice', async t => { t.true(actual.includes('.fixture { color: red; }')) t.true(actual.includes('.style-tag-fixture-js { color: yellow; }')) t.true(actual.includes('.style-tag-fixture-html { color: green; }')) + t.true(actual.includes('border-style: solid')) + t.true(actual.includes('background-color: red')) t.snapshot(actual) }) +test('it finds inline styles - HTML', async t => { + server.get('/inline-style-html.html', serveStatic) + const actual = await extractCss(server.url + '/inline-style-html.html') + + t.true(actual.includes('[x-inline-style-dfc776] { color: red; font-size: 12px; }')) + t.true(actual.includes('[x-inline-style-ea2739] { color: blue }')) + t.snapshot(actual) +}) + +test('it finds inline styles - JS', async t => { + server.get('/inline-style-js.html', serveStatic) + const actual = await extractCss(server.url + '/inline-style-js.html') + + t.true(actual.includes('[x-inline-style-874435] { color: red; font-size: 12px; border-style: solid; }')) + t.true(actual.includes('[x-inline-style-ea1c8f] { border-color: blue; border-width: 1px; }')) + t.snapshot(actual) +}) + test('it rejects if the url has an HTTP error status', async t => { server.get('/404-page', (req, res) => { res.status(404).send() diff --git a/test/inline-style-html.html b/test/inline-style-html.html index 8aa1536..e8c892d 100644 --- a/test/inline-style-html.html +++ b/test/inline-style-html.html @@ -7,5 +7,8 @@

Inline style in HTML

+

Another inline styled element

+

Element with empty style attribute

+

Another empty style attribute

\ No newline at end of file diff --git a/test/inline-style-js.html b/test/inline-style-js.html index 5b5a0b2..d4853ed 100644 --- a/test/inline-style-js.html +++ b/test/inline-style-js.html @@ -7,18 +7,20 @@

Inline styles with JS

+

Another inliner

\ No newline at end of file diff --git a/test/kitchen-sink.html b/test/kitchen-sink.html index c472454..7fada7f 100644 --- a/test/kitchen-sink.html +++ b/test/kitchen-sink.html @@ -15,6 +15,9 @@ +
+
+ + + + \ No newline at end of file diff --git a/test/snapshots/index.js.md b/test/snapshots/index.js.md index 112d7c9..93642f3 100644 --- a/test/snapshots/index.js.md +++ b/test/snapshots/index.js.md @@ -13,7 +13,9 @@ Generated by [AVA](https://ava.li). @import url("imported.css");␊ .fixture { color: red; }␊ @import url("imported.css");␊ - .fixture { color: red; }` + .fixture { color: red; }␊ + [x-inline-style-95ba24] { background-color: red; }␊ + [x-inline-style-d894e5] { border-style: solid; }` ## it finds css in a tag - HTML @@ -44,3 +46,17 @@ Generated by [AVA](https://ava.li). `@import url("imported.css");␊ .fixture { color: red; }␊ .imported { color: blue; }` + +## it finds inline styles - HTML + +> Snapshot 1 + + `[x-inline-style-dfc776] { color: red; font-size: 12px; }␊ + [x-inline-style-ea2739] { color: blue }` + +## it finds inline styles - JS + +> Snapshot 1 + + `[x-inline-style-874435] { color: red; font-size: 12px; border-style: solid; }␊ + [x-inline-style-ea1c8f] { border-color: blue; border-width: 1px; }` diff --git a/test/snapshots/index.js.snap b/test/snapshots/index.js.snap index 4f444c7..19d9be2 100644 Binary files a/test/snapshots/index.js.snap and b/test/snapshots/index.js.snap differ