Skip to content

add support for fetching inline styles #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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 =>
Expand All @@ -55,6 +61,33 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
.join('\n')
})

// Get all inline styles: <element style="">
// This creates a new CSSRule for every inline style
// attribute it encounters.
//
// Example:
//
// HTML:
// <h1 style="color: red;">Text</h1>
//
// 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
Expand All @@ -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')

Expand Down
20 changes: 20 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions test/inline-style-html.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
</head>
<body>
<h1 style="color: red; font-size: 12px;">Inline style in HTML</h1>
<p style="color: blue">Another inline styled element</p>
<p style="">Element with empty style attribute</p>
<p style>Another empty style attribute</p>
</body>
</html>
14 changes: 8 additions & 6 deletions test/inline-style-js.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@
</head>
<body>
<h1>Inline styles with JS</h1>
<h2>Another inliner</h2>

<script>
var element = document.querySelector('h1')
var h1 = document.querySelector('h1')

// Set multiple styles in a single statement
element.style.cssText = 'color: red; font-size: 12px;';

// Or ... this overrides ignore the previous line
// element.setAttribute('style', 'border-color: blue; border-width: 1px;');
h1.style.cssText = 'color: red; font-size: 12px;';

// Set a single style property
element.style.borderStyle = 'solid';
h1.style.borderStyle = 'solid';

// Alternatove way of .style.cssText
var h2 = document.querySelector('h2');
h2.setAttribute('style', 'border-color: blue; border-width: 1px;');
</script>
</body>
</html>
9 changes: 9 additions & 0 deletions test/kitchen-sink.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
</head>
<body>

<div style="background-color: red;"></div>
<div id="inline"></div>

<!-- <link> tag in JS -->
<script>
var style = document.createElement('link')
Expand All @@ -29,5 +32,11 @@
style.textContent = '.style-tag-fixture-js { color: yellow; }'
document.body.appendChild(style)
</script>

<!-- inline styles via JS -->
<script>
var element = document.querySelector('#inline')
element.style.borderStyle = 'solid';
</script>
</body>
</html>
18 changes: 17 additions & 1 deletion test/snapshots/index.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <link> tag - HTML

Expand Down Expand Up @@ -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; }`
Binary file modified test/snapshots/index.js.snap
Binary file not shown.