diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index 8329eabcbed..65cd8aea8da 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -13,5 +13,5 @@ "ul-style": { "style": "dash" }, }, "gitignore": true, - "ignores": ["**/THIRD-PARTY-LICENSES.md"], + "ignores": ["**/THIRD-PARTY-LICENSES.md", "node_modules"], } diff --git a/packages/calcite-ui-icons/bin/build-fonts.js b/packages/calcite-ui-icons/bin/build-fonts.js index 22c549049bd..074accb22a6 100755 --- a/packages/calcite-ui-icons/bin/build-fonts.js +++ b/packages/calcite-ui-icons/bin/build-fonts.js @@ -1,6 +1,16 @@ #!/usr/bin/env node import { execSync } from "node:child_process"; -import { readdirSync, mkdirSync, rmSync, existsSync, lstatSync, symlinkSync, unlinkSync, readFileSync, writeFileSync } from "fs"; +import { + readdirSync, + mkdirSync, + rmSync, + existsSync, + lstatSync, + symlinkSync, + unlinkSync, + readFileSync, + writeFileSync, +} from "fs"; import { join, basename } from "node:path"; import prettier from "@prettier/sync"; const SCRIPT_DIR = import.meta.dirname; @@ -10,49 +20,50 @@ const iconsDir = join(PACKAGE_ROOT, "icons"); const sizes = [16, 24, 32]; const ensureDir = (dir) => mkdirSync(dir, { recursive: true }); const clearAndPrepareDirs = () => { - if (existsSync(fontsDir)) { - rmSync(fontsDir, { recursive: true, force: true }); - } - sizes.forEach((size) => ensureDir(join(fontsDir, size.toString()))); + if (existsSync(fontsDir)) { + rmSync(fontsDir, { recursive: true, force: true }); + } + sizes.forEach((size) => ensureDir(join(fontsDir, size.toString()))); }; -const filterIcons = () => readdirSync(iconsDir).filter((file) => { +const filterIcons = () => + readdirSync(iconsDir).filter((file) => { const filePath = join(iconsDir, file); return file.endsWith(".svg") && !readFileSync(filePath, "utf8").includes("opacity"); -}); + }); const createLinks = (icons) => { - icons.forEach((icon) => { - const src = join(iconsDir, icon); - const dest = join(fontsDir, basename(icon)); - symlinkSync(src, dest); - }); + icons.forEach((icon) => { + const src = join(iconsDir, icon); + const dest = join(fontsDir, basename(icon)); + symlinkSync(src, dest); + }); }; const organizeIconsBySize = (size) => { - const sizeDir = join(fontsDir, size.toString()); - readdirSync(fontsDir).forEach((file) => { - if (file.includes(`-${size}`)) { - const src = join(fontsDir, file); - const dest = join(sizeDir, file.replace(`-${size}`, "")); - if (lstatSync(src).isSymbolicLink()) { - if (existsSync(dest)) - unlinkSync(dest); - symlinkSync(src, dest); - } - } - }); + const sizeDir = join(fontsDir, size.toString()); + readdirSync(fontsDir).forEach((file) => { + if (file.includes(`-${size}`)) { + const src = join(fontsDir, file); + const dest = join(sizeDir, file.replace(`-${size}`, "")); + if (lstatSync(src).isSymbolicLink()) { + if (existsSync(dest)) unlinkSync(dest); + symlinkSync(src, dest); + } + } + }); }; -const generateFonts = (size) => execSync(`fantasticon fonts/icons/${size}/ -n calcite-ui-icons-${size} --normalize true -t ttf -g json -o fonts/`, { +const generateFonts = (size) => + execSync(`fantasticon fonts/icons/${size}/ -n calcite-ui-icons-${size} --normalize true -t ttf -g json -o fonts/`, { stdio: "inherit", -}); + }); const updateConfig = () => { - const codepoints = JSON.parse(readFileSync(join(PACKAGE_ROOT, "fonts/calcite-ui-icons-16.json"), "utf8")); - const config = prettier.format(JSON.stringify({ codepoints }), { parser: "json" }); - writeFileSync(join(PACKAGE_ROOT, "fantasticonrc.json"), config); + const codepoints = JSON.parse(readFileSync(join(PACKAGE_ROOT, "fonts/calcite-ui-icons-16.json"), "utf8")); + const config = prettier.format(JSON.stringify({ codepoints }), { parser: "json" }); + writeFileSync(join(PACKAGE_ROOT, "fantasticonrc.json"), config); }; const main = () => { - clearAndPrepareDirs(); - createLinks(filterIcons()); - sizes.forEach(organizeIconsBySize); - sizes.forEach(generateFonts); - updateConfig(); + clearAndPrepareDirs(); + createLinks(filterIcons()); + sizes.forEach(organizeIconsBySize); + sizes.forEach(generateFonts); + updateConfig(); }; main(); diff --git a/packages/calcite-ui-icons/bin/convert-mobile.js b/packages/calcite-ui-icons/bin/convert-mobile.js index d14aaaa409f..c0ff7aa9c2d 100644 --- a/packages/calcite-ui-icons/bin/convert-mobile.js +++ b/packages/calcite-ui-icons/bin/convert-mobile.js @@ -3,31 +3,33 @@ import fsExtra from "fs-extra"; import svg2img from "svg2img"; import path from "node:path"; import yargs from "yargs"; -import { hideBin } from 'yargs/helpers'; +import { hideBin } from "yargs/helpers"; const { readdir, writeFile, readFile, mkdirSync, writeFileSync, existsSync } = fsExtra; const options = yargs(hideBin(process.argv)) - .usage("Usage: -n , \n-s , \n-o , \n-p ") - .option("n", { + .usage( + "Usage: -n , \n-s , \n-o , \n-p ", + ) + .option("n", { alias: "name", describe: "name of icon, without -32.svg; omit to convert all icons", type: "string", demandOption: false, -}) - .option("o", { + }) + .option("o", { alias: "outputDir", describe: "output path, relative to this script", type: "string", demandOption: false, -}) - .option("p", { + }) + .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; + }) + .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 @@ -38,26 +40,26 @@ const options = yargs(hideBin(process.argv)) * @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 (!existsSync(outputBasePath)) { - 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); - } - writeFileSync(real_output_path, buffer); + // make sure output base path exists + if (!existsSync(outputBasePath)) { + 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); + } + writeFileSync(real_output_path, buffer); + }); } /** * Creates an ImageSet (including Contents.json file) for an icon @@ -68,165 +70,155 @@ function convertSingleIconToPng(svgFilePath, width, height, outputBasePath, outp * @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(import.meta.dirname, "templates", "imageset.json"); - // create Contents.json for asset catalog asset - 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"); - writeFileSync(contentsJsonOutputPath, contentsJsonBuffer); - }); + 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(import.meta.dirname, "templates", "imageset.json"); + // create Contents.json for asset catalog asset + 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"); + 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 = {}; - 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); - }); + return new Promise((resolve) => { + const iconIndex = {}; + 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 + let base_name = path.basename(file); + base_name = base_name.replace(".svg", ""); + let 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 (!existsSync(directory)) { - mkdirSync(directory, { - recursive: true, - }); - } - // read contents.json template - let template_path = path.join(import.meta.dirname, "templates", "xcassets.json"); - // write out file - readFile(template_path, "utf8", function (error, buffer) { - if (error) { - console.log(error); - process.exit(1); - } - const contents_output_path = path.join(directory, "Contents.json"); - writeFile(contents_output_path, buffer, function (error) { - resolve(directory); - }); - }); + return new Promise((resolve) => { + // Put in .xcassets folder + const directory = path.join(xcAssetsBaseDirectory, "calcite.xcassets"); + // Make sure dir exists + if (!existsSync(directory)) { + mkdirSync(directory, { + recursive: true, + }); + } + // read contents.json template + const template_path = path.join(import.meta.dirname, "templates", "xcassets.json"); + // write out file + readFile(template_path, "utf8", function (error, buffer) { + if (error) { + console.log(error); + process.exit(1); + } + const contents_output_path = path.join(directory, "Contents.json"); + writeFile(contents_output_path, buffer, function () { + resolve(directory); + }); }); + }); } async function main() { - // index all calcite icons - let iconIndex = await indexCalciteIcons("./icons/"); - // establish output root path - var outputRoot = path.join(import.meta.dirname, "output"); - if (options.outputDir) { - outputRoot = path.join(import.meta.dirname, options.outputDir); - } - // establish input size - var inputSize = 24; - if (options.inSize === "16") { - inputSize = 16; + // index all calcite icons + const iconIndex = await indexCalciteIcons("./icons/"); + // establish output root path + let outputRoot = path.join(import.meta.dirname, "output"); + if (options.outputDir) { + outputRoot = path.join(import.meta.dirname, options.outputDir); + } + // establish input size + let 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) { + const size = parseInt(options.outSize); + if (size < 24) { + inputSize = 16; + } else if (size < 32) { + inputSize = 24; + } else if (size >= 32) { + inputSize = 32; } - else if (options.inSize === "24") { - inputSize = 24; + } + // establish output size (in pixels) + let outputSize = 24; + if (options.outSize) { + const size = parseInt(options.outSize); + if (size) { + outputSize = size; } - else if (options.inSize === "32") { - inputSize = 32; + } + // 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); } - 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 + } + // build xcassets if output for iOS + if (options.outputPlatform === "ios") { + const xcAssetsDirectory = await createCalciteXCAssets(outputRoot); if (options.name) { - if (!(options.name in iconIndex)) { - console.log("Invalid icon name " + options.name); - process.exit(1); - } + const name = options.name; + const file = iconIndex[name][inputSize]; + convertIconToXcodeImageSet(file, outputSize, outputSize, xcAssetsDirectory, name); + } else { + for (const key in iconIndex) { + const file = iconIndex[key][inputSize]; + convertIconToXcodeImageSet(file, outputSize, outputSize, xcAssetsDirectory, key); + } } - // 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); - } - } + } else { + // platform is not ios, render plain png + if (options.name) { + const name = options.name; + const file = iconIndex[name][inputSize]; + convertSingleIconToPng(file, outputSize, outputSize, outputRoot, name, undefined); + } else { + for (const key in iconIndex) { + const file = iconIndex[key][inputSize]; + convertSingleIconToPng(file, outputSize, outputSize, outputRoot, key, undefined); + } } + } } main(); diff --git a/packages/calcite-ui-icons/bin/optimize.js b/packages/calcite-ui-icons/bin/optimize.js index bb8c9053776..15a4fb6b481 100644 --- a/packages/calcite-ui-icons/bin/optimize.js +++ b/packages/calcite-ui-icons/bin/optimize.js @@ -4,23 +4,23 @@ import { optimize } from "svgo"; import progress from "cli-progress"; const { readFile, writeFile } = fsExtra; const options = { - plugins: [ - { - name: "preset-default", - overrides: { - cleanupIDs: { remove: false }, - removeUselessStrokeAndFill: false, - convertShapeToPath: { convertArcs: true }, - convertPathData: { noSpaceAfterFlags: false }, - mergePaths: false, - removeAttrs: { attrs: ["class", "(stroke)"] }, - }, + plugins: [ + { + name: "preset-default", + overrides: { + cleanupIDs: { remove: false }, + removeUselessStrokeAndFill: false, + convertShapeToPath: { convertArcs: true }, + convertPathData: { noSpaceAfterFlags: false }, + mergePaths: false, + removeAttrs: { attrs: ["class", "(stroke)"] }, }, - "removeStyleElement", - "removeTitle", - "removeDimensions", - ], - multipass: true, + }, + "removeStyleElement", + "removeTitle", + "removeDimensions", + ], + multipass: true, }; /** * Reads an icon file off disk and optimizes it, saving to same location @@ -29,27 +29,31 @@ const options = { * @return {Promise} */ function optimizeIcons(filePaths, bar) { - let num = 0; - return Promise.all(filePaths.map((path) => readFile(path, "utf-8") + let num = 0; + return Promise.all( + filePaths.map((path) => + readFile(path, "utf-8") .then((svg) => optimize(svg, { path, ...options })) .then((result) => { - num++; - bar.update(num); - return writeFile(path, result.data, "utf-8"); - }))); + num++; + bar.update(num); + return writeFile(path, result.data, "utf-8"); + }), + ), + ); } export default (function (files, remove = false) { - if (!files) { - return Promise.resolve(true); - } - options.plugins.find(({ name }) => name === "preset-default").overrides.cleanupIDs.remove = remove; - return glob(files).then((iconPaths) => { - const format = " \x1b[32m {bar} {percentage}% | {value}/{total} \x1b[0m"; - const bar = new progress.SingleBar({ format }, progress.Presets.shades_classic); - bar.start(iconPaths.length, 0); - return optimizeIcons(iconPaths, bar).then(() => { - bar.stop(); - console.log(""); - }); + if (!files) { + return Promise.resolve(true); + } + options.plugins.find(({ name }) => name === "preset-default").overrides.cleanupIDs.remove = remove; + return glob(files).then((iconPaths) => { + const format = " \x1b[32m {bar} {percentage}% | {value}/{total} \x1b[0m"; + const bar = new progress.SingleBar({ format }, progress.Presets.shades_classic); + bar.start(iconPaths.length, 0); + return optimizeIcons(iconPaths, bar).then(() => { + bar.stop(); + console.log(""); }); + }); }); diff --git a/packages/calcite-ui-icons/bin/path-data.js b/packages/calcite-ui-icons/bin/path-data.js index 40ef9394e12..42faf8ea558 100644 --- a/packages/calcite-ui-icons/bin/path-data.js +++ b/packages/calcite-ui-icons/bin/path-data.js @@ -12,15 +12,15 @@ const version = package$0.version; * @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), - }; + const file = path.basename(svg.file); + const 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 @@ -28,12 +28,12 @@ function formatSVG(svg) { * @return {array} - Array of paths */ function getPaths(svg) { - const bbPaths = ["M0 0h16v16H0z", "M0 0h24v24H0z", "M0 0h32v32H0z"]; - return svg.children - .filter((child) => child.name === "path" && bbPaths.indexOf(child.attributes.d) === -1) // filter out bounding box paths - .map((child) => ({ - opacity: child.attributes.opacity, - d: child.attributes.d, + const bbPaths = ["M0 0h16v16H0z", "M0 0h24v24H0z", "M0 0h32v32H0z"]; + return svg.children + .filter((child) => child.name === "path" && bbPaths.indexOf(child.attributes.d) === -1) // filter out bounding box paths + .map((child) => ({ + opacity: child.attributes.opacity, + d: child.attributes.d, })); } /** @@ -43,8 +43,8 @@ function getPaths(svg) { * @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" : ""); + const noF = name.replace("-f.svg", ".svg"); + return noF.substring(0, noF.length - 7) + (filled ? "-f" : ""); } /** * Find an icon's size @@ -52,8 +52,8 @@ function getVariant(name, filled) { * @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); + const 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 @@ -61,12 +61,14 @@ function getSize(name) { * @return {Promise} - Promise resolving to object which includes name and svgson data */ function readSVG(fileName) { - return new Promise((resolve, reject) => readFile(fileName, "utf-8").then((svg) => parse(svg).then((contents) => resolve({ file: fileName, contents })))); + return new Promise((resolve) => + readFile(fileName, "utf-8").then((svg) => parse(svg).then((contents) => resolve({ file: fileName, contents }))), + ); } export default (function generatePathFile() { - let banner = "// File generated automatically by path-data.js, do not edit directly\n"; - let jsFile = `${banner}`; - let tsFile = ` + const banner = "// File generated automatically by path-data.js, do not edit directly\n"; + let jsFile = `${banner}`; + let tsFile = ` ${banner} interface CalciteMultiPathEntry { d: string; @@ -74,53 +76,52 @@ interface CalciteMultiPathEntry { } 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 promises = []; - let keywords = JSON.parse(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`; - } - promises.push(writeFile(`js/${camelCaseName}.js`, contents, "utf8")); - promises.push(writeFile(`js/${camelCaseName}.d.ts`, tsContents, "utf8")); - promises.push(writeFile(`js/${camelCaseName}.json`, JSON.stringify(paths), "utf8")); - }); - promises.push(writeFile("docs/icons.json", JSON.stringify({ version, icons }), "utf8")); - promises.push(writeFile("index.d.ts", tsFile, "utf8")); - promises.push(writeFile("index.js", jsFile, "utf8")); - return Promise.all(promises); + return glob("icons/*.svg") + .then((filePaths) => Promise.all(filePaths.map(readSVG))) + .then((files) => files.map(formatSVG)) + .then((files) => { + const icons = {}; + const promises = []; + const keywords = JSON.parse(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: "" }; + const 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; + const 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`; + } + promises.push(writeFile(`js/${camelCaseName}.js`, contents, "utf8")); + promises.push(writeFile(`js/${camelCaseName}.d.ts`, tsContents, "utf8")); + promises.push(writeFile(`js/${camelCaseName}.json`, JSON.stringify(paths), "utf8")); + }); + promises.push(writeFile("docs/icons.json", JSON.stringify({ version, icons }), "utf8")); + promises.push(writeFile("index.d.ts", tsFile, "utf8")); + promises.push(writeFile("index.js", jsFile, "utf8")); + return Promise.all(promises); }); }); diff --git a/packages/calcite-ui-icons/bin/server.js b/packages/calcite-ui-icons/bin/server.js index 860ae9dee32..a6d3a81e0c5 100644 --- a/packages/calcite-ui-icons/bin/server.js +++ b/packages/calcite-ui-icons/bin/server.js @@ -7,33 +7,32 @@ import { execSync } from "node:child_process"; import { create } from "browser-sync"; const bs = { create }.create(); const options = { - awaitWriteFinish: true, - ignoreInitial: true, + awaitWriteFinish: true, + ignoreInitial: true, }; console.log("🗜 optimizing icons... \n"); build().then(() => { - bs.init({ - server: "./docs", - notify: false, - ui: false, - port: 8080, - }); - execSync("npm run build:fonts"); - bs.watch("./icons/*.svg", options, onChange); - bs.watch("./docs/keywords.json", options, onChange); - function onChange(event, file) { - if (event === "add") { - console.log("🗜 new icon detected, optimizing... \n"); - optimize(file, true).then(() => { }); - } - else { - update(); - } + bs.init({ + server: "./docs", + notify: false, + ui: false, + port: 8080, + }); + execSync("npm run build:fonts"); + bs.watch("./icons/*.svg", options, onChange); + bs.watch("./docs/keywords.json", options, onChange); + function onChange(event, file) { + if (event === "add") { + console.log("🗜 new icon detected, optimizing... \n"); + optimize(file, true).then(() => {}); + } else { + update(); } - const update = debounce(function () { - pathData().then(() => { - console.log("✨ path file updated"); - bs.reload(); - }); - }, 300); + } + const update = debounce(function () { + pathData().then(() => { + console.log("✨ path file updated"); + bs.reload(); + }); + }, 300); }); diff --git a/packages/calcite-ui-icons/docs/app.js b/packages/calcite-ui-icons/docs/app.js index b6d69d78863..92b17667413 100644 --- a/packages/calcite-ui-icons/docs/app.js +++ b/packages/calcite-ui-icons/docs/app.js @@ -1,117 +1,118 @@ (function () { - var icons = {}; - var $icons = []; - fetch("./icons.json") - .then(function (response) { - return response.json(); + let icons = {}; + const $icons = []; + fetch("./icons.json") + .then(function (response) { + return response.json(); }) - .then(function (payload) { - icons = payload.icons; - document.querySelector(".js-version").innerHTML = payload.version; - document.querySelector(".js-search").addEventListener("input", searchIcons); - calcite.bus.on("modal:close", removeHash); - startup(); + .then(function (payload) { + icons = payload.icons; + document.querySelector(".js-version").innerHTML = payload.version; + document.querySelector(".js-search").addEventListener("input", searchIcons); + calcite.bus.on("modal:close", removeHash); + startup(); }); - function startup() { - document.querySelector(".js-loader").classList.add("hide"); - var $iconContainer = document.querySelector(".js-icons"); - Object.keys(icons) - .map(function (key) { - return { name: key, icon: icons[key] }; - }) - .forEach(function (detail) { - var $btn = document.createElement("button"); - $btn.classList = - "js-modal-toggle block padding-leader-2 padding-trailer-2 trailer-1 js-icon-select icon-select btn btn-transparent"; - $btn.setAttribute("data-icon", detail.name); - $btn.setAttribute("data-modal", "iconDetail"); - $btn.setAttribute("aria-label", "View details of icon: " + detail.name); - $btn.appendChild(getSVG(detail.icon["32"], 32)); - var $name = document.createElement("span"); - $name.innerHTML = detail.name; - $name.classList.add("icon-select--name"); - $btn.appendChild($name); - $iconContainer.appendChild($btn); - $btn.addEventListener("click", showDetail); - $icons.push($btn); - }); - calcite.init(); - if (window.location.hash.length > 1) { - var active = window.location.hash.substring(1); - if (icons[active]) { - $iconContainer.querySelector('.js-icon-select[data-icon="' + active + '"]').click(); - } - } - } - function searchIcons(e) { - $icons.forEach(function ($btn) { - var name = $btn.getAttribute("data-icon"); - var icon = icons[name]; - var iconText = name + icon.alias.join(""); - var terms = e.target.value.toLowerCase().split(" "); - var matches = terms.reduce((acc, term) => acc && iconText.toLowerCase().includes(term), true); - if (matches) { - $btn.classList.remove("hide"); - } - else { - $btn.classList.add("hide"); - } - }); + function startup() { + document.querySelector(".js-loader").classList.add("hide"); + const $iconContainer = document.querySelector(".js-icons"); + Object.keys(icons) + .map(function (key) { + return { name: key, icon: icons[key] }; + }) + .forEach(function (detail) { + const $btn = document.createElement("button"); + $btn.classList = + "js-modal-toggle block padding-leader-2 padding-trailer-2 trailer-1 js-icon-select icon-select btn btn-transparent"; + $btn.setAttribute("data-icon", detail.name); + $btn.setAttribute("data-modal", "iconDetail"); + $btn.setAttribute("aria-label", "View details of icon: " + detail.name); + $btn.appendChild(getSVG(detail.icon["32"], 32)); + const $name = document.createElement("span"); + $name.innerHTML = detail.name; + $name.classList.add("icon-select--name"); + $btn.appendChild($name); + $iconContainer.appendChild($btn); + $btn.addEventListener("click", showDetail); + $icons.push($btn); + }); + calcite.init(); + if (window.location.hash.length > 1) { + const active = window.location.hash.substring(1); + if (icons[active]) { + $iconContainer.querySelector('.js-icon-select[data-icon="' + active + '"]').click(); + } } - function showDetail(e) { - var key = e.target.getAttribute("data-icon"); - var icon = icons[key]; - var filled = key.substring(key.length - 2); - var isFilled = filled === "-f"; - var baseName = isFilled ? key.substring(0, key.length - 2) : key; - var baseURL = "https://raw.githubusercontent.com/Esri/calcite-design-system/main/packages/calcite-ui-icons/icons/" + encodeURIComponent(baseName) + "-"; - var suffix = ".svg"; - var tags = icon.alias - .map(function (alias) { - const span = document.createElement("span"); - span.classList.add("label", "inline-block", "margin-right-quarter", "trailer-quarter"); - span.textContent = alias; - return span.outerHTML; - }) - .join(""); - window.location.hash = encodeURIComponent(key); - document.querySelector(".js-detail-name").textContent = key; - document.querySelector(".js-detail-aliases").innerHTML = (tags && tags) || "---"; - document.querySelector(".js-detail-category").textContent = (icon.category && icon.category) || "---"; - document.querySelector(".js-detail-release").textContent = (icon.release && icon.release) || "---"; - [16, 24, 32].forEach(function (size) { - document.querySelector(".js-link-" + size).href = - baseURL + size + (isFilled ? encodeURIComponent(filled) : "") + suffix; - var iconDetail = document.querySelector(".js-detail-" + size); - iconDetail.innerHTML = ""; - iconDetail.appendChild(getSVG(icon[size], size)); - }); - } - function getSVG(paths, size) { - var $svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - $svg.setAttribute("width", size); - $svg.setAttribute("height", size); - if (typeof paths === "string") { - paths = [paths]; - } - paths.forEach(function (path) { - var $path = document.createElementNS("http://www.w3.org/2000/svg", "path"); - if (typeof path === "string") { - $path.setAttribute("d", path); - } - else { - $path.setAttribute("d", path.d); - if (path.opacity) { - $path.setAttribute("opacity", path.opacity); - } - } - $svg.appendChild($path); - }); - return $svg; + } + function searchIcons(e) { + $icons.forEach(function ($btn) { + const name = $btn.getAttribute("data-icon"); + const icon = icons[name]; + const iconText = name + icon.alias.join(""); + const terms = e.target.value.toLowerCase().split(" "); + const matches = terms.reduce((acc, term) => acc && iconText.toLowerCase().includes(term), true); + if (matches) { + $btn.classList.remove("hide"); + } else { + $btn.classList.add("hide"); + } + }); + } + function showDetail(e) { + const key = e.target.getAttribute("data-icon"); + const icon = icons[key]; + const filled = key.substring(key.length - 2); + const isFilled = filled === "-f"; + const baseName = isFilled ? key.substring(0, key.length - 2) : key; + const baseURL = + "https://raw.githubusercontent.com/Esri/calcite-design-system/main/packages/calcite-ui-icons/icons/" + + encodeURIComponent(baseName) + + "-"; + const suffix = ".svg"; + const tags = icon.alias + .map(function (alias) { + const span = document.createElement("span"); + span.classList.add("label", "inline-block", "margin-right-quarter", "trailer-quarter"); + span.textContent = alias; + return span.outerHTML; + }) + .join(""); + window.location.hash = encodeURIComponent(key); + document.querySelector(".js-detail-name").textContent = key; + document.querySelector(".js-detail-aliases").innerHTML = (tags && tags) || "---"; + document.querySelector(".js-detail-category").textContent = (icon.category && icon.category) || "---"; + document.querySelector(".js-detail-release").textContent = (icon.release && icon.release) || "---"; + [16, 24, 32].forEach(function (size) { + document.querySelector(".js-link-" + size).href = + baseURL + size + (isFilled ? encodeURIComponent(filled) : "") + suffix; + const iconDetail = document.querySelector(".js-detail-" + size); + iconDetail.innerHTML = ""; + iconDetail.appendChild(getSVG(icon[size], size)); + }); + } + function getSVG(paths, size) { + const $svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + $svg.setAttribute("width", size); + $svg.setAttribute("height", size); + if (typeof paths === "string") { + paths = [paths]; } - function removeHash(fromOpen) { - if (!fromOpen) { - window.location.hash = "?"; + paths.forEach(function (path) { + const $path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + if (typeof path === "string") { + $path.setAttribute("d", path); + } else { + $path.setAttribute("d", path.d); + if (path.opacity) { + $path.setAttribute("opacity", path.opacity); } + } + $svg.appendChild($path); + }); + return $svg; + } + function removeHash(fromOpen) { + if (!fromOpen) { + window.location.hash = "?"; } + } })(); diff --git a/packages/calcite-ui-icons/eslint.config.mjs b/packages/calcite-ui-icons/eslint.config.mjs index c59c1c921ad..4cf264255e0 100644 --- a/packages/calcite-ui-icons/eslint.config.mjs +++ b/packages/calcite-ui-icons/eslint.config.mjs @@ -1,19 +1,15 @@ -import calciteCoreConfig from "@esri/eslint-config-calcite/core.js"; +// @ts-check import tseslint from "typescript-eslint"; +import eslint from "@eslint/js"; -export default tseslint.config( - { - ignores: ["**/js"], - }, - - { - extends: [calciteCoreConfig], - - languageOptions: { - parserOptions: { - tsconfigRootDir: import.meta.dirname, - project: ["tsconfig-eslint.json"], - }, +export default tseslint.config({ + ignores: ["**/js", "docs/resources/*"], + files: ["**/*.js"], + extends: [eslint.configs.recommended, tseslint.configs.recommended], + languageOptions: { + parserOptions: { + tsconfigRootDir: import.meta.dirname, + project: ["tsconfig-eslint.json"], }, }, -); +}); diff --git a/packages/calcite-ui-icons/lib/spriter/cli.js b/packages/calcite-ui-icons/lib/spriter/cli.js index f3450c3abe1..9bcc4999530 100755 --- a/packages/calcite-ui-icons/lib/spriter/cli.js +++ b/packages/calcite-ui-icons/lib/spriter/cli.js @@ -1,41 +1,40 @@ +"use strict"; import spriter from "./index.js"; import { readFileSync } from "node:fs"; -"use strict"; const args = process.argv.slice(2); // skip runtime & script args function hasArg(name, shorthand) { - return getArgIndex(name, shorthand) > -1; + return getArgIndex(name, shorthand) > -1; } function getArgIndex(name, shorthand) { - return args.findIndex((arg, index) => arg === `--${name}` || arg === `-${shorthand}`); + return args.findIndex((arg) => arg === `--${name}` || arg === `-${shorthand}`); } function getArg(name, shorthand) { - return args[getArgIndex(name, shorthand) + 1]; + return args[getArgIndex(name, shorthand) + 1]; } if (hasArg("help", "h")) { - process.stdout.write(` + process.stdout.write(` --input, -i path to configuration file --output, -o output location for generated SVG sprite --help, -h display this help message `); - process.exit(0); + process.exit(0); } function getConfig() { - let input = getArg("input", "i"); - if (input) { - try { - const configFileContents = readFileSync(input); - input = JSON.parse(configFileContents).input; - } - catch (error) { - process.stderr.write(`config - could not read input: ${error}`); - process.exit(1); - } + let input = getArg("input", "i"); + if (input) { + try { + const configFileContents = readFileSync(input); + input = JSON.parse(configFileContents).input; + } catch (error) { + process.stderr.write(`config - could not read input: ${error}`); + process.exit(1); } - const output = getArg("output", "o"); - return { input, output }; + } + const output = getArg("output", "o"); + return { input, output }; } spriter(getConfig()) - .then((summary) => { + .then((summary) => { const { ellapsed, spritesheets } = summary; process.stdout.write(`Success! @@ -45,8 +44,8 @@ ${spritesheets.map((spritesheet) => `* ${spritesheet.output} (${spritesheet.icon `); process.exit(0); -}) - .catch((err) => { + }) + .catch((err) => { process.stderr.write(`Fail! ${err}`); process.exit(1); -}); + }); diff --git a/packages/calcite-ui-icons/lib/spriter/index.js b/packages/calcite-ui-icons/lib/spriter/index.js index b864c9efe01..fd8594c831f 100644 --- a/packages/calcite-ui-icons/lib/spriter/index.js +++ b/packages/calcite-ui-icons/lib/spriter/index.js @@ -1,13 +1,12 @@ +"use strict"; import fsExtra from "fs-extra"; import path from "node:path"; -"use strict"; -const { readdir, mkdir, writeFile, readFile, lstatSync } = fsExtra; +const { readdir, mkdir, writeFile, readFile } = fsExtra; const ICONS = path.resolve(path.dirname(process.argv[1]), "../icons"); const NAME = "generated"; const SIZES = [16, 24, 32]; const OUTLINE = "outline"; const FILL = "fill"; -const isDir = (file) => lstatSync(`${ICONS}/${file}`).isDirectory(); const readSVG = (icon) => readFile(`${ICONS}/${icon.fileName}`, { encoding: "utf-8" }); const has = (haystack, needle) => haystack.indexOf(needle) > -1; /** @@ -79,12 +78,12 @@ const has = (haystack, needle) => haystack.indexOf(needle) > -1; * @return {ThenPromise} - Promise that resolves when directory creation is ensured. */ function ensureDir(dir) { - return mkdir(dir).catch((error) => { - const triedToCreateExisting = error.code === "EEXIST"; - if (!triedToCreateExisting) { - throw error; - } - }); + return mkdir(dir).catch((error) => { + const triedToCreateExisting = error.code === "EEXIST"; + if (!triedToCreateExisting) { + throw error; + } + }); } /** * Builds map of requested icons. @@ -94,19 +93,19 @@ function ensureDir(dir) { * @return {ExportInfo} - Key-value pair where keys correspond to icon size and values are @link{IconRequest[] requested icons}. */ function getRequestedIcons(input) { - const iconsPerSize = {}; - SIZES.forEach((size) => (iconsPerSize[size] = [])); - input.forEach((icon) => { - const { name, sizes = SIZES[0], style = OUTLINE } = icon; - sizes - .filter((size) => has(SIZES, size)) - .forEach((size) => { - const fillPart = style === FILL ? "-f" : ""; - const fileName = `${name}-${size}${fillPart}.svg`; - iconsPerSize[size].push({ name, size, style, fileName }); - }); - }); - return iconsPerSize; + const iconsPerSize = {}; + SIZES.forEach((size) => (iconsPerSize[size] = [])); + input.forEach((icon) => { + const { name, sizes = SIZES[0], style = OUTLINE } = icon; + sizes + .filter((size) => has(SIZES, size)) + .forEach((size) => { + const fillPart = style === FILL ? "-f" : ""; + const fileName = `${name}-${size}${fillPart}.svg`; + iconsPerSize[size].push({ name, size, style, fileName }); + }); + }); + return iconsPerSize; } /** * Creates spritesheet export details. @@ -116,51 +115,51 @@ function getRequestedIcons(input) { * @return {ThenPromise} - Promise that resolves with export info. */ function generateExportInfo(requested) { - const processRequested = (icons) => { - SIZES.forEach((size) => { - requested[size].forEach((icon) => { - if (!has(icons, icon.fileName)) { - return; - } - exportInfo[size].push({ - name: icon.name, - style: icon.style, - size, - fileName: icon.fileName, - }); - }); - }); - }; - const processAll = (icons) => { - icons.forEach((icon) => { - SIZES.forEach((size) => { - const fileMatchesSize = icon.indexOf(`-${size}`) > -1; - if (!fileMatchesSize) { - return; - } - const parserPattern = /(.+)-\d\d(-f)?\.svg/; - const [, name, filled] = parserPattern.exec(icon); - exportInfo[size].push({ - name, - style: filled ? FILL : OUTLINE, - size, - fileName: icon, - }); - }); + const processRequested = (icons) => { + SIZES.forEach((size) => { + requested[size].forEach((icon) => { + if (!has(icons, icon.fileName)) { + return; + } + exportInfo[size].push({ + name: icon.name, + style: icon.style, + size, + fileName: icon.fileName, }); - }; - const includeAll = SIZES.every((size) => requested[size].length === 0); - const exportInfo = {}; - SIZES.forEach((size) => (exportInfo[size] = [])); - return readdir(ICONS) - .then((icons) => { - if (includeAll) { - processAll(icons); - return; + }); + }); + }; + const processAll = (icons) => { + icons.forEach((icon) => { + SIZES.forEach((size) => { + const fileMatchesSize = icon.indexOf(`-${size}`) > -1; + if (!fileMatchesSize) { + return; } - processRequested(icons); + const parserPattern = /(.+)-\d\d(-f)?\.svg/; + const [, name, filled] = parserPattern.exec(icon); + exportInfo[size].push({ + name, + style: filled ? FILL : OUTLINE, + size, + fileName: icon, + }); + }); + }); + }; + const includeAll = SIZES.every((size) => requested[size].length === 0); + const exportInfo = {}; + SIZES.forEach((size) => (exportInfo[size] = [])); + return readdir(ICONS) + .then((icons) => { + if (includeAll) { + processAll(icons); + return; + } + processRequested(icons); }) - .then(() => exportInfo); + .then(() => exportInfo); } /** * Converts an SVG into a Symbol element. @@ -170,12 +169,12 @@ function generateExportInfo(requested) { * @return {ThenPromise} - Promise that resolves with symbol element text content. */ function svgToSymbol(icon) { - return readSVG(icon).then((svgContent) => { - const svgContentCapturingPattern = /^\s*\]*>(.+)\<\/svg>\s*$/; - const [, innerContent] = svgContentCapturingPattern.exec(svgContent); - const { size } = icon; - return `${innerContent}`; - }); + return readSVG(icon).then((svgContent) => { + const svgContentCapturingPattern = /^\s*]*>(.+)<\/svg>\s*$/; + const [, innerContent] = svgContentCapturingPattern.exec(svgContent); + const { size } = icon; + return `${innerContent}`; + }); } /** * Creates spritesheet content. @@ -188,9 +187,9 @@ function svgToSymbol(icon) { * @return {ThenPromise} - Promise that resolves when spritesheet is created */ function createSpritesheet({ icons, output, size }) { - return Promise.all(icons.map(svgToSymbol)) - .then((symbols) => `${symbols.join("")}`) - .then((content) => writeFile(`${output}/${`${NAME}-${size}.svg`}`, content)); + return Promise.all(icons.map(svgToSymbol)) + .then((symbols) => `${symbols.join("")}`) + .then((content) => writeFile(`${output}/${`${NAME}-${size}.svg`}`, content)); } /** * Creates icon spritesheet from config. @@ -200,28 +199,32 @@ function createSpritesheet({ icons, output, size }) { * @return {ThenPromise} - Promise that resolves with export summary. */ function spriter(config) { - const startTime = process.hrtime(); - const { input = [], output = "./output" } = config; - return ensureDir(output) - .then(() => generateExportInfo(getRequestedIcons(input))) - .then((exportInfo) => Promise.all(SIZES.map((size) => { - const icons = exportInfo[size]; - if (icons.length === 0) { + const startTime = process.hrtime(); + const { input = [], output = "./output" } = config; + return ensureDir(output) + .then(() => generateExportInfo(getRequestedIcons(input))) + .then((exportInfo) => + Promise.all( + SIZES.map((size) => { + const icons = exportInfo[size]; + if (icons.length === 0) { return; - } - return createSpritesheet({ icons, output, size }); - })).then(() => exportInfo)) - .then((exportInfo) => { - const endTime = process.hrtime(startTime); - const nanoToMillis = 1000000; - const ellapsed = endTime[1] / nanoToMillis; - const spritesheets = Object.keys(exportInfo).map((size) => { - return { - output: `${output}/${NAME}-${size}.svg`, - icons: exportInfo[size], - }; - }); - return { ellapsed, spritesheets }; + } + return createSpritesheet({ icons, output, size }); + }), + ).then(() => exportInfo), + ) + .then((exportInfo) => { + const endTime = process.hrtime(startTime); + const nanoToMillis = 1000000; + const ellapsed = endTime[1] / nanoToMillis; + const spritesheets = Object.keys(exportInfo).map((size) => { + return { + output: `${output}/${NAME}-${size}.svg`, + icons: exportInfo[size], + }; + }); + return { ellapsed, spritesheets }; }); } export default spriter; diff --git a/packages/calcite-ui-icons/lint-staged.config.mjs b/packages/calcite-ui-icons/lint-staged.config.mjs new file mode 100644 index 00000000000..e41556a0ff1 --- /dev/null +++ b/packages/calcite-ui-icons/lint-staged.config.mjs @@ -0,0 +1,10 @@ +import baseConfig from "../../lint-staged.config.mjs"; + +/** + * @filename: lint-staged.config.mjs + * @type {import('lint-staged').Configuration} + */ +export default { + ...baseConfig, + "*.{m,c,}js": ["eslint --fix", "prettier --write"], +}; diff --git a/packages/calcite-ui-icons/tsconfig-base.json b/packages/calcite-ui-icons/tsconfig-base.json new file mode 100644 index 00000000000..d0fe2115def --- /dev/null +++ b/packages/calcite-ui-icons/tsconfig-base.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowUnreachableCode": false, + "declaration": true, + "esModuleInterop": true, + "lib": ["dom", "dom.iterable", "ES2023"], + "module": "esnext", + "moduleResolution": "nodenext", + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "target": "ES2022" + }, + "exclude": ["node_modules", "js"] +} diff --git a/packages/calcite-ui-icons/tsconfig-eslint.json b/packages/calcite-ui-icons/tsconfig-eslint.json new file mode 100644 index 00000000000..2c207635801 --- /dev/null +++ b/packages/calcite-ui-icons/tsconfig-eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig-base.json", + "include": ["**/*.*"] +}