@svgd/cli
Version:
Command-line utility for generating constants from SVG assets
271 lines (262 loc) • 9.7 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
generateSvgConstants: () => generateSvgConstants,
parseCliArgs: () => parseCliArgs,
runCLI: () => runCLI
});
module.exports = __toCommonJS(index_exports);
var import_fs2 = __toESM(require("fs"), 1);
var import_path2 = __toESM(require("path"), 1);
// src/generate.ts
var import_path = __toESM(require("path"), 1);
var import_utils = require("@svgd/utils");
var import_fs = require("fs");
// src/templates.ts
var jsRowTemplate = ({ name, d, quote }) => `export const ${name} = ${quote}${d}${quote};
`;
var jsRowTemplateWithJSDoc = ({ name, d, image, quote, filePath, ts }) => `/**
* @filepath ${filePath}
* @return ${image}
*/
export const ${name} = ${quote}${d}${quote}${ts ? ` as "${name}"` : ""};
`;
var dtsRowTemplate = ({ name, image, filePath }) => `/**
* @filepath ${filePath}
* @return ${image}
*/
export const ${name}: string;
`;
var mdRowTemplate = ({ name, filePath, relativePath }) => `|  | ${name} | ${filePath} |`;
var mdFileTemplate = (rows) => `# List of icons
| Source | Name | Path |
|---|---|---|
${rows}
`;
var htmlRowTemplate = ({ name, filePath, svg }) => `<tr><td>${svg}</td><td>${name}</td><td>${filePath}</td></tr>`;
var htmlFileTemplate = (rows) => `<!DOCTYPE html>
<html lang="">
<head>
<style>
table {
border-collapse: collapse;
}
th {
text-align: center;
border: 1px solid darkgray;
padding: 4px 8px;
}
td {
text-align: left;
border: 1px solid darkgray;
padding: 4px 8px;
}
</style>
</head>
<body>
<table>
<tr><th>Icon</th><th>Name</th><th>Path</th></tr>
${rows}
</table>
</body>
</html>
`;
// src/generate.ts
var defoultOptions = {
input: "src/assets/icons",
output: "src/components/Icon/paths.js",
quote: false,
template: "",
format: "camelCase",
colors: false,
size: 24
};
async function generateSvgConstants(options) {
const root = process.cwd();
const filledOptions = { ...defoultOptions, ...options };
const baseDir = import_path.default.resolve(root, filledOptions.input);
const svgoConfig = (0, import_utils.getSvgoConfig)({
...import_utils.defaultConfig,
colors: filledOptions.colors,
resize: {
targetViewBox: {
minX: 0,
minY: 0,
width: filledOptions.size ?? 24,
height: filledOptions.size ?? 24
}
}
});
const svgFiles = (0, import_utils.getSvgFileNames)(baseDir);
const singleQuote = filledOptions.quote;
const quote = singleQuote ? "'" : '"';
const outputs = /* @__PURE__ */ new Map();
let md;
if (filledOptions.md) {
md = {
rows: [],
fileTemplate: mdFileTemplate,
rowTemplate: mdRowTemplate,
path: import_path.default.resolve(root, filledOptions.md)
};
outputs.set(md.path, md);
}
let html;
if (filledOptions.html) {
html = {
rows: [],
fileTemplate: htmlFileTemplate,
rowTemplate: htmlRowTemplate,
path: import_path.default.resolve(root, filledOptions.html)
};
outputs.set(html.path, html);
}
await Promise.all(svgFiles.map(async (file, index) => {
try {
const getRelativePath = getRelativePathFactory(file);
const constantName = (0, import_utils.generateConstantName)(
file,
baseDir,
filledOptions.template,
filledOptions.format
);
const outputFileName = (0, import_utils.generateFileName)(file, baseDir, filledOptions.output);
const outputFilePath = import_path.default.resolve(root, outputFileName);
let constants = outputs.get(outputFilePath);
if (!constants) {
constants = {
rows: [],
path: outputFilePath,
rowTemplate: filledOptions.dts ? jsRowTemplate : jsRowTemplateWithJSDoc
};
outputs.set(outputFilePath, constants);
}
let dts;
if (filledOptions.dts) {
const dtsOutputFilePath = outputFilePath.replace(/\.js|\.ts$/, ".d.ts");
dts = outputs.get(dtsOutputFilePath);
if (!dts) {
dts = {
rows: [],
path: dtsOutputFilePath,
rowTemplate: dtsRowTemplate
};
outputs.set(dtsOutputFilePath, dts);
}
}
const d = (0, import_utils.parseSvg)((0, import_fs.readFileSync)(file, "utf8"), svgoConfig);
const svg = (0, import_utils.getSvg)(d);
const png = await (0, import_utils.getPng)(svg);
const templateProps = {
name: constantName,
d,
quote,
svg,
image: ``,
filePath: import_path.default.relative(baseDir, file).split("\\").join("/"),
ts: /\.ts$/.test(outputFilePath)
};
const orderedRowItem = (code) => ({
order: constantName,
code
});
constants.rows.push(orderedRowItem(constants.rowTemplate({
...templateProps,
relativePath: getRelativePath(outputFilePath)
})));
dts?.rows.push(orderedRowItem(dts.rowTemplate({
...templateProps,
relativePath: getRelativePath(dts.path)
})));
md?.rows.push(orderedRowItem(md.rowTemplate({
...templateProps,
relativePath: getRelativePath(md.path)
})));
html?.rows.push(orderedRowItem(html.rowTemplate({
...templateProps,
relativePath: getRelativePath(html.path)
})));
} catch (error) {
console.error(`Error processing svg file ${file}:`, error);
}
if ((index + 1) % 100 === 0) {
console.log(`Processed svg files: ${index + 1}/${svgFiles.length}`);
}
}));
return [...outputs.entries()].map(([outPath, rawData]) => {
const content = rawData.rows.sort(({ order: a }, { order: b }) => a.localeCompare(b)).map(({ code }) => code).join("\n");
return {
path: outPath,
content: rawData.fileTemplate ? rawData.fileTemplate(content) : content
};
});
}
var getRelativePathFactory = (file) => (absolutePath) => import_path.default.relative(import_path.default.dirname(absolutePath), file).split("\\").join("/");
// src/parseCliArgs.ts
var import_commander = require("commander");
function commanderParseInt(value) {
const parsedValue = parseInt(value, 10);
if (isNaN(parsedValue)) {
throw new import_commander.InvalidArgumentError("Not a number.");
}
return parsedValue;
}
function parseCliArgs(argv) {
const program = (0, import_commander.createCommand)();
program.version("1.0.5").description("CLI tool to generate constants from SVG files").option("-i, --input <directory>", "Input directory containing SVG files", "src/assets/icons").option("-o, --output <file>", "Output file path or pattern", "src/components/Icon/paths.js").option("-c, --colors", "Keep colors", false).option("-s, --size <number>", "Icon Size", commanderParseInt, 24).option("-q, --quote", "Use single quotes in the output", false).option("-t, --template <string>", "Template string for naming convention", "").option("-m, --md <string>", "Path to the output MD file", "").option("-h, --html <string>", "Path to the output HTML file", "").option("-d, --dts", "Path to the output HTML file", false).option(
"-f, --format <format>",
"Naming format: camelCase, PascalCase, snake_case, SCREAMING_SNAKE_CASE, or material",
"camelCase"
).parse(argv);
return program.opts();
}
// src/index.ts
async function runCLI(argv) {
const options = parseCliArgs(argv);
const generatedFiles = await generateSvgConstants(options);
generatedFiles.forEach(({ path: outputFilePath, content }) => {
ensureDirectoryExistence(outputFilePath);
import_fs2.default.writeFileSync(outputFilePath, content, "utf8");
console.log(`Constants file successfully created: ${outputFilePath}`);
});
}
function ensureDirectoryExistence(filePath) {
const dirname = import_path2.default.dirname(filePath);
if (!import_fs2.default.existsSync(dirname)) {
import_fs2.default.mkdirSync(dirname, { recursive: true });
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
generateSvgConstants,
parseCliArgs,
runCLI
});