Skip to content

Commit

Permalink
add support for fetching inline styles (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartveneman committed Feb 16, 2020
1 parent 86dcd8c commit c46a9df
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 9 deletions.
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.

0 comments on commit c46a9df

Please sign in to comment.