Skip to content

Commit

Permalink
chore(scripts): update collate script and log targets
Browse files Browse the repository at this point in the history
  • Loading branch information
rektdeckard committed Mar 29, 2024
1 parent e4152e9 commit 44a0566
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 71 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@phosphor-icons/core",
"version": "2.0.8",
"version": "2.1.0",
"description": "Icon catalog and assets for Phosphor",
"license": "MIT",
"repository": "https://github.com/phosphor-icons/phosphor-core.git",
Expand Down Expand Up @@ -48,6 +48,7 @@
"./assets"
],
"scripts": {
"collate": "tsx ./scripts/collate.ts",
"catalog": "tsx ./scripts/catalog.ts && pnpm format",
"format": "prettier --write ./src/** ./scripts/**",
"build": "vite build && tsc --emitDeclarationOnly"
Expand Down
4 changes: 2 additions & 2 deletions scripts/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const icons = <const>[
updated_in: ${icon.updated_in.toFixed(1)},
},
`;
console.log(`${chalk.inverse.green(" DONE ")} ${icon.name}`);
console.info(`${chalk.inverse.green(" DONE ")} ${icon.name}`);
});

fileString += `
Expand All @@ -91,7 +91,7 @@ export const icons = <const>[

try {
await fs.writeFile(CATALOG_PATH, fileString);
console.log(
console.info(
`${chalk.green(" DONE ")} ${res.data.icons.length} icons ingested`
);
} catch (e) {
Expand Down
107 changes: 60 additions & 47 deletions scripts/collate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,134 +2,147 @@
import fs from "node:fs";
import path from "node:path";
import { Transform } from "node:stream";
import chalk from "chalk";

let source_path = "./SVGs";
let file_type = "svg";
let svg_type = "raw";
import { ASSETS_PATH, RAW_PATH } from ".";

let sourcePath = "./SVGs";
let destPath = ASSETS_PATH;
let fileType = "svg";
let svgType = "raw";

main().catch(console.error);

async function main() {
if (process.argv[2]) {
const dest = process.argv[2];
if (fs.existsSync(dest) && fs.lstatSync(dest).isDirectory()) {
source_path = dest;
sourcePath = dest;
} else {
console.error(`Invalid destination ${dest}`);
console.error(
`${chalk.inverse.red(" FAIL ")} Invalid destination ${dest}`
);
process.exit(1);
}
}

if (process.argv[3]) {
const input_type = process.argv[3].toLowerCase();
if (["svg", "png"].includes(input_type)) {
file_type = input_type;
const format = process.argv[3].toLowerCase();
if (["svg", "png"].includes(format)) {
fileType = format;
} else {
console.error(`Invalid file type ${process.argv[3]}`);
console.error(
`${chalk.inverse.red(" FAIL ")} Invalid file type ${process.argv[3]}`
);
process.exit(1);
}
}

if (process.argv[4]) {
const input_type = process.argv[4].toLowerCase();
if (["raw", "flat"].includes(input_type)) {
svg_type = input_type;
const inputType = process.argv[4].toLowerCase();
if (["raw", "flat"].includes(inputType)) {
svgType = inputType;
if (inputType === "raw") {
destPath = RAW_PATH;
}
} else {
console.error(`Invalid svg type ${process.argv[4]}`);
console.error(
`${chalk.inverse.red(" FAIL ")} Invalid svg type ${process.argv[4]}`
);
process.exit(1);
}
}

const files = fs.readdirSync(source_path, "utf-8");
const filetype_re = RegExp(`.*\.${file_type}$`);
const files = fs.readdirSync(sourcePath, "utf-8");
const fileTypeExpr = RegExp(`.*\.${fileType}$`);

for (let file of files) {
// Only matching filetypes!
if (!file.match(filetype_re)) continue;
if (!file.match(fileTypeExpr)) continue;

let folder = getWeightFromFilename(file);
await transformAndRelocateFile(file, folder);
}
}

function getWeightFromFilename(filename) {
const filename_parts = filename.split(`.${file_type}`)[0].split("-");
const weight_or_last_identifier = filename_parts.slice(-1)[0];
switch (weight_or_last_identifier) {
function getWeightFromFilename(fileName: string) {
const parts = fileName.split(`.${fileType}`)[0].split("-");
const weightOrLastIdentifier = parts.slice(-1)[0];
switch (weightOrLastIdentifier) {
case "thin":
case "light":
case "bold":
case "fill":
case "duotone":
return weight_or_last_identifier;
return weightOrLastIdentifier;
default:
return "regular";
}
}

async function transformAndRelocateFile(file_name, folder_name) {
const old_path = path.join(source_path, file_name);
const folder_path = path.join(source_path, folder_name);
const new_path = path.join(folder_path, file_name);
async function transformAndRelocateFile(fileName: string, folderName: string) {
const oldPath = path.join(sourcePath, fileName);
const folderPath = path.join(destPath, folderName);
const newPath = path.join(folderPath, fileName);

// Replace literal black "#000" with "currentColor"
const color_literal_re = /#0+/g;
const color_literal_replacer = new Transform({
const colorLiteralExpr = /#0+/g;
const colorLiteralReplacer = new Transform({
// NOTE: this may be flaky due to chunks split in the middle of a color literal!
// Though unlikely due to default `highWaterMark` of 64kb, it is totally possible
// for smaller chunks to be emitted. We can revert to a synchronous transform if needed.
transform(chunk, _encoding, callback) {
const replaced = chunk
.toString()
.replaceAll(color_literal_re, "currentColor");
.replaceAll(colorLiteralExpr, "currentColor");
callback(null, replaced);
},
});

// Append `fill="currentColor"` attribute to <svg> node
const svg_opening_tag_re = /<svg ([^>]*)>/g;
const svg_fill_injector = new Transform({
const svgOpenTagExpr = /<svg ([^>]*)>/g;
const svgFillInjector = new Transform({
// NOTE: this may be flaky due to chunks split in the middle of a color literal!
// Though unlikely due to default `highWaterMark` of 64kb, it is totally possible
// for smaller chunks to be emitted. We can revert to a synchronous transform if needed.
transform(chunk, _encoding, callback) {
const replaced = chunk
.toString()
.replace(svg_opening_tag_re, `<svg $1 fill="currentColor">`);
.replace(svgOpenTagExpr, `<svg $1 fill="currentColor">`);
callback(null, replaced);
},
});

// Make directory if needed
if (!fs.existsSync(folder_path) || !fs.lstatSync(folder_path).isDirectory()) {
fs.mkdirSync(folder_path);
if (!fs.existsSync(folderPath) || !fs.lstatSync(folderPath).isDirectory()) {
fs.mkdirSync(folderPath);
}

console.log(`${new_path}`);
console.info(chalk.green`${newPath}`);

return new Promise((resolve, reject) => {
const read_stream = fs.createReadStream(old_path);
const write_stream = fs.createWriteStream(new_path);

read_stream.on("error", reject);
write_stream.on("error", reject);
color_literal_replacer.on("error", reject);
svg_fill_injector.on("error", reject);
read_stream.on("close", () => {
const readStream = fs.createReadStream(oldPath);
const writeStream = fs.createWriteStream(newPath);

readStream.on("error", reject);
writeStream.on("error", reject);
colorLiteralReplacer.on("error", reject);
svgFillInjector.on("error", reject);
readStream.on("close", () => {
// fs.unlink(oldPath, (err) => {
// if (err) reject(err);
// resolve();
// });
resolve(void 0);
});

if (file_type === "png") {
read_stream.pipe(write_stream);
if (fileType === "png") {
readStream.pipe(writeStream);
} else {
if (svg_type === "raw") {
read_stream.pipe(color_literal_replacer).pipe(write_stream);
if (svgType === "raw") {
readStream.pipe(colorLiteralReplacer).pipe(writeStream);
} else {
read_stream.pipe(svg_fill_injector).pipe(write_stream);
readStream.pipe(svgFillInjector).pipe(writeStream);
}
}
});
Expand Down
42 changes: 21 additions & 21 deletions scripts/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function verifyINode(i: INode, name: string, weight: string): boolean {

for (const [err, assertion] of Object.entries(INODE_WARNINGS)) {
if (assertion(i)) {
console.error(
console.warn(
`${chalk.inverse.yellow(" WARN ")} ${name}${
weight === "regular" ? "" : `-${weight}`
} ${err}`
Expand Down Expand Up @@ -110,26 +110,26 @@ export async function assertValidAssets(): Promise<void> {
}

const files = await fs.readdir(path.join(ASSETS_PATH, weight));
await Promise.all(
files.map(async (filename) => {
let name: string;
const nameParts = filename.split(".svg")[0].split("-");
if (nameParts[nameParts.length - 1] === weight) {
name = nameParts.slice(0, -1).join("-");
} else {
name = nameParts.join("-");
}

if (!icons[name]) {
icons[name] = {};
}

const filepath = path.join(ASSETS_PATH, weight, filename);
const file = (await fs.readFile(filepath)).toString("utf-8");
const inode = await parse(file);
icons[name][weight] = verifyINode(inode, name, weight);
})
);

// NOTE: We have so many icons now that if we try to parrallelize this, we'll get EMFILE
for (const filename of files) {
let name: string;
const nameParts = filename.split(".svg")[0].split("-");
if (nameParts[nameParts.length - 1] === weight) {
name = nameParts.slice(0, -1).join("-");
} else {
name = nameParts.join("-");
}

if (!icons[name]) {
icons[name] = {};
}

const filepath = path.join(ASSETS_PATH, weight, filename);
const file = (await fs.readFile(filepath)).toString("utf-8");
const inode = await parse(file);
icons[name][weight] = verifyINode(inode, name, weight);
}
})
);

Expand Down

0 comments on commit 44a0566

Please sign in to comment.