@percy/cli-snapshot 1.0.0-beta.71 → 1.0.0-beta.72
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/README.md +33 -26
- package/dist/config.js +10 -12
- package/dist/file.js +71 -0
- package/dist/index.js +11 -1
- package/dist/sitemap.js +33 -0
- package/dist/snapshot.js +147 -0
- package/dist/static.js +164 -0
- package/dist/utils.js +2 -124
- package/package.json +19 -25
- package/dist/commands/snapshot.js +0 -249
- package/dist/hooks/init.js +0 -26
- package/oclif.manifest.json +0 -1
package/README.md
CHANGED
|
@@ -4,39 +4,46 @@ Snapshot a list or static directory of web pages.
|
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
<!-- commands -->
|
|
7
|
-
* [`percy snapshot
|
|
7
|
+
* [`percy snapshot`](#percy-snapshot)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### `percy snapshot`
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Snapshot a static directory, snapshots file, or sitemap URL
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
|
|
15
|
-
$ percy snapshot
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-b, --base-url
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
--
|
|
30
|
-
--
|
|
31
|
-
--
|
|
32
|
-
--
|
|
33
|
-
--
|
|
34
|
-
|
|
35
|
-
|
|
14
|
+
Usage:
|
|
15
|
+
$ percy snapshot [options] <dir|file|sitemap>
|
|
16
|
+
|
|
17
|
+
Arguments:
|
|
18
|
+
dir|file|sitemap Static directory, snapshots file, or sitemap url
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
-b, --base-url <string> The base url pages are hosted at when snapshotting
|
|
22
|
+
--include <pattern> One or more globs/patterns matching snapshots to include
|
|
23
|
+
--exclude <pattern> One or more globs/patterns matching snapshots to exclude
|
|
24
|
+
|
|
25
|
+
Static options:
|
|
26
|
+
--clean-urls Rewrite static index and filepath URLs to be clean
|
|
27
|
+
|
|
28
|
+
Percy options:
|
|
29
|
+
-c, --config <file> Config file path
|
|
30
|
+
-d, --dry-run Print snapshot names only
|
|
31
|
+
-h, --allowed-hostname <hostname> Allowed hostnames to capture in asset discovery
|
|
32
|
+
-t, --network-idle-timeout <ms> Asset discovery network idle timeout
|
|
33
|
+
--disable-cache Disable asset discovery caches
|
|
34
|
+
--debug Debug asset discovery and do not upload snapshots
|
|
35
|
+
|
|
36
|
+
Global options:
|
|
37
|
+
-v, --verbose Log everything
|
|
38
|
+
-q, --quiet Log errors only
|
|
39
|
+
-s, --silent Log nothing
|
|
40
|
+
--help Display command help
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
36
43
|
$ percy snapshot ./public
|
|
37
44
|
$ percy snapshot snapshots.yml
|
|
45
|
+
$ percy snapshot https://percy.io/sitemap.xml
|
|
38
46
|
```
|
|
39
|
-
|
|
40
47
|
<!-- commandsstop -->
|
|
41
48
|
|
|
42
49
|
## Usage
|
package/dist/config.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
8
|
-
exports.
|
|
6
|
+
exports.commonSchema = void 0;
|
|
7
|
+
exports.configMigration = configMigration;
|
|
8
|
+
exports.snapshotsFileSchema = exports.configSchema = void 0;
|
|
9
9
|
|
|
10
10
|
var _config = require("@percy/core/dist/config");
|
|
11
11
|
|
|
12
12
|
// Common schemas referenced by other schemas
|
|
13
|
-
const
|
|
13
|
+
const commonSchema = {
|
|
14
14
|
$id: '/snapshot/cli',
|
|
15
15
|
$refs: {
|
|
16
16
|
predicate: {
|
|
@@ -30,7 +30,7 @@ const cliSchema = {
|
|
|
30
30
|
}
|
|
31
31
|
}; // Config schema for static directories
|
|
32
32
|
|
|
33
|
-
exports.
|
|
33
|
+
exports.commonSchema = commonSchema;
|
|
34
34
|
const configSchema = {
|
|
35
35
|
static: {
|
|
36
36
|
type: 'object',
|
|
@@ -94,11 +94,11 @@ const configSchema = {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
}; //
|
|
97
|
+
}; // Snapshots file schema
|
|
98
98
|
|
|
99
99
|
exports.configSchema = configSchema;
|
|
100
|
-
const
|
|
101
|
-
$id: '/snapshot/
|
|
100
|
+
const snapshotsFileSchema = {
|
|
101
|
+
$id: '/snapshot/file',
|
|
102
102
|
oneOf: [{
|
|
103
103
|
type: 'array',
|
|
104
104
|
items: {
|
|
@@ -131,11 +131,9 @@ const snapshotListSchema = {
|
|
|
131
131
|
}
|
|
132
132
|
}]
|
|
133
133
|
};
|
|
134
|
-
exports.
|
|
135
|
-
const schemas = [cliSchema, configSchema, snapshotListSchema];
|
|
136
|
-
exports.schemas = schemas;
|
|
134
|
+
exports.snapshotsFileSchema = snapshotsFileSchema;
|
|
137
135
|
|
|
138
|
-
function
|
|
136
|
+
function configMigration(config, util) {
|
|
139
137
|
/* eslint-disable curly */
|
|
140
138
|
if (config.version < 2) {
|
|
141
139
|
// static-snapshots and options were renamed
|
package/dist/file.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadSnapshotsFile = loadSnapshotsFile;
|
|
7
|
+
|
|
8
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
+
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
|
|
12
|
+
var _config = _interopRequireDefault(require("@percy/config"));
|
|
13
|
+
|
|
14
|
+
var _utils = require("./utils");
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
19
|
+
|
|
20
|
+
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; }
|
|
21
|
+
|
|
22
|
+
// Loads snapshots from a js, json, or yaml file.
|
|
23
|
+
async function loadSnapshotsFile(file, flags, invalid) {
|
|
24
|
+
var _PercyConfig$validate;
|
|
25
|
+
|
|
26
|
+
let ext = _path.default.extname(file);
|
|
27
|
+
|
|
28
|
+
let config = {}; // load snapshots file
|
|
29
|
+
|
|
30
|
+
if (ext === '.js') {
|
|
31
|
+
({
|
|
32
|
+
default: config
|
|
33
|
+
} = await Promise.resolve(`${_path.default.resolve(file)}`).then(s => _interopRequireWildcard(require(s))));
|
|
34
|
+
if (typeof config === 'function') config = await config();
|
|
35
|
+
} else if (ext === '.json') {
|
|
36
|
+
config = JSON.parse(_fs.default.readFileSync(file, {
|
|
37
|
+
encoding: 'utf-8'
|
|
38
|
+
}));
|
|
39
|
+
} else if (ext.match(/\.ya?ml$/)) {
|
|
40
|
+
let YAML = await Promise.resolve().then(() => _interopRequireWildcard(require('yaml')));
|
|
41
|
+
config = YAML.parse(_fs.default.readFileSync(file, {
|
|
42
|
+
encoding: 'utf-8'
|
|
43
|
+
}));
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`Unsupported filetype: ${file}`);
|
|
46
|
+
} // validate base-url before config options
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if (flags.baseUrl && !flags.baseUrl.startsWith('http')) {
|
|
50
|
+
throw new Error('The base-url must include a protocol ' + 'and hostname when providing a list of snapshots');
|
|
51
|
+
} // validate snapshot config options
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
(_PercyConfig$validate = _config.default.validate(config, '/snapshot/file')) === null || _PercyConfig$validate === void 0 ? void 0 : _PercyConfig$validate.forEach(invalid); // flags override config options
|
|
55
|
+
|
|
56
|
+
let {
|
|
57
|
+
baseUrl,
|
|
58
|
+
include,
|
|
59
|
+
exclude
|
|
60
|
+
} = { ...config,
|
|
61
|
+
...flags
|
|
62
|
+
}; // support config that only contains a list of snapshots
|
|
63
|
+
|
|
64
|
+
return (Array.isArray(config) ? config : config.snapshots || []).reduce((snapshots, snap) => {
|
|
65
|
+
// reduce matching snapshots with default options
|
|
66
|
+
snap = (0, _utils.withDefaults)(snap, {
|
|
67
|
+
host: baseUrl
|
|
68
|
+
});
|
|
69
|
+
return (0, _utils.snapshotMatches)(snap, include, exclude) ? snapshots.concat(snap) : snapshots;
|
|
70
|
+
}, []);
|
|
71
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "snapshot", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _snapshot.snapshot;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
var _snapshot = require("./snapshot");
|
package/dist/sitemap.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadSitemapSnapshots = loadSitemapSnapshots;
|
|
7
|
+
|
|
8
|
+
var _static = require("./static");
|
|
9
|
+
|
|
10
|
+
var _utils = require("@percy/core/dist/utils");
|
|
11
|
+
|
|
12
|
+
// Fetches and maps sitemap URLs to snapshots.
|
|
13
|
+
async function loadSitemapSnapshots(sitemapUrl, config) {
|
|
14
|
+
// fetch sitemap URLs
|
|
15
|
+
let urls = await (0, _utils.request)(sitemapUrl, (body, res) => {
|
|
16
|
+
// validate sitemap content-type
|
|
17
|
+
let [contentType] = res.headers['content-type'].split(';');
|
|
18
|
+
|
|
19
|
+
if (!/^(application|text)\/xml$/.test(contentType)) {
|
|
20
|
+
throw new Error('The sitemap must be an XML document, ' + `but the content-type was "${contentType}"`);
|
|
21
|
+
} // parse XML content into a list of URLs
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
let urls = body.match(/(?<=<loc>)(.*)(?=<\/loc>)/ig); // filter out duplicate URLs that differ by a trailing slash
|
|
25
|
+
|
|
26
|
+
return urls.filter((url, i) => {
|
|
27
|
+
let match = urls.indexOf(url.replace(/\/$/, ''));
|
|
28
|
+
return match === -1 || match === i;
|
|
29
|
+
});
|
|
30
|
+
}); // map with inherited static options
|
|
31
|
+
|
|
32
|
+
return (0, _static.mapStaticSnapshots)(urls, config);
|
|
33
|
+
}
|
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.snapshot = exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _fs = require("fs");
|
|
9
|
+
|
|
10
|
+
var _cliCommand = _interopRequireDefault(require("@percy/cli-command"));
|
|
11
|
+
|
|
12
|
+
var SnapshotConfig = _interopRequireWildcard(require("./config"));
|
|
13
|
+
|
|
14
|
+
var _package = _interopRequireDefault(require("../package.json"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
19
|
+
|
|
20
|
+
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; }
|
|
21
|
+
|
|
22
|
+
const snapshot = (0, _cliCommand.default)('snapshot', {
|
|
23
|
+
description: 'Snapshot a static directory, snapshots file, or sitemap URL',
|
|
24
|
+
args: [{
|
|
25
|
+
name: 'dir|file|sitemap',
|
|
26
|
+
description: 'Static directory, snapshots file, or sitemap url',
|
|
27
|
+
required: true,
|
|
28
|
+
attribute: val => {
|
|
29
|
+
if (/^https?:\/\//.test(val)) return 'sitemap';
|
|
30
|
+
if (!(0, _fs.existsSync)(val)) throw new Error(`Not found: ${val}`);
|
|
31
|
+
return (0, _fs.lstatSync)(val).isDirectory() ? 'dir' : 'file';
|
|
32
|
+
}
|
|
33
|
+
}],
|
|
34
|
+
flags: [{
|
|
35
|
+
name: 'base-url',
|
|
36
|
+
description: 'The base url pages are hosted at when snapshotting',
|
|
37
|
+
type: 'string',
|
|
38
|
+
short: 'b'
|
|
39
|
+
}, {
|
|
40
|
+
name: 'include',
|
|
41
|
+
description: 'One or more globs/patterns matching snapshots to include',
|
|
42
|
+
type: 'pattern',
|
|
43
|
+
multiple: true
|
|
44
|
+
}, {
|
|
45
|
+
name: 'exclude',
|
|
46
|
+
description: 'One or more globs/patterns matching snapshots to exclude',
|
|
47
|
+
type: 'pattern',
|
|
48
|
+
multiple: true
|
|
49
|
+
}, {
|
|
50
|
+
// static only
|
|
51
|
+
name: 'clean-urls',
|
|
52
|
+
description: 'Rewrite static index and filepath URLs to be clean',
|
|
53
|
+
percyrc: 'static.cleanUrls',
|
|
54
|
+
group: 'Static'
|
|
55
|
+
}, {
|
|
56
|
+
// deprecated
|
|
57
|
+
name: 'files',
|
|
58
|
+
deprecated: ['1.0.0', '--include'],
|
|
59
|
+
percyrc: 'static.include',
|
|
60
|
+
type: 'pattern'
|
|
61
|
+
}, {
|
|
62
|
+
name: 'ignore',
|
|
63
|
+
deprecated: ['1.0.0', '--exclude'],
|
|
64
|
+
percyrc: 'static.exclude',
|
|
65
|
+
type: 'pattern'
|
|
66
|
+
}],
|
|
67
|
+
examples: ['$0 ./public', '$0 snapshots.yml', '$0 https://percy.io/sitemap.xml'],
|
|
68
|
+
percy: {
|
|
69
|
+
clientInfo: `${_package.default.name}/${_package.default.version}`,
|
|
70
|
+
environmentInfo: `node/${process.version}`
|
|
71
|
+
},
|
|
72
|
+
config: {
|
|
73
|
+
schemas: [SnapshotConfig.commonSchema, SnapshotConfig.configSchema, SnapshotConfig.snapshotsFileSchema],
|
|
74
|
+
migrations: [SnapshotConfig.configMigration]
|
|
75
|
+
}
|
|
76
|
+
}, async function* ({
|
|
77
|
+
percy,
|
|
78
|
+
args,
|
|
79
|
+
flags,
|
|
80
|
+
log,
|
|
81
|
+
exit
|
|
82
|
+
}) {
|
|
83
|
+
if (!percy) exit(0, 'Percy is disabled'); // set and validate static or sitemap config flags
|
|
84
|
+
|
|
85
|
+
if (args.dir || args.sitemap) {
|
|
86
|
+
percy.setConfig({
|
|
87
|
+
[args.dir ? 'static' : 'sitemap']: {
|
|
88
|
+
include: flags.include,
|
|
89
|
+
exclude: flags.exclude
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
} // gather snapshots
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
let snapshots, server;
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
if (args.sitemap) {
|
|
99
|
+
let {
|
|
100
|
+
loadSitemapSnapshots
|
|
101
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./sitemap')));
|
|
102
|
+
let config = { ...percy.config.sitemap,
|
|
103
|
+
...flags
|
|
104
|
+
};
|
|
105
|
+
snapshots = yield loadSitemapSnapshots(args.sitemap, config);
|
|
106
|
+
} else if (args.dir) {
|
|
107
|
+
let {
|
|
108
|
+
serve,
|
|
109
|
+
loadStaticSnapshots
|
|
110
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./static')));
|
|
111
|
+
let config = { ...percy.config.static,
|
|
112
|
+
...flags
|
|
113
|
+
};
|
|
114
|
+
server = yield serve(args.dir, config);
|
|
115
|
+
snapshots = yield loadStaticSnapshots(args.dir, { ...config,
|
|
116
|
+
server
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
let {
|
|
120
|
+
loadSnapshotsFile
|
|
121
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./file')));
|
|
122
|
+
snapshots = yield loadSnapshotsFile(args.file, flags, (invalid, i) => {
|
|
123
|
+
if (i === 0) log.warn('Invalid snapshot options:');
|
|
124
|
+
log.warn(`- ${invalid.path}: ${invalid.message}`);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!snapshots.length) {
|
|
129
|
+
exit(1, 'No snapshots found');
|
|
130
|
+
} // start processing snapshots
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
yield* percy.start();
|
|
134
|
+
percy.snapshot(snapshots);
|
|
135
|
+
yield* percy.stop();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
await percy.stop(true);
|
|
138
|
+
throw error;
|
|
139
|
+
} finally {
|
|
140
|
+
var _server;
|
|
141
|
+
|
|
142
|
+
await ((_server = server) === null || _server === void 0 ? void 0 : _server.close());
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
exports.snapshot = snapshot;
|
|
146
|
+
var _default = snapshot;
|
|
147
|
+
exports.default = _default;
|
package/dist/static.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadStaticSnapshots = loadStaticSnapshots;
|
|
7
|
+
exports.mapStaticSnapshots = mapStaticSnapshots;
|
|
8
|
+
exports.serve = serve;
|
|
9
|
+
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
|
|
12
|
+
var _http = require("http");
|
|
13
|
+
|
|
14
|
+
var _serveHandler = _interopRequireDefault(require("serve-handler"));
|
|
15
|
+
|
|
16
|
+
var pathToRegexp = _interopRequireWildcard(require("path-to-regexp"));
|
|
17
|
+
|
|
18
|
+
var _utils = require("./utils");
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
|
|
22
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
23
|
+
|
|
24
|
+
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; }
|
|
25
|
+
|
|
26
|
+
// Transforms a source-destination map into an array of source-destination objects
|
|
27
|
+
function mapRewrites(map, arr) {
|
|
28
|
+
return Object.entries(map).reduce((r, [source, destination]) => {
|
|
29
|
+
return (r || []).concat({
|
|
30
|
+
source,
|
|
31
|
+
destination
|
|
32
|
+
});
|
|
33
|
+
}, arr);
|
|
34
|
+
} // Serves a static directory with the provided options and returns an object containing adjusted
|
|
35
|
+
// rewrites (combined with any baseUrl), the server host, a close method, and the server
|
|
36
|
+
// instance. The `dryRun` option will prevent the server from actually starting.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async function serve(dir, {
|
|
40
|
+
dryRun,
|
|
41
|
+
baseUrl,
|
|
42
|
+
cleanUrls,
|
|
43
|
+
rewrites = {}
|
|
44
|
+
}) {
|
|
45
|
+
let host = 'http://localhost';
|
|
46
|
+
let connections = new Set(); // coerce any provided base-url into a base-url path
|
|
47
|
+
|
|
48
|
+
if (baseUrl && !baseUrl.startsWith('/')) {
|
|
49
|
+
baseUrl = (0, _utils.validURL)(baseUrl).path;
|
|
50
|
+
} // map rewrite options with the base-url
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
rewrites = mapRewrites(rewrites, baseUrl && [{
|
|
54
|
+
source: _path.default.posix.join(baseUrl, '/:path*'),
|
|
55
|
+
destination: '/:path*'
|
|
56
|
+
}]); // start the server
|
|
57
|
+
|
|
58
|
+
let server = !dryRun && (await new Promise(resolve => {
|
|
59
|
+
let server = (0, _http.createServer)((req, res) => (0, _serveHandler.default)(req, res, {
|
|
60
|
+
public: dir,
|
|
61
|
+
cleanUrls,
|
|
62
|
+
rewrites
|
|
63
|
+
})).listen(() => resolve(server)).on('connection', s => {
|
|
64
|
+
connections.add(s.on('close', () => connections.delete(s)));
|
|
65
|
+
});
|
|
66
|
+
})); // easy clean up
|
|
67
|
+
|
|
68
|
+
let close = () => server && new Promise(resolve => {
|
|
69
|
+
/* istanbul ignore next: sometimes needed when connections are hanging */
|
|
70
|
+
connections.forEach(s => s.destroy());
|
|
71
|
+
server.close(resolve);
|
|
72
|
+
}); // add the port to the host and return
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if (server) host += `:${server.address().port}`;
|
|
76
|
+
return {
|
|
77
|
+
host,
|
|
78
|
+
rewrites,
|
|
79
|
+
server,
|
|
80
|
+
close
|
|
81
|
+
};
|
|
82
|
+
} // Maps an array of snapshots or paths to options ready to pass along to the core snapshot
|
|
83
|
+
// method. Paths are normalized before overrides are conditionally applied via their own include and
|
|
84
|
+
// exclude options. Snapshot URLs are then rewritten accordingly before default options are applied,
|
|
85
|
+
// including prepending the appropriate host. The returned set of snapshot options are sorted and
|
|
86
|
+
// filtered by the top-level include and exclude options.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
function mapStaticSnapshots(snapshots,
|
|
90
|
+
/* istanbul ignore next: safe defaults */
|
|
91
|
+
{
|
|
92
|
+
host,
|
|
93
|
+
include,
|
|
94
|
+
exclude,
|
|
95
|
+
cleanUrls,
|
|
96
|
+
rewrites = [],
|
|
97
|
+
overrides = [],
|
|
98
|
+
server
|
|
99
|
+
} = {}) {
|
|
100
|
+
var _server$host, _server$rewrites;
|
|
101
|
+
|
|
102
|
+
// prioritize server properties
|
|
103
|
+
host = (_server$host = server === null || server === void 0 ? void 0 : server.host) !== null && _server$host !== void 0 ? _server$host : host;
|
|
104
|
+
rewrites = (_server$rewrites = server === null || server === void 0 ? void 0 : server.rewrites) !== null && _server$rewrites !== void 0 ? _server$rewrites : mapRewrites(rewrites, []); // reduce rewrites into a single function
|
|
105
|
+
|
|
106
|
+
let applyRewrites = [{
|
|
107
|
+
test: url => !/^(https?:\/)?\//.test(url) && url,
|
|
108
|
+
rewrite: url => _path.default.posix.normalize(_path.default.posix.join('/', url))
|
|
109
|
+
}, ...rewrites.map(({
|
|
110
|
+
source,
|
|
111
|
+
destination
|
|
112
|
+
}) => ({
|
|
113
|
+
test: pathToRegexp.match(destination),
|
|
114
|
+
rewrite: pathToRegexp.compile(source)
|
|
115
|
+
})), {
|
|
116
|
+
test: url => cleanUrls && url,
|
|
117
|
+
rewrite: url => url.replace(/(\/index)?\.html$/, '')
|
|
118
|
+
}].reduceRight((apply, {
|
|
119
|
+
test,
|
|
120
|
+
rewrite
|
|
121
|
+
}) => snap => {
|
|
122
|
+
var _snap$url, _res$params;
|
|
123
|
+
|
|
124
|
+
let res = test((_snap$url = snap.url) !== null && _snap$url !== void 0 ? _snap$url : snap);
|
|
125
|
+
if (res) snap = rewrite((_res$params = res.params) !== null && _res$params !== void 0 ? _res$params : res);
|
|
126
|
+
return apply(snap);
|
|
127
|
+
}, s => s); // reduce overrides into a single function
|
|
128
|
+
|
|
129
|
+
let applyOverrides = overrides.reduceRight((apply, {
|
|
130
|
+
include,
|
|
131
|
+
exclude,
|
|
132
|
+
...opts
|
|
133
|
+
}) => snap => {
|
|
134
|
+
if ((0, _utils.snapshotMatches)(snap, include, exclude)) Object.assign(snap, opts);
|
|
135
|
+
return apply(snap);
|
|
136
|
+
}, s => s); // sort and reduce snapshots with overrides
|
|
137
|
+
|
|
138
|
+
return [...snapshots].sort().reduce((snapshots, snap) => {
|
|
139
|
+
snap = (0, _utils.withDefaults)(applyRewrites(snap), {
|
|
140
|
+
host
|
|
141
|
+
});
|
|
142
|
+
return (0, _utils.snapshotMatches)(snap, include, exclude) ? snapshots.concat(applyOverrides(snap)) : snapshots;
|
|
143
|
+
}, []);
|
|
144
|
+
} // Serves a static directory and returns a list of snapshots.
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async function loadStaticSnapshots(dir, config) {
|
|
148
|
+
let {
|
|
149
|
+
default: globby
|
|
150
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('globby'))); // gather paths with globby, which only accepts string patterns
|
|
151
|
+
|
|
152
|
+
let isStr = s => typeof s === 'string';
|
|
153
|
+
|
|
154
|
+
let strOr = (a, b) => a.length && a.every(isStr) ? a : b;
|
|
155
|
+
|
|
156
|
+
let files = strOr([].concat(config.include || []), '**/*.html');
|
|
157
|
+
let ignore = strOr([].concat(config.exclude || []), []);
|
|
158
|
+
let paths = await globby(files, {
|
|
159
|
+
cwd: dir,
|
|
160
|
+
ignore
|
|
161
|
+
}); // map snapshots from paths and config
|
|
162
|
+
|
|
163
|
+
return mapStaticSnapshots(paths, config);
|
|
164
|
+
}
|
package/dist/utils.js
CHANGED
|
@@ -3,21 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.mapStaticSnapshots = mapStaticSnapshots;
|
|
7
|
-
exports.serve = serve;
|
|
8
6
|
exports.snapshotMatches = snapshotMatches;
|
|
7
|
+
exports.validURL = validURL;
|
|
9
8
|
exports.withDefaults = withDefaults;
|
|
10
9
|
|
|
11
|
-
var _path = _interopRequireDefault(require("path"));
|
|
12
|
-
|
|
13
|
-
var pathToRegexp = _interopRequireWildcard(require("path-to-regexp"));
|
|
14
|
-
|
|
15
10
|
var _picomatch = _interopRequireDefault(require("picomatch"));
|
|
16
11
|
|
|
17
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
18
|
-
|
|
19
|
-
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; }
|
|
20
|
-
|
|
21
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
22
13
|
|
|
23
14
|
// used to deserialize regular expression strings
|
|
@@ -48,59 +39,6 @@ function withDefaults(options, {
|
|
|
48
39
|
|
|
49
40
|
options.url = url.href;
|
|
50
41
|
return options;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function mapRewrites(map, arr) {
|
|
54
|
-
return Object.entries(map).reduce((r, [source, destination]) => {
|
|
55
|
-
return (r || []).concat({
|
|
56
|
-
source,
|
|
57
|
-
destination
|
|
58
|
-
});
|
|
59
|
-
}, arr);
|
|
60
|
-
} // Serves a static directory with the provided options and returns an object containing adjusted
|
|
61
|
-
// rewrites (combined with any baseUrl), the server host, a close method, and the server
|
|
62
|
-
// instance. The `dryRun` option will prevent the server from actually starting.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
async function serve(dir, {
|
|
66
|
-
dryRun,
|
|
67
|
-
baseUrl,
|
|
68
|
-
cleanUrls,
|
|
69
|
-
rewrites = {}
|
|
70
|
-
}) {
|
|
71
|
-
let host = 'http://localhost'; // map rewrite options with any base-url
|
|
72
|
-
|
|
73
|
-
rewrites = mapRewrites(rewrites, baseUrl && [{
|
|
74
|
-
source: _path.default.posix.join(baseUrl, '/:path*'),
|
|
75
|
-
destination: '/:path*'
|
|
76
|
-
}]); // start the server
|
|
77
|
-
|
|
78
|
-
let server = !dryRun && (await new Promise(resolve => {
|
|
79
|
-
let server = require('http').createServer((req, res) => {
|
|
80
|
-
require('serve-handler')(req, res, {
|
|
81
|
-
public: dir,
|
|
82
|
-
cleanUrls,
|
|
83
|
-
rewrites
|
|
84
|
-
});
|
|
85
|
-
}).listen(() => resolve(server));
|
|
86
|
-
})); // easy clean up
|
|
87
|
-
|
|
88
|
-
let close = () => {
|
|
89
|
-
if (server) {
|
|
90
|
-
return new Promise(resolve => {
|
|
91
|
-
server.close(resolve);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}; // add the port to the host and return
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (server) host += `:${server.address().port}`;
|
|
98
|
-
return {
|
|
99
|
-
host,
|
|
100
|
-
rewrites,
|
|
101
|
-
server,
|
|
102
|
-
close
|
|
103
|
-
};
|
|
104
42
|
} // Returns true or false if a snapshot matches the provided include and exclude predicates. A
|
|
105
43
|
// predicate can be an array of predicates, a regular expression, a glob pattern, or a function.
|
|
106
44
|
|
|
@@ -119,7 +57,7 @@ function snapshotMatches(snapshot, include, exclude) {
|
|
|
119
57
|
try {
|
|
120
58
|
let [, parsed = predicate, flags] = RE_REGEXP.exec(predicate) || [];
|
|
121
59
|
result = new RegExp(parsed, flags).test(snapshot.name);
|
|
122
|
-
} catch
|
|
60
|
+
} catch {}
|
|
123
61
|
}
|
|
124
62
|
|
|
125
63
|
return result;
|
|
@@ -140,64 +78,4 @@ function snapshotMatches(snapshot, include, exclude) {
|
|
|
140
78
|
|
|
141
79
|
|
|
142
80
|
return !test(exclude, false) && test(include, true);
|
|
143
|
-
} // Maps an array of snapshots or paths to options ready to pass along to the core snapshot
|
|
144
|
-
// method. Paths are normalized before overrides are conditionally applied via their own include and
|
|
145
|
-
// exclude options. Snapshot URLs are then rewritten accordingly before default options are applied,
|
|
146
|
-
// including prepending the appropriate host. The returned set of snapshot options are sorted and
|
|
147
|
-
// filtered by the top-level include and exclude options.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
function mapStaticSnapshots(snapshots, {
|
|
151
|
-
host,
|
|
152
|
-
include,
|
|
153
|
-
exclude,
|
|
154
|
-
cleanUrls,
|
|
155
|
-
rewrites = [],
|
|
156
|
-
overrides = [],
|
|
157
|
-
server
|
|
158
|
-
} = {}) {
|
|
159
|
-
var _server$host, _server$rewrites;
|
|
160
|
-
|
|
161
|
-
// prioritize server properties
|
|
162
|
-
host = (_server$host = server === null || server === void 0 ? void 0 : server.host) !== null && _server$host !== void 0 ? _server$host : host;
|
|
163
|
-
rewrites = (_server$rewrites = server === null || server === void 0 ? void 0 : server.rewrites) !== null && _server$rewrites !== void 0 ? _server$rewrites : mapRewrites(rewrites, []); // reduce rewrites into a single function
|
|
164
|
-
|
|
165
|
-
let applyRewrites = [{
|
|
166
|
-
test: url => !/^(https?:\/)?\//.test(url) && url,
|
|
167
|
-
rewrite: url => _path.default.posix.normalize(_path.default.posix.join('/', url))
|
|
168
|
-
}, ...rewrites.map(({
|
|
169
|
-
source,
|
|
170
|
-
destination
|
|
171
|
-
}) => ({
|
|
172
|
-
test: pathToRegexp.match(destination),
|
|
173
|
-
rewrite: pathToRegexp.compile(source)
|
|
174
|
-
})), {
|
|
175
|
-
test: url => cleanUrls && url,
|
|
176
|
-
rewrite: url => url.replace(/(\/index)?\.html$/, '')
|
|
177
|
-
}].reduceRight((apply, {
|
|
178
|
-
test,
|
|
179
|
-
rewrite
|
|
180
|
-
}) => snap => {
|
|
181
|
-
var _snap$url, _res$params;
|
|
182
|
-
|
|
183
|
-
let res = test((_snap$url = snap.url) !== null && _snap$url !== void 0 ? _snap$url : snap);
|
|
184
|
-
if (res) snap = rewrite((_res$params = res.params) !== null && _res$params !== void 0 ? _res$params : res);
|
|
185
|
-
return apply(snap);
|
|
186
|
-
}, s => s); // reduce overrides into a single function
|
|
187
|
-
|
|
188
|
-
let applyOverrides = overrides.reduceRight((apply, {
|
|
189
|
-
include,
|
|
190
|
-
exclude,
|
|
191
|
-
...opts
|
|
192
|
-
}) => snap => {
|
|
193
|
-
if (snapshotMatches(snap, include, exclude)) Object.assign(snap, opts);
|
|
194
|
-
return apply(snap);
|
|
195
|
-
}, s => s); // sort and reduce snapshots with overrides
|
|
196
|
-
|
|
197
|
-
return [...snapshots].sort().reduce((snapshots, snap) => {
|
|
198
|
-
snap = withDefaults(applyRewrites(snap), {
|
|
199
|
-
host
|
|
200
|
-
});
|
|
201
|
-
return snapshotMatches(snap, include, exclude) ? snapshots.concat(applyOverrides(snap)) : snapshots;
|
|
202
|
-
}, []);
|
|
203
81
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/cli-snapshot",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.72",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/percy/cli",
|
|
8
|
+
"directory": "packages/cli-snapshot"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
5
13
|
"main": "dist/index.js",
|
|
6
14
|
"files": [
|
|
7
|
-
"dist"
|
|
8
|
-
"oclif.manifest.json"
|
|
15
|
+
"dist"
|
|
9
16
|
],
|
|
10
17
|
"engines": {
|
|
11
18
|
"node": ">=12"
|
|
@@ -13,37 +20,24 @@
|
|
|
13
20
|
"scripts": {
|
|
14
21
|
"build": "node ../../scripts/build",
|
|
15
22
|
"lint": "eslint --ignore-path ../../.gitignore .",
|
|
16
|
-
"
|
|
17
|
-
"readme": "oclif-dev readme",
|
|
23
|
+
"readme": "percy-cli-readme",
|
|
18
24
|
"test": "node ../../scripts/test",
|
|
19
25
|
"test:coverage": "yarn test --coverage"
|
|
20
26
|
},
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"bin": "percy",
|
|
26
|
-
"commands": "./dist/commands",
|
|
27
|
-
"hooks": {
|
|
28
|
-
"init": "./dist/hooks/init"
|
|
29
|
-
}
|
|
27
|
+
"@percy/cli": {
|
|
28
|
+
"commands": [
|
|
29
|
+
"./dist/snapshot.js"
|
|
30
|
+
]
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@percy/cli-command": "1.0.0-beta.
|
|
33
|
-
"@percy/config": "1.0.0-beta.
|
|
34
|
-
"@percy/core": "1.0.0-beta.
|
|
35
|
-
"@percy/dom": "1.0.0-beta.71",
|
|
36
|
-
"@percy/logger": "1.0.0-beta.71",
|
|
33
|
+
"@percy/cli-command": "1.0.0-beta.72",
|
|
34
|
+
"@percy/config": "1.0.0-beta.72",
|
|
35
|
+
"@percy/core": "1.0.0-beta.72",
|
|
37
36
|
"globby": "^11.0.4",
|
|
38
37
|
"path-to-regexp": "^6.2.0",
|
|
39
38
|
"picomatch": "^2.3.0",
|
|
40
39
|
"serve-handler": "^6.1.3",
|
|
41
40
|
"yaml": "^1.10.0"
|
|
42
41
|
},
|
|
43
|
-
"
|
|
44
|
-
"type": "git",
|
|
45
|
-
"url": "https://github.com/percy/cli",
|
|
46
|
-
"directory": "packages/cli-snapshot"
|
|
47
|
-
},
|
|
48
|
-
"gitHead": "364d1df717fb19a26ccb024458df6e78a9c11f99"
|
|
42
|
+
"gitHead": "6219287e18a0cacb609d0c2696a5785abc9009b9"
|
|
49
43
|
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.Snapshot = void 0;
|
|
7
|
-
|
|
8
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
-
|
|
10
|
-
var _path = _interopRequireDefault(require("path"));
|
|
11
|
-
|
|
12
|
-
var _config = _interopRequireDefault(require("@percy/config"));
|
|
13
|
-
|
|
14
|
-
var _cliCommand = _interopRequireWildcard(require("@percy/cli-command"));
|
|
15
|
-
|
|
16
|
-
var _request = _interopRequireDefault(require("@percy/client/dist/request"));
|
|
17
|
-
|
|
18
|
-
var _core = _interopRequireDefault(require("@percy/core"));
|
|
19
|
-
|
|
20
|
-
var _logger = _interopRequireDefault(require("@percy/logger"));
|
|
21
|
-
|
|
22
|
-
var _globby = _interopRequireDefault(require("globby"));
|
|
23
|
-
|
|
24
|
-
var _yaml = _interopRequireDefault(require("yaml"));
|
|
25
|
-
|
|
26
|
-
var _package = _interopRequireDefault(require("../../package.json"));
|
|
27
|
-
|
|
28
|
-
var _utils = require("../utils");
|
|
29
|
-
|
|
30
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
31
|
-
|
|
32
|
-
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; }
|
|
33
|
-
|
|
34
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
35
|
-
|
|
36
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
37
|
-
|
|
38
|
-
class Snapshot extends _cliCommand.default {
|
|
39
|
-
constructor(...args) {
|
|
40
|
-
super(...args);
|
|
41
|
-
|
|
42
|
-
_defineProperty(this, "log", (0, _logger.default)('cli:snapshot'));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async run() {
|
|
46
|
-
// skip snapshots
|
|
47
|
-
if (!this.isPercyEnabled()) {
|
|
48
|
-
return this.log.info('Percy is disabled. Skipping snapshots');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let {
|
|
52
|
-
'dir|file|sitemap': arg
|
|
53
|
-
} = this.args;
|
|
54
|
-
let isSitemap = /^https?:\/\//.test(arg); // validate directory or file existence
|
|
55
|
-
|
|
56
|
-
if (!isSitemap && !_fs.default.existsSync(arg)) this.error(`Not found: ${arg}`);
|
|
57
|
-
|
|
58
|
-
let isStatic = !isSitemap && _fs.default.lstatSync(arg).isDirectory(); // initialize percy
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.percy = new _core.default({ ...this.percyrc({
|
|
62
|
-
[isSitemap ? 'sitemap' : 'static']: isSitemap || isStatic ? {
|
|
63
|
-
include: this.flags.include,
|
|
64
|
-
exclude: this.flags.exclude
|
|
65
|
-
} : undefined
|
|
66
|
-
}),
|
|
67
|
-
clientInfo: `${_package.default.name}/${_package.default.version}`,
|
|
68
|
-
environmentInfo: `node/${process.version}`,
|
|
69
|
-
server: false
|
|
70
|
-
}); // gather snapshots
|
|
71
|
-
|
|
72
|
-
let snapshots = isSitemap && (await this.loadSitemapSnapshots(arg)) || isStatic && (await this.loadStaticSnapshots(arg)) || (await this.loadSnapshotsFile(arg));
|
|
73
|
-
|
|
74
|
-
if (!snapshots.length) {
|
|
75
|
-
this.error('No snapshots found');
|
|
76
|
-
} // start processing snapshots
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
await this.percy.start();
|
|
80
|
-
this.percy.snapshot(snapshots);
|
|
81
|
-
} // Called on error, interupt, or after running
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
async finally(error) {
|
|
85
|
-
var _this$percy, _this$server;
|
|
86
|
-
|
|
87
|
-
await ((_this$percy = this.percy) === null || _this$percy === void 0 ? void 0 : _this$percy.stop(!!error));
|
|
88
|
-
await ((_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.close());
|
|
89
|
-
} // Fetches and maps sitemap URLs to snapshots.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
async loadSitemapSnapshots(sitemap) {
|
|
93
|
-
let config = this.percy.config.sitemap; // fetch sitemap URLs
|
|
94
|
-
|
|
95
|
-
let urls = await (0, _request.default)(sitemap, (body, res) => {
|
|
96
|
-
// validate sitemap content-type
|
|
97
|
-
let [contentType] = res.headers['content-type'].split(';');
|
|
98
|
-
|
|
99
|
-
if (!/^(application|text)\/xml$/.test(contentType)) {
|
|
100
|
-
this.error('The sitemap must be an XML document, ' + `but the content-type was "${contentType}"`);
|
|
101
|
-
} // parse XML content into a list of URLs
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
let urls = body.match(/(?<=<loc>)(.*)(?=<\/loc>)/ig); // filter out duplicate URLs that differ by a trailing slash
|
|
105
|
-
|
|
106
|
-
return urls.filter((url, i) => {
|
|
107
|
-
let match = urls.indexOf(url.replace(/\/$/, ''));
|
|
108
|
-
return match === -1 || match === i;
|
|
109
|
-
});
|
|
110
|
-
}); // map with inherited static options
|
|
111
|
-
|
|
112
|
-
return (0, _utils.mapStaticSnapshots)(urls, config);
|
|
113
|
-
} // Serves a static directory and returns a list of snapshots.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
async loadStaticSnapshots(dir) {
|
|
117
|
-
let config = this.percy.config.static;
|
|
118
|
-
let baseUrl = this.flags['base-url'] || config.baseUrl;
|
|
119
|
-
let dryRun = this.flags['dry-run']; // validate any provided base-url
|
|
120
|
-
|
|
121
|
-
if (baseUrl && !baseUrl.startsWith('/')) {
|
|
122
|
-
this.error('The base-url must begin with a forward slash (/) ' + 'when snapshotting static directories');
|
|
123
|
-
} // start the server
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.server = await (0, _utils.serve)(dir, { ...config,
|
|
127
|
-
baseUrl,
|
|
128
|
-
dryRun
|
|
129
|
-
}); // gather paths
|
|
130
|
-
|
|
131
|
-
let isStr = s => typeof s === 'string';
|
|
132
|
-
|
|
133
|
-
let strOr = (a, b) => a.length && a.every(isStr) ? a : b;
|
|
134
|
-
|
|
135
|
-
let files = strOr([].concat(config.include || []), '**/*.html');
|
|
136
|
-
let ignore = strOr([].concat(config.exclude || []), []);
|
|
137
|
-
let paths = await (0, _globby.default)(files, {
|
|
138
|
-
cwd: dir,
|
|
139
|
-
ignore
|
|
140
|
-
}); // map snapshots from paths and config
|
|
141
|
-
|
|
142
|
-
return (0, _utils.mapStaticSnapshots)(paths, { ...config,
|
|
143
|
-
server: this.server
|
|
144
|
-
});
|
|
145
|
-
} // Loads snapshots from a js, json, or yaml file.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
async loadSnapshotsFile(file) {
|
|
149
|
-
let ext = _path.default.extname(file);
|
|
150
|
-
|
|
151
|
-
let config = {}; // load snapshots file
|
|
152
|
-
|
|
153
|
-
if (ext === '.js') {
|
|
154
|
-
config = require(_path.default.resolve(file));
|
|
155
|
-
if (typeof config === 'function') config = await config();
|
|
156
|
-
} else if (ext === '.json') {
|
|
157
|
-
config = JSON.parse(_fs.default.readFileSync(file, {
|
|
158
|
-
encoding: 'utf-8'
|
|
159
|
-
}));
|
|
160
|
-
} else if (ext.match(/\.ya?ml$/)) {
|
|
161
|
-
config = _yaml.default.parse(_fs.default.readFileSync(file, {
|
|
162
|
-
encoding: 'utf-8'
|
|
163
|
-
}));
|
|
164
|
-
} else {
|
|
165
|
-
this.error(`Unsupported filetype: ${file}`);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let {
|
|
169
|
-
// flags override config options
|
|
170
|
-
'base-url': baseUrl = config.baseUrl,
|
|
171
|
-
include = config.include,
|
|
172
|
-
exclude = config.exclude
|
|
173
|
-
} = this.flags; // validate base-url before config options
|
|
174
|
-
|
|
175
|
-
if (baseUrl && !baseUrl.startsWith('http')) {
|
|
176
|
-
this.error('The base-url must include a protocol and hostname ' + 'when providing a list of snapshots');
|
|
177
|
-
} // validate snapshot config options
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
let errors = _config.default.validate(config, '/snapshot/list');
|
|
181
|
-
|
|
182
|
-
if (errors) {
|
|
183
|
-
this.log.warn('Invalid snapshot options:');
|
|
184
|
-
|
|
185
|
-
for (let e of errors) this.log.warn(`- ${e.path}: ${e.message}`);
|
|
186
|
-
} // support config that only contains a list of snapshots
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return (Array.isArray(config) ? config : config.snapshots || []).reduce((snapshots, snap) => {
|
|
190
|
-
// reduce matching snapshots with default options
|
|
191
|
-
snap = (0, _utils.withDefaults)(snap, {
|
|
192
|
-
host: baseUrl
|
|
193
|
-
});
|
|
194
|
-
return (0, _utils.snapshotMatches)(snap, include, exclude) ? snapshots.concat(snap) : snapshots;
|
|
195
|
-
}, []);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
exports.Snapshot = Snapshot;
|
|
201
|
-
|
|
202
|
-
_defineProperty(Snapshot, "description", 'Take snapshots from a static directory, snapshots file, or sitemap url');
|
|
203
|
-
|
|
204
|
-
_defineProperty(Snapshot, "args", [{
|
|
205
|
-
name: 'dir|file|sitemap',
|
|
206
|
-
description: 'static directory, snapshots file, or sitemap url',
|
|
207
|
-
required: true
|
|
208
|
-
}]);
|
|
209
|
-
|
|
210
|
-
_defineProperty(Snapshot, "flags", { ..._cliCommand.flags.logging,
|
|
211
|
-
..._cliCommand.flags.discovery,
|
|
212
|
-
..._cliCommand.flags.config,
|
|
213
|
-
'base-url': _cliCommand.flags.string({
|
|
214
|
-
description: 'the base url pages are hosted at when snapshotting',
|
|
215
|
-
char: 'b'
|
|
216
|
-
}),
|
|
217
|
-
include: _cliCommand.flags.string({
|
|
218
|
-
description: 'one or more globs/patterns matching snapshots to include',
|
|
219
|
-
multiple: true
|
|
220
|
-
}),
|
|
221
|
-
exclude: _cliCommand.flags.string({
|
|
222
|
-
description: 'one or more globs/patterns matching snapshots to exclude',
|
|
223
|
-
multiple: true
|
|
224
|
-
}),
|
|
225
|
-
// static only flags
|
|
226
|
-
'clean-urls': _cliCommand.flags.boolean({
|
|
227
|
-
description: 'rewrite static index and filepath URLs to be clean',
|
|
228
|
-
percyrc: 'static.cleanUrls'
|
|
229
|
-
}),
|
|
230
|
-
// deprecated flags
|
|
231
|
-
files: _cliCommand.flags.string({
|
|
232
|
-
deprecated: {
|
|
233
|
-
map: 'include',
|
|
234
|
-
until: '1.0.0'
|
|
235
|
-
},
|
|
236
|
-
percyrc: 'static.include',
|
|
237
|
-
hidden: true
|
|
238
|
-
}),
|
|
239
|
-
ignore: _cliCommand.flags.string({
|
|
240
|
-
deprecated: {
|
|
241
|
-
map: 'exclude',
|
|
242
|
-
until: '1.0.0'
|
|
243
|
-
},
|
|
244
|
-
percyrc: 'static.exclude',
|
|
245
|
-
hidden: true
|
|
246
|
-
})
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
_defineProperty(Snapshot, "examples", ['$ percy snapshot ./public', '$ percy snapshot snapshots.yml']);
|
package/dist/hooks/init.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = _default;
|
|
7
|
-
|
|
8
|
-
var _config = _interopRequireDefault(require("@percy/config"));
|
|
9
|
-
|
|
10
|
-
var CoreConfig = _interopRequireWildcard(require("@percy/core/dist/config"));
|
|
11
|
-
|
|
12
|
-
var SnapshotConfig = _interopRequireWildcard(require("../config"));
|
|
13
|
-
|
|
14
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
|
-
|
|
16
|
-
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; }
|
|
17
|
-
|
|
18
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
-
|
|
20
|
-
function _default() {
|
|
21
|
-
_config.default.addSchema(CoreConfig.schemas);
|
|
22
|
-
|
|
23
|
-
_config.default.addSchema(SnapshotConfig.schemas);
|
|
24
|
-
|
|
25
|
-
_config.default.addMigration(SnapshotConfig.migration);
|
|
26
|
-
}
|
package/oclif.manifest.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"1.0.0-beta.71","commands":{"snapshot":{"id":"snapshot","description":"Take snapshots from a static directory, snapshots file, or sitemap url","pluginName":"@percy/cli-snapshot","pluginType":"core","aliases":[],"examples":["$ percy snapshot ./public","$ percy snapshot snapshots.yml"],"flags":{"verbose":{"name":"verbose","type":"boolean","char":"v","description":"log everything","allowNo":false},"quiet":{"name":"quiet","type":"boolean","char":"q","description":"log errors only","allowNo":false},"silent":{"name":"silent","type":"boolean","description":"log nothing","allowNo":false},"allowed-hostname":{"name":"allowed-hostname","type":"option","char":"h","description":"allowed hostnames to capture in asset discovery"},"network-idle-timeout":{"name":"network-idle-timeout","type":"option","char":"t","description":"asset discovery network idle timeout"},"disable-cache":{"name":"disable-cache","type":"boolean","description":"disable asset discovery caches","allowNo":false},"dry-run":{"name":"dry-run","type":"boolean","char":"d","description":"print logs only, do not run asset discovery or upload snapshots","allowNo":false},"debug":{"name":"debug","type":"boolean","description":"debug asset discovery and do not upload snapshots","allowNo":false},"config":{"name":"config","type":"option","char":"c","description":"configuration file path"},"base-url":{"name":"base-url","type":"option","char":"b","description":"the base url pages are hosted at when snapshotting"},"include":{"name":"include","type":"option","description":"one or more globs/patterns matching snapshots to include"},"exclude":{"name":"exclude","type":"option","description":"one or more globs/patterns matching snapshots to exclude"},"clean-urls":{"name":"clean-urls","type":"boolean","description":"rewrite static index and filepath URLs to be clean","allowNo":false},"files":{"name":"files","type":"option","hidden":true},"ignore":{"name":"ignore","type":"option","hidden":true}},"args":[{"name":"dir|file|sitemap","description":"static directory, snapshots file, or sitemap url","required":true}]}}}
|