@esri/calcite-ui-icons
Version:
A collection of UI SVG icons created by Esri for applications.
137 lines (128 loc) • 5.03 kB
JavaScript
const camelCase = require('camelcase');
const fs = require('fs-extra');
const glob = require('glob-promise');
const path = require('path');
const util = require('util');
const svgson = util.promisify(require('svgson'));
const version = require('../package.json').version;
/**
* Gets all important information about an icon.
* @param {string} svg - Path to icon file.
* @return {object} - Formatted object with all icon metadata
*/
function formatSVG (svg) {
let file = path.basename(svg.file);
let filled = file.indexOf('-f.svg') > -1;
return {
file,
filled,
paths: getPaths(svg.contents),
size: getSize(file),
variant: getVariant(file, filled)
};
}
/**
* Find the path(s) from an icon's svgson data
* @param {object} svg - Object as returned from svgson.
* @return {array} - Array of paths
*/
function getPaths (svg) {
const bbPaths = ['M0 0h16v16H0z', 'M0 0h24v24H0z', 'M0 0h32v32H0z'];
return svg.childs
.filter(child => child.name === 'path' && bbPaths.indexOf(child.attrs.d) === -1) // filter out bounding box paths
.map(child => ({ opacity: child.attrs.opacity, d: child.attrs.d }));
}
/**
* Find the base icon name
* @param {string} name - Icon filename
* @param {boolean} filled - Icon filename
* @return {array} - Icon filename without size, fill, or file extension
*/
function getVariant (name, filled) {
var noF = name.replace('-f.svg', '.svg');
return noF.substring(0, noF.length - 7) + (filled ? "-f" : "");
}
/**
* Find an icon's size
* @param {string} name - Icon filename
* @return {integer} - 16, 24, 36
*/
function getSize(name) {
var noF = name.replace('-f.svg', '.svg');
return parseInt(noF.substring(noF.length - 4, noF.length - 6), 10);
}
/**
* Read an icon from disc and get data as json
* @param {string} fileName - Icon filename (full path)
* @return {Promise} - Promise resolving to object which includes name and svgson data
*/
function readSVG (fileName) {
return new Promise(function(resolve, reject) {
fs.readFile(fileName, 'utf-8').then(function (svg) {
svgson(svg, {}, function (contents) {
resolve({file: fileName, contents});
});
});
});
}
module.exports = function generatePathFile () {
let banner = '// File generated automatically by path-data.js, do not edit directly\n';
let jsFile = `${banner}`;
let tsFile = `
${banner}
interface CalciteMultiPathEntry {
d: string;
opacity?: string;
}
export type CalciteIconPath = string | CalciteMultiPathEntry[];
`;
return glob('icons/*.svg')
.then(filePaths => Promise.all(filePaths.map(readSVG)))
.then(files => files.map(formatSVG))
.then(files => {
let icons = {};
let keywords = JSON.parse(fs.readFileSync('docs/keywords.json', 'utf-8'));
files.forEach(file => {
// add to json file
icons[file.variant] = icons[file.variant] || keywords[file.variant] || { alias: [], category: "", release: "" };
var icon = icons[file.variant];
const firstPath = file.paths[0] || { d: "" }; // back up for "blank" icon
const paths = file.paths.length > 1 ? file.paths : firstPath.d;
icon[file.size] = paths;
var base = file.variant.substring(0, file.variant.length - 2);
// make sure filled variants get the keywords from their standard counterpart
if (file.filled && !icon.release) {
const variantKeywords = keywords[base];
if (variantKeywords) {
icon.alias = variantKeywords.alias;
icon.category = variantKeywords.category;
icon.release = variantKeywords.release;
}
}
// add to ts and js files
const variant = file.variant.match(/^\d/) ? `i${file.variant}`: file.variant;
const camelCaseName = camelCase(`${file.filled ? base: variant }-${file.size}${ file.filled ? "-f" : ""}`);
jsFile += `export {${camelCaseName}} from "./js/${camelCaseName}.js";\n`;
let contents, tsContents;
if (typeof paths === "string") {
tsFile += `export const ${camelCaseName}: string;\n`;
contents = `export const ${camelCaseName} = "${paths}";\n`;
tsContents = `export const ${camelCaseName}: string;\n`;
} else {
icon.multiPath = true;
tsFile += `export const ${camelCaseName}: CalciteMultiPathEntry[];\n`;
contents = `export const ${camelCaseName} = ${JSON.stringify(paths)};\n`;
tsContents = `export const ${camelCaseName}: CalciteMultiPathEntry[];\n`;
}
fs.writeFile(`js/${camelCaseName}.js`, contents, 'utf8');
fs.writeFile(`js/${camelCaseName}.d.ts`, tsContents, 'utf8');
fs.writeFile(`js/${camelCaseName}.json`, JSON.stringify(paths), 'utf8');
});
let promises = [
fs.writeFile('docs/icons.json', JSON.stringify({ version, icons }), 'utf8'),
fs.writeFile('index.d.ts', tsFile, 'utf8'),
fs.writeFile('index.js', jsFile, 'utf8')
];
return Promise.all(promises);
});
};