Skip to content

Commit

Permalink
feat(package:icons): add icon packages (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
mimshins authored Nov 10, 2024
1 parent a1b8f53 commit 4ac0cf0
Show file tree
Hide file tree
Showing 404 changed files with 9,071 additions and 2,704 deletions.
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
registry=https://registry.npmjs.org/
always-auth=true
14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
"web-components:release": "pnpm --filter @tapsioss/rasti-web-components run release",
"theme:build": "pnpm --filter @tapsioss/rasti-theme run build",
"theme:release": "pnpm --filter @tapsioss/rasti-theme run release",
"icons:build": "pnpm --filter @tapsioss/rasti-icons run build",
"icons:release": "pnpm --filter @tapsioss/rasti-icons run release",
"web-icons:build": "pnpm --filter @tapsioss/rasti-web-icons run build",
"web-icons:release": "pnpm --filter @tapsioss/rasti-web-icons run release",
"react-icons:build": "pnpm --filter @tapsioss/rasti-react-icons run build",
"react-icons:release": "pnpm --filter @tapsioss/rasti-react-icons run release",
"dev:transpile": "tsc --project tsconfig.dev.json --watch --preserveWatchOutput",
"dev": "pnpm clear:dist && pnpm dev:transpile & wds",
"build:packages": "pnpm run -r --parallel build",
Expand Down Expand Up @@ -41,8 +47,12 @@
"@types/chai": "^4.3.12",
"@types/eslint__js": "^8.42.3",
"@types/mocha": "^10.0.6",
"@types/mustache": "^4.2.5",
"@types/node": "^20.12.10",
"@types/postcss-import": "^14.0.3",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/semver": "^7.5.8",
"@types/sinon": "^17.0.3",
"@web/dev-server": "^0.4.2",
"@web/dev-server-esbuild": "^1.0.2",
Expand All @@ -59,13 +69,17 @@
"eslint-plugin-wc": "^2.2.0",
"fast-glob": "^3.3.2",
"lit": "^3.2.1",
"mustache": "^4.2.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.47",
"postcss-cli": "^11.0.0",
"postcss-combine-duplicated-selectors": "^10.0.3",
"postcss-import": "^16.1.0",
"prettier": "^3.2.5",
"prettier-plugin-organize-imports": "^4.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"semver": "^7.6.3",
"shx": "^0.3.4",
"sinon": "^18.0.0",
"tslib": "^2.8.0",
Expand Down
9 changes: 9 additions & 0 deletions packages/icons/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
src
templates
scripts
node_modules

tsconfig.*

dist/*.ts
!dist/*.d.ts
28 changes: 25 additions & 3 deletions packages/icons/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
{
"sideEffects": false,
"name": "@tapsioss/rasti-icons",
"version": "0.1.0",
"type": "module",
"scripts": {},
"devDependencies": {},
"dependencies": {}
"engines": {
"node": ">=20"
},
"files": [
"./dist/**/*.js",
"./dist/**/*.d.ts",
"./dist/**/package.json"
],
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./*": {
"types": "./dist/*.d.ts",
"default": "./dist/*.js"
}
},
"scripts": {
"build": "tsx ./scripts/build.ts",
"release": "pnpm publish ./dist --tag latest --access public"
}
}
184 changes: 184 additions & 0 deletions packages/icons/scripts/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/* eslint-disable no-console */
import globAsync from "fast-glob";
import Mustache from "mustache";
import { exec } from "node:child_process";
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { ensureDirExists } from "../../../scripts/utils";

const execCmd = promisify(exec);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const packageDir = path.resolve(__dirname, "..");
const iconsDir = path.join(packageDir, "src");
const distDir = path.join(packageDir, "dist");
const templatesDir = path.join(packageDir, "templates");

const pathsJSONFile = path.join(distDir, "paths.json");
const entryFile = path.join(distDir, "index.ts");
const entryTemplate = path.join(templatesDir, "entry.txt");
const tsconfigFile = path.join(packageDir, "tsconfig.build.json");

type SVGPathInfo = {
clipRule?: string;
fillRule?: string;
xlinkHref?: string;
d: string;
};

type SVGIconInfo = {
kebabName: string;
pascalName: string;
paths: SVGPathInfo[];
};

const toPascalCase = (str: string, splitRegex: RegExp | string) => {
const baseCase = str.split(splitRegex);

return baseCase
.map(part => part.charAt(0).toUpperCase() + part.substring(1))
.join("");
};

const doesFileExist = async (filePath: string) => {
try {
await fs.stat(filePath);

return true;
} catch {
return false;
}
};

const extractPathsInfo = (svgData: string) => {
const paths = svgData
// Remove the opening <svg> tag
.replace(/<svg[^>]*>/g, "")
// Remove the closing </svg> tag
.replace(/<\/svg>/g, "")
// Ensure proper closing tags with spaces
.replace(/"\/>/g, '" />')
// Remove fill attributes to make them more generic
.replace(/ fill=".+?"/g, "")
// Remove fill-opacity attributes
.replace(/ fill-opacity=".+?"/g, "")
// Remove clip-path attributes to fix visibility issue and save some bytes
.replace(/ clip-path=".+?"/g, "")
// Remove entire <clipPath> elements
.replace(/<clipPath.+?<\/clipPath>/g, "");

const pathsAsString = paths.trim();

// Split paths into individual path elements
const pathElements = pathsAsString.split(/<\/path>/).filter(Boolean);

const svgPathDataArray: SVGPathInfo[] = pathElements.map(element => {
const dMatch = element.match(/ d="([^"]+)"/);
const clipRuleMatch = element.match(/ clip-rule="([^"]+)"/);
const fillRuleMatch = element.match(/ fill-rule="([^"]+)"/);
const xlinkHrefMatch = element.match(/ xlink:href="([^"]+)"/);

const pathData: SVGPathInfo = {
d: dMatch ? (dMatch[1] ?? "") : "",
};

if (clipRuleMatch?.[1]) pathData.clipRule = clipRuleMatch[1];
if (fillRuleMatch?.[1]) pathData.fillRule = fillRuleMatch[1];
if (xlinkHrefMatch?.[1]) pathData.xlinkHref = xlinkHrefMatch[1];

return pathData;
});

return svgPathDataArray;
};

const generatePaths = async () => {
console.log("> generating paths...");

await ensureDirExists(distDir);
await fs.writeFile(pathsJSONFile, "{", { encoding: "utf-8" });

const svgs = await globAsync(path.join(iconsDir, "**/*.svg"));

for (let i = 0; i < svgs.length; i++) {
const svg = svgs[i]!;
const normalizedPath = path.normalize(svg);
const pathInfo = path.parse(normalizedPath);

const data = await fs.readFile(svg, { encoding: "utf-8" });
const pathsInfo = extractPathsInfo(data);

const name = toPascalCase(pathInfo.name, "-");
const shouldAttachComma = i !== 0;

const iconInfo: SVGIconInfo = {
pascalName: name,
kebabName: pathInfo.name,
paths: pathsInfo,
};

await fs.appendFile(
pathsJSONFile,
`${shouldAttachComma ? "," : ""}\n"${name}": ${JSON.stringify(
iconInfo,
null,
2,
)}`,
{ encoding: "utf-8" },
);
}

await fs.appendFile(pathsJSONFile, "\n}", { encoding: "utf-8" });

const entryTemplateStr = await fs.readFile(entryTemplate, {
encoding: "utf-8",
});

const entryCode = Mustache.render(entryTemplateStr, {});

await fs.writeFile(entryFile, entryCode, { encoding: "utf-8", flag: "w" });
await execCmd(["tsc", "--project", tsconfigFile].join(" "));
await execCmd(["shx", "rm", entryFile].join(" "));
};

const createModulePackages = async () => {
console.log("> creating module packages...");

const moduleDirectories = globAsync
.sync(path.join(distDir, "**/index.js"))
.map(p => path.dirname(p));

for (const moduleDirectory of moduleDirectories) {
const typesPath = path.join(moduleDirectory, "index.d.ts");
const typesExist = await doesFileExist(typesPath);

const packageJsonPath = path.join(moduleDirectory, "package.json");

await fs.writeFile(
packageJsonPath,
JSON.stringify(
{
sideEffects: false,
types: typesExist ? "./index.d.ts" : undefined,
main: "./index.js",
type: "module",
},
null,
2,
),
);
}
};

void (async () => {
console.time("build");
await execCmd(["shx", "rm", "-rf", distDir].join(" "));
await generatePaths();
await createModulePackages();
console.timeEnd("build");
})();
/* eslint-enable no-console */
3 changes: 3 additions & 0 deletions packages/icons/src/alarm-clock-fill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/alarm-clock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-capsulepath.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/arrow-circlepath.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-down-in-line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/arrow-down-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/arrow-right-from-line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions packages/icons/src/arrow-two-circlepath-horizontal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/arrow-two-circlepath-vertical.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/icons/src/arrow-two-rectanglepath-horizontal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions packages/icons/src/arrow-up-arrow-down-small.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/icons/src/arrow-up-arrow-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4ac0cf0

Please sign in to comment.