|
| 1 | +import degit from "degit"; |
| 2 | +import fs from "fs"; |
| 3 | +import fsAsync from "fs/promises"; |
| 4 | +import { JSDOM } from "jsdom"; |
| 5 | +import { exec } from "child_process"; |
| 6 | +import svgtojsx from "svg-to-jsx"; |
| 7 | + |
| 8 | +interface ConfigEntry { |
| 9 | + name: string; |
| 10 | + tags: string[]; |
| 11 | + versions: { |
| 12 | + svg: string[]; |
| 13 | + font: string[]; |
| 14 | + }; |
| 15 | + color: string; |
| 16 | + aliases: { |
| 17 | + base: string; |
| 18 | + alias: string; |
| 19 | + }[]; |
| 20 | +} |
| 21 | + |
| 22 | +(async () => { |
| 23 | + const index: [string, string][] = []; |
| 24 | + |
| 25 | + if (fs.existsSync(`${__dirname}/tmp`)) |
| 26 | + fs.rmSync(`${__dirname}/tmp`, { recursive: true }); |
| 27 | + if (fs.existsSync(`${__dirname}/dist`)) |
| 28 | + fs.rmSync(`${__dirname}/dist`, { recursive: true }); |
| 29 | + fsAsync.mkdir(`${__dirname}/tmp`); |
| 30 | + |
| 31 | + await degit("https://github.com/devicons/devicon.git").clone( |
| 32 | + `${__dirname}/tmp/devicon` |
| 33 | + ); |
| 34 | + |
| 35 | + const deviconConfig: ConfigEntry[] = JSON.parse( |
| 36 | + (await fsAsync.readFile(`${__dirname}/tmp/devicon/devicon.json`)).toString() |
| 37 | + ); |
| 38 | + |
| 39 | + await fsAsync.mkdir(`${__dirname}/tmp/dist`); |
| 40 | + await fsAsync.copyFile( |
| 41 | + `${__dirname}/readme.md`, |
| 42 | + `${__dirname}/tmp/dist/readme.md` |
| 43 | + ); |
| 44 | + await fsAsync.copyFile( |
| 45 | + `${__dirname}/package.json`, |
| 46 | + `${__dirname}/tmp/dist/package.json` |
| 47 | + ); |
| 48 | + |
| 49 | + await Promise.all( |
| 50 | + deviconConfig.map(async (entry) => { |
| 51 | + await fsAsync.mkdir(`${__dirname}/tmp/dist/${entry.name}`); |
| 52 | + await Promise.all( |
| 53 | + entry.versions.svg.map(async (version) => { |
| 54 | + const name = `${entry.name}-${version}`; |
| 55 | + const icon = await fsAsync.readFile( |
| 56 | + `${__dirname}/tmp/devicon/icons/${entry.name}/${name}.svg` |
| 57 | + ); |
| 58 | + const { document } = new JSDOM(icon).window; |
| 59 | + const dir = `${__dirname}/tmp/dist/${entry.name}/${version}`; |
| 60 | + const reactName = |
| 61 | + name |
| 62 | + .split("-") |
| 63 | + .map((el) => el.charAt(0).toUpperCase() + el.slice(1)) |
| 64 | + .join("") + "Icon"; |
| 65 | + index.push([reactName, `./${entry.name}/${version}`]); |
| 66 | + await fsAsync.mkdir(dir); |
| 67 | + // await fsAsync.writeFile( |
| 68 | + // `${dir}/index.js`, |
| 69 | + // `export { default } from "./${reactName}"` |
| 70 | + // ); |
| 71 | + const svg = document.getElementsByTagName("svg")[0]; |
| 72 | + svg.removeAttribute("width"); |
| 73 | + svg.removeAttribute("height"); |
| 74 | + svg.removeAttribute("xmlns:xlink"); |
| 75 | + const isPlain = |
| 76 | + version.includes("plain") || |
| 77 | + version.includes("line") || |
| 78 | + !!entry.aliases.find( |
| 79 | + (x) => |
| 80 | + x.base == version && |
| 81 | + (x.alias.includes("plain") || x.alias.includes("line")) |
| 82 | + ); |
| 83 | + if (isPlain) { |
| 84 | + svg.removeAttribute("fill"); |
| 85 | + const elements = svg.getElementsByTagName("*"); |
| 86 | + for (let i = 0; i < elements.length; i++) { |
| 87 | + const element = elements[i] as SVGElement; |
| 88 | + element.removeAttribute("fill"); |
| 89 | + element.style.removeProperty("fill"); |
| 90 | + element.style.removeProperty("fill-rule"); |
| 91 | + element.style.removeProperty("fill-opacity"); |
| 92 | + } |
| 93 | + } |
| 94 | + await fsAsync.writeFile( |
| 95 | + `${dir}/index.js`, |
| 96 | + `const React = require("react"); |
| 97 | +module.exports = function ${reactName}({size = "1em", ${ |
| 98 | + isPlain ? `color = "${entry.color}",` : "" |
| 99 | + } ...props}){ |
| 100 | + props = { |
| 101 | + ...props, |
| 102 | + style: { |
| 103 | + ...(props.style ? props.style : {}), |
| 104 | + width: size, |
| 105 | + height: size,${ |
| 106 | + isPlain |
| 107 | + ? ` |
| 108 | + ...(color ? { fill: color } : {} )` |
| 109 | + : "" |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + return (${(await svgtojsx(svg.outerHTML)).replace( |
| 114 | + "<svg", |
| 115 | + "<svg {...props}" |
| 116 | + )}); |
| 117 | +}` |
| 118 | + ); |
| 119 | + const definitions = `import React from "react"; |
| 120 | +interface Props extends React.SVGProps<SVGElement> { |
| 121 | + size?: number | string;${ |
| 122 | + isPlain |
| 123 | + ? ` |
| 124 | + color?: string;` |
| 125 | + : "" |
| 126 | + } |
| 127 | +} |
| 128 | +declare const ${reactName}: React.FunctionComponent<Props>; |
| 129 | +export default ${reactName};`; |
| 130 | + await fsAsync.writeFile(`${dir}/index.d.ts`, definitions); |
| 131 | + }) |
| 132 | + ); |
| 133 | + }) |
| 134 | + ); |
| 135 | + |
| 136 | + await fsAsync.writeFile( |
| 137 | + `${__dirname}/tmp/dist/index.js`, |
| 138 | + index.map((e) => `const ${e[0]} = require("${e[1]}")`).join(";\n") + |
| 139 | + ";\n" + |
| 140 | + `module.exports = {${index.map((e) => e[0]).join(",")}}` |
| 141 | + ); |
| 142 | + await fsAsync.writeFile( |
| 143 | + `${__dirname}/tmp/dist/index.d.ts`, |
| 144 | + index.map((e) => `export { default as ${e[0]} } from "${e[1]}"`).join(";\n") |
| 145 | + ); |
| 146 | +})(); |
0 commit comments