UNPKG

@esri/calcite-ui-icons

Version:

A collection of UI SVG icons created by Esri for applications.

219 lines (208 loc) 7.88 kB
#!/usr/bin/env node const fs = require('fs'); const svg2img = require('svg2img'); const path = require('path'); const yargs = require('yargs'); const options = yargs .usage('Usage: -n <name of icon, omit if doing bulk>, \n-s <output size, defaults to 24>, \n-o <output path (defaults to ./output)>, \n-p <target platform (e.g. ios) \n-i <16, 24, 32, omit for 16>') .option('n', { alias: 'name', describe: 'name of icon, without -32.svg; omit to convert all icons', type: 'string', demandOption: false }) .option('o', { alias: 'outputDir', describe: 'output path, relative to this script', type: 'string', demandOption: false }) .option('p', { alias: 'outputPlatform', describe: 'target platform, valid options are: ios', type: 'string', demandOption: false }) .option('i', { alias: 'inSize', describe: 'source svg variant, defaults to 16', type: 'string', demandOption: false }) .option('s', { alias: 'outSize', describe: 'size of output image', type: 'string', demandOption: false}) .argv; /** * Converts a single svg to png, with given width & height values. The function will automatically append '.png' * @param {string} svgFilePath - filepath to icon .svg * @param {int} width - width of output file * @param {int} height - height of output file * @param {string} outputBasePath - base directory in which to store output * @param {string} outputName - name of output png image, excluding '.png' * @param {string} outputSuffix - suffix appended to output file name (ex, '@2x') */ function convertSingleIconToPng(svgFilePath, width, height, outputBasePath, outputName, outputSuffix=null) { // make sure output base path exists if (!fs.existsSync(outputBasePath)) { fs.mkdirSync(outputBasePath, { recursive: true }); } // concatenate real output path let real_output_path = path.join(outputBasePath, outputName); if (outputSuffix) { real_output_path += outputSuffix } real_output_path += '.png' // convert and save the image svg2img(svgFilePath, { 'width': width, 'height': height }, function (error, buffer) { if (error){ console.log(error); process.exit(1); } fs.writeFileSync(real_output_path, buffer); }); } /** * Creates an ImageSet (including Contents.json file) for an icon * @param {string} svgFilePath - filepath to icon .svg * @param {int} width - width of output file @1x * @param {int} height - height of output file @1x * @param {string} outputBasePath - base directory in which to store output * @param {string} outputName - name of output png image, excluding '.png' */ function convertIconToXcodeImageSet(svgFilePath, width, height, outputBasePath, outputName) { const outputImagesetPath = path.join(outputBasePath, outputName + '.imageset'); // Create images at 3 sizes convertSingleIconToPng(svgFilePath, width, height, outputImagesetPath, outputName, '@1x'); convertSingleIconToPng(svgFilePath, width * 2, height * 2, outputImagesetPath, outputName, '@2x'); convertSingleIconToPng(svgFilePath, width * 3, height * 3, outputImagesetPath, outputName, '@3x'); // read template const imagesetTemplatePath = path.join(__dirname, 'templates', 'imageset.json'); // create Contents.json for asset catalog asset fs.readFile(imagesetTemplatePath, 'utf8', function (error, buffer) { if (error) { console.log(error); process.exit(1); } const contentsJsonBuffer = buffer.replace(/\$\{NAME\}/g, outputName); const contentsJsonOutputPath = path.join(outputImagesetPath, 'Contents.json'); fs.writeFileSync(contentsJsonOutputPath, contentsJsonBuffer) }); } /** * Indexes all calcite icons contained in directory at path * @param {string} baseIconPath - path to calcite .svg icons directory */ async function indexCalciteIcons(baseIconPath) { return new Promise(resolve => { var iconIndex = {}; fs.readdir(baseIconPath, function (error, files) { if (error) { console.log(error); process.exit(1); } files.forEach(function (file) { // strip all files of file size information, catalog in an index var base_name = path.basename(file); base_name = base_name.replace('.svg', ''); var size = undefined; if (base_name.includes('-16')) { base_name = base_name.replace('-16', ''); size = 16; } else if (base_name.includes('-24')) { base_name = base_name.replace('-24', ''); size = 24; } else if (base_name.includes('-32')) { base_name = base_name.replace('-32', ''); size = 32; } if (!iconIndex[base_name]) { iconIndex[base_name] = {} } iconIndex[base_name][size] = path.join(baseIconPath, file); }); resolve(iconIndex); }); }); } /** * Indexes all calcite icons contained in directory at path * @param {string} xcAssetsBaseDirectory - path where to derive calcite.xcassets */ async function createCalciteXCAssets(xcAssetsBaseDirectory) { return new Promise(resolve => { // Put in .xcassets folder var directory = path.join(xcAssetsBaseDirectory, 'calcite.xcassets'); // Make sure dir exists if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); } // read contents.json template let template_path = path.join(__dirname, 'templates', 'xcassets.json'); // write out file fs.readFile(template_path, 'utf8', function (error, buffer) { if (error) { console.log(error); process.exit(1); } const contents_output_path = path.join(directory, 'Contents.json'); fs.writeFile(contents_output_path, buffer, function (error) { resolve(directory); }); }); }); } async function main() { // index all calcite icons let iconIndex = await indexCalciteIcons('./icons/'); // establish output root path var outputRoot = path.join(__dirname, 'output') if (options.outputDir) { outputRoot = path.join(__dirname, options.outputDir); } // establish input size var inputSize = 24; if (options.inSize === '16'){ inputSize = 16; } else if (options.inSize === '24'){ inputSize = 24; } else if (options.inSize === '32'){ inputSize = 32; } else if (options.outSize) { let size = parseInt(options.outSize); if (size < 24) { inputSize = 16; } else if (size < 32) { inputSize = 24; } else if (size >= 32) { inputSize = 32; } } // establish output size (in pixels) var outputSize = 24; if (options.outSize) { let size = parseInt(options.outSize); if (size) { outputSize = size; } } // ensure icon name is valid, checking index if (options.name) { if (!(options.name in iconIndex)) { console.log("Invalid icon name " + options.name); process.exit(1); } } // build xcassets if output for iOS if (options.outputPlatform === 'ios') { let xcAssetsDirectory = await createCalciteXCAssets(outputRoot); if (options.name) { let name = options.name; let file = iconIndex[name][inputSize]; convertIconToXcodeImageSet(file, outputSize, outputSize, xcAssetsDirectory, name); } else { for (let key in iconIndex) { let file = iconIndex[key][inputSize]; convertIconToXcodeImageSet(file, outputSize, outputSize, xcAssetsDirectory, key) } } } else { // platform is not ios, render plain png if (options.name) { let name = options.name; let file = iconIndex[name][inputSize]; convertSingleIconToPng(file, outputSize, outputSize, outputRoot, name, undefined); } else { for (let key in iconIndex) { let file = iconIndex[key][inputSize]; convertSingleIconToPng(file, outputSize, outputSize, outputRoot, key, undefined); } } } } main();