You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

extract-css-core

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

extract-css-core - npm Package Compare versions

Comparing version

to
2.1.0

5

package.json
{
"name": "extract-css-core",
"description": "Extract all CSS from a given url, both server side and client side rendered.",
"version": "2.0.0",
"version": "2.1.0",
"homepage": "https://www.projectwallace.com/oss",

@@ -30,3 +30,4 @@ "repository": "https://github.com/bartveneman/extract-css-core",

"create-test-server": "^3.0.1",
"eslint": "^6.7.2"
"eslint": "^6.7.2",
"sirv": "^0.4.2"
},

@@ -33,0 +34,0 @@ "dependencies": {

44

readme.md

@@ -15,2 +15,18 @@ <div align="center">

## 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

@@ -23,4 +39,4 @@

look at a server-generated piece of HTML and get all the `<link>` and `<style>`
tags from it. This works fine for 100% server rendered pages, and pages with
CSS-in-JS styling.
tags from it. This works fine for 100% server rendered pages 👍, but not for pages with
CSS-in-JS styling and inline styles 👎.

@@ -33,20 +49,4 @@ ### Solution

is the power behind finding most of the CSS. Additionally, the
`document.styleSheets` API is used to get CSS-inJS styling.
`document.styleSheets` API is used to get CSS-in-JS styling. Lastly, a plain old `document.querySelectorAll('[style]')` finds all inline 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')
```
## API

@@ -63,3 +63,3 @@

Default: `null`
Default: `{}`

@@ -70,3 +70,3 @@ #### waitUntil

Default: `networkidle2`
Default: `networkidle0`

@@ -80,2 +80,2 @@ Can be any value as provided by the

- [get-css](https://github.com/cssstats/cssstats/tree/master/packages/get-css) -
The original get-css
The original get-css from CSSStats

@@ -0,1 +1,2 @@

/* global document */
const puppeteer = require('puppeteer')

@@ -10,3 +11,8 @@

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
* @returns {string} All CSS that was found
*/
module.exports = async (url, {waitUntil = 'networkidle0'} = {}) => {
// Setup a browser instance

@@ -17,4 +23,2 @@ const browser = await puppeteer.launch()

const page = await browser.newPage()
// Start CSS coverage. This is the meat and bones of this module
await page.coverage.startCSSCoverage()

@@ -37,24 +41,51 @@ const response = await page.goto(url, {waitUntil})

// Coverage contains a lot of <style> and <link> CSS,
// but not all...
// If the response is a CSS file, return that file
// instead of running our complicated setup
const headers = response.headers()
if (headers['content-type'].includes('text/css')) {
return Promise.resolve(response.text())
}
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 */
return [...document.styleSheets]
// Only take the stylesheets without href (BUT WHY)
.filter(stylesheet => stylesheet.href === null)
.map(stylesheet =>
[...stylesheet.cssRules]
.map(cssStyleRule => cssStyleRule.cssText)
.join('')
)
.join('')
.map(stylesheet => {
return {
type: stylesheet.ownerNode.tagName.toLowerCase(),
href: stylesheet.href || document.location.href,
css: [...stylesheet.cssRules].map(({cssText}) => cssText).join('\n')
}
})
})
await browser.close()
// 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-extract-css-inline-style] { color: red; }
//
const inlineCssRules = await page.evaluate(() => {
return [...document.querySelectorAll('[style]')]
.map(element => element.getAttribute('style'))
// Filter out empty style="" attributes
.filter(Boolean)
})
const inlineCss = inlineCssRules
.map(rule => `[x-extract-css-inline-style] { ${rule} }`)
.map(css => ({type: 'inline', href: url, css}))
// Turn the coverage Array into a single string of CSS
const coverageCss = coverage
const links = coverage
// Filter out the <style> tags that were found in the coverage

@@ -64,8 +95,18 @@ // report since we've conducted our own search for them.

// we requested is an indication that this was a <style> tag
.filter(styles => styles.url !== url)
// The `text` property contains the actual CSS
.map(({text}) => text)
.join('')
.filter(entry => entry.url !== url)
.map(entry => ({
href: entry.url,
css: entry.text,
type: 'link-or-import'
}))
return Promise.resolve(styleSheetsApiCss + coverageCss)
await browser.close()
const css = links
.concat(styleSheetsApiCss)
.concat(inlineCss)
.map(({css}) => css)
.join('\n')
return Promise.resolve(css)
}