diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 00000000..ead65078
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,40 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [10.x, 12.x, 14.x]
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v2-beta
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: Get yarn cache directory path
+ id: yarn-cache-dir-path
+ run: echo "::set-output name=dir::$(yarn cache dir)"
+ - uses: actions/cache@v2
+ id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
+ with:
+ path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+ - run: yarn
+ - run: yarn lintcheck
+ - run: yarn test --runInBand
+ - run: yarn e2e
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 00000000..471de961
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,8 @@
+*.peterbe
+*~
+dummy*
+hack*
+coverage
+/tests
+scripts/lintcheck.sh
+/.github
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 9002000d..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-sudo: required
-language: node_js
-node_js:
- stable
-services:
- - docker
-branches:
- only:
- - master
-before_install:
- - docker build -t minimalcss:tests .
-script:
- - docker container run -it minimalcss:tests yarn lintcheck
- - docker container run -it minimalcss:tests yarn test
- - docker container run -it --env CI=$CI minimalcss:tests yarn e2e
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7fd7966..59e64331 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,48 @@
+# 0.11.3
+
+* Cope with selectors with a `\` character before the `:`
+ [pull#426](https://github.com/peterbe/minimalcss/pull/426)
+
+# 0.11.2
+
+* Add a `.npmignore` to avoid shipping tests and backup files.
+
+# 0.11.1
+
+* Upgrade sub-dependency `find-my-way`
+ [pull#407](https://github.com/peterbe/minimalcss/pull/407)
+
+# 0.11.0
+
+* The main parameter `urls` can no be a string called just `url`. You just
+ need to either use `urls` (array) or `url` (string).
+
+* New `ignoreRequestErrors` option to ignore HTTP responses that are `>=400`.
+ [pull#365](https://github.com/peterbe/minimalcss/pull/365)
+ Thanks @Fgruntjes
+
+* (Chore) Switching from TravisCI to GitHub Actions
+
+# 0.10.0
+
+* Upgrade dependency on `puppeteer` to `^2.0.0`
+
+# 0.9.0
+
+* Ability to pass a list of whitelist selector regexes
+ [pull#344](https://github.com/peterbe/minimalcss/pull/344)
+ Thanks @AlexDubok
+
+* Upgrade dependency on `css-tree` to `1.0.0-alpha.37`
+
+* Upgrade dependency on `csso` to `~4.0.2`
+
+# 0.8.3
+
+* You can now render exclusively with JavaScript disabled.
+ [pull#312](https://github.com/peterbe/minimalcss/pull/312)
+ Thanks @VladislavTkachuk
+
# 0.8.2
* Big optimization. By looking up the "parent CSS selector" pre-emptively
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 359918ce..3742e17e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,12 +5,12 @@ The README has instructions about how to do testing and lint checking.
Generally you do:
```sh
-$ git clone https://github.com/peterbe/minimalcss.git
-$ cd minimalcss
-$ ./bin/minimalcss.js https://news.ycombinator.com
+git clone https://github.com/peterbe/minimalcss.git
+cd minimalcss
+./bin/minimalcss.js https://news.ycombinator.com
```
-If you make a PR, Travis will run unit tests, lint checks and end-to-end
+If you make a PR, GitHub Actions will run unit tests, lint checks and end-to-end
testing. Hopefully it's clear from any errors there what needs to be done.
## Style guide
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 630cd578..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,27 +0,0 @@
-FROM node:8
-
-RUN apt-get update && \
-apt-get install -yq gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
-libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
-libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
-libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
-ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
-
-ADD yarn.lock /yarn.lock
-ADD package.json /package.json
-
-ENV NODE_PATH=/node_modules
-ENV PATH=$PATH:/node_modules/.bin
-RUN yarn
-
-# I don't know why, but unless you do this 'yarn add puppeteer', Chromium
-# won't be installed.
-# Why isn't that taken care of why the 'yarn' above?
-RUN yarn add puppeteer
-
-
-WORKDIR /app
-ADD . /app
-
-ENTRYPOINT ["/bin/bash", "/app/tests/run.sh"]
-CMD ["e2e"]
diff --git a/README.md b/README.md
index 5ce06f97..0cfac370 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# minimalcss
-[](https://travis-ci.org/peterbe/minimalcss)
+
[](https://www.npmjs.com/package/minimalcss)
[](#badge)
[](https://renovateapp.com/)
@@ -13,7 +13,7 @@ This minimal CSS is also known as [critical path CSS](https://developers.google.
and ultimately a web performance technique to make web pages load faster
at initial load.
-## What does it do?
+## What does it do
You supply a list of URLs that it opens (one at a time) and for each page
it downloads all external CSS files (e.g.
@@ -42,24 +42,24 @@ one "merged" and minified CSS payload.
Install:
-```
+```bash
yarn add minimalcss --dev
```
You can install it globally if you like:
-```
+```bash
yarn global add minimalcss
```
-```
+```bash
npm install [--save-dev|--global] minimalcss
```
Now you can run it:
-```shell
-$ ./node_modules/.bin/minimalcss https://example.com/ https://example.com/aboutus > minimal.min.css
+```bash
+./node_modules/.bin/minimalcss https://example.com/ https://example.com/aboutus > minimal.min.css
```
## Prior art
@@ -136,7 +136,7 @@ For example:
```javascript
minimalcss
- .minimize({ urls: ['https://example.com/'] })
+ .minimize({ url: 'https://example.com/' })
.then(result => {
console.log('OUTPUT', result.finalCss.length, result.finalCss);
})
@@ -151,16 +151,27 @@ That `result` object that is returned by the `minimize` function contains:
* `stylesheetContents` - an object of stylesheet URLs as keys and their
content as text.
+Optionally, you can supply a list of URLs like this:
+
+```javascript
+minimalcss
+ .minimize({ urls: ['https://example.com/page1', 'https://example.com/page2'] })
+ ...
+```
+
+and `minimalcss` will try to merge the minimal critical CSS across all pages.
+But we aware that this can be "dangerous" because of the inherit order of CSS.
+
## API Options
Calling `minimalcss.run(options)` takes an object whose only mandatory
-key is `urls`. Other optional options are:
+key is `urls` or `url`. Other optional options are:
* `debug` - all console logging during page rendering are included in the
stdout. Also, any malformed selector that cause errors in `document.querySelector`
will be raised as new errors.
* `skippable` - function which takes
- [request](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-request)
+ [request](https://pptr.dev/#?product=Puppeteer&show=api-class-httprequest)
as an argument and returns boolean. If it returns true then given request
will be aborted (skipped). Can be used to block requests to Google Analytics
etc.
@@ -169,6 +180,7 @@ key is `urls`. Other optional options are:
without JavaScript. By default `minimalcss` will evaluate the DOM as plain as
can be, and then with JavaScript enabled _and_ waiting for network activity
to be idle.
+* `disableJavaScript` - By default JavaScript is enabled. If set to `true` it will ignore `withoutjavascript` option and loading the page only one time without JavaScript.
* `browser` - Instance of a [Browser](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser), which will be used instead of launching another one.
* `userAgent` - specific user agent to use (string)
* `viewport` - viewport object as specified in [page.setViewport](https://github.com/GoogleChrome/puppeteer/blob/v1.0.0/docs/api.md#pagesetviewportviewport)
@@ -178,10 +190,12 @@ key is `urls`. Other optional options are:
* `timeout` - Maximum navigation time in milliseconds, defaults to 30 seconds, pass 0 to disable timeout.
* `ignoreCSSErrors` - By default, any CSS parsing error throws an error in `minimalcss`. If you know it's safe to ignore (for example, third-party CSS resources), set this to `true`.
* `ignoreJSErrors` - By default, any JavaScript error encountered by puppeteer
+* `ignoreRequestErrors` - When CSS files return 404 or another request error `minimalcss` will ignore this instead of throwing an error.
will be thrown by `minimalcss`. If you know it's safe to ignore errors (for example, on
third-party webpages), set this to `true`.
* `styletags` - If set to `true`, on-page `` tags are parsed along with external stylesheets. By default, only external stylesheets are parsed.
* `enableServiceWorkers` - By default all Service Workers are disabled. This option enables them as is.
+* `whitelist` - Array of css selectors that should be left in final CSS. RegExp patterns are supported (e.g. `['sidebar', icon-.*, .*-error]`).
## Warnings
@@ -212,7 +226,7 @@ With the API, you can do it like this:
```javascript
minimalcss
.minimize({
- urls: ['https://example.com'],
+ url: 'https://example.com',
skippable: request => {
return !!request.url().match('fonts.googleapis.com');
}
@@ -245,9 +259,9 @@ and another URL with...:
When combining these, it will optimize the CSS in this order:
-1. `base.css`
-2. `specific.css`
-3. `base.css`
+1. `base.css`
+2. `specific.css`
+3. `base.css`
But if `specific.css` was meant to override something in `base.css` in the
first URL, that might get undone when `base.css` becomes the last CSS
@@ -321,9 +335,18 @@ to the the `.prettierrc` file in the root of the project.
To check that all your code conforms, run:
- yarn lintcheck
+```sh
+yarn lintcheck
+```
+
+## Use without a server
+
+[This blog post](https://www.peterbe.com/plog/how-to-use-minimalcss-without-a-server)
+demonstrates technique to use `minimalcss` when you don't yet have a server.
+Using the `http-server` package you can start a server right before you run
+and shut down as soon as you're done.
## License
-Copyright (c) 2017-2018 [Peter Bengtsson](https://www.peterbe.com).
+Copyright (c) 2017-2020 [Peter Bengtsson](https://www.peterbe.com).
See the [LICENSE](/LICENSE) file for license rights and limitations (MIT).
diff --git a/bin/minimalcss.js b/bin/minimalcss.js
index 260389aa..f76a4b39 100755
--- a/bin/minimalcss.js
+++ b/bin/minimalcss.js
@@ -20,7 +20,7 @@ const argv = minimist(args, {
'styletags',
'withoutjavascript',
'nosandbox',
- 'enableserviceworkers'
+ 'enableserviceworkers',
],
string: ['output', 'skip', 'viewport'],
default: {
@@ -30,14 +30,14 @@ const argv = minimist(args, {
debug: 'd',
help: 'h',
version: 'v',
- output: 'o'
+ output: 'o',
},
- unknown: param => {
+ unknown: (param) => {
if (param.startsWith('-')) {
console.warn('Ignored unknown option: ' + param + '\n');
return false;
}
- }
+ },
});
if (argv['version']) {
@@ -68,7 +68,7 @@ if (argv['help']) {
const urls = argv['_'];
-urls.forEach(url => {
+urls.forEach((url) => {
try {
const parsed = new URL(url);
} catch (ex) {
@@ -77,7 +77,7 @@ urls.forEach(url => {
}
});
-const parseViewport = asString => {
+const parseViewport = (asString) => {
if (!asString) {
return null;
}
@@ -95,7 +95,7 @@ const options = {
loadimages: argv['loadimages'],
styletags: argv['styletags'],
withoutjavascript: argv['withoutjavascript'],
- skippable: request => {
+ skippable: (request) => {
let skips = argv['skip'];
if (!skips) {
return false;
@@ -103,20 +103,20 @@ const options = {
if (!Array.isArray(skips)) {
skips = [skips];
}
- return skips.some(skip => !!request.url().match(skip));
+ return skips.some((skip) => !!request.url().match(skip));
},
viewport: parseViewport(argv['viewport']),
puppeteerArgs: argv['nosandbox']
? ['--no-sandbox', '--disable-setuid-sandbox']
: [],
- enableServiceWorkers: argv['enableserviceworkers']
+ enableServiceWorkers: argv['enableserviceworkers'],
};
const start = Date.now();
minimalcss
.minimize(options)
- .then(result => {
+ .then((result) => {
let output = result.finalCss;
const end = Date.now();
if (argv['verbose']) {
@@ -150,7 +150,7 @@ minimalcss
console.log(output);
}
})
- .catch(error => {
+ .catch((error) => {
console.error(error);
process.exit(3);
});
diff --git a/package.json b/package.json
index 6162bba8..42edbdde 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "minimalcss",
- "version": "0.8.2",
+ "version": "0.11.3",
"description": "Extract the minimal CSS used in a set of URLs with puppeteer",
"main": "./index.js",
"author": "Peter Bengtsson",
@@ -23,23 +23,23 @@
"url": "https://github.com/peterbe/minimalcss/issues"
},
"dependencies": {
- "cheerio": "1.0.0-rc.2",
- "css-tree": "1.0.0-alpha.28",
- "csso": "~3.5.0",
- "filesize": "^4.0.0",
+ "cheerio": "1.0.0-rc.3",
+ "css-tree": "1.0.0-alpha.39",
+ "csso": "4.0.3",
+ "filesize": "^6.0.0",
"minimist": "^1.2.0",
- "puppeteer": "^1.8.0"
+ "puppeteer": "^2.0.0"
},
"devDependencies": {
- "fastify": "1.14.3",
- "fastify-static": "1.1.0",
- "jest": "24.3.1",
- "prettier": "1.16.4"
+ "fastify": "3.4.1",
+ "fastify-static": "3.1.0",
+ "jest": "26.1.0",
+ "prettier": "2.1.2"
},
"scripts": {
"tsc": "tsc -p .",
"lintcheck": "scripts/lintcheck.sh",
"test": "jest",
- "e2e": "./bin/e2e.js"
+ "e2e": "scripts/e2e.js"
}
}
diff --git a/renovate.json b/renovate.json
deleted file mode 100644
index 61291d59..00000000
--- a/renovate.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "extends": [
- "config:base",
- "docker:disable"
- ]
-}
diff --git a/bin/e2e.js b/scripts/e2e.js
similarity index 66%
rename from bin/e2e.js
rename to scripts/e2e.js
index b0731902..ec4d7176 100755
--- a/bin/e2e.js
+++ b/scripts/e2e.js
@@ -6,8 +6,7 @@ const inCI = process.env.CI || false;
function assert(truth, failure) {
if (!truth) {
- console.error(failure);
- process.exit(1);
+ throw new Error(failure);
}
}
function assertStatus(spawned) {
@@ -41,31 +40,33 @@ function openUrl(url, ...options) {
}
// Simplest form of opening
-openUrl('https://minimalcss.app/').then(spawned => {
+openUrl('https://minimalcss.app/').then((spawned) => {
const css = spawned.stdout.toString();
assert(
- css.length > 8000 && css.length < 10000,
- 'Expect CSS to be between 8,000...10,000'
+ css.length > 7000 && css.length < 10000,
+ 'Expect CSS to be between 7,000...10,000'
);
});
// Open with -o
-openUrl('https://travis-ci.org/', '-o', '/tmp/travisci.css').then(spawned => {
- const stdout = spawned.stdout.toString();
- assert(!stdout.trim(), 'Output should be empty');
- const css = fs.readFileSync('/tmp/travisci.css').toString();
- assert(
- css.length > 10000 && css.length < 40000,
- 'Expect CSS to be between 1K...15K'
- );
-});
+openUrl('https://developer.mozilla.org/', '-o', '/tmp/mdn.css').then(
+ (spawned) => {
+ const stdout = spawned.stdout.toString();
+ assert(!stdout.trim(), 'Output should be empty');
+ const css = fs.readFileSync('/tmp/mdn.css').toString();
+ assert(
+ css.length > 10000 && css.length < 30000,
+ 'Expect CSS to be between 10K...30K'
+ );
+ }
+);
// With verbose output
-openUrl('https://news.ycombinator.com/', '--verbose').then(spawned => {
+openUrl('https://developer.mozilla.org/', '--verbose').then((spawned) => {
const css = spawned.stdout.toString();
assert(/\/\*\nGenerated /.test(css), 'Expected verbose leading comment');
assert(
- css.length > 1000 && css.length < 3000,
- 'Expect CSS to be between 1K...3K'
+ css.length > 10000 && css.length < 30000,
+ 'Expect CSS to be between 10K...30K'
);
});
diff --git a/src/run.js b/src/run.js
index 7810dd15..59b02581 100644
--- a/src/run.js
+++ b/src/run.js
@@ -10,7 +10,7 @@ const utils = require('./utils');
const { createTracker } = require('./tracker');
const url = require('url');
-const isOk = response => response.ok() || response.status() === 304;
+const isOk = (response) => response.ok() || response.status() === 304;
/**
* Take in a csstree AST, mutate it and return a csstree AST.
@@ -30,13 +30,13 @@ const isOk = response => response.ok() || response.status() === 304;
* @param {Object} ast
* @return Object
*/
-const postProcessOptimize = ast => {
+const postProcessOptimize = (ast) => {
// First walk the AST to know which animations are ever mentioned
// by the remaining rules.
const activeAnimationNames = new Set(
csstree.lexer
.findAllFragments(ast, 'Type', 'keyframes-name')
- .map(entry => csstree.generate(entry.nodes.first()))
+ .map((entry) => csstree.generate(entry.nodes.first()))
);
// This is the function we use to filter @keyframes atrules out,
@@ -55,31 +55,31 @@ const postProcessOptimize = ast => {
list.remove(item);
}
}
- }
+ },
});
// Now figure out what font-families are at all used in the AST.
const activeFontFamilyNames = new Set();
csstree.walk(ast, {
visit: 'Declaration',
- enter: function(node) {
+ enter: function (node) {
// walker pass through `font-family` declarations inside @font-face too
// this condition filter them, to walk through declarations
// inside a rules only.
if (this.rule) {
csstree.lexer
.findDeclarationValueFragments(node, 'Type', 'family-name')
- .forEach(entry => {
+ .forEach((entry) => {
const name = utils.unquoteString(
csstree.generate({
type: 'Value',
- children: entry.nodes
+ children: entry.nodes,
})
);
activeFontFamilyNames.add(name);
});
}
- }
+ },
});
// Walk into every font-family rule and inspect if we uses its declarations
@@ -90,7 +90,7 @@ const postProcessOptimize = ast => {
// We're inside a font-face rule! Let's dig deeper.
csstree.walk(atrule, {
visit: 'Declaration',
- enter: declaration => {
+ enter: (declaration) => {
if (csstree.property(declaration.property).name === 'font-family') {
const name = utils.unquoteString(
csstree.generate(declaration.value)
@@ -100,10 +100,10 @@ const postProcessOptimize = ast => {
atruleList.remove(atruleItem);
}
}
- }
+ },
});
}
- }
+ },
});
};
@@ -112,15 +112,10 @@ const processStylesheet = ({
pageUrl,
responseUrl,
stylesheetAsts,
- stylesheetContents
+ stylesheetContents,
}) => {
- // Semicolon sequences can crash CSSO,
- // so we remove them from the CSS text.
- // https://github.com/peterbe/minimalcss/issues/243
- // https://github.com/css/csso/issues/378
- text = utils.removeSequentialSemis(text);
const ast = csstree.parse(text);
- csstree.walk(ast, node => {
+ csstree.walk(ast, (node) => {
if (node.type !== 'Url') return;
const value = node.value;
let path = value.value;
@@ -159,7 +154,7 @@ const processPage = ({
doms,
allHrefs,
redirectResponses,
- skippedUrls
+ skippedUrls,
}) =>
new Promise(async (resolve, reject) => {
// If anything goes wrong, for example a `pageerror` event or
@@ -169,10 +164,10 @@ const processPage = ({
let fulfilledPromise = false;
const tracker = createTracker(page);
- const safeReject = error => {
+ const safeReject = (error) => {
if (fulfilledPromise) return;
fulfilledPromise = true;
- if (error.message.startsWith('Navigation Timeout Exceeded')) {
+ if (error.message.startsWith('Navigation timeout')) {
const urls = tracker.urls();
if (urls.length > 1) {
error.message += `\nTracked URLs that have not finished: ${urls.join(
@@ -193,6 +188,7 @@ const processPage = ({
options.withoutjavascript === undefined
? true
: !!options.withoutjavascript;
+ const disableJavaScript = !!options.disableJavaScript;
try {
if (options.userAgent) {
@@ -208,7 +204,7 @@ const processPage = ({
}
// A must or else you can't do console.log from within page.evaluate()
- page.on('console', msg => {
+ page.on('console', (msg) => {
if (debug) {
for (let i = 0; i < msg.args.length; ++i) {
console.log(`${i}: ${msg.args[i]}`);
@@ -217,7 +213,7 @@ const processPage = ({
});
await page.setRequestInterception(true);
- page.on('request', request => {
+ page.on('request', (request) => {
const resourceType = request.resourceType();
const requestUrl = request.url();
if (/data:image\//.test(requestUrl)) {
@@ -244,13 +240,17 @@ const processPage = ({
});
// To build up a map of all downloaded CSS
- page.on('response', response => {
+ page.on('response', (response) => {
const responseUrl = response.url();
const resourceType = response.request().resourceType();
if (response.status() >= 400) {
- return safeReject(
- new Error(`${response.status()} on ${responseUrl}`)
- );
+ if (options.ignoreRequestErrors) {
+ skippedUrls.add(responseUrl);
+ } else {
+ return safeReject(
+ new Error(`${response.status()} on ${responseUrl}`)
+ );
+ }
} else if (response.status() >= 300 && response.status() !== 304) {
// If the 'Location' header points to a relative URL,
// convert it to an absolute URL.
@@ -261,19 +261,19 @@ const processPage = ({
).toString();
redirectResponses[responseUrl] = redirectsTo;
} else if (resourceType === 'stylesheet') {
- response.text().then(text => {
+ response.text().then((text) => {
processStylesheet({
text,
pageUrl,
responseUrl,
stylesheetAsts,
- stylesheetContents
+ stylesheetContents,
});
});
}
});
- page.on('pageerror', error => {
+ page.on('pageerror', (error) => {
if (options.ignoreJSErrors) {
console.warn(error);
} else {
@@ -283,7 +283,9 @@ const processPage = ({
let response;
- if (withoutjavascript) {
+ if (disableJavaScript) {
+ await page.setJavaScriptEnabled(false);
+ } else if (withoutjavascript) {
// First, go to the page with JavaScript disabled.
await page.setJavaScriptEnabled(false);
response = await page.goto(pageUrl);
@@ -321,11 +323,11 @@ const processPage = ({
// supported in ES5.
const hrefs = [];
const styles = [];
- const isCssStyleTag = elem =>
+ const isCssStyleTag = (elem) =>
elem.tagName === 'STYLE' &&
(!elem.type || elem.type.toLowerCase() === 'text/css');
- const isStylesheetLink = elem =>
+ const isStylesheetLink = (elem) =>
elem.tagName === 'LINK' &&
elem.href &&
elem.rel.toLowerCase() === 'stylesheet' &&
@@ -336,7 +338,7 @@ const processPage = ({
// #fragments are omitted from puppeteer's response.url(), so
// we need to strip them from stylesheet links, otherwise the
// hrefs won't always match when we check for missing ASTs.
- const defragment = href => href.split('#')[0];
+ const defragment = (href) => href.split('#')[0];
const pageUrl = defragment(window.location.href);
// Create a unique identifier for each style tag by appending
// an xpath-like fragment to the page URL. This allows us to
@@ -347,7 +349,7 @@ const processPage = ({
// in order of appearance. For each element, collect the URI
// of all the ones we're going to assess. For style elements,
// also extract each tag's content.
- Array.from(document.querySelectorAll('link, style')).forEach(elem => {
+ Array.from(document.querySelectorAll('link, style')).forEach((elem) => {
if (isStylesheetLink(elem)) {
const href = defragment(elem.href);
hrefs.push(href);
@@ -372,7 +374,7 @@ const processPage = ({
pageUrl,
stylesheetAsts,
stylesheetContents,
- responseUrl: href
+ responseUrl: href,
});
});
} else {
@@ -385,7 +387,7 @@ const processPage = ({
});
}
- evalWithJavascript.hrefs.forEach(href => {
+ evalWithJavascript.hrefs.forEach((href) => {
// The order of allHrefs is important! That's what browsers do.
// But we can't blindly using allHrefs.push() because the href
// *might* already have been encountered. If it has been encountered
@@ -407,22 +409,33 @@ const processPage = ({
/**
*
- * @param {{ urls: Array, debug: boolean, loadimages: boolean, skippable: function, browser: any, userAgent: string, withoutjavascript: boolean, viewport: any, puppeteerArgs: Array, cssoOptions: Object, ignoreCSSErrors?: boolean, ignoreJSErrors?: boolean, styletags?: boolean, enableServiceWorkers?: boolean }} options
- * @return Promise<{ finalCss: string, stylesheetContents: { [key: string]: string } }>
+ * @param {{ urls: Array, url: string, debug: boolean, loadimages: boolean, skippable: function, browser: any, userAgent: string, withoutjavascript: boolean, viewport: any, puppeteerArgs: Array, cssoOptions: Object, ignoreCSSErrors?: boolean, ignoreJSErrors?: boolean, styletags?: boolean, enableServiceWorkers?: boolean, disableJavaScript?: boolean, whitelist?: Array, ignoreRequestErrors?: boolean }} options
+ * @return Promise<{ finalCss: string, stylesheetContents: { [key: string]: string }, doms: Array