@percy/cli-upload 1.0.0 → 1.0.3
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/dist/config.js +50 -0
- package/dist/index.js +1 -0
- package/dist/resources.js +54 -0
- package/dist/upload.js +125 -0
- package/package.json +4 -4
package/dist/config.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const schema = {
|
|
2
|
+
upload: {
|
|
3
|
+
type: 'object',
|
|
4
|
+
additionalProperties: false,
|
|
5
|
+
properties: {
|
|
6
|
+
files: {
|
|
7
|
+
anyOf: [{
|
|
8
|
+
type: 'string'
|
|
9
|
+
}, {
|
|
10
|
+
type: 'array',
|
|
11
|
+
items: {
|
|
12
|
+
type: 'string'
|
|
13
|
+
}
|
|
14
|
+
}],
|
|
15
|
+
default: '**/*.{png,jpg,jpeg}'
|
|
16
|
+
},
|
|
17
|
+
ignore: {
|
|
18
|
+
anyOf: [{
|
|
19
|
+
type: 'string'
|
|
20
|
+
}, {
|
|
21
|
+
type: 'array',
|
|
22
|
+
items: {
|
|
23
|
+
type: 'string'
|
|
24
|
+
}
|
|
25
|
+
}],
|
|
26
|
+
default: ''
|
|
27
|
+
},
|
|
28
|
+
stripExtensions: {
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
default: false
|
|
31
|
+
},
|
|
32
|
+
concurrency: {
|
|
33
|
+
type: 'number',
|
|
34
|
+
minimum: 1
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
export function migration(config, {
|
|
40
|
+
map,
|
|
41
|
+
del
|
|
42
|
+
}) {
|
|
43
|
+
/* eslint-disable curly */
|
|
44
|
+
if (config.version < 2) {
|
|
45
|
+
// image-snapshots and options were renamed
|
|
46
|
+
map('imageSnapshots.files', 'upload.files');
|
|
47
|
+
map('imageSnapshots.ignore', 'upload.ignore');
|
|
48
|
+
del('imageSnapshots');
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, upload } from './upload.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { sha256hash } from '@percy/client/utils'; // Returns a root resource object with a sha and mimetype.
|
|
3
|
+
|
|
4
|
+
function createRootResource(url, content) {
|
|
5
|
+
return {
|
|
6
|
+
url,
|
|
7
|
+
content,
|
|
8
|
+
sha: sha256hash(content),
|
|
9
|
+
mimetype: 'text/html',
|
|
10
|
+
root: true
|
|
11
|
+
};
|
|
12
|
+
} // Returns an image resource object with a sha.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function createImageResource(url, content, mimetype) {
|
|
16
|
+
return {
|
|
17
|
+
url,
|
|
18
|
+
content,
|
|
19
|
+
sha: sha256hash(content),
|
|
20
|
+
mimetype
|
|
21
|
+
};
|
|
22
|
+
} // Returns root resource and image resource objects based on an image's
|
|
23
|
+
// filename, contents, and dimensions. The root resource is a generated DOM
|
|
24
|
+
// designed to display an image at it's native size without margins or padding.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export function createImageResources(filename, content, size) {
|
|
28
|
+
let {
|
|
29
|
+
dir,
|
|
30
|
+
name,
|
|
31
|
+
ext
|
|
32
|
+
} = path.parse(filename);
|
|
33
|
+
let rootUrl = `/${encodeURIComponent(path.join(dir, name))}`;
|
|
34
|
+
let imageUrl = `/${encodeURIComponent(filename)}`;
|
|
35
|
+
let mimetype = ext === '.png' ? 'image/png' : 'image/jpeg';
|
|
36
|
+
return [createRootResource(rootUrl, `
|
|
37
|
+
<!doctype html>
|
|
38
|
+
<html lang="en">
|
|
39
|
+
<head>
|
|
40
|
+
<meta charset="utf-8">
|
|
41
|
+
<title>${filename}</title>
|
|
42
|
+
<style>
|
|
43
|
+
*, *::before, *::after { margin: 0; padding: 0; font-size: 0; }
|
|
44
|
+
html, body { width: 100%; }
|
|
45
|
+
img { max-width: 100%; }
|
|
46
|
+
</style>
|
|
47
|
+
</head>
|
|
48
|
+
<body>
|
|
49
|
+
<img src="${imageUrl}" width="${size.width}px" height="${size.height}px"/>
|
|
50
|
+
</body>
|
|
51
|
+
</html>
|
|
52
|
+
`), createImageResource(imageUrl, content, mimetype)];
|
|
53
|
+
}
|
|
54
|
+
export default createImageResources;
|
package/dist/upload.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import command from '@percy/cli-command';
|
|
4
|
+
import * as UploadConfig from './config.js';
|
|
5
|
+
const ALLOWED_FILE_TYPES = /\.(png|jpg|jpeg)$/i;
|
|
6
|
+
export const upload = command('upload', {
|
|
7
|
+
description: 'Upload a directory of images to Percy',
|
|
8
|
+
args: [{
|
|
9
|
+
name: 'dirname',
|
|
10
|
+
description: 'Directory of images to upload',
|
|
11
|
+
required: true,
|
|
12
|
+
validate: dir => {
|
|
13
|
+
if (!fs.existsSync(dir)) {
|
|
14
|
+
throw new Error(`Not found: ${dir}`);
|
|
15
|
+
} else if (!fs.lstatSync(dir).isDirectory()) {
|
|
16
|
+
throw new Error(`Not a directory: ${dir}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}],
|
|
20
|
+
flags: [{
|
|
21
|
+
name: 'files',
|
|
22
|
+
description: 'One or more globs matching image file paths to upload',
|
|
23
|
+
default: UploadConfig.schema.upload.properties.files.default,
|
|
24
|
+
percyrc: 'upload.files',
|
|
25
|
+
type: 'pattern',
|
|
26
|
+
multiple: true,
|
|
27
|
+
short: 'f'
|
|
28
|
+
}, {
|
|
29
|
+
name: 'ignore',
|
|
30
|
+
description: 'One or more globs matching image file paths to ignore',
|
|
31
|
+
percyrc: 'upload.ignore',
|
|
32
|
+
type: 'pattern',
|
|
33
|
+
multiple: true,
|
|
34
|
+
short: 'i'
|
|
35
|
+
}, {
|
|
36
|
+
name: 'strip-extensions',
|
|
37
|
+
description: 'Strips file extensions from snapshot names',
|
|
38
|
+
percyrc: 'upload.stripExtensions',
|
|
39
|
+
short: 'e'
|
|
40
|
+
}],
|
|
41
|
+
examples: ['$0 ./images'],
|
|
42
|
+
percy: {
|
|
43
|
+
discoveryFlags: false,
|
|
44
|
+
deferUploads: true
|
|
45
|
+
},
|
|
46
|
+
config: {
|
|
47
|
+
schemas: [UploadConfig.schema],
|
|
48
|
+
migrations: [UploadConfig.migration]
|
|
49
|
+
}
|
|
50
|
+
}, async function* ({
|
|
51
|
+
flags,
|
|
52
|
+
args,
|
|
53
|
+
percy,
|
|
54
|
+
log,
|
|
55
|
+
exit
|
|
56
|
+
}) {
|
|
57
|
+
if (!percy) exit(0, 'Percy is disabled');
|
|
58
|
+
let config = percy.config.upload;
|
|
59
|
+
let {
|
|
60
|
+
default: glob
|
|
61
|
+
} = await import('fast-glob');
|
|
62
|
+
let pathnames = yield glob(config.files, {
|
|
63
|
+
ignore: [].concat(config.ignore || []),
|
|
64
|
+
cwd: args.dirname,
|
|
65
|
+
fs
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!pathnames.length) {
|
|
69
|
+
exit(1, `No matching files found in '${args.dirname}'`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let {
|
|
73
|
+
default: imageSize
|
|
74
|
+
} = await import('image-size');
|
|
75
|
+
let {
|
|
76
|
+
createImageResources
|
|
77
|
+
} = await import('./resources.js'); // the internal upload queue shares a concurrency with the snapshot queue
|
|
78
|
+
|
|
79
|
+
percy.setConfig({
|
|
80
|
+
discovery: {
|
|
81
|
+
concurrency: config.concurrency
|
|
82
|
+
}
|
|
83
|
+
}); // do not launch a browser when starting
|
|
84
|
+
|
|
85
|
+
yield* percy.yield.start({
|
|
86
|
+
browser: false
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
for (let filename of pathnames) {
|
|
90
|
+
let file = path.parse(filename);
|
|
91
|
+
let name = config.stripExtensions ? path.join(file.dir, file.name) : filename;
|
|
92
|
+
|
|
93
|
+
if (!ALLOWED_FILE_TYPES.test(filename)) {
|
|
94
|
+
log.info(`Skipping unsupported file type: ${filename}`);
|
|
95
|
+
} else {
|
|
96
|
+
if (percy.dryRun) log.info(`Snapshot found: ${name}`);
|
|
97
|
+
|
|
98
|
+
percy._scheduleUpload(filename, async () => {
|
|
99
|
+
let filepath = path.resolve(args.dirname, filename);
|
|
100
|
+
let buffer = fs.readFileSync(filepath); // width and height is clamped to API min and max
|
|
101
|
+
|
|
102
|
+
let size = imageSize(filepath);
|
|
103
|
+
let widths = [Math.max(10, Math.min(size.width, 2000))];
|
|
104
|
+
let minHeight = Math.max(10, Math.min(size.height, 2000));
|
|
105
|
+
let resources = createImageResources(filename, buffer, size);
|
|
106
|
+
return {
|
|
107
|
+
name,
|
|
108
|
+
widths,
|
|
109
|
+
minHeight,
|
|
110
|
+
resources
|
|
111
|
+
};
|
|
112
|
+
}).then(() => {
|
|
113
|
+
log.info(`Snapshot uploaded: ${name}`);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
yield* percy.yield.stop();
|
|
120
|
+
} catch (error) {
|
|
121
|
+
await percy.stop(true);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
export default upload;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/cli-upload",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"node": ">=14"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"
|
|
17
|
+
"dist"
|
|
18
18
|
],
|
|
19
19
|
"main": "./dist/index.js",
|
|
20
20
|
"type": "module",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@percy/cli-command": "1.0.
|
|
35
|
+
"@percy/cli-command": "1.0.3",
|
|
36
36
|
"fast-glob": "^3.2.11",
|
|
37
37
|
"image-size": "^1.0.0"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "a259d5cff0933711bced21a979c577e70765d318"
|
|
40
40
|
}
|