Skip to content

Commit c46a9df

Browse files
authored
add support for fetching inline styles (#23)
1 parent 86dcd8c commit c46a9df

File tree

7 files changed

+92
-9
lines changed

7 files changed

+92
-9
lines changed

src/index.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1+
/* global document */
2+
13
const puppeteer = require('puppeteer')
4+
const crypto = require('crypto')
5+
6+
function hashString(str) {
7+
return crypto.createHash('md5').update(str, 'utf8').digest('hex')
8+
}
29

310
function InvalidUrlError({url, statusCode, statusText}) {
411
this.name = 'InvalidUrlError'
@@ -44,7 +51,6 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
4451
// This is primarily for CSS-in-JS solutions
4552
// See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule/cssText
4653
const styleSheetsApiCss = await page.evaluate(() => {
47-
/* global document */
4854
return [...document.styleSheets]
4955
.filter(stylesheet => stylesheet.href === null)
5056
.map(stylesheet =>
@@ -55,6 +61,33 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
5561
.join('\n')
5662
})
5763

64+
// Get all inline styles: <element style="">
65+
// This creates a new CSSRule for every inline style
66+
// attribute it encounters.
67+
//
68+
// Example:
69+
//
70+
// HTML:
71+
// <h1 style="color: red;">Text</h1>
72+
//
73+
// CSSRule:
74+
// [x-inline-style-237a7d] { color: red; }
75+
// ^^^^^^
76+
//
77+
// The 6-digit hash is based on the actual CSS, so it's not
78+
// necessarily unique!
79+
const inlineCssRules = await page.evaluate(() => {
80+
return [...document.querySelectorAll('[style]')]
81+
.map(element => element.getAttribute('style'))
82+
.filter(Boolean)
83+
})
84+
const inlineCss = inlineCssRules
85+
.map(rule => {
86+
const hash = hashString(rule).slice(-6)
87+
return `[x-inline-style-${hash}] { ${rule} }`
88+
})
89+
.join('\n')
90+
5891
await browser.close()
5992

6093
// Turn the coverage Array into a single string of CSS
@@ -68,7 +101,7 @@ module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
68101
.map(({text}) => text)
69102
.join('\n')
70103

71-
const css = [styleSheetsApiCss, coverageCss]
104+
const css = [styleSheetsApiCss, coverageCss, inlineCss]
72105
.filter(Boolean)
73106
.join('\n')
74107

test/index.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,30 @@ test('it does not report the same CSS twice', async t => {
8383
t.true(actual.includes('.fixture { color: red; }'))
8484
t.true(actual.includes('.style-tag-fixture-js { color: yellow; }'))
8585
t.true(actual.includes('.style-tag-fixture-html { color: green; }'))
86+
t.true(actual.includes('border-style: solid'))
87+
t.true(actual.includes('background-color: red'))
8688

8789
t.snapshot(actual)
8890
})
8991

92+
test('it finds inline styles - HTML', async t => {
93+
server.get('/inline-style-html.html', serveStatic)
94+
const actual = await extractCss(server.url + '/inline-style-html.html')
95+
96+
t.true(actual.includes('[x-inline-style-dfc776] { color: red; font-size: 12px; }'))
97+
t.true(actual.includes('[x-inline-style-ea2739] { color: blue }'))
98+
t.snapshot(actual)
99+
})
100+
101+
test('it finds inline styles - JS', async t => {
102+
server.get('/inline-style-js.html', serveStatic)
103+
const actual = await extractCss(server.url + '/inline-style-js.html')
104+
105+
t.true(actual.includes('[x-inline-style-874435] { color: red; font-size: 12px; border-style: solid; }'))
106+
t.true(actual.includes('[x-inline-style-ea1c8f] { border-color: blue; border-width: 1px; }'))
107+
t.snapshot(actual)
108+
})
109+
90110
test('it rejects if the url has an HTTP error status', async t => {
91111
server.get('/404-page', (req, res) => {
92112
res.status(404).send()

test/inline-style-html.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@
77
</head>
88
<body>
99
<h1 style="color: red; font-size: 12px;">Inline style in HTML</h1>
10+
<p style="color: blue">Another inline styled element</p>
11+
<p style="">Element with empty style attribute</p>
12+
<p style>Another empty style attribute</p>
1013
</body>
1114
</html>

test/inline-style-js.html

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77
</head>
88
<body>
99
<h1>Inline styles with JS</h1>
10+
<h2>Another inliner</h2>
1011

1112
<script>
12-
var element = document.querySelector('h1')
13+
var h1 = document.querySelector('h1')
1314

1415
// Set multiple styles in a single statement
15-
element.style.cssText = 'color: red; font-size: 12px;';
16-
17-
// Or ... this overrides ignore the previous line
18-
// element.setAttribute('style', 'border-color: blue; border-width: 1px;');
16+
h1.style.cssText = 'color: red; font-size: 12px;';
1917

2018
// Set a single style property
21-
element.style.borderStyle = 'solid';
19+
h1.style.borderStyle = 'solid';
20+
21+
// Alternatove way of .style.cssText
22+
var h2 = document.querySelector('h2');
23+
h2.setAttribute('style', 'border-color: blue; border-width: 1px;');
2224
</script>
2325
</body>
2426
</html>

test/kitchen-sink.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
</head>
1616
<body>
1717

18+
<div style="background-color: red;"></div>
19+
<div id="inline"></div>
20+
1821
<!-- <link> tag in JS -->
1922
<script>
2023
var style = document.createElement('link')
@@ -29,5 +32,11 @@
2932
style.textContent = '.style-tag-fixture-js { color: yellow; }'
3033
document.body.appendChild(style)
3134
</script>
35+
36+
<!-- inline styles via JS -->
37+
<script>
38+
var element = document.querySelector('#inline')
39+
element.style.borderStyle = 'solid';
40+
</script>
3241
</body>
3342
</html>

test/snapshots/index.js.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ Generated by [AVA](https://ava.li).
1313
@import url("imported.css");␊
1414
.fixture { color: red; }␊
1515
@import url("imported.css");␊
16-
.fixture { color: red; }`
16+
.fixture { color: red; }␊
17+
[x-inline-style-95ba24] { background-color: red; }␊
18+
[x-inline-style-d894e5] { border-style: solid; }`
1719

1820
## it finds css in a <link> tag - HTML
1921

@@ -44,3 +46,17 @@ Generated by [AVA](https://ava.li).
4446
`@import url("imported.css");␊
4547
.fixture { color: red; }␊
4648
.imported { color: blue; }`
49+
50+
## it finds inline styles - HTML
51+
52+
> Snapshot 1
53+
54+
`[x-inline-style-dfc776] { color: red; font-size: 12px; }␊
55+
[x-inline-style-ea2739] { color: blue }`
56+
57+
## it finds inline styles - JS
58+
59+
> Snapshot 1
60+
61+
`[x-inline-style-874435] { color: red; font-size: 12px; border-style: solid; }␊
62+
[x-inline-style-ea1c8f] { border-color: blue; border-width: 1px; }`

test/snapshots/index.js.snap

181 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)