lighthouse-badges 1.1.26 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -1
- package/.eslintrc.yml +2 -1
- package/.github/workflows/build.yml +9 -13
- package/Dockerfile +4 -5
- package/LICENSE.md +1 -1
- package/README.md +1 -1
- package/__tests__/argparser.js +7 -5
- package/__tests__/index.js +2 -2
- package/__tests__/lighthouse-badges.js +19 -14
- package/dist/LICENSE.md +21 -0
- package/dist/README.md +103 -0
- package/dist/package.json +75 -0
- package/dist/src/argparser.js +49 -0
- package/dist/src/calculations.js +65 -0
- package/dist/src/index.js +57 -0
- package/dist/src/lighthouse-badges.js +229 -0
- package/dist/src/util.js +25 -0
- package/jest.config.js +16 -0
- package/package.json +34 -33
- package/src/argparser.js +3 -5
- package/src/calculations.js +4 -10
- package/src/index.js +4 -6
- package/src/lighthouse-badges.js +39 -38
- package/src/util.js +3 -9
package/.eslintignore
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
coverage/
|
|
1
|
+
coverage/
|
|
2
|
+
dist/
|
package/.eslintrc.yml
CHANGED
|
@@ -14,20 +14,15 @@ jobs:
|
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
steps:
|
|
16
16
|
- name: Checkout
|
|
17
|
-
uses: actions/checkout@
|
|
18
|
-
|
|
19
|
-
- name: Set up Docker Context for Buildx
|
|
20
|
-
id: buildx-context
|
|
21
|
-
run: docker context create builders
|
|
17
|
+
uses: actions/checkout@v3
|
|
22
18
|
|
|
23
19
|
- name: Set up QEMU
|
|
24
|
-
uses: docker/setup-qemu-action@
|
|
20
|
+
uses: docker/setup-qemu-action@v2
|
|
25
21
|
|
|
26
22
|
- name: Set up Docker Buildx
|
|
27
|
-
uses: docker/setup-buildx-action@
|
|
23
|
+
uses: docker/setup-buildx-action@v2
|
|
28
24
|
with:
|
|
29
25
|
version: latest
|
|
30
|
-
endpoint: builders
|
|
31
26
|
|
|
32
27
|
- name: Versions
|
|
33
28
|
run: |
|
|
@@ -39,16 +34,17 @@ jobs:
|
|
|
39
34
|
run: |
|
|
40
35
|
npm install
|
|
41
36
|
npm run lint
|
|
37
|
+
npm run build
|
|
42
38
|
|
|
43
39
|
- name: Login to DockerHub
|
|
44
40
|
if: github.ref == 'refs/heads/master'
|
|
45
|
-
uses: docker/login-action@
|
|
41
|
+
uses: docker/login-action@v2
|
|
46
42
|
with:
|
|
47
43
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
48
44
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
49
45
|
|
|
50
46
|
- name: Docker Build
|
|
51
|
-
uses: docker/build-push-action@
|
|
47
|
+
uses: docker/build-push-action@v3
|
|
52
48
|
with:
|
|
53
49
|
context: .
|
|
54
50
|
file: ./Dockerfile
|
|
@@ -77,7 +73,7 @@ jobs:
|
|
|
77
73
|
npm config set //npm.pkg.github.com/:_authToken ${GITHUB_TOKEN}
|
|
78
74
|
[[ "$(npm show ${package_name} version)" == "${current_version}" ]] && \
|
|
79
75
|
echo "Current version ${current_version} already published" || \
|
|
80
|
-
npm publish
|
|
76
|
+
npm run ci:publish
|
|
81
77
|
env:
|
|
82
78
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
83
79
|
|
|
@@ -91,7 +87,7 @@ jobs:
|
|
|
91
87
|
npm config set //registry.npmjs.org/:_authToken ${NPM_AUTH_TOKEN}
|
|
92
88
|
[[ "$(npm show ${package_name} version)" == "${current_version}" ]] && \
|
|
93
89
|
echo "Current version ${current_version} already published" || \
|
|
94
|
-
npm publish
|
|
90
|
+
npm run ci:publish
|
|
95
91
|
env:
|
|
96
92
|
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|
|
97
93
|
|
|
@@ -101,7 +97,7 @@ jobs:
|
|
|
101
97
|
|
|
102
98
|
- name: Deploy to Dockerhub
|
|
103
99
|
if: github.ref == 'refs/heads/master'
|
|
104
|
-
uses: docker/build-push-action@
|
|
100
|
+
uses: docker/build-push-action@v3
|
|
105
101
|
with:
|
|
106
102
|
context: .
|
|
107
103
|
file: ./Dockerfile
|
package/Dockerfile
CHANGED
|
@@ -15,15 +15,14 @@ LABEL maintainer="hello@mazzotta.me" \
|
|
|
15
15
|
org.label-schema.version=$VERSION \
|
|
16
16
|
org.label-schema.schema-version="1.0"
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
RUN apk --update --no-cache add chromium
|
|
18
|
+
RUN apk --update --no-cache add chromium git
|
|
20
19
|
|
|
20
|
+
# Add lighthouse
|
|
21
21
|
RUN mkdir -p /home/lighthouse
|
|
22
22
|
WORKDIR /home/lighthouse
|
|
23
|
+
COPY dist/src /home/lighthouse/src
|
|
24
|
+
COPY dist/package.json /home/lighthouse/package.json
|
|
23
25
|
|
|
24
|
-
# Add lighthouse
|
|
25
|
-
COPY src /home/lighthouse/src
|
|
26
|
-
COPY package.json /home/lighthouse/package.json
|
|
27
26
|
RUN npm install . && npm link && rm -rf /root/.npm
|
|
28
27
|
|
|
29
28
|
# Set Chromium bin path
|
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ Required arguments:
|
|
|
54
54
|
average score(s) of all the urls supplied, combined
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
Additionally you can pass parameters to the lighthouse process directly via environment variable:
|
|
57
|
+
Additionally, you can pass parameters to the lighthouse process directly via environment variable:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
# This will pass '--preset=desktop' to the lighthouse process
|
package/__tests__/argparser.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import parser from '../src/argparser';
|
|
2
2
|
|
|
3
3
|
describe('test argparser', () => {
|
|
4
|
+
const baseUrl = 'https://emanuelemazzotta.com';
|
|
5
|
+
|
|
4
6
|
it('should return expected default values', () => {
|
|
5
|
-
const actualArgs = parser.parse_args(['--urls',
|
|
7
|
+
const actualArgs = parser.parse_args(['--urls', baseUrl, `${baseUrl}/cv`]);
|
|
6
8
|
expect(actualArgs.single_badge).toBe(false);
|
|
7
9
|
expect(actualArgs.badge_style).toBe('flat');
|
|
8
10
|
expect(actualArgs.save_report).toBe(false);
|
|
9
|
-
expect(actualArgs.urls).toStrictEqual([
|
|
11
|
+
expect(actualArgs.urls).toStrictEqual([baseUrl, `${baseUrl}/cv`]);
|
|
10
12
|
});
|
|
11
13
|
|
|
12
14
|
it('should overwrite values', () => {
|
|
@@ -14,12 +16,12 @@ describe('test argparser', () => {
|
|
|
14
16
|
'--single-badge',
|
|
15
17
|
'--save-report',
|
|
16
18
|
'--badge-style', 'flat-square',
|
|
17
|
-
'--urls',
|
|
19
|
+
'--urls', baseUrl,
|
|
18
20
|
]);
|
|
19
21
|
|
|
20
22
|
expect(actualArgs.single_badge).toBe(true);
|
|
21
23
|
expect(actualArgs.badge_style).toBe('flat-square');
|
|
22
24
|
expect(actualArgs.save_report).toBe(true);
|
|
23
|
-
expect(actualArgs.urls).toStrictEqual([
|
|
25
|
+
expect(actualArgs.urls).toStrictEqual([baseUrl]);
|
|
24
26
|
});
|
|
25
27
|
});
|
package/__tests__/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import parser from '../src/argparser';
|
|
2
|
+
import handleUserInput from '../src/index';
|
|
3
3
|
import * as lighthouseBadges from '../src/lighthouse-badges';
|
|
4
4
|
|
|
5
5
|
jest.mock('../src/lighthouse-badges');
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import
|
|
3
|
-
import lighthouseBadges, {
|
|
2
|
+
import {
|
|
4
3
|
htmlReportsToFile,
|
|
5
4
|
metricsToSvg,
|
|
5
|
+
processParameters,
|
|
6
6
|
processRawLighthouseResult,
|
|
7
7
|
} from '../src/lighthouse-badges';
|
|
8
8
|
import { zip } from '../src/util';
|
|
9
|
-
import
|
|
9
|
+
import parser from '../src/argparser';
|
|
10
10
|
import reportFixture from '../assets/report/emanuelemazzotta.com.json';
|
|
11
11
|
|
|
12
12
|
describe('test lighthouse badges', () => {
|
|
@@ -14,7 +14,7 @@ describe('test lighthouse badges', () => {
|
|
|
14
14
|
it('should return correct metrics and no report', async () => {
|
|
15
15
|
const url = 'https://emanuelemazzotta.com';
|
|
16
16
|
const shouldSaveReport = false;
|
|
17
|
-
const result = await processRawLighthouseResult(reportFixture, url, shouldSaveReport);
|
|
17
|
+
const result = await processRawLighthouseResult(reportFixture, '', url, shouldSaveReport);
|
|
18
18
|
expect({
|
|
19
19
|
metrics: {
|
|
20
20
|
'lighthouse performance': 98,
|
|
@@ -30,10 +30,15 @@ describe('test lighthouse badges', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
it('should return correct metrics and a valid report', async () => {
|
|
33
|
-
const expectedHtmlReport =
|
|
33
|
+
const expectedHtmlReport = '<html>Fake report</html>';
|
|
34
34
|
const url = 'https://emanuelemazzotta.com';
|
|
35
35
|
const shouldSaveReport = true;
|
|
36
|
-
const result = await processRawLighthouseResult(
|
|
36
|
+
const result = await processRawLighthouseResult(
|
|
37
|
+
reportFixture,
|
|
38
|
+
expectedHtmlReport,
|
|
39
|
+
url,
|
|
40
|
+
shouldSaveReport,
|
|
41
|
+
);
|
|
37
42
|
expect({
|
|
38
43
|
metrics: {
|
|
39
44
|
'lighthouse performance': 98,
|
|
@@ -142,8 +147,8 @@ describe('test lighthouse badges', () => {
|
|
|
142
147
|
]);
|
|
143
148
|
|
|
144
149
|
const calculateLighthouseMetrics = jest.fn();
|
|
145
|
-
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, 'https://example.org', args.save_report));
|
|
146
|
-
await
|
|
150
|
+
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, '<html>Fake report</html>', 'https://example.org', args.save_report));
|
|
151
|
+
await processParameters(args, calculateLighthouseMetrics);
|
|
147
152
|
|
|
148
153
|
expect(output.length).toBe(2);
|
|
149
154
|
});
|
|
@@ -155,8 +160,8 @@ describe('test lighthouse badges', () => {
|
|
|
155
160
|
]);
|
|
156
161
|
|
|
157
162
|
const calculateLighthouseMetrics = jest.fn();
|
|
158
|
-
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, 'https://example.org', args.save_report));
|
|
159
|
-
await
|
|
163
|
+
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, '<html>Fake report</html>', 'https://example.org', args.save_report));
|
|
164
|
+
await processParameters(args, calculateLighthouseMetrics);
|
|
160
165
|
|
|
161
166
|
expect(output.length).toBe(6);
|
|
162
167
|
});
|
|
@@ -168,8 +173,8 @@ describe('test lighthouse badges', () => {
|
|
|
168
173
|
]);
|
|
169
174
|
|
|
170
175
|
const calculateLighthouseMetrics = jest.fn();
|
|
171
|
-
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, 'https://example.org', args.save_report));
|
|
172
|
-
await
|
|
176
|
+
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, null, 'https://example.org', args.save_report));
|
|
177
|
+
await processParameters(args, calculateLighthouseMetrics);
|
|
173
178
|
|
|
174
179
|
expect(output.length).toBe(1);
|
|
175
180
|
});
|
|
@@ -180,8 +185,8 @@ describe('test lighthouse badges', () => {
|
|
|
180
185
|
]);
|
|
181
186
|
|
|
182
187
|
const calculateLighthouseMetrics = jest.fn();
|
|
183
|
-
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, 'https://example.org', args.save_report));
|
|
184
|
-
await
|
|
188
|
+
calculateLighthouseMetrics.mockReturnValue(await processRawLighthouseResult(reportFixture, null, 'https://example.org', args.save_report));
|
|
189
|
+
await processParameters(args, calculateLighthouseMetrics);
|
|
185
190
|
|
|
186
191
|
expect(output.length).toBe(5);
|
|
187
192
|
});
|
package/dist/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Emanuele Mazzotta
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
[](https://github.com/emazzotta/lighthouse-badges/actions)
|
|
2
|
+
[](https://github.com/emazzotta/lighthouse-badges/actions)
|
|
3
|
+
[](https://www.npmjs.org/package/lighthouse-badges)
|
|
4
|
+
[](https://www.npmjs.org/package/lighthouse-badges)
|
|
5
|
+
[](https://emanuelemazzotta.com/mit-license)
|
|
6
|
+
|
|
7
|
+
# Lighthouse Badges
|
|
8
|
+
|
|
9
|
+
[](https://github.com/GoogleChrome/lighthouse)
|
|
10
|
+
|
|
11
|
+
This package allows you to easily create Lighthouse badges for all Lighthouse categories.
|
|
12
|
+
Ever wanted to brag about your sites's awesome Lighthouse performance? Then this is the package for you!
|
|
13
|
+
|
|
14
|
+
## Examples
|
|
15
|
+
|
|
16
|
+
### All Badges
|
|
17
|
+
|
|
18
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
19
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
20
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
21
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
22
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
23
|
+
|
|
24
|
+
### Single Badge
|
|
25
|
+
|
|
26
|
+
[](https://github.com/emazzotta/lighthouse-badges)
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Help
|
|
31
|
+
|
|
32
|
+
```txt
|
|
33
|
+
usage: lighthouse-badges [-h] [-v] [-s]
|
|
34
|
+
[-b {flat,flat-square,plastic,for-the-badge,popout,popout-square,social}]
|
|
35
|
+
[-o OUTPUT_PATH] [-r] -u URLS [URLS ...]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Generate gh-badges (shields.io) based on lighthouse performance.
|
|
39
|
+
|
|
40
|
+
Optional arguments:
|
|
41
|
+
-h, --help Show this help message and exit.
|
|
42
|
+
-v, --version Show program's version number and exit.
|
|
43
|
+
-s, --single-badge Output only one single badge averaging all lighthouse
|
|
44
|
+
categories' scores
|
|
45
|
+
-b {flat,flat-square,plastic,for-the-badge,popout,popout-square,social}, --badge-style {flat,flat-square,plastic,for-the-badge,popout,popout-square,social}
|
|
46
|
+
Define look and feel for the badge
|
|
47
|
+
-o OUTPUT_PATH, --output-path OUTPUT_PATH
|
|
48
|
+
Define output path for artifacts
|
|
49
|
+
-r, --save-report Save lighthouse report as html for every supplied url
|
|
50
|
+
|
|
51
|
+
Required arguments:
|
|
52
|
+
-u URLS [URLS ...], --urls URLS [URLS ...]
|
|
53
|
+
The lighthouse badge(s) will contain the respective
|
|
54
|
+
average score(s) of all the urls supplied, combined
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Additionally, you can pass parameters to the lighthouse process directly via environment variable:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# This will pass '--preset=desktop' to the lighthouse process
|
|
61
|
+
export LIGHTHOUSE_BADGES_PARAMS="--preset=desktop"
|
|
62
|
+
lighthouse-badges --urls https://www.youtube.com/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Run
|
|
66
|
+
|
|
67
|
+
Hint: Only node >= 12 is supported.
|
|
68
|
+
|
|
69
|
+
#### Option 1: npm
|
|
70
|
+
```bash
|
|
71
|
+
npm i -g lighthouse-badges
|
|
72
|
+
lighthouse-badges --urls https://www.youtube.com/ https://www.youtube.com/feed/trending -o test_results
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Option 2: npx
|
|
76
|
+
```bash
|
|
77
|
+
npx lighthouse-badges --urls https://www.youtube.com/ https://www.youtube.com/feed/trending -o test_results
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Option 3: Docker
|
|
81
|
+
```bash
|
|
82
|
+
# Warning, the docker version may alter the lighthouse results
|
|
83
|
+
docker run --rm \
|
|
84
|
+
-v $PWD/test_results:/home/chrome/reports \
|
|
85
|
+
emazzotta/lighthouse-badges \
|
|
86
|
+
/bin/sh -c "lighthouse-badges --urls https://www.youtube.com/ https://www.youtube.com/feed/trending"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Contributing
|
|
90
|
+
|
|
91
|
+
See [contribution guideline](./CONTRIBUTING.md)
|
|
92
|
+
|
|
93
|
+
## Sponsors
|
|
94
|
+
|
|
95
|
+
Sponsored by [JetBrains](https://www.jetbrains.com/?from=Lighthouse-Badges)
|
|
96
|
+
|
|
97
|
+
<a href="https://www.jetbrains.com/?from=Lighthouse-Badges">
|
|
98
|
+
<img alt="Jetbrains Logo" src="./assets/img/jetbrains.svg" height="100">
|
|
99
|
+
</a>
|
|
100
|
+
|
|
101
|
+
## Author
|
|
102
|
+
|
|
103
|
+
[Emanuele Mazzotta](mailto:hello@mazzotta.me)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lighthouse-badges",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "🚦Generate gh-badges (shields.io) based on Lighthouse performance.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"lighthouse-badges": "src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"app:install": "npm i -g .",
|
|
11
|
+
"app:reinstall": "npm-run-all app:uninstall app:install",
|
|
12
|
+
"app:uninstall": "npm uninstall -g @emazzotta/lighthouse-badges",
|
|
13
|
+
"build": "npm run clean && babel src --out-dir dist/src && sed 's#\"dist/src/index.js\"#\"src/index.js\"#' package.json > ./dist/package.json && cp README.md dist && cp LICENSE.md dist",
|
|
14
|
+
"ci:publish": "npm run build && npm publish --prefix dist",
|
|
15
|
+
"clean": "rm -rf *.svg *.html coverage dist results",
|
|
16
|
+
"docker:build": "npm run build && docker build --build-arg VCS_REF=`git rev-parse --short HEAD` --build-arg BUILD_DATE=`date -u +\"%Y-%m-%dT%H:%M:%SZ\"` --build-arg VERSION=latest -t emazzotta/lighthouse-badges .",
|
|
17
|
+
"docker:system-test:run": "docker run emazzotta/lighthouse-badges /bin/sh -c 'lighthouse-badges -rsu https://google.com && EXEC_PATH=/home/chrome/reports npm run system-test:verify --prefix /home/lighthouse'",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"lint:fix": "eslint --fix .",
|
|
20
|
+
"pre-push": "npm-run-all lint:fix test:all",
|
|
21
|
+
"run:global-installation": "[ -z ${PAGE} ] && PAGE=https://google.com ; lighthouse-badges -rsu ${PAGE} -o results",
|
|
22
|
+
"run:local-installation": "[ -z ${PAGE} ] && PAGE=https://google.com ; node dist/src/index.js -rsu ${PAGE} -o results",
|
|
23
|
+
"system-test:full-run": "npm-run-all clean build app:reinstall run:global-installation system-test:verify",
|
|
24
|
+
"system-test:light-run": "npm-run-all clean build run:local-installation system-test:verify",
|
|
25
|
+
"system-test:verify": "[ -z ${EXEC_PATH} ] && EXEC_PATH=$PWD/results ; grep -q '<svg xmlns' ${EXEC_PATH}/*.svg && grep -q '<title>Lighthouse Report</title>' ${EXEC_PATH}/*.html",
|
|
26
|
+
"test": "jest",
|
|
27
|
+
"test:all": "npm-run-all test system-test:full-run",
|
|
28
|
+
"test:related": "jest --findRelatedTests"
|
|
29
|
+
},
|
|
30
|
+
"husky": {
|
|
31
|
+
"hooks": {
|
|
32
|
+
"pre-commit": "lint-staged"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"lint-staged": {
|
|
36
|
+
"*.js": [
|
|
37
|
+
"npm run lint:fix",
|
|
38
|
+
"npm run test:related"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/emazzotta/lighthouse-badges.git"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"argparse": "2.0.1",
|
|
47
|
+
"badge-maker": "^3.3.1",
|
|
48
|
+
"chrome-launcher": "^0.15.1",
|
|
49
|
+
"clui": "^0.3.6",
|
|
50
|
+
"lighthouse": "^10.0.0",
|
|
51
|
+
"ramda": "^0.28.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@babel/cli": "^7.20.7",
|
|
55
|
+
"@babel/core": "^7.20.12",
|
|
56
|
+
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
57
|
+
"@babel/preset-env": "^7.20.2",
|
|
58
|
+
"@types/jest": "^29.4.0",
|
|
59
|
+
"eslint": "^8.33.0",
|
|
60
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
61
|
+
"eslint-plugin-import": "^2.27.5",
|
|
62
|
+
"husky": "^8.0.3",
|
|
63
|
+
"jest": "^29.4.2",
|
|
64
|
+
"lint-staged": "^13.1.1",
|
|
65
|
+
"npm-run-all": "^4.1.5"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"npm": ">=7.0.0",
|
|
69
|
+
"node": ">=16.0.0"
|
|
70
|
+
},
|
|
71
|
+
"packageManager": "yarn@1.21.1",
|
|
72
|
+
"private": false,
|
|
73
|
+
"author": "Emanuele Mazzotta",
|
|
74
|
+
"license": "MIT"
|
|
75
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _argparse = require("argparse");
|
|
8
|
+
var _package = require("../package.json");
|
|
9
|
+
var parser = new _argparse.ArgumentParser({
|
|
10
|
+
add_help: true,
|
|
11
|
+
description: 'Generate gh-badges (shields.io) based on lighthouse performance.'
|
|
12
|
+
});
|
|
13
|
+
var requiredArgs = parser.add_argument_group({
|
|
14
|
+
title: 'Required arguments'
|
|
15
|
+
});
|
|
16
|
+
parser.add_argument('-v', '--version', {
|
|
17
|
+
action: 'version',
|
|
18
|
+
version: _package.version
|
|
19
|
+
});
|
|
20
|
+
parser.add_argument('-s', '--single-badge', {
|
|
21
|
+
action: 'store_true',
|
|
22
|
+
required: false,
|
|
23
|
+
help: 'Output only one single badge averaging all lighthouse categories\' scores '
|
|
24
|
+
});
|
|
25
|
+
parser.add_argument('-b', '--badge-style', {
|
|
26
|
+
action: 'store',
|
|
27
|
+
required: false,
|
|
28
|
+
choices: ['flat', 'flat-square', 'plastic', 'for-the-badge', 'popout', 'popout-square', 'social'],
|
|
29
|
+
"default": 'flat',
|
|
30
|
+
help: 'Define look and feel for the badge'
|
|
31
|
+
});
|
|
32
|
+
parser.add_argument('-o', '--output-path', {
|
|
33
|
+
action: 'store',
|
|
34
|
+
required: false,
|
|
35
|
+
help: 'Define output path for artifacts'
|
|
36
|
+
});
|
|
37
|
+
parser.add_argument('-r', '--save-report', {
|
|
38
|
+
action: 'store_true',
|
|
39
|
+
required: false,
|
|
40
|
+
help: 'Save lighthouse report as html for every supplied url'
|
|
41
|
+
});
|
|
42
|
+
requiredArgs.add_argument('-u', '--urls', {
|
|
43
|
+
action: 'store',
|
|
44
|
+
required: true,
|
|
45
|
+
nargs: _argparse.ONE_OR_MORE,
|
|
46
|
+
help: 'The lighthouse badge(s) will contain the respective average score(s) of all the urls supplied, combined'
|
|
47
|
+
});
|
|
48
|
+
var _default = parser;
|
|
49
|
+
exports["default"] = _default;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.percentageToColor = exports.getSquashedScore = exports.getAverageScore = void 0;
|
|
9
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
10
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
12
|
+
var R = _interopRequireWildcard(require("ramda"));
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
14
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
15
|
+
var percentageToColor = function percentageToColor(percentage) {
|
|
16
|
+
if (percentage >= 95) return 'brightgreen';
|
|
17
|
+
if (percentage >= 90) return 'green';
|
|
18
|
+
if (percentage >= 75) return 'yellowgreen';
|
|
19
|
+
if (percentage >= 60) return 'yellow';
|
|
20
|
+
if (percentage >= 40) return 'orange';
|
|
21
|
+
return 'red';
|
|
22
|
+
};
|
|
23
|
+
exports.percentageToColor = percentageToColor;
|
|
24
|
+
var getAverageScore = /*#__PURE__*/function () {
|
|
25
|
+
var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(metrics) {
|
|
26
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
27
|
+
while (1) switch (_context.prev = _context.next) {
|
|
28
|
+
case 0:
|
|
29
|
+
return _context.abrupt("return", R.pipe(R.head, R.keys, R.map(function (category) {
|
|
30
|
+
return (0, _defineProperty2["default"])({}, category, Math.round(R.sum(R.pluck(category, metrics)) / R.length(metrics)));
|
|
31
|
+
}), R.mergeAll)(metrics));
|
|
32
|
+
case 1:
|
|
33
|
+
case "end":
|
|
34
|
+
return _context.stop();
|
|
35
|
+
}
|
|
36
|
+
}, _callee);
|
|
37
|
+
}));
|
|
38
|
+
return function getAverageScore(_x) {
|
|
39
|
+
return _ref.apply(this, arguments);
|
|
40
|
+
};
|
|
41
|
+
}();
|
|
42
|
+
exports.getAverageScore = getAverageScore;
|
|
43
|
+
var getSquashedScore = /*#__PURE__*/function () {
|
|
44
|
+
var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(metrics) {
|
|
45
|
+
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
|
46
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
47
|
+
case 0:
|
|
48
|
+
return _context2.abrupt("return", {
|
|
49
|
+
lighthouse: R.pipe(R.map(function (metric) {
|
|
50
|
+
return R.sum(R.values(metric));
|
|
51
|
+
}), R.sum, function (x) {
|
|
52
|
+
return x / (R.length(metrics) * R.length(R.keys(R.head(metrics))));
|
|
53
|
+
}, R.curry(Math.round))(metrics)
|
|
54
|
+
});
|
|
55
|
+
case 1:
|
|
56
|
+
case "end":
|
|
57
|
+
return _context2.stop();
|
|
58
|
+
}
|
|
59
|
+
}, _callee2);
|
|
60
|
+
}));
|
|
61
|
+
return function getSquashedScore(_x2) {
|
|
62
|
+
return _ref3.apply(this, arguments);
|
|
63
|
+
};
|
|
64
|
+
}();
|
|
65
|
+
exports.getSquashedScore = getSquashedScore;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports["default"] = void 0;
|
|
9
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
10
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
11
|
+
var _clui = _interopRequireDefault(require("clui"));
|
|
12
|
+
var _lighthouseBadges = require("./lighthouse-badges");
|
|
13
|
+
var _argparser = _interopRequireDefault(require("./argparser"));
|
|
14
|
+
var handleUserInput = /*#__PURE__*/function () {
|
|
15
|
+
var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(spinner) {
|
|
16
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
17
|
+
while (1) switch (_context.prev = _context.next) {
|
|
18
|
+
case 0:
|
|
19
|
+
_context.prev = 0;
|
|
20
|
+
if (process.env.LIGHTHOUSE_BADGES_PARAMS) {
|
|
21
|
+
process.stdout.write("LIGHTHOUSE_BADGES_PARAMS: ".concat(process.env.LIGHTHOUSE_BADGES_PARAMS, "\n"));
|
|
22
|
+
}
|
|
23
|
+
spinner.start();
|
|
24
|
+
_context.t0 = _lighthouseBadges.processParameters;
|
|
25
|
+
_context.next = 6;
|
|
26
|
+
return _argparser["default"].parse_args();
|
|
27
|
+
case 6:
|
|
28
|
+
_context.t1 = _context.sent;
|
|
29
|
+
_context.t2 = _lighthouseBadges.calculateLighthouseMetrics;
|
|
30
|
+
_context.next = 10;
|
|
31
|
+
return (0, _context.t0)(_context.t1, _context.t2);
|
|
32
|
+
case 10:
|
|
33
|
+
spinner.stop();
|
|
34
|
+
_context.next = 17;
|
|
35
|
+
break;
|
|
36
|
+
case 13:
|
|
37
|
+
_context.prev = 13;
|
|
38
|
+
_context.t3 = _context["catch"](0);
|
|
39
|
+
process.stderr.write("".concat(_context.t3, "\n"));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
case 17:
|
|
42
|
+
case "end":
|
|
43
|
+
return _context.stop();
|
|
44
|
+
}
|
|
45
|
+
}, _callee, null, [[0, 13]]);
|
|
46
|
+
}));
|
|
47
|
+
return function handleUserInput(_x) {
|
|
48
|
+
return _ref.apply(this, arguments);
|
|
49
|
+
};
|
|
50
|
+
}();
|
|
51
|
+
|
|
52
|
+
// Only self-invoke if not imported but called directly as executable
|
|
53
|
+
(function () {
|
|
54
|
+
return !module.parent && handleUserInput(new _clui["default"].Spinner('Running Lighthouse, please wait...', ['◜', '◠', '◝', '◞', '◡', '◟']));
|
|
55
|
+
})();
|
|
56
|
+
var _default = handleUserInput;
|
|
57
|
+
exports["default"] = _default;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.processRawLighthouseResult = exports.processParameters = exports.metricsToSvg = exports.htmlReportsToFile = exports.calculateLighthouseMetrics = void 0;
|
|
9
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
10
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
12
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
13
|
+
var _badgeMaker = require("badge-maker");
|
|
14
|
+
var _path = _interopRequireDefault(require("path"));
|
|
15
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
16
|
+
var R = _interopRequireWildcard(require("ramda"));
|
|
17
|
+
var chromeLauncher = _interopRequireWildcard(require("chrome-launcher"));
|
|
18
|
+
var _index = _interopRequireDefault(require("lighthouse/core/index.cjs"));
|
|
19
|
+
var _util = require("./util");
|
|
20
|
+
var _calculations = require("./calculations");
|
|
21
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
23
|
+
var metricsToSvg = /*#__PURE__*/function () {
|
|
24
|
+
var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(lighthouseMetrics, badgeStyle, outputPath) {
|
|
25
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
26
|
+
while (1) switch (_context.prev = _context.next) {
|
|
27
|
+
case 0:
|
|
28
|
+
R.keys(lighthouseMetrics).map(function (lighthouseMetricKey) {
|
|
29
|
+
var filepath = _path["default"].join(outputPath, "".concat(lighthouseMetricKey.replace(/ /g, '_'), ".svg"));
|
|
30
|
+
var badgeColor = (0, _calculations.percentageToColor)(lighthouseMetrics[lighthouseMetricKey]);
|
|
31
|
+
var svg = (0, _badgeMaker.makeBadge)({
|
|
32
|
+
label: lighthouseMetricKey,
|
|
33
|
+
message: "".concat(lighthouseMetrics[lighthouseMetricKey], "%"),
|
|
34
|
+
color: badgeColor,
|
|
35
|
+
style: badgeStyle
|
|
36
|
+
});
|
|
37
|
+
_fs["default"].writeFile(filepath, svg, function (error) {
|
|
38
|
+
return (0, _util.statusMessage)("Saved svg to ".concat(filepath, "\n"), "Failed to save svg to ".concat(outputPath), error);
|
|
39
|
+
});
|
|
40
|
+
return true;
|
|
41
|
+
});
|
|
42
|
+
case 1:
|
|
43
|
+
case "end":
|
|
44
|
+
return _context.stop();
|
|
45
|
+
}
|
|
46
|
+
}, _callee);
|
|
47
|
+
}));
|
|
48
|
+
return function metricsToSvg(_x, _x2, _x3) {
|
|
49
|
+
return _ref.apply(this, arguments);
|
|
50
|
+
};
|
|
51
|
+
}();
|
|
52
|
+
exports.metricsToSvg = metricsToSvg;
|
|
53
|
+
var htmlReportsToFile = /*#__PURE__*/function () {
|
|
54
|
+
var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(htmlReports, outputPath) {
|
|
55
|
+
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
|
56
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
57
|
+
case 0:
|
|
58
|
+
return _context2.abrupt("return", htmlReports.map(function (report) {
|
|
59
|
+
var url = R.head(R.keys(report));
|
|
60
|
+
if (report[url]) {
|
|
61
|
+
var filepath = _path["default"].join(outputPath, "".concat((0, _util.urlEscaper)(url), ".html"));
|
|
62
|
+
_fs["default"].writeFile(filepath, report[url], function (error) {
|
|
63
|
+
return (0, _util.statusMessage)("Saved report to ".concat(filepath, "\n"), "Failed to save report to ".concat(outputPath), error);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}));
|
|
68
|
+
case 1:
|
|
69
|
+
case "end":
|
|
70
|
+
return _context2.stop();
|
|
71
|
+
}
|
|
72
|
+
}, _callee2);
|
|
73
|
+
}));
|
|
74
|
+
return function htmlReportsToFile(_x4, _x5) {
|
|
75
|
+
return _ref2.apply(this, arguments);
|
|
76
|
+
};
|
|
77
|
+
}();
|
|
78
|
+
exports.htmlReportsToFile = htmlReportsToFile;
|
|
79
|
+
var generateArtifacts = /*#__PURE__*/function () {
|
|
80
|
+
var _ref4 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(_ref3) {
|
|
81
|
+
var reports, svg, outputPath;
|
|
82
|
+
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
|
83
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
84
|
+
case 0:
|
|
85
|
+
reports = _ref3.reports, svg = _ref3.svg, outputPath = _ref3.outputPath;
|
|
86
|
+
_context3.next = 3;
|
|
87
|
+
return Promise.all([htmlReportsToFile(reports, outputPath), metricsToSvg(svg.results, svg.style, outputPath)]);
|
|
88
|
+
case 3:
|
|
89
|
+
case "end":
|
|
90
|
+
return _context3.stop();
|
|
91
|
+
}
|
|
92
|
+
}, _callee3);
|
|
93
|
+
}));
|
|
94
|
+
return function generateArtifacts(_x6) {
|
|
95
|
+
return _ref4.apply(this, arguments);
|
|
96
|
+
};
|
|
97
|
+
}();
|
|
98
|
+
var processRawLighthouseResult = /*#__PURE__*/function () {
|
|
99
|
+
var _ref5 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(data, html, url, shouldSaveReport) {
|
|
100
|
+
var htmlReport, categories, scores, lighthouseMetrics;
|
|
101
|
+
return _regenerator["default"].wrap(function _callee4$(_context4) {
|
|
102
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
103
|
+
case 0:
|
|
104
|
+
htmlReport = shouldSaveReport ? html : false;
|
|
105
|
+
categories = data.categories;
|
|
106
|
+
scores = R.keys(categories).map(function (category) {
|
|
107
|
+
return (0, _defineProperty2["default"])({}, "lighthouse ".concat(category.toLowerCase()), categories[category].score * 100);
|
|
108
|
+
});
|
|
109
|
+
lighthouseMetrics = Object.assign.apply(Object, [{}].concat((0, _toConsumableArray2["default"])(scores)));
|
|
110
|
+
return _context4.abrupt("return", {
|
|
111
|
+
metrics: lighthouseMetrics,
|
|
112
|
+
report: (0, _defineProperty2["default"])({}, url, htmlReport)
|
|
113
|
+
});
|
|
114
|
+
case 5:
|
|
115
|
+
case "end":
|
|
116
|
+
return _context4.stop();
|
|
117
|
+
}
|
|
118
|
+
}, _callee4);
|
|
119
|
+
}));
|
|
120
|
+
return function processRawLighthouseResult(_x7, _x8, _x9, _x10) {
|
|
121
|
+
return _ref5.apply(this, arguments);
|
|
122
|
+
};
|
|
123
|
+
}();
|
|
124
|
+
exports.processRawLighthouseResult = processRawLighthouseResult;
|
|
125
|
+
var calculateLighthouseMetrics = /*#__PURE__*/function () {
|
|
126
|
+
var _ref7 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(url, shouldSaveReport) {
|
|
127
|
+
var additionalParams,
|
|
128
|
+
chromeParameters,
|
|
129
|
+
chrome,
|
|
130
|
+
options,
|
|
131
|
+
runnerResult,
|
|
132
|
+
reportHtml,
|
|
133
|
+
reportJson,
|
|
134
|
+
_args5 = arguments;
|
|
135
|
+
return _regenerator["default"].wrap(function _callee5$(_context5) {
|
|
136
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
137
|
+
case 0:
|
|
138
|
+
additionalParams = _args5.length > 2 && _args5[2] !== undefined ? _args5[2] : '';
|
|
139
|
+
chromeParameters = ['--headless', '--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', '--no-default-browser-check', '--no-first-run', '--disable-default-apps', '--output=json', '--output-path=stdout', '--quiet', additionalParams];
|
|
140
|
+
_context5.next = 4;
|
|
141
|
+
return chromeLauncher.launch({
|
|
142
|
+
chromeFlags: chromeParameters
|
|
143
|
+
});
|
|
144
|
+
case 4:
|
|
145
|
+
chrome = _context5.sent;
|
|
146
|
+
options = {
|
|
147
|
+
logLevel: 'silent',
|
|
148
|
+
output: 'html',
|
|
149
|
+
port: chrome.port
|
|
150
|
+
};
|
|
151
|
+
_context5.next = 8;
|
|
152
|
+
return (0, _index["default"])(url, options);
|
|
153
|
+
case 8:
|
|
154
|
+
runnerResult = _context5.sent;
|
|
155
|
+
reportHtml = runnerResult.report;
|
|
156
|
+
reportJson = runnerResult.lhr;
|
|
157
|
+
_context5.next = 13;
|
|
158
|
+
return chrome.kill();
|
|
159
|
+
case 13:
|
|
160
|
+
return _context5.abrupt("return", processRawLighthouseResult(reportJson, reportHtml, url, shouldSaveReport));
|
|
161
|
+
case 14:
|
|
162
|
+
case "end":
|
|
163
|
+
return _context5.stop();
|
|
164
|
+
}
|
|
165
|
+
}, _callee5);
|
|
166
|
+
}));
|
|
167
|
+
return function calculateLighthouseMetrics(_x11, _x12) {
|
|
168
|
+
return _ref7.apply(this, arguments);
|
|
169
|
+
};
|
|
170
|
+
}();
|
|
171
|
+
exports.calculateLighthouseMetrics = calculateLighthouseMetrics;
|
|
172
|
+
var processParameters = /*#__PURE__*/function () {
|
|
173
|
+
var _ref8 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(args, func) {
|
|
174
|
+
var outputPath, additionalParams, results, metrics, reports, metricsResults;
|
|
175
|
+
return _regenerator["default"].wrap(function _callee6$(_context6) {
|
|
176
|
+
while (1) switch (_context6.prev = _context6.next) {
|
|
177
|
+
case 0:
|
|
178
|
+
outputPath = args.output_path || process.cwd();
|
|
179
|
+
_fs["default"].mkdir(outputPath, {
|
|
180
|
+
recursive: true
|
|
181
|
+
}, function (err) {
|
|
182
|
+
if (err) throw err;
|
|
183
|
+
});
|
|
184
|
+
additionalParams = process.env.LIGHTHOUSE_BADGES_PARAMS || '';
|
|
185
|
+
_context6.next = 5;
|
|
186
|
+
return Promise.all(args.urls.map(function (url) {
|
|
187
|
+
return func(url, args.save_report, additionalParams);
|
|
188
|
+
}));
|
|
189
|
+
case 5:
|
|
190
|
+
results = _context6.sent;
|
|
191
|
+
metrics = R.pluck('metrics', results);
|
|
192
|
+
reports = R.pluck('report', results);
|
|
193
|
+
if (!args.single_badge) {
|
|
194
|
+
_context6.next = 14;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
_context6.next = 11;
|
|
198
|
+
return (0, _calculations.getSquashedScore)(metrics);
|
|
199
|
+
case 11:
|
|
200
|
+
_context6.t0 = _context6.sent;
|
|
201
|
+
_context6.next = 17;
|
|
202
|
+
break;
|
|
203
|
+
case 14:
|
|
204
|
+
_context6.next = 16;
|
|
205
|
+
return (0, _calculations.getAverageScore)(metrics);
|
|
206
|
+
case 16:
|
|
207
|
+
_context6.t0 = _context6.sent;
|
|
208
|
+
case 17:
|
|
209
|
+
metricsResults = _context6.t0;
|
|
210
|
+
_context6.next = 20;
|
|
211
|
+
return generateArtifacts({
|
|
212
|
+
reports: reports,
|
|
213
|
+
svg: {
|
|
214
|
+
results: metricsResults,
|
|
215
|
+
style: args.badge_style
|
|
216
|
+
},
|
|
217
|
+
outputPath: outputPath
|
|
218
|
+
});
|
|
219
|
+
case 20:
|
|
220
|
+
case "end":
|
|
221
|
+
return _context6.stop();
|
|
222
|
+
}
|
|
223
|
+
}, _callee6);
|
|
224
|
+
}));
|
|
225
|
+
return function processParameters(_x13, _x14) {
|
|
226
|
+
return _ref8.apply(this, arguments);
|
|
227
|
+
};
|
|
228
|
+
}();
|
|
229
|
+
exports.processParameters = processParameters;
|
package/dist/src/util.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.zip = exports.urlEscaper = exports.statusMessage = void 0;
|
|
7
|
+
var urlEscaper = function urlEscaper(url) {
|
|
8
|
+
return url.toLowerCase().replace(/(^\w+:|^)\/\//, '').replace(/[^a-z0-9]/g, '_');
|
|
9
|
+
};
|
|
10
|
+
exports.urlEscaper = urlEscaper;
|
|
11
|
+
var zip = function zip(rows) {
|
|
12
|
+
return rows[0].map(function (_, c) {
|
|
13
|
+
return rows.map(function (row) {
|
|
14
|
+
return row[c];
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
exports.zip = zip;
|
|
19
|
+
var statusMessage = function statusMessage(successMessage, errorMessage, error) {
|
|
20
|
+
if (error) {
|
|
21
|
+
throw new Error(errorMessage);
|
|
22
|
+
}
|
|
23
|
+
process.stdout.write(successMessage);
|
|
24
|
+
};
|
|
25
|
+
exports.statusMessage = statusMessage;
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module.exports = async () => ({
|
|
2
|
+
collectCoverageFrom: [
|
|
3
|
+
'src/**/*.{js,jsx,mjs}',
|
|
4
|
+
],
|
|
5
|
+
collectCoverage: true,
|
|
6
|
+
coverageReporters: [
|
|
7
|
+
'json',
|
|
8
|
+
'html',
|
|
9
|
+
],
|
|
10
|
+
transform: {
|
|
11
|
+
'^.+\\.(js|jsx)$': 'babel-jest',
|
|
12
|
+
},
|
|
13
|
+
transformIgnorePatterns: [
|
|
14
|
+
'/node_modules/(?!lighthouse)',
|
|
15
|
+
],
|
|
16
|
+
});
|
package/package.json
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse-badges",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "🚦Generate gh-badges (shields.io) based on Lighthouse performance.",
|
|
5
|
-
"main": "src/index.js",
|
|
5
|
+
"main": "dist/src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"lighthouse-badges": "src/index.js"
|
|
7
|
+
"lighthouse-badges": "dist/src/index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"app:install": "npm i -g .",
|
|
11
|
+
"app:reinstall": "npm-run-all app:uninstall app:install",
|
|
12
|
+
"app:uninstall": "npm uninstall -g @emazzotta/lighthouse-badges",
|
|
13
|
+
"build": "npm run clean && babel src --out-dir dist/src && sed 's#\"dist/src/index.js\"#\"src/index.js\"#' package.json > ./dist/package.json && cp README.md dist && cp LICENSE.md dist",
|
|
14
|
+
"ci:publish": "npm run build && npm publish --prefix dist",
|
|
15
|
+
"clean": "rm -rf *.svg *.html coverage dist results",
|
|
16
|
+
"docker:build": "npm run build && docker build --build-arg VCS_REF=`git rev-parse --short HEAD` --build-arg BUILD_DATE=`date -u +\"%Y-%m-%dT%H:%M:%SZ\"` --build-arg VERSION=latest -t emazzotta/lighthouse-badges .",
|
|
12
17
|
"docker:system-test:run": "docker run emazzotta/lighthouse-badges /bin/sh -c 'lighthouse-badges -rsu https://google.com && EXEC_PATH=/home/chrome/reports npm run system-test:verify --prefix /home/lighthouse'",
|
|
13
18
|
"lint": "eslint .",
|
|
14
19
|
"lint:fix": "eslint --fix .",
|
|
15
|
-
"pre-push": "npm-run-all lint:fix test
|
|
16
|
-
"
|
|
17
|
-
"run:
|
|
18
|
-
"
|
|
19
|
-
"system-test:
|
|
20
|
-
"system-test:
|
|
21
|
-
"system-test:start-server": "npx http-server -a 127.0.0.1 -p 8080 &",
|
|
22
|
-
"system-test:verify": "[ -z ${EXEC_PATH} ] && EXEC_PATH=$PWD ; grep -q '<svg xmlns' ${EXEC_PATH}/*.svg && grep -q '<title>Lighthouse Report</title>' ${EXEC_PATH}/*.html",
|
|
20
|
+
"pre-push": "npm-run-all lint:fix test:all",
|
|
21
|
+
"run:global-installation": "[ -z ${PAGE} ] && PAGE=https://google.com ; lighthouse-badges -rsu ${PAGE} -o results",
|
|
22
|
+
"run:local-installation": "[ -z ${PAGE} ] && PAGE=https://google.com ; node dist/src/index.js -rsu ${PAGE} -o results",
|
|
23
|
+
"system-test:full-run": "npm-run-all clean build app:reinstall run:global-installation system-test:verify",
|
|
24
|
+
"system-test:light-run": "npm-run-all clean build run:local-installation system-test:verify",
|
|
25
|
+
"system-test:verify": "[ -z ${EXEC_PATH} ] && EXEC_PATH=$PWD/results ; grep -q '<svg xmlns' ${EXEC_PATH}/*.svg && grep -q '<title>Lighthouse Report</title>' ${EXEC_PATH}/*.html",
|
|
23
26
|
"test": "jest",
|
|
27
|
+
"test:all": "npm-run-all test system-test:full-run",
|
|
24
28
|
"test:related": "jest --findRelatedTests"
|
|
25
29
|
},
|
|
26
30
|
"husky": {
|
|
@@ -41,34 +45,31 @@
|
|
|
41
45
|
"dependencies": {
|
|
42
46
|
"argparse": "2.0.1",
|
|
43
47
|
"badge-maker": "^3.3.1",
|
|
48
|
+
"chrome-launcher": "^0.15.1",
|
|
44
49
|
"clui": "^0.3.6",
|
|
45
|
-
"lighthouse": "^
|
|
50
|
+
"lighthouse": "^10.0.0",
|
|
46
51
|
"ramda": "^0.28.0"
|
|
47
52
|
},
|
|
48
53
|
"devDependencies": {
|
|
49
|
-
"@babel/
|
|
50
|
-
"@babel/
|
|
51
|
-
"@babel/
|
|
52
|
-
"@babel/
|
|
53
|
-
"
|
|
54
|
-
"eslint": "^8.
|
|
54
|
+
"@babel/cli": "^7.20.7",
|
|
55
|
+
"@babel/core": "^7.20.12",
|
|
56
|
+
"@babel/plugin-transform-runtime": "^7.19.6",
|
|
57
|
+
"@babel/preset-env": "^7.20.2",
|
|
58
|
+
"@types/jest": "^29.4.0",
|
|
59
|
+
"eslint": "^8.33.0",
|
|
55
60
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
56
|
-
"eslint-plugin-import": "^2.
|
|
57
|
-
"husky": "^8.0.
|
|
58
|
-
"jest": "^
|
|
59
|
-
"lint-staged": "^13.
|
|
61
|
+
"eslint-plugin-import": "^2.27.5",
|
|
62
|
+
"husky": "^8.0.3",
|
|
63
|
+
"jest": "^29.4.2",
|
|
64
|
+
"lint-staged": "^13.1.1",
|
|
60
65
|
"npm-run-all": "^4.1.5"
|
|
61
66
|
},
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
],
|
|
66
|
-
"collectCoverage": true,
|
|
67
|
-
"coverageReporters": [
|
|
68
|
-
"json",
|
|
69
|
-
"html"
|
|
70
|
-
]
|
|
67
|
+
"engines": {
|
|
68
|
+
"npm": ">=7.0.0",
|
|
69
|
+
"node": ">=16.0.0"
|
|
71
70
|
},
|
|
71
|
+
"packageManager": "yarn@1.21.1",
|
|
72
|
+
"private": false,
|
|
72
73
|
"author": "Emanuele Mazzotta",
|
|
73
74
|
"license": "MIT"
|
|
74
75
|
}
|
package/src/argparser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { ArgumentParser, ONE_OR_MORE } from 'argparse';
|
|
2
|
+
import { version } from '../package.json';
|
|
3
3
|
|
|
4
4
|
const parser = new ArgumentParser({
|
|
5
5
|
add_help: true,
|
|
@@ -46,6 +46,4 @@ requiredArgs.add_argument('-u', '--urls', {
|
|
|
46
46
|
help: 'The lighthouse badge(s) will contain the respective average score(s) of all the urls supplied, combined',
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
parser,
|
|
51
|
-
};
|
|
49
|
+
export default parser;
|
package/src/calculations.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import * as R from 'ramda';
|
|
2
2
|
|
|
3
|
-
const percentageToColor = (percentage) => {
|
|
3
|
+
export const percentageToColor = (percentage) => {
|
|
4
4
|
if (percentage >= 95) return 'brightgreen';
|
|
5
5
|
if (percentage >= 90) return 'green';
|
|
6
6
|
if (percentage >= 75) return 'yellowgreen';
|
|
@@ -9,7 +9,7 @@ const percentageToColor = (percentage) => {
|
|
|
9
9
|
return 'red';
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const getAverageScore = async (metrics) => R.pipe(
|
|
12
|
+
export const getAverageScore = async (metrics) => R.pipe(
|
|
13
13
|
R.head,
|
|
14
14
|
R.keys,
|
|
15
15
|
R.map((category) => (
|
|
@@ -17,7 +17,7 @@ const getAverageScore = async (metrics) => R.pipe(
|
|
|
17
17
|
R.mergeAll,
|
|
18
18
|
)(metrics);
|
|
19
19
|
|
|
20
|
-
const getSquashedScore = async (metrics) => ({
|
|
20
|
+
export const getSquashedScore = async (metrics) => ({
|
|
21
21
|
lighthouse: R.pipe(
|
|
22
22
|
R.map((metric) => R.sum(R.values(metric))),
|
|
23
23
|
R.sum,
|
|
@@ -25,9 +25,3 @@ const getSquashedScore = async (metrics) => ({
|
|
|
25
25
|
R.curry(Math.round),
|
|
26
26
|
)(metrics),
|
|
27
27
|
});
|
|
28
|
-
|
|
29
|
-
module.exports = {
|
|
30
|
-
percentageToColor,
|
|
31
|
-
getAverageScore,
|
|
32
|
-
getSquashedScore,
|
|
33
|
-
};
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import CLI from 'clui';
|
|
4
|
+
import { calculateLighthouseMetrics, processParameters } from './lighthouse-badges';
|
|
5
|
+
import parser from './argparser';
|
|
6
6
|
|
|
7
7
|
const handleUserInput = async (spinner) => {
|
|
8
8
|
try {
|
|
@@ -21,6 +21,4 @@ const handleUserInput = async (spinner) => {
|
|
|
21
21
|
// Only self-invoke if not imported but called directly as executable
|
|
22
22
|
(() => !module.parent && handleUserInput(new CLI.Spinner('Running Lighthouse, please wait...', ['◜', '◠', '◝', '◞', '◡', '◟'])))();
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
handleUserInput,
|
|
26
|
-
};
|
|
24
|
+
export default handleUserInput;
|
package/src/lighthouse-badges.js
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const { percentageToColor } = require('./calculations');
|
|
12
|
-
|
|
13
|
-
// Buffer size for stdout, must be big enough to handle lighthouse CLI output
|
|
14
|
-
const maxBuffer = 1024 * 50000;
|
|
15
|
-
|
|
16
|
-
const metricsToSvg = async (lighthouseMetrics, badgeStyle, outputPath) => {
|
|
1
|
+
import { makeBadge } from 'badge-maker';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import * as R from 'ramda';
|
|
5
|
+
import * as chromeLauncher from 'chrome-launcher';
|
|
6
|
+
import lighthouse from 'lighthouse/core/index.cjs';
|
|
7
|
+
import { statusMessage, urlEscaper } from './util';
|
|
8
|
+
import { getAverageScore, getSquashedScore, percentageToColor } from './calculations';
|
|
9
|
+
|
|
10
|
+
export const metricsToSvg = async (lighthouseMetrics, badgeStyle, outputPath) => {
|
|
17
11
|
R.keys(lighthouseMetrics).map((lighthouseMetricKey) => {
|
|
18
12
|
const filepath = path.join(outputPath, `${lighthouseMetricKey.replace(/ /g, '_')}.svg`);
|
|
19
13
|
const badgeColor = percentageToColor(lighthouseMetrics[lighthouseMetricKey]);
|
|
@@ -35,11 +29,11 @@ const metricsToSvg = async (lighthouseMetrics, badgeStyle, outputPath) => {
|
|
|
35
29
|
});
|
|
36
30
|
};
|
|
37
31
|
|
|
38
|
-
const htmlReportsToFile = async (htmlReports, outputPath) => htmlReports.map((
|
|
39
|
-
const url = R.head(R.keys(
|
|
40
|
-
if (
|
|
32
|
+
export const htmlReportsToFile = async (htmlReports, outputPath) => htmlReports.map((report) => {
|
|
33
|
+
const url = R.head(R.keys(report));
|
|
34
|
+
if (report[url]) {
|
|
41
35
|
const filepath = path.join(outputPath, `${urlEscaper(url)}.html`);
|
|
42
|
-
fs.writeFile(filepath,
|
|
36
|
+
fs.writeFile(filepath, report[url], (error) => statusMessage(
|
|
43
37
|
`Saved report to ${filepath}\n`,
|
|
44
38
|
`Failed to save report to ${outputPath}`,
|
|
45
39
|
error,
|
|
@@ -55,8 +49,8 @@ const generateArtifacts = async ({ reports, svg, outputPath }) => {
|
|
|
55
49
|
]);
|
|
56
50
|
};
|
|
57
51
|
|
|
58
|
-
const processRawLighthouseResult = async (data, url, shouldSaveReport) => {
|
|
59
|
-
const htmlReport = shouldSaveReport ?
|
|
52
|
+
export const processRawLighthouseResult = async (data, html, url, shouldSaveReport) => {
|
|
53
|
+
const htmlReport = shouldSaveReport ? html : false;
|
|
60
54
|
const { categories } = data;
|
|
61
55
|
const scores = R.keys(categories).map((category) => (
|
|
62
56
|
{ [`lighthouse ${category.toLowerCase()}`]: categories[category].score * 100 }
|
|
@@ -65,16 +59,31 @@ const processRawLighthouseResult = async (data, url, shouldSaveReport) => {
|
|
|
65
59
|
return { metrics: lighthouseMetrics, report: { [url]: htmlReport } };
|
|
66
60
|
};
|
|
67
61
|
|
|
68
|
-
const calculateLighthouseMetrics = async (url, shouldSaveReport, additionalParams = '') => {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
62
|
+
export const calculateLighthouseMetrics = async (url, shouldSaveReport, additionalParams = '') => {
|
|
63
|
+
const chromeParameters = [
|
|
64
|
+
'--headless',
|
|
65
|
+
'--no-sandbox',
|
|
66
|
+
'--disable-gpu',
|
|
67
|
+
'--disable-dev-shm-usage',
|
|
68
|
+
'--no-default-browser-check',
|
|
69
|
+
'--no-first-run',
|
|
70
|
+
'--disable-default-apps',
|
|
71
|
+
'--output=json',
|
|
72
|
+
'--output-path=stdout',
|
|
73
|
+
'--quiet',
|
|
74
|
+
additionalParams,
|
|
75
|
+
];
|
|
76
|
+
const chrome = await chromeLauncher.launch({ chromeFlags: chromeParameters });
|
|
77
|
+
const options = { logLevel: 'silent', output: 'html', port: chrome.port };
|
|
78
|
+
const runnerResult = await lighthouse(url, options);
|
|
79
|
+
const reportHtml = runnerResult.report;
|
|
80
|
+
const reportJson = runnerResult.lhr;
|
|
81
|
+
await chrome.kill();
|
|
82
|
+
|
|
83
|
+
return processRawLighthouseResult(reportJson, reportHtml, url, shouldSaveReport);
|
|
75
84
|
};
|
|
76
85
|
|
|
77
|
-
const processParameters = async (args, func) => {
|
|
86
|
+
export const processParameters = async (args, func) => {
|
|
78
87
|
const outputPath = args.output_path || process.cwd();
|
|
79
88
|
|
|
80
89
|
fs.mkdir(outputPath, { recursive: true }, (err) => {
|
|
@@ -99,11 +108,3 @@ const processParameters = async (args, func) => {
|
|
|
99
108
|
outputPath,
|
|
100
109
|
});
|
|
101
110
|
};
|
|
102
|
-
|
|
103
|
-
module.exports = {
|
|
104
|
-
metricsToSvg,
|
|
105
|
-
htmlReportsToFile,
|
|
106
|
-
processRawLighthouseResult,
|
|
107
|
-
calculateLighthouseMetrics,
|
|
108
|
-
processParameters,
|
|
109
|
-
};
|
package/src/util.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
const urlEscaper = (url) => url.toLowerCase().replace(/(^\w+:|^)\/\//, '').replace(/[^a-z0-9]/g, '_');
|
|
1
|
+
export const urlEscaper = (url) => url.toLowerCase().replace(/(^\w+:|^)\/\//, '').replace(/[^a-z0-9]/g, '_');
|
|
2
2
|
|
|
3
|
-
const zip = (rows) => rows[0].map((_, c) => rows.map((row) => row[c]));
|
|
3
|
+
export const zip = (rows) => rows[0].map((_, c) => rows.map((row) => row[c]));
|
|
4
4
|
|
|
5
|
-
const statusMessage = (successMessage, errorMessage, error) => {
|
|
5
|
+
export const statusMessage = (successMessage, errorMessage, error) => {
|
|
6
6
|
if (error) {
|
|
7
7
|
throw new Error(errorMessage);
|
|
8
8
|
}
|
|
9
9
|
process.stdout.write(successMessage);
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
module.exports = {
|
|
13
|
-
urlEscaper,
|
|
14
|
-
zip,
|
|
15
|
-
statusMessage,
|
|
16
|
-
};
|