-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
executable file
·131 lines (111 loc) · 3.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const args = require('args');
const puppeteer = require('puppeteer');
const mergeImages = require('merge-images');
const Canvas = require('canvas');
const ora = require('ora');
const chalk = require('chalk');
const tmp = require('tmp');
const filenamify = require('filenamify');
const filenamifyUrl = require('filenamify-url');
const List = require('prompt-list');
const devices = require('./devices.js');
tmp.setGracefulCleanup();
const {log} = console;
const {
cyan: info,
red: error,
yellow: tip
} = chalk;
(async () => {
args
.option('url', 'The URL of the website that you wish to mockup')
.option(
'assets',
'Path to folder that contains Facebook Devices',
process.cwd()
)
.option('device', 'The device for which you want a mockup')
.option('shadows', 'Should the mockup have shadows?', true);
// .option('landscape', 'Landscape mode', false); image rotation needed in merge-images
const flags = args.parse(process.argv, {
mri: {
boolean: ['s']
}
});
const {url, assets, shadows} = flags;
let deviceToMock = flags.device;
if (!url || url.length === 0) {
log(error('\nPlease enter a URL.\n'));
log(`\nRun ${tip('mockgen help')} to know more.\n`);
process.exit(1);
}
let device = devices[deviceToMock];
if (!device) {
if (deviceToMock) {
log(error('\nInvalid device name passed.\n'));
}
const devicePrompt = new List({
name: 'deviceToMock',
message: 'Please select a device.',
choices: Object.keys(devices)
});
deviceToMock = await devicePrompt.run();
device = devices[deviceToMock];
}
if (!fs.existsSync(path.join(assets, 'Facebook Devices'))) {
log(error('\nPlease enter a valid assets path.\n'));
process.exit(1);
}
try {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const puppeteerSpinner = ora(`Visiting ${url}`).start();
const screenshot = tmp.fileSync({postfix: '.png'});
await page.goto(url);
const {deviceObject, viewport} = device;
if (deviceObject) {
await page.emulate(deviceObject);
}
if (viewport) {
await page.setViewport(viewport);
}
await page.screenshot({path: screenshot.name});
puppeteerSpinner.stop();
let deviceBasePath = path.join(assets, device.mockup);
deviceBasePath = shadows ? deviceBasePath : deviceBasePath.replace(/Device With Shadow/ig, 'Device');
const baseImageVariants = fs.readdirSync(deviceBasePath);
let variant;
if (baseImageVariants.length > 1) {
const variantPrompt = new List({
name: 'variant',
message: 'Which base image would you like to use?',
choices: baseImageVariants
});
variant = await variantPrompt.run();
} else {
[variant] = baseImageVariants;
}
const imageSpinner = ora('Generating mockup').start();
const b64 = await mergeImages(
[
{src: screenshot.name, x: device.offsetX || 0, y: device.offsetY || 0},
path.join(deviceBasePath, variant)
],
{Canvas}
);
const data = b64.replace(/^data:image\/\w+;base64,/, '');
const buffer = Buffer.from(data, 'base64');
const deviceNameFormatted = filenamify(deviceToMock).split(' ').join('-').toLowerCase();
const mockup = `${filenamifyUrl(url)}-${deviceNameFormatted}.png`;
fs.writeFileSync(mockup, buffer);
imageSpinner.stop();
log(`\n✨ Mockup saved to ${info(mockup)}\n`);
await browser.close();
} catch (err) {
log(error(`\n${err}`));
process.exit(1);
}
})();