You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
8.8 KiB

#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = __importDefault(require("chalk"));
const commander_1 = require("commander");
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const _1 = require(".");
const HTML_1 = require("./HTML");
const update_1 = __importDefault(require("./update"));
const packageJson = () => require('../package.json');
const program = new commander_1.Command(packageJson().name).version(packageJson().version);
const validateSourceArgument = (src, command) => {
if (!src) {
console.error(chalk_1.default.black.bgRed(`You must supply a valid image path or remote URL. Example:`));
console.error(`\n $ expo-pwa ${command} -i ./assets/icon.png`);
console.error();
process.exit(-1);
}
};
function outputCommand(name, examples = []) {
return program
.command(`${name} [project-root]`)
.option('-i, --input <file>', 'Input file to process')
.option('-o, --output <path>', 'Output directory. Default: <project-root/>web')
.option('-p, --public <path>', 'Public folder. Default: <output>')
.on('--help', () => {
if (!examples.length)
return;
console.log();
console.log('Examples:');
console.log();
for (const example of examples) {
console.log(` $ expo-pwa ${name} ${example}`);
}
console.log();
});
}
function assetCommand(name, examples = []) {
return outputCommand(name, examples)
.option('-r, --resize', 'Resize mode to use [contain, cover]', 'contain')
.option('-c, --color', 'CSS background color for to use for the images (should be opaque).');
}
assetCommand('icon', ['--platform safari -i ./icon.png', '--platform chrome -i ./icon.png'])
.description('Generate the home screen icons for a PWA')
.option('--platform [string]', 'Platform to generate for: safari, chrome')
.action(async (inputProjectRoot, options) => {
var _a;
validateSourceArgument(options.input, 'favicon');
const projectRoot = inputProjectRoot !== null && inputProjectRoot !== void 0 ? inputProjectRoot : process.cwd();
const output = (_a = options.output) !== null && _a !== void 0 ? _a : (0, path_1.join)(projectRoot, 'web');
try {
await generateAssets(projectRoot, options.platform + '-icon', {
src: options.input,
output,
publicPath: options.public || output,
resizeMode: options.resize,
color: options.color || 'transparent',
});
await (0, update_1.default)();
}
catch (error) {
await commandDidThrowAsync(error);
}
});
assetCommand('favicon', ['-i ./icon.png'])
.description('Generate the favicons for a website')
.action(async (inputProjectRoot, options) => {
var _a;
validateSourceArgument(options.input, 'favicon');
const projectRoot = inputProjectRoot !== null && inputProjectRoot !== void 0 ? inputProjectRoot : process.cwd();
const output = (_a = options.output) !== null && _a !== void 0 ? _a : (0, path_1.join)(projectRoot, 'web');
try {
await generateAssets(projectRoot, 'favicon', {
src: options.input,
output,
publicPath: options.public || output,
resizeMode: options.resize,
color: options.color || 'transparent',
});
await (0, update_1.default)();
}
catch (error) {
await commandDidThrowAsync(error);
}
});
assetCommand('splash', ['--color blue --resize cover -i ./splash.png'])
.description('Generate the Safari splash screens for a PWA')
.action(async (inputProjectRoot, options) => {
var _a;
validateSourceArgument(options.input, 'favicon');
const projectRoot = inputProjectRoot !== null && inputProjectRoot !== void 0 ? inputProjectRoot : process.cwd();
const output = (_a = options.output) !== null && _a !== void 0 ? _a : (0, path_1.join)(projectRoot, 'web');
try {
await generateAssets(projectRoot, 'splash', {
src: options.input,
output,
publicPath: options.public || output,
resizeMode: options.resize,
color: options.color || 'white',
});
await (0, update_1.default)();
}
catch (error) {
await commandDidThrowAsync(error);
}
});
outputCommand('manifest', ['-i ./random.config.js'])
.description('Generate the PWA manifest from an Expo project config')
.action(async (inputProjectRoot, options) => {
var _a, _b;
const projectRoot = (0, path_1.resolve)(inputProjectRoot !== null && inputProjectRoot !== void 0 ? inputProjectRoot : process.cwd());
const output = (_a = options.output) !== null && _a !== void 0 ? _a : (0, path_1.join)(projectRoot, 'web');
const publicPath = (0, path_1.resolve)((_b = options.public) !== null && _b !== void 0 ? _b : output);
const outputPath = (0, path_1.resolve)(output);
try {
const items = await (0, _1.generateManifestAsync)({
projectRoot: (0, path_1.resolve)(projectRoot),
publicPath,
}, options.input ? (0, path_1.resolve)(options.input) : undefined);
await resolveOutputAsync(publicPath, outputPath, items);
await (0, update_1.default)();
}
catch (error) {
await commandDidThrowAsync(error);
}
});
program.parse(process.argv);
async function generateAssets(projectRoot, type, { src, output, publicPath, color: backgroundColor, resizeMode = 'contain' }) {
if (!isResizeMode(resizeMode)) {
console.error(chalk_1.default.black.bgRed(`The provided resizeMode "${resizeMode}" is invalid. Please use one of [cover, contain]`));
process.exit(-1);
}
const items = await (0, _1.generateAsync)(type, { projectRoot: (0, path_1.resolve)(projectRoot || process.cwd()), publicPath: (0, path_1.resolve)(publicPath) }, { src, backgroundColor, resizeMode });
const outputPath = (0, path_1.resolve)(output);
await resolveOutputAsync(publicPath, outputPath, items);
}
async function resolveOutputAsync(publicPath, outputPath, items) {
var _a, _b, _c, _d, _e;
fs_1.default.mkdirSync(outputPath, { recursive: true });
const meta = [];
const manifest = {};
for (const item of items) {
if (item.tag) {
if ((_b = (_a = item.tag) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.href) {
item.tag.attributes.href = '/' + (0, path_1.relative)(publicPath, (_d = (_c = item.tag) === null || _c === void 0 ? void 0 : _c.attributes) === null || _d === void 0 ? void 0 : _d.href);
}
// Write HTML
meta.push((0, HTML_1.htmlTagObjectToString)(item.tag));
}
if (item.manifest) {
// Write Manifest
if (!Array.isArray(manifest.icons))
manifest.icons = [];
if ((_e = item.manifest) === null || _e === void 0 ? void 0 : _e.src) {
item.manifest.src = '/' + (0, path_1.relative)(publicPath, item.manifest.src);
}
manifest.icons.push(item.manifest);
}
// Write image
const assetPath = (0, path_1.resolve)(outputPath, item.asset.path);
fs_1.default.mkdirSync((0, path_1.dirname)(assetPath), { recursive: true });
fs_1.default.writeFileSync(assetPath, item.asset.source);
}
if (meta.length) {
logMeta(meta);
}
if (Object.keys(manifest).length) {
logManifest(manifest);
}
}
function logManifest(manifest) {
if (!Object.keys(manifest).length)
return;
console.log();
console.log(chalk_1.default.magenta('\u203A Copy the following lines into your PWA `manifest.json` to link the new assets.'));
console.log();
console.log(JSON.stringify(manifest, null, 2));
console.log();
}
function logMeta(meta) {
if (!meta.length)
return;
console.log();
console.log(chalk_1.default.magenta('\u203A Copy the following lines into your HTML <head/> to link the new assets.'));
console.log();
for (const metaLine of meta) {
console.log(metaLine);
}
console.log();
}
function isResizeMode(input) {
return input && ['contain', 'cover', 'fill', 'inside', 'outside'].includes(input);
}
async function commandDidThrowAsync(reason) {
console.log();
console.log('Aborting run');
if (reason.command) {
console.log(` ${chalk_1.default.magenta(reason.command)} has failed.`);
}
else {
console.log(chalk_1.default.black.bgRed `An unexpected error was encountered. Please report it as a bug:`);
console.log(reason);
}
console.log();
await (0, update_1.default)();
process.exit(1);
}
//# sourceMappingURL=cli.js.map