@charcoal-ui/icons-cli 5.0.0-beta.5 → 5.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
- package/src/GitHubClient.ts +6 -9
- package/src/GitlabClient.ts +6 -6
- package/src/figma/FigmaFileClient.ts +8 -8
- package/src/generateSource.ts +8 -8
- package/src/getChangedFiles.ts +5 -5
- package/src/index.ts +8 -8
- package/src/svg/optimizeSvgInDirectory.ts +8 -6
- package/src/utils.ts +1 -1
- package/src/v2/transformCSS.ts +13 -13
- package/src/v2/transformDataUri.ts +7 -7
- package/src/v2/transformReact.ts +18 -19
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ yarn icons-cli svg:optimize --color "#000" --ignoreFile ./misc/icons-cli-denylis
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
SVG ファイルに SVGO による最適化をかけつつ、指定した色を `currentColor` に置換します。
|
|
49
|
-
`ignoreFile`では、処理から除外する SVG ファイルの一覧を記したファイルを指定することができます。[
|
|
49
|
+
`ignoreFile`では、処理から除外する SVG ファイルの一覧を記したファイルを指定することができます。[glob](https://nodejs.org/api/fs.html#fspromisesglobpattern-options)のパターンを使用できます。
|
|
50
50
|
|
|
51
51
|
必要な環境変数は以下です。
|
|
52
52
|
|
package/dist/index.js
CHANGED
|
@@ -52,8 +52,10 @@ let polished = require("polished");
|
|
|
52
52
|
polished = __toESM(polished);
|
|
53
53
|
let svgo = require("svgo");
|
|
54
54
|
svgo = __toESM(svgo);
|
|
55
|
-
let
|
|
56
|
-
|
|
55
|
+
let fs_promises = require("fs/promises");
|
|
56
|
+
fs_promises = __toESM(fs_promises);
|
|
57
|
+
let node_fs_promises = require("node:fs/promises");
|
|
58
|
+
node_fs_promises = __toESM(node_fs_promises);
|
|
57
59
|
|
|
58
60
|
//#region src/concurrently.ts
|
|
59
61
|
function concurrently(tasks) {
|
|
@@ -441,7 +443,7 @@ function addViewboxToRootSvg(svg) {
|
|
|
441
443
|
const optimizeSvgInDirectory = async (outputDir, replaceColor, ignoreFile) => {
|
|
442
444
|
const rootDir = path.default.join(outputDir, "svg");
|
|
443
445
|
const ignorePatterns = ignoreFile !== void 0 ? (await fs_extra.default.readFile(ignoreFile, "utf8")).trim().split(/\r?\n/u) : [];
|
|
444
|
-
await concurrently((await (0,
|
|
446
|
+
await concurrently((await Array.fromAsync((0, fs_promises.glob)("**/*.svg", { cwd: rootDir }))).map((file) => async () => {
|
|
445
447
|
console.log(`Optimizing ${file}...`);
|
|
446
448
|
const fullPath = path.default.join(rootDir, file);
|
|
447
449
|
const optimizedSvg = await optimizeSvg(await fs_extra.default.readFile(fullPath, "utf8"), {
|
|
@@ -493,7 +495,7 @@ const generateEntrypoint = async (outputDir, icons) => {
|
|
|
493
495
|
const generateIconSource = async (outputDir) => {
|
|
494
496
|
const svgRoot = path.default.join(outputDir, "svg");
|
|
495
497
|
const srcRoot = path.default.join(outputDir, "src");
|
|
496
|
-
const icons = (await (0,
|
|
498
|
+
const icons = (await Array.fromAsync((0, node_fs_promises.glob)("**/*.svg", { cwd: svgRoot }))).map((path$7) => path$7.slice(0, -4)).sort();
|
|
497
499
|
for (const it of icons) {
|
|
498
500
|
const data = await fs_extra.default.readFile(path.default.join(svgRoot, `${it}.svg`));
|
|
499
501
|
const outputPath = path.default.join(srcRoot, `${it}.js`);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["PQueue","Figma","c","repoOwner: string","repoName: string","defaultBranch: string","Octokit","tree: TreeItem[]","host: string","projectId: number","defaultBranch: string","Gitlab","actions: CommitAction[]","svgo","Svgo","JSDOM","fs","fs","path"],"sources":["../src/concurrently.ts","../src/figma/FigmaFileClient.ts","../src/utils.ts","../src/getChangedFiles.ts","../src/GitHubClient.ts","../src/GitlabClient.ts","../src/svg/optimizeSvg.ts","../src/svg/optimizeSvgInDirectory.ts","../src/generateSource.ts","../src/index.ts"],"sourcesContent":["import PQueue from 'p-queue'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function concurrently(tasks: (() => Promise<any>)[]) {\n const queue = new PQueue({ concurrency: 3 })\n for (const task of tasks) {\n void queue.add(task)\n }\n queue.start()\n return queue.onIdle()\n}\n","/* eslint-disable no-console */\nimport path from 'path'\nimport camelCase from 'camelcase'\nimport * as Figma from 'figma-js'\nimport { ensureDir, remove, writeFile } from 'fs-extra'\nimport got from 'got'\nimport { match } from 'path-to-regexp'\nimport { concurrently } from '../concurrently'\n\nconst DRY_RUN = Boolean(process.env.DRY_RUN)\n\nconst matchPath = match<{ fileId: string; name: string }>('/file/:fileId/:name')\n\nfunction extractParams(url: string): { fileId: string; nodeId?: string } {\n const { pathname, searchParams } = new URL(url)\n\n const result = matchPath(pathname)\n if (result === false) {\n throw new Error('No fileId found in url')\n }\n\n return {\n fileId: result.params.fileId,\n nodeId: searchParams.get('node-id') ?? undefined,\n }\n}\n\nfunction filenamify(name: string) {\n return camelCase(name, { pascalCase: true }).replace(' ', '')\n}\n\nconst iconName = /^(?:\\d+|Inline)\\s*\\//u\n\nfunction isIconNode(node: Figma.Node) {\n return iconName.test(node.name)\n}\n\nfunction parseV2IconName(name: string) {\n return name\n .split(',')\n .map((f) => f.split('=').map((s) => s.trim())[1])\n .join('/')\n .toLowerCase()\n}\n\ntype ExportFormat = 'svg' | 'pdf'\n\ninterface Component {\n id: string\n name: string\n image?: string\n variant?: string\n}\n\ntype FigmaIconFileLayoutVersion = 'v1' | 'v2'\n\nexport class FigmaFileClient {\n private readonly fileId: string\n private readonly nodeId?: string\n private readonly exportFormat: ExportFormat\n private readonly client: Figma.ClientInterface\n private readonly layoutVersion: FigmaIconFileLayoutVersion\n\n private components: Record<string, Component> = {}\n\n static async runFromCli(\n url: string,\n token: string,\n outputRootDir: string,\n exportFormat: ExportFormat,\n layoutVersion: FigmaIconFileLayoutVersion = 'v1'\n ) {\n const client = new this(url, token, exportFormat, layoutVersion)\n\n const outputDir = path.join(process.cwd(), outputRootDir, exportFormat)\n\n console.log(\n `Exporting components from ${url} using layout ${layoutVersion}`\n )\n await client.loadSvg(outputDir)\n\n console.log('success!')\n }\n\n constructor(\n url: string,\n personalAccessToken: string,\n exportFormat: ExportFormat,\n layoutVersion: FigmaIconFileLayoutVersion\n ) {\n this.client = Figma.Client({\n personalAccessToken,\n })\n\n const { fileId, nodeId } = extractParams(url)\n this.fileId = fileId\n this.nodeId = nodeId\n\n this.exportFormat = exportFormat\n this.layoutVersion = layoutVersion\n }\n\n async loadSvg(outputDir: string) {\n await remove(outputDir)\n await ensureDir(outputDir)\n\n await this.loadComponents()\n await this.loadImageUrls()\n await this.downloadImages(outputDir)\n }\n\n private async loadComponents() {\n const { document } = await this.getFile()\n // const { document } = (\n // await import('../../../../blob-report/scripts/doc.json')\n // ).default as Figma.FileResponse\n\n if (this.layoutVersion === 'v2') {\n this.findComponentsV2(document)\n } else {\n // nodeIdが指定されている場合は、IDが一致するノードのみを探索対象にする\n // 指定されていない場合はドキュメント全体が探索対象\n const targets =\n this.nodeId !== undefined\n ? document.children.filter((node) => node.id === this.nodeId)\n : document.children\n\n // 対象ノードの子孫を探索してアイコンのコンポーネントを見つける\n targets.forEach((child) => this.findComponentsRecursively(child))\n }\n\n const len = Object.keys(this.components).length\n if (len === 0) {\n throw new Error('No components found!')\n } else {\n console.log(`found ${len} icons`)\n }\n }\n\n private async loadImageUrls() {\n console.log('Getting export urls')\n\n const { data } = await this.client.fileImages(this.fileId, {\n format: this.exportFormat,\n ids: Object.keys(this.components),\n scale: 1,\n ...(this.exportFormat == 'pdf' ? { use_absolute_bounds: true } : {}),\n })\n\n for (const [id, image] of Object.entries(data.images)) {\n this.components[id].image = image\n }\n }\n\n private async downloadImages(outputDir: string) {\n return concurrently(\n Object.values(this.components).map((component) => async () => {\n if (component.image === undefined) {\n return\n }\n\n const filename = component.variant\n ? `${parseV2IconName(component.variant)}/${component.name}.${\n this.exportFormat\n }`\n : `${filenamify(component.name)}.${this.exportFormat}`\n const fullname = path.join(outputDir, filename)\n const dirname = path.dirname(fullname)\n\n if (DRY_RUN) {\n console.log(`[DRY_RUN] skip: ${filename} => ✅ writing...`)\n return\n }\n\n const response = await got.get(\n component.image,\n this.exportFormat == 'pdf' ? { responseType: 'buffer' } : {}\n )\n\n await ensureDir(dirname)\n\n console.log(`found: ${filename} => ✅ writing...`)\n await writeFile(fullname, response.body, 'utf8')\n })\n )\n }\n\n private async getFile() {\n console.log('Processing response')\n\n const { data } = await this.client.file(this.fileId.toString())\n\n return data\n }\n\n private findComponentsRecursively(child: Figma.Node) {\n if (child.type === 'COMPONENT') {\n const { name, id } = child\n\n if (isIconNode(child)) {\n this.components[id] = {\n name,\n id,\n }\n }\n } else if ('children' in child) {\n child.children.forEach((grandChild) =>\n this.findComponentsRecursively(grandChild)\n )\n }\n }\n\n private findComponentsV2(document: Figma.Document) {\n const iconsPage = document.children.find(\n (child): child is Figma.Canvas =>\n child.name === 'Icons 一覧' && child.type === 'CANVAS'\n )\n const iconComponentSets = iconsPage?.children.flatMap((c) => {\n if (c.type !== 'FRAME') return []\n return c.children.filter(\n (c): c is Figma.ComponentSet => c.type === 'COMPONENT_SET'\n )\n })\n iconComponentSets?.forEach((set) => {\n set.children.forEach((i) => {\n if (i.type !== 'COMPONENT') return null\n this.components[i.id] = {\n name: set.name,\n variant: i.name,\n id: i.id,\n }\n })\n })\n }\n}\n","import { exec } from 'child_process'\n\n/**\n * FIXME: util.promisify を使うと node-libs-browser に入っている方が使われてしまい、壊れる\n */\nexport const execp = (command: string) =>\n new Promise<string>((resolve, reject) => {\n exec(command, (err, stdout) => {\n if (err) {\n return reject(err)\n }\n\n return resolve(stdout)\n })\n })\n\nexport function mustBeDefined<T>(\n value: T,\n name: string\n): asserts value is NonNullable<T> {\n if (typeof value === 'undefined') {\n throw new TypeError(`${name} must be defined.`)\n }\n}\n","import { promises as fs, existsSync } from 'fs'\nimport path from 'path'\nimport { execp } from './utils'\n\n/**\n * dir 内で変更があったファイル情報を for await で回せるようにするやつ\n */\nexport async function* getChangedFiles(dir: string) {\n if (!existsSync(dir))\n throw new Error(`icons-cli: target directory not found (${dir})`)\n const gitStatus = await collectGitStatus()\n for (const [relativePath, status] of gitStatus) {\n const fullpath = path.resolve(process.cwd(), '../../', relativePath)\n if (!fullpath.startsWith(`${dir}/`)) {\n continue\n }\n if (!existsSync(fullpath))\n throw new Error(`icons-cli: could not load svg (${fullpath})`)\n const content = await fs.readFile(fullpath, { encoding: 'utf-8' })\n yield { relativePath, content, status }\n }\n}\n\nasync function collectGitStatus() {\n return new Map(\n /**\n * @see https://git-scm.com/docs/git-status#_porcelain_format_version_1\n */\n (await execp(`git status --porcelain`)).split('\\n').map((s) => {\n return [\n s.slice(3),\n s.startsWith(' M')\n ? 'modified'\n : s.startsWith('??')\n ? 'untracked'\n : s.startsWith(' D')\n ? 'deleted'\n : null,\n ] as const\n })\n )\n}\n","import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'\nimport path from 'path'\nimport { getChangedFiles } from './getChangedFiles'\n\ntype RefResponse = ReturnType<GithubClient['createBranch']> extends Promise<\n infer R\n>\n ? R\n : never\n\ninterface TreeItem {\n path?: string\n mode?: '100644' | '100755' | '040000' | '160000' | '120000'\n type?: 'blob' | 'commit' | 'tree'\n sha?: string | null\n content?: string\n}\n\nexport class GithubClient {\n private readonly api: Octokit\n private readonly now: Date\n\n static async runFromCli(\n repoOwner: string,\n repoName: string,\n token: string,\n defaultBranch: string,\n outputDir: string\n ): Promise<ReturnType<GithubClient['createPullRequest']> | void> {\n const client = new this(repoOwner, repoName, token, defaultBranch)\n const outputDirFullPath = path.resolve(process.cwd(), outputDir)\n const diff = await client.createTreeFromDiff(outputDirFullPath)\n // eslint-disable-next-line no-console\n console.log(`${diff.length} files are changed`)\n if (diff.length === 0) {\n // eslint-disable-next-line no-console\n console.log('no changes. aborting')\n return\n }\n\n const newBranch = await client.createBranch()\n\n await client.createCommit(diff, newBranch)\n return client.createPullRequest(newBranch)\n }\n\n constructor(\n private readonly repoOwner: string,\n private readonly repoName: string,\n token: string,\n private readonly defaultBranch: string,\n now = new Date()\n ) {\n this.api = new Octokit({\n auth: token,\n })\n\n this.now = now\n }\n\n get branch() {\n return `icons/update/${this.now.getTime()}`\n }\n\n /**\n * both used for commit message or pull request title\n */\n get message() {\n return `[icons-cli] Update icons ${this.now.toDateString()}`\n }\n\n async createTreeFromDiff(outputDir: string): Promise<TreeItem[]> {\n const tree: TreeItem[] = []\n\n for await (const file of getChangedFiles(outputDir)) {\n const item = {\n path: file.relativePath,\n // 100 はファイル 644 は実行不可なファイルであるという意味\n // @see https://octokit.github.io/rest.js/v18#git-create-tree\n mode: '100644' as const,\n content: file.content,\n }\n\n if (file.status === 'deleted') {\n // https://stackoverflow.com/questions/23637961/how-do-i-mark-a-file-as-deleted-in-a-tree-using-the-github-api\n tree.push({\n ...item,\n sha: null,\n })\n } else {\n tree.push(item)\n }\n }\n\n return tree\n }\n\n async createCommit(\n tree: TreeItem[],\n targetBranch: RefResponse\n ): Promise<RestEndpointMethodTypes['git']['createCommit']['response']> {\n const parentCommit = await this.api.git.getCommit({\n owner: this.repoOwner,\n repo: this.repoName,\n\n commit_sha: targetBranch.data.object.sha,\n })\n\n const newTree = await this.api.git.createTree({\n owner: this.repoOwner,\n repo: this.repoName,\n\n base_tree: parentCommit.data.tree.sha,\n tree,\n })\n\n // この時点ではどのブランチにも属さないコミットができる\n const commit = await this.api.git.createCommit({\n owner: this.repoOwner,\n repo: this.repoName,\n message: this.message,\n tree: newTree.data.sha,\n parents: [parentCommit.data.sha],\n })\n\n // ref を更新することで、commit が targetBranch に属するようになる\n await this.api.git.updateRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `heads/${this.branch}`,\n sha: commit.data.sha,\n })\n\n return commit\n }\n\n async createPullRequest(\n targetBranch: RefResponse\n ): Promise<ReturnType<GithubClient['api']['pulls']['create']>> {\n const defaultBranch = await this.getDefaultBranchRef()\n\n return this.api.pulls.create({\n owner: this.repoOwner,\n repo: this.repoName,\n head: targetBranch.data.ref,\n base: defaultBranch.data.ref,\n title: this.message,\n body: '',\n })\n }\n\n private getDefaultBranchRef() {\n return this.api.git.getRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `heads/${this.defaultBranch}`,\n })\n }\n\n async createBranch(): ReturnType<GithubClient['api']['git']['createRef']> {\n const defaultBranch = await this.getDefaultBranchRef()\n\n return this.api.git.createRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `refs/heads/${this.branch}`,\n sha: defaultBranch.data.object.sha,\n })\n }\n}\n","import type { CommitAction } from '@gitbeaker/core/dist/types/services/Commits'\nimport { Gitlab } from '@gitbeaker/node'\nimport path from 'path'\nimport { getChangedFiles } from './getChangedFiles'\n\ntype GitlabApi = InstanceType<typeof Gitlab>\n\nexport class GitlabClient {\n private readonly api: GitlabApi\n private readonly now: Date\n\n static async runFromCli(\n host: string,\n projectId: number,\n privateToken: string,\n defaultBranch: string,\n outputDir: string\n ) {\n const client = new this(host, projectId, privateToken, defaultBranch)\n const outputDirFullPath = path.resolve(process.cwd(), outputDir)\n const diff = await client.createActionsFromDiff(outputDirFullPath)\n // eslint-disable-next-line no-console\n console.log(`${diff.length} files are changed`)\n if (diff.length === 0) {\n // eslint-disable-next-line no-console\n console.log('no changes. aborting')\n return\n }\n\n await client.createCommit(diff)\n return client.createMergeRequest()\n }\n\n constructor(\n private readonly host: string,\n private readonly projectId: number,\n privateToken: string,\n private readonly defaultBranch: string,\n now = new Date()\n ) {\n this.api = new Gitlab({\n host: this.host,\n token: privateToken,\n })\n this.now = now\n }\n\n get branch() {\n return `icons/update/${this.now.getTime()}`\n }\n\n /**\n * both used for commit message or merge request title\n */\n get message() {\n return `[icons-cli] Update icons ${this.now.toDateString()}`\n }\n\n async createActionsFromDiff(outputDir: string): Promise<CommitAction[]> {\n const actions: CommitAction[] = []\n\n for await (const file of getChangedFiles(outputDir)) {\n actions.push({\n action:\n file.status === 'untracked'\n ? 'create'\n : file.status === 'deleted'\n ? 'delete'\n : 'update',\n filePath: file.relativePath,\n content: file.content,\n })\n }\n\n return actions\n }\n\n async createCommit(diff: CommitAction[]) {\n return this.api.Commits.create(\n this.projectId,\n this.branch,\n this.message,\n diff,\n {\n start_branch: this.defaultBranch,\n }\n )\n }\n\n createMergeRequest() {\n return this.api.MergeRequests.create(\n this.projectId,\n this.branch,\n this.defaultBranch,\n this.message\n )\n }\n}\n","import { JSDOM } from 'jsdom'\nimport { parseToRgb } from 'polished'\nimport type { RgbColor, RgbaColor } from 'polished/lib/types/color'\nimport Svgo from 'svgo'\n\nexport const DEFAULT_CURRENT_COLOR_TARGET = '#858585'\n\nconst svgo = new Svgo({\n plugins: [\n // NOTICE: SVGO は「svg 内のすべての fill を currentColor に変える」機能しかない\n // icons-cli に必要なのは「特定の黒っぽい色だけ currentColor に変える」機能\n // なので、convertColors plugin は使わない\n // { convertColors: { currentColor: true } },\n { removeViewBox: false },\n { removeAttrs: { attrs: ['stroke-opacity', 'fill-opacity'] } },\n ],\n})\n\n/**\n * SVGを最適化するオプション\n */\ninterface Options {\n /**\n * currentColorに置換する色 #ffffff\n */\n convertedColor: string\n /**\n * svgoによる最適化を行わない\n */\n withoutOptimizeBySVGO?: boolean\n}\n\nexport async function optimizeSvg(input: string, options: Options) {\n const { document } = new JSDOM(input).window\n const svg = document.querySelector('svg')\n if (!svg) {\n throw new Error('optimizeSvg: input string seems not to have <svg>')\n }\n\n addViewboxToRootSvg(svg)\n convertToCurrentColor(svg, options.convertedColor)\n\n if (options.withoutOptimizeBySVGO === true) {\n return svg.outerHTML\n } else {\n return (await svgo.optimize(svg.outerHTML)).data\n }\n}\n\nconst TARGET_ATTRS = ['fill', 'stroke']\n\nfunction convertToCurrentColor(svg: SVGSVGElement, convertedColor: string) {\n const targetColor = parseColor(convertedColor)\n if (!targetColor) {\n throw new Error(`${convertedColor} is not a valid color`)\n }\n\n for (const attr of TARGET_ATTRS) {\n const targets = Array.from(svg.querySelectorAll<SVGElement>(`[${attr}]`))\n\n for (const el of targets) {\n const value = parseColor(el.getAttribute(attr))\n if (!value) {\n continue\n }\n\n if (!colorEquals(value, targetColor)) {\n continue\n }\n\n el.setAttribute(attr, 'currentColor')\n }\n }\n}\n\nfunction parseColor(value: string | null) {\n if (value == null) {\n return null\n }\n\n try {\n return parseToRgb(value)\n } catch {\n return null\n }\n}\n\nfunction colorEquals(self: RgbColor | RgbaColor, other: RgbColor | RgbaColor) {\n if (self.red !== other.red) {\n return false\n }\n\n if (self.blue !== other.blue) {\n return false\n }\n\n if (self.green !== other.green) {\n return false\n }\n\n if ('alpha' in self) {\n if ('alpha' in other) {\n if (self.alpha !== other.alpha) {\n return false\n }\n }\n }\n\n return true\n}\n\nfunction addViewboxToRootSvg(svg: SVGSVGElement) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const width = svg.getAttribute('width')!\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const height = svg.getAttribute('height')!\n\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`)\n}\n","import path from 'path'\nimport glob from 'fast-glob'\nimport fs from 'fs-extra'\nimport { concurrently } from '../concurrently'\nimport { optimizeSvg } from './optimizeSvg'\n\n/* eslint-disable no-console */\n\nexport const optimizeSvgInDirectory = async (\n outputDir: string,\n replaceColor: string,\n ignoreFile?: string\n) => {\n const rootDir = path.join(outputDir, 'svg')\n\n const ignorePatterns =\n ignoreFile !== undefined\n ? (await fs.readFile(ignoreFile, 'utf8')).trim().split(/\\r?\\n/u)\n : []\n\n const files = await glob('**/*.svg', {\n cwd: rootDir,\n })\n\n await concurrently(\n files.map((file) => async () => {\n console.log(`Optimizing ${file}...`)\n const fullPath = path.join(rootDir, file)\n\n const originalSvg = await fs.readFile(fullPath, 'utf8')\n const optimizedSvg = await optimizeSvg(originalSvg, {\n convertedColor: replaceColor,\n withoutOptimizeBySVGO: ignorePatterns.includes(file),\n })\n await fs.writeFile(fullPath, optimizedSvg)\n })\n )\n}\n","import path from 'path'\nimport glob from 'fast-glob'\nimport fs from 'fs-extra'\n\nconst generateIconSvgEmbeddedSource = (svgString: string) => {\n const str = svgString.replace(/\\r?\\n/g, '')\n\n return `/** This file is auto generated. DO NOT EDIT BY HAND. */\nexport default '${str}'\n`\n}\n\nconst generateMjsEntrypoint = (\n icons: string[]\n) => `/** This file is auto generated. DO NOT EDIT BY HAND. */\n\nexport default {\n${icons\n .map((it) => ` '${it}': () => import('./${it}.js').then(m => m.default)`)\n .join(',\\n')}\n}\n`\n\nconst generateCjsEntrypoint = (\n icons: string[]\n) => `/** This file is auto generated. DO NOT EDIT BY HAND. */\n\nmodule.exports = {\n${icons\n .map((it) => ` '${it}': () => import('./${it}.js').then(m => m.default)`)\n .join(',\\n')}\n}\n`\n\nconst generateTypeDefinitionEntrypoint = (\n icons: string[]\n) => `/** This file is auto generated. DO NOt EDIT BY HAND. */\n\ndeclare var _default: {\n${icons.map((it) => ` '${it}': () => Promise<string>`).join(';\\n')}\n};\nexport default _default;\n`\n\nexport const generateEntrypoint = async (\n outputDir: string,\n icons: string[]\n) => {\n const srcRoot = path.join(outputDir, 'src')\n const mjsPath = path.join(srcRoot, 'index.js')\n await fs.ensureFile(mjsPath)\n await fs.writeFile(mjsPath, generateMjsEntrypoint(icons))\n\n const cjsPath = path.join(srcRoot, 'index.cjs')\n await fs.ensureFile(cjsPath)\n await fs.writeFile(cjsPath, generateCjsEntrypoint(icons))\n\n const dtsPath = path.join(srcRoot, 'index.d.ts')\n await fs.ensureFile(dtsPath)\n await fs.writeFile(dtsPath, generateTypeDefinitionEntrypoint(icons))\n}\n\nexport const generateIconSource = async (outputDir: string) => {\n const svgRoot = path.join(outputDir, 'svg')\n const srcRoot = path.join(outputDir, 'src')\n const icons = (await glob('**/*.svg', { cwd: svgRoot }))\n .map(\n (path) => path.slice(0, -4) // e.g. '16/Add.svg' -> '16/Add'\n )\n .sort()\n\n for (const it of icons) {\n const data = await fs.readFile(path.join(svgRoot, `${it}.svg`))\n const outputPath = path.join(srcRoot, `${it}.js`)\n await fs.ensureFile(outputPath)\n await fs.writeFile(\n outputPath,\n generateIconSvgEmbeddedSource(data.toString())\n )\n }\n\n await generateEntrypoint(outputDir, icons)\n}\n","#!/usr/bin/env node\n\nimport yargs from 'yargs'\nimport { FigmaFileClient } from './figma/FigmaFileClient'\nimport { GithubClient } from './GitHubClient'\nimport { GitlabClient } from './GitlabClient'\nimport { DEFAULT_CURRENT_COLOR_TARGET } from './svg/optimizeSvg'\nimport { optimizeSvgInDirectory } from './svg/optimizeSvgInDirectory'\nimport { generateIconSource } from './generateSource'\nimport { mustBeDefined } from './utils'\n\n/**\n * Figma\n */\nconst FIGMA_TOKEN = process.env.FIGMA_TOKEN\nconst FIGMA_FILE_URL = process.env.FIGMA_FILE_URL\nconst OUTPUT_ROOT_DIR = process.env.OUTPUT_ROOT_DIR\n\n/**\n * GitLab\n */\nconst GITLAB_ACCESS_TOKEN = process.env.GITLAB_ACCESS_TOKEN\nconst GITLAB_DEFAULT_BRANCH = process.env.GITLAB_DEFAULT_BRANCH\nconst GITLAB_HOST = process.env.GITLAB_HOST\nconst GITLAB_PROJECT_ID = process.env.GITLAB_PROJECT_ID\n\n/**\n * GitHub\n */\nconst GITHUB_ACCESS_TOKEN = process.env.GITHUB_ACCESS_TOKEN\nconst GITHUB_REPO_OWNER = process.env.GITHUB_REPO_OWNER\nconst GITHUB_REPO_NAME = process.env.GITHUB_REPO_NAME\nconst GITHUB_DEFAULT_BRANCH = process.env.GITHUB_DEFAULT_BRANCH\n\nvoid yargs\n .scriptName('icons-cli')\n .command(\n 'figma:export',\n 'Load all icons from Figma and save to files',\n {\n format: {\n default: 'svg',\n choices: ['svg', 'pdf'],\n describe: 'Output format',\n },\n layout: {\n default: 'v1',\n describe: 'Figma icon file layout version',\n },\n },\n async ({ format, layout }) => {\n mustBeDefined(FIGMA_FILE_URL, 'FIGMA_FILE_URL')\n mustBeDefined(FIGMA_TOKEN, 'FIGMA_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await FigmaFileClient.runFromCli(\n FIGMA_FILE_URL,\n FIGMA_TOKEN,\n OUTPUT_ROOT_DIR,\n format as 'svg' | 'pdf',\n layout as 'v1' | 'v2'\n )\n }\n )\n .command(\n 'svg:optimize',\n 'Optimize svg files in output directory',\n {\n color: {\n default: DEFAULT_CURRENT_COLOR_TARGET,\n type: 'string',\n describe: 'Color code that should be converted into `currentColor`',\n },\n ignoreFile: {\n type: 'string',\n describe:\n 'A file that contains the list of path to SVG files that should not be optimized',\n },\n },\n async ({ color, ignoreFile }) => {\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await optimizeSvgInDirectory(OUTPUT_ROOT_DIR, color, ignoreFile)\n }\n )\n .command(\n 'files:generate',\n 'Enumerate svg files in output directory and generate icon files',\n {},\n () => {\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n void generateIconSource(OUTPUT_ROOT_DIR).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e)\n process.exit(1)\n })\n }\n )\n .command(\n 'gitlab:mr',\n 'Create a merge request in the name of icons-cli',\n {},\n async () => {\n mustBeDefined(GITLAB_PROJECT_ID, 'GITLAB_PROJECT_ID')\n mustBeDefined(GITLAB_ACCESS_TOKEN, 'GITLAB_ACCESS_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await GitlabClient.runFromCli(\n GITLAB_HOST ?? 'https://gitlab.com',\n Number(GITLAB_PROJECT_ID),\n GITLAB_ACCESS_TOKEN,\n GITLAB_DEFAULT_BRANCH ?? 'main',\n OUTPUT_ROOT_DIR\n )\n }\n )\n .command(\n 'github:pr',\n 'Create a pull request in the name of icons-cli',\n {},\n async () => {\n mustBeDefined(GITHUB_ACCESS_TOKEN, 'GITHUB_ACCESS_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await GithubClient.runFromCli(\n GITHUB_REPO_OWNER ?? 'pixiv',\n GITHUB_REPO_NAME ?? 'charcoal',\n GITHUB_ACCESS_TOKEN,\n GITHUB_DEFAULT_BRANCH ?? 'main',\n OUTPUT_ROOT_DIR\n )\n }\n )\n .demandCommand()\n .strict()\n .help()\n .parse()\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["PQueue","Figma","c","repoOwner: string","repoName: string","defaultBranch: string","Octokit","tree: TreeItem[]","host: string","projectId: number","defaultBranch: string","Gitlab","actions: CommitAction[]","svgo","Svgo","JSDOM","fs","fs","path"],"sources":["../src/concurrently.ts","../src/figma/FigmaFileClient.ts","../src/utils.ts","../src/getChangedFiles.ts","../src/GitHubClient.ts","../src/GitlabClient.ts","../src/svg/optimizeSvg.ts","../src/svg/optimizeSvgInDirectory.ts","../src/generateSource.ts","../src/index.ts"],"sourcesContent":["import PQueue from 'p-queue'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function concurrently(tasks: (() => Promise<any>)[]) {\n const queue = new PQueue({ concurrency: 3 })\n for (const task of tasks) {\n void queue.add(task)\n }\n queue.start()\n return queue.onIdle()\n}\n","/* eslint-disable no-console */\nimport path from 'path'\nimport camelCase from 'camelcase'\nimport * as Figma from 'figma-js'\nimport { ensureDir, remove, writeFile } from 'fs-extra'\nimport got from 'got'\nimport { match } from 'path-to-regexp'\nimport { concurrently } from '../concurrently'\n\nconst DRY_RUN = Boolean(process.env.DRY_RUN)\n\nconst matchPath = match<{ fileId: string; name: string }>('/file/:fileId/:name')\n\nfunction extractParams(url: string): { fileId: string; nodeId?: string } {\n const { pathname, searchParams } = new URL(url)\n\n const result = matchPath(pathname)\n if (result === false) {\n throw new Error('No fileId found in url')\n }\n\n return {\n fileId: result.params.fileId,\n nodeId: searchParams.get('node-id') ?? undefined,\n }\n}\n\nfunction filenamify(name: string) {\n return camelCase(name, { pascalCase: true }).replace(' ', '')\n}\n\nconst iconName = /^(?:\\d+|Inline)\\s*\\//u\n\nfunction isIconNode(node: Figma.Node) {\n return iconName.test(node.name)\n}\n\nfunction parseV2IconName(name: string) {\n return name\n .split(',')\n .map((f) => f.split('=').map((s) => s.trim())[1])\n .join('/')\n .toLowerCase()\n}\n\ntype ExportFormat = 'svg' | 'pdf'\n\ninterface Component {\n id: string\n name: string\n image?: string\n variant?: string\n}\n\ntype FigmaIconFileLayoutVersion = 'v1' | 'v2'\n\nexport class FigmaFileClient {\n private readonly fileId: string\n private readonly nodeId?: string\n private readonly exportFormat: ExportFormat\n private readonly client: Figma.ClientInterface\n private readonly layoutVersion: FigmaIconFileLayoutVersion\n\n private components: Record<string, Component> = {}\n\n static async runFromCli(\n url: string,\n token: string,\n outputRootDir: string,\n exportFormat: ExportFormat,\n layoutVersion: FigmaIconFileLayoutVersion = 'v1',\n ) {\n const client = new this(url, token, exportFormat, layoutVersion)\n\n const outputDir = path.join(process.cwd(), outputRootDir, exportFormat)\n\n console.log(\n `Exporting components from ${url} using layout ${layoutVersion}`,\n )\n await client.loadSvg(outputDir)\n\n console.log('success!')\n }\n\n constructor(\n url: string,\n personalAccessToken: string,\n exportFormat: ExportFormat,\n layoutVersion: FigmaIconFileLayoutVersion,\n ) {\n this.client = Figma.Client({\n personalAccessToken,\n })\n\n const { fileId, nodeId } = extractParams(url)\n this.fileId = fileId\n this.nodeId = nodeId\n\n this.exportFormat = exportFormat\n this.layoutVersion = layoutVersion\n }\n\n async loadSvg(outputDir: string) {\n await remove(outputDir)\n await ensureDir(outputDir)\n\n await this.loadComponents()\n await this.loadImageUrls()\n await this.downloadImages(outputDir)\n }\n\n private async loadComponents() {\n const { document } = await this.getFile()\n // const { document } = (\n // await import('../../../../blob-report/scripts/doc.json')\n // ).default as Figma.FileResponse\n\n if (this.layoutVersion === 'v2') {\n this.findComponentsV2(document)\n } else {\n // nodeIdが指定されている場合は、IDが一致するノードのみを探索対象にする\n // 指定されていない場合はドキュメント全体が探索対象\n const targets =\n this.nodeId !== undefined\n ? document.children.filter((node) => node.id === this.nodeId)\n : document.children\n\n // 対象ノードの子孫を探索してアイコンのコンポーネントを見つける\n targets.forEach((child) => this.findComponentsRecursively(child))\n }\n\n const len = Object.keys(this.components).length\n if (len === 0) {\n throw new Error('No components found!')\n } else {\n console.log(`found ${len} icons`)\n }\n }\n\n private async loadImageUrls() {\n console.log('Getting export urls')\n\n const { data } = await this.client.fileImages(this.fileId, {\n format: this.exportFormat,\n ids: Object.keys(this.components),\n scale: 1,\n ...(this.exportFormat == 'pdf' ? { use_absolute_bounds: true } : {}),\n })\n\n for (const [id, image] of Object.entries(data.images)) {\n this.components[id].image = image\n }\n }\n\n private async downloadImages(outputDir: string) {\n return concurrently(\n Object.values(this.components).map((component) => async () => {\n if (component.image === undefined) {\n return\n }\n\n const filename = component.variant\n ? `${parseV2IconName(component.variant)}/${component.name}.${\n this.exportFormat\n }`\n : `${filenamify(component.name)}.${this.exportFormat}`\n const fullname = path.join(outputDir, filename)\n const dirname = path.dirname(fullname)\n\n if (DRY_RUN) {\n console.log(`[DRY_RUN] skip: ${filename} => ✅ writing...`)\n return\n }\n\n const response = await got.get(\n component.image,\n this.exportFormat == 'pdf' ? { responseType: 'buffer' } : {},\n )\n\n await ensureDir(dirname)\n\n console.log(`found: ${filename} => ✅ writing...`)\n await writeFile(fullname, response.body, 'utf8')\n }),\n )\n }\n\n private async getFile() {\n console.log('Processing response')\n\n const { data } = await this.client.file(this.fileId.toString())\n\n return data\n }\n\n private findComponentsRecursively(child: Figma.Node) {\n if (child.type === 'COMPONENT') {\n const { name, id } = child\n\n if (isIconNode(child)) {\n this.components[id] = {\n name,\n id,\n }\n }\n } else if ('children' in child) {\n child.children.forEach((grandChild) =>\n this.findComponentsRecursively(grandChild),\n )\n }\n }\n\n private findComponentsV2(document: Figma.Document) {\n const iconsPage = document.children.find(\n (child): child is Figma.Canvas =>\n child.name === 'Icons 一覧' && child.type === 'CANVAS',\n )\n const iconComponentSets = iconsPage?.children.flatMap((c) => {\n if (c.type !== 'FRAME') return []\n return c.children.filter(\n (c): c is Figma.ComponentSet => c.type === 'COMPONENT_SET',\n )\n })\n iconComponentSets?.forEach((set) => {\n set.children.forEach((i) => {\n if (i.type !== 'COMPONENT') return null\n this.components[i.id] = {\n name: set.name,\n variant: i.name,\n id: i.id,\n }\n })\n })\n }\n}\n","import { exec } from 'child_process'\n\n/**\n * FIXME: util.promisify を使うと node-libs-browser に入っている方が使われてしまい、壊れる\n */\nexport const execp = (command: string) =>\n new Promise<string>((resolve, reject) => {\n exec(command, (err, stdout) => {\n if (err) {\n return reject(err)\n }\n\n return resolve(stdout)\n })\n })\n\nexport function mustBeDefined<T>(\n value: T,\n name: string,\n): asserts value is NonNullable<T> {\n if (typeof value === 'undefined') {\n throw new TypeError(`${name} must be defined.`)\n }\n}\n","import { promises as fs, existsSync } from 'fs'\nimport path from 'path'\nimport { execp } from './utils'\n\n/**\n * dir 内で変更があったファイル情報を for await で回せるようにするやつ\n */\nexport async function* getChangedFiles(dir: string) {\n if (!existsSync(dir))\n throw new Error(`icons-cli: target directory not found (${dir})`)\n const gitStatus = await collectGitStatus()\n for (const [relativePath, status] of gitStatus) {\n const fullpath = path.resolve(process.cwd(), '../../', relativePath)\n if (!fullpath.startsWith(`${dir}/`)) {\n continue\n }\n if (!existsSync(fullpath))\n throw new Error(`icons-cli: could not load svg (${fullpath})`)\n const content = await fs.readFile(fullpath, { encoding: 'utf-8' })\n yield { relativePath, content, status }\n }\n}\n\nasync function collectGitStatus() {\n return new Map(\n /**\n * @see https://git-scm.com/docs/git-status#_porcelain_format_version_1\n */\n (await execp(`git status --porcelain`)).split('\\n').map((s) => {\n return [\n s.slice(3),\n s.startsWith(' M')\n ? 'modified'\n : s.startsWith('??')\n ? 'untracked'\n : s.startsWith(' D')\n ? 'deleted'\n : null,\n ] as const\n }),\n )\n}\n","import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'\nimport path from 'path'\nimport { getChangedFiles } from './getChangedFiles'\n\ntype RefResponse =\n ReturnType<GithubClient['createBranch']> extends Promise<infer R> ? R : never\n\ninterface TreeItem {\n path?: string\n mode?: '100644' | '100755' | '040000' | '160000' | '120000'\n type?: 'blob' | 'commit' | 'tree'\n sha?: string | null\n content?: string\n}\n\nexport class GithubClient {\n private readonly api: Octokit\n private readonly now: Date\n\n static async runFromCli(\n repoOwner: string,\n repoName: string,\n token: string,\n defaultBranch: string,\n outputDir: string,\n ): Promise<ReturnType<GithubClient['createPullRequest']> | void> {\n const client = new this(repoOwner, repoName, token, defaultBranch)\n const outputDirFullPath = path.resolve(process.cwd(), outputDir)\n const diff = await client.createTreeFromDiff(outputDirFullPath)\n // eslint-disable-next-line no-console\n console.log(`${diff.length} files are changed`)\n if (diff.length === 0) {\n // eslint-disable-next-line no-console\n console.log('no changes. aborting')\n return\n }\n\n const newBranch = await client.createBranch()\n\n await client.createCommit(diff, newBranch)\n return client.createPullRequest(newBranch)\n }\n\n constructor(\n private readonly repoOwner: string,\n private readonly repoName: string,\n token: string,\n private readonly defaultBranch: string,\n now = new Date(),\n ) {\n this.api = new Octokit({\n auth: token,\n })\n\n this.now = now\n }\n\n get branch() {\n return `icons/update/${this.now.getTime()}`\n }\n\n /**\n * both used for commit message or pull request title\n */\n get message() {\n return `[icons-cli] Update icons ${this.now.toDateString()}`\n }\n\n async createTreeFromDiff(outputDir: string): Promise<TreeItem[]> {\n const tree: TreeItem[] = []\n\n for await (const file of getChangedFiles(outputDir)) {\n const item = {\n path: file.relativePath,\n // 100 はファイル 644 は実行不可なファイルであるという意味\n // @see https://octokit.github.io/rest.js/v18#git-create-tree\n mode: '100644' as const,\n content: file.content,\n }\n\n if (file.status === 'deleted') {\n // https://stackoverflow.com/questions/23637961/how-do-i-mark-a-file-as-deleted-in-a-tree-using-the-github-api\n tree.push({\n ...item,\n sha: null,\n })\n } else {\n tree.push(item)\n }\n }\n\n return tree\n }\n\n async createCommit(\n tree: TreeItem[],\n targetBranch: RefResponse,\n ): Promise<RestEndpointMethodTypes['git']['createCommit']['response']> {\n const parentCommit = await this.api.git.getCommit({\n owner: this.repoOwner,\n repo: this.repoName,\n\n commit_sha: targetBranch.data.object.sha,\n })\n\n const newTree = await this.api.git.createTree({\n owner: this.repoOwner,\n repo: this.repoName,\n\n base_tree: parentCommit.data.tree.sha,\n tree,\n })\n\n // この時点ではどのブランチにも属さないコミットができる\n const commit = await this.api.git.createCommit({\n owner: this.repoOwner,\n repo: this.repoName,\n message: this.message,\n tree: newTree.data.sha,\n parents: [parentCommit.data.sha],\n })\n\n // ref を更新することで、commit が targetBranch に属するようになる\n await this.api.git.updateRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `heads/${this.branch}`,\n sha: commit.data.sha,\n })\n\n return commit\n }\n\n async createPullRequest(\n targetBranch: RefResponse,\n ): Promise<ReturnType<GithubClient['api']['pulls']['create']>> {\n const defaultBranch = await this.getDefaultBranchRef()\n\n return this.api.pulls.create({\n owner: this.repoOwner,\n repo: this.repoName,\n head: targetBranch.data.ref,\n base: defaultBranch.data.ref,\n title: this.message,\n body: '',\n })\n }\n\n private getDefaultBranchRef() {\n return this.api.git.getRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `heads/${this.defaultBranch}`,\n })\n }\n\n async createBranch(): ReturnType<GithubClient['api']['git']['createRef']> {\n const defaultBranch = await this.getDefaultBranchRef()\n\n return this.api.git.createRef({\n owner: this.repoOwner,\n repo: this.repoName,\n ref: `refs/heads/${this.branch}`,\n sha: defaultBranch.data.object.sha,\n })\n }\n}\n","import type { CommitAction } from '@gitbeaker/core/dist/types/services/Commits'\nimport { Gitlab } from '@gitbeaker/node'\nimport path from 'path'\nimport { getChangedFiles } from './getChangedFiles'\n\ntype GitlabApi = InstanceType<typeof Gitlab>\n\nexport class GitlabClient {\n private readonly api: GitlabApi\n private readonly now: Date\n\n static async runFromCli(\n host: string,\n projectId: number,\n privateToken: string,\n defaultBranch: string,\n outputDir: string,\n ) {\n const client = new this(host, projectId, privateToken, defaultBranch)\n const outputDirFullPath = path.resolve(process.cwd(), outputDir)\n const diff = await client.createActionsFromDiff(outputDirFullPath)\n // eslint-disable-next-line no-console\n console.log(`${diff.length} files are changed`)\n if (diff.length === 0) {\n // eslint-disable-next-line no-console\n console.log('no changes. aborting')\n return\n }\n\n await client.createCommit(diff)\n return client.createMergeRequest()\n }\n\n constructor(\n private readonly host: string,\n private readonly projectId: number,\n privateToken: string,\n private readonly defaultBranch: string,\n now = new Date(),\n ) {\n this.api = new Gitlab({\n host: this.host,\n token: privateToken,\n })\n this.now = now\n }\n\n get branch() {\n return `icons/update/${this.now.getTime()}`\n }\n\n /**\n * both used for commit message or merge request title\n */\n get message() {\n return `[icons-cli] Update icons ${this.now.toDateString()}`\n }\n\n async createActionsFromDiff(outputDir: string): Promise<CommitAction[]> {\n const actions: CommitAction[] = []\n\n for await (const file of getChangedFiles(outputDir)) {\n actions.push({\n action:\n file.status === 'untracked'\n ? 'create'\n : file.status === 'deleted'\n ? 'delete'\n : 'update',\n filePath: file.relativePath,\n content: file.content,\n })\n }\n\n return actions\n }\n\n async createCommit(diff: CommitAction[]) {\n return this.api.Commits.create(\n this.projectId,\n this.branch,\n this.message,\n diff,\n {\n start_branch: this.defaultBranch,\n },\n )\n }\n\n createMergeRequest() {\n return this.api.MergeRequests.create(\n this.projectId,\n this.branch,\n this.defaultBranch,\n this.message,\n )\n }\n}\n","import { JSDOM } from 'jsdom'\nimport { parseToRgb } from 'polished'\nimport type { RgbColor, RgbaColor } from 'polished/lib/types/color'\nimport Svgo from 'svgo'\n\nexport const DEFAULT_CURRENT_COLOR_TARGET = '#858585'\n\nconst svgo = new Svgo({\n plugins: [\n // NOTICE: SVGO は「svg 内のすべての fill を currentColor に変える」機能しかない\n // icons-cli に必要なのは「特定の黒っぽい色だけ currentColor に変える」機能\n // なので、convertColors plugin は使わない\n // { convertColors: { currentColor: true } },\n { removeViewBox: false },\n { removeAttrs: { attrs: ['stroke-opacity', 'fill-opacity'] } },\n ],\n})\n\n/**\n * SVGを最適化するオプション\n */\ninterface Options {\n /**\n * currentColorに置換する色 #ffffff\n */\n convertedColor: string\n /**\n * svgoによる最適化を行わない\n */\n withoutOptimizeBySVGO?: boolean\n}\n\nexport async function optimizeSvg(input: string, options: Options) {\n const { document } = new JSDOM(input).window\n const svg = document.querySelector('svg')\n if (!svg) {\n throw new Error('optimizeSvg: input string seems not to have <svg>')\n }\n\n addViewboxToRootSvg(svg)\n convertToCurrentColor(svg, options.convertedColor)\n\n if (options.withoutOptimizeBySVGO === true) {\n return svg.outerHTML\n } else {\n return (await svgo.optimize(svg.outerHTML)).data\n }\n}\n\nconst TARGET_ATTRS = ['fill', 'stroke']\n\nfunction convertToCurrentColor(svg: SVGSVGElement, convertedColor: string) {\n const targetColor = parseColor(convertedColor)\n if (!targetColor) {\n throw new Error(`${convertedColor} is not a valid color`)\n }\n\n for (const attr of TARGET_ATTRS) {\n const targets = Array.from(svg.querySelectorAll<SVGElement>(`[${attr}]`))\n\n for (const el of targets) {\n const value = parseColor(el.getAttribute(attr))\n if (!value) {\n continue\n }\n\n if (!colorEquals(value, targetColor)) {\n continue\n }\n\n el.setAttribute(attr, 'currentColor')\n }\n }\n}\n\nfunction parseColor(value: string | null) {\n if (value == null) {\n return null\n }\n\n try {\n return parseToRgb(value)\n } catch {\n return null\n }\n}\n\nfunction colorEquals(self: RgbColor | RgbaColor, other: RgbColor | RgbaColor) {\n if (self.red !== other.red) {\n return false\n }\n\n if (self.blue !== other.blue) {\n return false\n }\n\n if (self.green !== other.green) {\n return false\n }\n\n if ('alpha' in self) {\n if ('alpha' in other) {\n if (self.alpha !== other.alpha) {\n return false\n }\n }\n }\n\n return true\n}\n\nfunction addViewboxToRootSvg(svg: SVGSVGElement) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const width = svg.getAttribute('width')!\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const height = svg.getAttribute('height')!\n\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`)\n}\n","import path from 'path'\nimport { glob } from 'fs/promises'\nimport fs from 'fs-extra'\nimport { concurrently } from '../concurrently'\nimport { optimizeSvg } from './optimizeSvg'\n\n/* eslint-disable no-console */\n\nexport const optimizeSvgInDirectory = async (\n outputDir: string,\n replaceColor: string,\n ignoreFile?: string,\n) => {\n const rootDir = path.join(outputDir, 'svg')\n\n const ignorePatterns =\n ignoreFile !== undefined\n ? (await fs.readFile(ignoreFile, 'utf8')).trim().split(/\\r?\\n/u)\n : []\n\n const files = await Array.fromAsync(\n glob('**/*.svg', {\n cwd: rootDir,\n }),\n )\n\n await concurrently(\n files.map((file) => async () => {\n console.log(`Optimizing ${file}...`)\n const fullPath = path.join(rootDir, file)\n\n const originalSvg = await fs.readFile(fullPath, 'utf8')\n const optimizedSvg = await optimizeSvg(originalSvg, {\n convertedColor: replaceColor,\n withoutOptimizeBySVGO: ignorePatterns.includes(file),\n })\n await fs.writeFile(fullPath, optimizedSvg)\n }),\n )\n}\n","import path from 'path'\nimport { glob } from 'node:fs/promises'\nimport fs from 'fs-extra'\n\nconst generateIconSvgEmbeddedSource = (svgString: string) => {\n const str = svgString.replace(/\\r?\\n/g, '')\n\n return `/** This file is auto generated. DO NOT EDIT BY HAND. */\nexport default '${str}'\n`\n}\n\nconst generateMjsEntrypoint = (\n icons: string[],\n) => `/** This file is auto generated. DO NOT EDIT BY HAND. */\n\nexport default {\n${icons\n .map((it) => ` '${it}': () => import('./${it}.js').then(m => m.default)`)\n .join(',\\n')}\n}\n`\n\nconst generateCjsEntrypoint = (\n icons: string[],\n) => `/** This file is auto generated. DO NOT EDIT BY HAND. */\n\nmodule.exports = {\n${icons\n .map((it) => ` '${it}': () => import('./${it}.js').then(m => m.default)`)\n .join(',\\n')}\n}\n`\n\nconst generateTypeDefinitionEntrypoint = (\n icons: string[],\n) => `/** This file is auto generated. DO NOt EDIT BY HAND. */\n\ndeclare var _default: {\n${icons.map((it) => ` '${it}': () => Promise<string>`).join(';\\n')}\n};\nexport default _default;\n`\n\nexport const generateEntrypoint = async (\n outputDir: string,\n icons: string[],\n) => {\n const srcRoot = path.join(outputDir, 'src')\n const mjsPath = path.join(srcRoot, 'index.js')\n await fs.ensureFile(mjsPath)\n await fs.writeFile(mjsPath, generateMjsEntrypoint(icons))\n\n const cjsPath = path.join(srcRoot, 'index.cjs')\n await fs.ensureFile(cjsPath)\n await fs.writeFile(cjsPath, generateCjsEntrypoint(icons))\n\n const dtsPath = path.join(srcRoot, 'index.d.ts')\n await fs.ensureFile(dtsPath)\n await fs.writeFile(dtsPath, generateTypeDefinitionEntrypoint(icons))\n}\n\nexport const generateIconSource = async (outputDir: string) => {\n const svgRoot = path.join(outputDir, 'svg')\n const srcRoot = path.join(outputDir, 'src')\n const icons = (await Array.fromAsync(glob('**/*.svg', { cwd: svgRoot })))\n .map(\n (path) => path.slice(0, -4), // e.g. '16/Add.svg' -> '16/Add'\n )\n .sort()\n\n for (const it of icons) {\n const data = await fs.readFile(path.join(svgRoot, `${it}.svg`))\n const outputPath = path.join(srcRoot, `${it}.js`)\n await fs.ensureFile(outputPath)\n await fs.writeFile(\n outputPath,\n generateIconSvgEmbeddedSource(data.toString()),\n )\n }\n\n await generateEntrypoint(outputDir, icons)\n}\n","#!/usr/bin/env node\n\nimport yargs from 'yargs'\nimport { FigmaFileClient } from './figma/FigmaFileClient'\nimport { GithubClient } from './GitHubClient'\nimport { GitlabClient } from './GitlabClient'\nimport { DEFAULT_CURRENT_COLOR_TARGET } from './svg/optimizeSvg'\nimport { optimizeSvgInDirectory } from './svg/optimizeSvgInDirectory'\nimport { generateIconSource } from './generateSource'\nimport { mustBeDefined } from './utils'\n\n/**\n * Figma\n */\nconst FIGMA_TOKEN = process.env.FIGMA_TOKEN\nconst FIGMA_FILE_URL = process.env.FIGMA_FILE_URL\nconst OUTPUT_ROOT_DIR = process.env.OUTPUT_ROOT_DIR\n\n/**\n * GitLab\n */\nconst GITLAB_ACCESS_TOKEN = process.env.GITLAB_ACCESS_TOKEN\nconst GITLAB_DEFAULT_BRANCH = process.env.GITLAB_DEFAULT_BRANCH\nconst GITLAB_HOST = process.env.GITLAB_HOST\nconst GITLAB_PROJECT_ID = process.env.GITLAB_PROJECT_ID\n\n/**\n * GitHub\n */\nconst GITHUB_ACCESS_TOKEN = process.env.GITHUB_ACCESS_TOKEN\nconst GITHUB_REPO_OWNER = process.env.GITHUB_REPO_OWNER\nconst GITHUB_REPO_NAME = process.env.GITHUB_REPO_NAME\nconst GITHUB_DEFAULT_BRANCH = process.env.GITHUB_DEFAULT_BRANCH\n\nvoid yargs\n .scriptName('icons-cli')\n .command(\n 'figma:export',\n 'Load all icons from Figma and save to files',\n {\n format: {\n default: 'svg',\n choices: ['svg', 'pdf'],\n describe: 'Output format',\n },\n layout: {\n default: 'v1',\n describe: 'Figma icon file layout version',\n },\n },\n async ({ format, layout }) => {\n mustBeDefined(FIGMA_FILE_URL, 'FIGMA_FILE_URL')\n mustBeDefined(FIGMA_TOKEN, 'FIGMA_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await FigmaFileClient.runFromCli(\n FIGMA_FILE_URL,\n FIGMA_TOKEN,\n OUTPUT_ROOT_DIR,\n format as 'svg' | 'pdf',\n layout as 'v1' | 'v2',\n )\n },\n )\n .command(\n 'svg:optimize',\n 'Optimize svg files in output directory',\n {\n color: {\n default: DEFAULT_CURRENT_COLOR_TARGET,\n type: 'string',\n describe: 'Color code that should be converted into `currentColor`',\n },\n ignoreFile: {\n type: 'string',\n describe:\n 'A file that contains the list of path to SVG files that should not be optimized',\n },\n },\n async ({ color, ignoreFile }) => {\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await optimizeSvgInDirectory(OUTPUT_ROOT_DIR, color, ignoreFile)\n },\n )\n .command(\n 'files:generate',\n 'Enumerate svg files in output directory and generate icon files',\n {},\n () => {\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n void generateIconSource(OUTPUT_ROOT_DIR).catch((e) => {\n // eslint-disable-next-line no-console\n console.error(e)\n process.exit(1)\n })\n },\n )\n .command(\n 'gitlab:mr',\n 'Create a merge request in the name of icons-cli',\n {},\n async () => {\n mustBeDefined(GITLAB_PROJECT_ID, 'GITLAB_PROJECT_ID')\n mustBeDefined(GITLAB_ACCESS_TOKEN, 'GITLAB_ACCESS_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await GitlabClient.runFromCli(\n GITLAB_HOST ?? 'https://gitlab.com',\n Number(GITLAB_PROJECT_ID),\n GITLAB_ACCESS_TOKEN,\n GITLAB_DEFAULT_BRANCH ?? 'main',\n OUTPUT_ROOT_DIR,\n )\n },\n )\n .command(\n 'github:pr',\n 'Create a pull request in the name of icons-cli',\n {},\n async () => {\n mustBeDefined(GITHUB_ACCESS_TOKEN, 'GITHUB_ACCESS_TOKEN')\n mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')\n\n await GithubClient.runFromCli(\n GITHUB_REPO_OWNER ?? 'pixiv',\n GITHUB_REPO_NAME ?? 'charcoal',\n GITHUB_ACCESS_TOKEN,\n GITHUB_DEFAULT_BRANCH ?? 'main',\n OUTPUT_ROOT_DIR,\n )\n },\n )\n .demandCommand()\n .strict()\n .help()\n .parse()\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charcoal-ui/icons-cli",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.7",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": "./dist/index.js",
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"@gitbeaker/node": "^25.6.0",
|
|
19
19
|
"@octokit/rest": "^18.12.0",
|
|
20
20
|
"camelcase": "^6.3.0",
|
|
21
|
-
"fast-glob": "^3.2.12",
|
|
22
21
|
"figma-js": "^1.14.0",
|
|
23
22
|
"fs-extra": "^10.0.0",
|
|
24
23
|
"got": "^11.8.3",
|
|
@@ -48,8 +47,8 @@
|
|
|
48
47
|
"build:react-v1": "pnpm svgr ../icon-files/svg/ --out-dir ../icons/src/react/v1 --typescript --ref --no-index --no-svgo && OUTPUT_ROOT_DIR=../icons/src/react/v1 VERSION=v1 pnpm tsx src/v2/transformReact.ts",
|
|
49
48
|
"build:css": "VERSION=v2 SOURCE_ROOT_DIR=../../../icon-files/v2/svg/ OUTPUT_ROOT_DIR=../icons/css/v2 pnpm tsx src/v2/transformCSS.ts",
|
|
50
49
|
"build:css-v1": "VERSION=v1 SOURCE_ROOT_DIR=../../../icon-files/svg/ OUTPUT_ROOT_DIR=../icons/css/v1 pnpm tsx src/v2/transformCSS.ts",
|
|
51
|
-
"build:uri": "SOURCE_ROOT_DIR=../../../icon-files/v2/svg/ OUTPUT_ROOT_DIR=../icon-files/v2
|
|
52
|
-
"build:uri-v1": "SOURCE_ROOT_DIR=../../../icon-files/svg/ OUTPUT_ROOT_DIR=../icon-files/v1
|
|
50
|
+
"build:uri": "SOURCE_ROOT_DIR=../../../icon-files/v2/svg/ OUTPUT_ROOT_DIR=../icon-files/v2/datauri pnpm tsx src/v2/transformDataUri.ts",
|
|
51
|
+
"build:uri-v1": "SOURCE_ROOT_DIR=../../../icon-files/svg/ OUTPUT_ROOT_DIR=../icon-files/v1/datauri pnpm tsx src/v2/transformDataUri.ts",
|
|
53
52
|
"typecheck": "tsc --pretty --noEmit",
|
|
54
53
|
"clean": "rimraf dist .tsbuildinfo",
|
|
55
54
|
"cli:icons": "./dist/index.js",
|
package/src/GitHubClient.ts
CHANGED
|
@@ -2,11 +2,8 @@ import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'
|
|
|
2
2
|
import path from 'path'
|
|
3
3
|
import { getChangedFiles } from './getChangedFiles'
|
|
4
4
|
|
|
5
|
-
type RefResponse =
|
|
6
|
-
infer R
|
|
7
|
-
>
|
|
8
|
-
? R
|
|
9
|
-
: never
|
|
5
|
+
type RefResponse =
|
|
6
|
+
ReturnType<GithubClient['createBranch']> extends Promise<infer R> ? R : never
|
|
10
7
|
|
|
11
8
|
interface TreeItem {
|
|
12
9
|
path?: string
|
|
@@ -25,7 +22,7 @@ export class GithubClient {
|
|
|
25
22
|
repoName: string,
|
|
26
23
|
token: string,
|
|
27
24
|
defaultBranch: string,
|
|
28
|
-
outputDir: string
|
|
25
|
+
outputDir: string,
|
|
29
26
|
): Promise<ReturnType<GithubClient['createPullRequest']> | void> {
|
|
30
27
|
const client = new this(repoOwner, repoName, token, defaultBranch)
|
|
31
28
|
const outputDirFullPath = path.resolve(process.cwd(), outputDir)
|
|
@@ -49,7 +46,7 @@ export class GithubClient {
|
|
|
49
46
|
private readonly repoName: string,
|
|
50
47
|
token: string,
|
|
51
48
|
private readonly defaultBranch: string,
|
|
52
|
-
now = new Date()
|
|
49
|
+
now = new Date(),
|
|
53
50
|
) {
|
|
54
51
|
this.api = new Octokit({
|
|
55
52
|
auth: token,
|
|
@@ -97,7 +94,7 @@ export class GithubClient {
|
|
|
97
94
|
|
|
98
95
|
async createCommit(
|
|
99
96
|
tree: TreeItem[],
|
|
100
|
-
targetBranch: RefResponse
|
|
97
|
+
targetBranch: RefResponse,
|
|
101
98
|
): Promise<RestEndpointMethodTypes['git']['createCommit']['response']> {
|
|
102
99
|
const parentCommit = await this.api.git.getCommit({
|
|
103
100
|
owner: this.repoOwner,
|
|
@@ -135,7 +132,7 @@ export class GithubClient {
|
|
|
135
132
|
}
|
|
136
133
|
|
|
137
134
|
async createPullRequest(
|
|
138
|
-
targetBranch: RefResponse
|
|
135
|
+
targetBranch: RefResponse,
|
|
139
136
|
): Promise<ReturnType<GithubClient['api']['pulls']['create']>> {
|
|
140
137
|
const defaultBranch = await this.getDefaultBranchRef()
|
|
141
138
|
|
package/src/GitlabClient.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class GitlabClient {
|
|
|
14
14
|
projectId: number,
|
|
15
15
|
privateToken: string,
|
|
16
16
|
defaultBranch: string,
|
|
17
|
-
outputDir: string
|
|
17
|
+
outputDir: string,
|
|
18
18
|
) {
|
|
19
19
|
const client = new this(host, projectId, privateToken, defaultBranch)
|
|
20
20
|
const outputDirFullPath = path.resolve(process.cwd(), outputDir)
|
|
@@ -36,7 +36,7 @@ export class GitlabClient {
|
|
|
36
36
|
private readonly projectId: number,
|
|
37
37
|
privateToken: string,
|
|
38
38
|
private readonly defaultBranch: string,
|
|
39
|
-
now = new Date()
|
|
39
|
+
now = new Date(),
|
|
40
40
|
) {
|
|
41
41
|
this.api = new Gitlab({
|
|
42
42
|
host: this.host,
|
|
@@ -65,8 +65,8 @@ export class GitlabClient {
|
|
|
65
65
|
file.status === 'untracked'
|
|
66
66
|
? 'create'
|
|
67
67
|
: file.status === 'deleted'
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
? 'delete'
|
|
69
|
+
: 'update',
|
|
70
70
|
filePath: file.relativePath,
|
|
71
71
|
content: file.content,
|
|
72
72
|
})
|
|
@@ -83,7 +83,7 @@ export class GitlabClient {
|
|
|
83
83
|
diff,
|
|
84
84
|
{
|
|
85
85
|
start_branch: this.defaultBranch,
|
|
86
|
-
}
|
|
86
|
+
},
|
|
87
87
|
)
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -92,7 +92,7 @@ export class GitlabClient {
|
|
|
92
92
|
this.projectId,
|
|
93
93
|
this.branch,
|
|
94
94
|
this.defaultBranch,
|
|
95
|
-
this.message
|
|
95
|
+
this.message,
|
|
96
96
|
)
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -68,14 +68,14 @@ export class FigmaFileClient {
|
|
|
68
68
|
token: string,
|
|
69
69
|
outputRootDir: string,
|
|
70
70
|
exportFormat: ExportFormat,
|
|
71
|
-
layoutVersion: FigmaIconFileLayoutVersion = 'v1'
|
|
71
|
+
layoutVersion: FigmaIconFileLayoutVersion = 'v1',
|
|
72
72
|
) {
|
|
73
73
|
const client = new this(url, token, exportFormat, layoutVersion)
|
|
74
74
|
|
|
75
75
|
const outputDir = path.join(process.cwd(), outputRootDir, exportFormat)
|
|
76
76
|
|
|
77
77
|
console.log(
|
|
78
|
-
`Exporting components from ${url} using layout ${layoutVersion}
|
|
78
|
+
`Exporting components from ${url} using layout ${layoutVersion}`,
|
|
79
79
|
)
|
|
80
80
|
await client.loadSvg(outputDir)
|
|
81
81
|
|
|
@@ -86,7 +86,7 @@ export class FigmaFileClient {
|
|
|
86
86
|
url: string,
|
|
87
87
|
personalAccessToken: string,
|
|
88
88
|
exportFormat: ExportFormat,
|
|
89
|
-
layoutVersion: FigmaIconFileLayoutVersion
|
|
89
|
+
layoutVersion: FigmaIconFileLayoutVersion,
|
|
90
90
|
) {
|
|
91
91
|
this.client = Figma.Client({
|
|
92
92
|
personalAccessToken,
|
|
@@ -174,14 +174,14 @@ export class FigmaFileClient {
|
|
|
174
174
|
|
|
175
175
|
const response = await got.get(
|
|
176
176
|
component.image,
|
|
177
|
-
this.exportFormat == 'pdf' ? { responseType: 'buffer' } : {}
|
|
177
|
+
this.exportFormat == 'pdf' ? { responseType: 'buffer' } : {},
|
|
178
178
|
)
|
|
179
179
|
|
|
180
180
|
await ensureDir(dirname)
|
|
181
181
|
|
|
182
182
|
console.log(`found: ${filename} => ✅ writing...`)
|
|
183
183
|
await writeFile(fullname, response.body, 'utf8')
|
|
184
|
-
})
|
|
184
|
+
}),
|
|
185
185
|
)
|
|
186
186
|
}
|
|
187
187
|
|
|
@@ -205,7 +205,7 @@ export class FigmaFileClient {
|
|
|
205
205
|
}
|
|
206
206
|
} else if ('children' in child) {
|
|
207
207
|
child.children.forEach((grandChild) =>
|
|
208
|
-
this.findComponentsRecursively(grandChild)
|
|
208
|
+
this.findComponentsRecursively(grandChild),
|
|
209
209
|
)
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -213,12 +213,12 @@ export class FigmaFileClient {
|
|
|
213
213
|
private findComponentsV2(document: Figma.Document) {
|
|
214
214
|
const iconsPage = document.children.find(
|
|
215
215
|
(child): child is Figma.Canvas =>
|
|
216
|
-
child.name === 'Icons 一覧' && child.type === 'CANVAS'
|
|
216
|
+
child.name === 'Icons 一覧' && child.type === 'CANVAS',
|
|
217
217
|
)
|
|
218
218
|
const iconComponentSets = iconsPage?.children.flatMap((c) => {
|
|
219
219
|
if (c.type !== 'FRAME') return []
|
|
220
220
|
return c.children.filter(
|
|
221
|
-
(c): c is Figma.ComponentSet => c.type === 'COMPONENT_SET'
|
|
221
|
+
(c): c is Figma.ComponentSet => c.type === 'COMPONENT_SET',
|
|
222
222
|
)
|
|
223
223
|
})
|
|
224
224
|
iconComponentSets?.forEach((set) => {
|
package/src/generateSource.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
-
import glob from '
|
|
2
|
+
import { glob } from 'node:fs/promises'
|
|
3
3
|
import fs from 'fs-extra'
|
|
4
4
|
|
|
5
5
|
const generateIconSvgEmbeddedSource = (svgString: string) => {
|
|
@@ -11,7 +11,7 @@ export default '${str}'
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const generateMjsEntrypoint = (
|
|
14
|
-
icons: string[]
|
|
14
|
+
icons: string[],
|
|
15
15
|
) => `/** This file is auto generated. DO NOT EDIT BY HAND. */
|
|
16
16
|
|
|
17
17
|
export default {
|
|
@@ -22,7 +22,7 @@ ${icons
|
|
|
22
22
|
`
|
|
23
23
|
|
|
24
24
|
const generateCjsEntrypoint = (
|
|
25
|
-
icons: string[]
|
|
25
|
+
icons: string[],
|
|
26
26
|
) => `/** This file is auto generated. DO NOT EDIT BY HAND. */
|
|
27
27
|
|
|
28
28
|
module.exports = {
|
|
@@ -33,7 +33,7 @@ ${icons
|
|
|
33
33
|
`
|
|
34
34
|
|
|
35
35
|
const generateTypeDefinitionEntrypoint = (
|
|
36
|
-
icons: string[]
|
|
36
|
+
icons: string[],
|
|
37
37
|
) => `/** This file is auto generated. DO NOt EDIT BY HAND. */
|
|
38
38
|
|
|
39
39
|
declare var _default: {
|
|
@@ -44,7 +44,7 @@ export default _default;
|
|
|
44
44
|
|
|
45
45
|
export const generateEntrypoint = async (
|
|
46
46
|
outputDir: string,
|
|
47
|
-
icons: string[]
|
|
47
|
+
icons: string[],
|
|
48
48
|
) => {
|
|
49
49
|
const srcRoot = path.join(outputDir, 'src')
|
|
50
50
|
const mjsPath = path.join(srcRoot, 'index.js')
|
|
@@ -63,9 +63,9 @@ export const generateEntrypoint = async (
|
|
|
63
63
|
export const generateIconSource = async (outputDir: string) => {
|
|
64
64
|
const svgRoot = path.join(outputDir, 'svg')
|
|
65
65
|
const srcRoot = path.join(outputDir, 'src')
|
|
66
|
-
const icons = (await glob('**/*.svg', { cwd: svgRoot }))
|
|
66
|
+
const icons = (await Array.fromAsync(glob('**/*.svg', { cwd: svgRoot })))
|
|
67
67
|
.map(
|
|
68
|
-
(path) => path.slice(0, -4) // e.g. '16/Add.svg' -> '16/Add'
|
|
68
|
+
(path) => path.slice(0, -4), // e.g. '16/Add.svg' -> '16/Add'
|
|
69
69
|
)
|
|
70
70
|
.sort()
|
|
71
71
|
|
|
@@ -75,7 +75,7 @@ export const generateIconSource = async (outputDir: string) => {
|
|
|
75
75
|
await fs.ensureFile(outputPath)
|
|
76
76
|
await fs.writeFile(
|
|
77
77
|
outputPath,
|
|
78
|
-
generateIconSvgEmbeddedSource(data.toString())
|
|
78
|
+
generateIconSvgEmbeddedSource(data.toString()),
|
|
79
79
|
)
|
|
80
80
|
}
|
|
81
81
|
|
package/src/getChangedFiles.ts
CHANGED
|
@@ -32,11 +32,11 @@ async function collectGitStatus() {
|
|
|
32
32
|
s.startsWith(' M')
|
|
33
33
|
? 'modified'
|
|
34
34
|
: s.startsWith('??')
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
? 'untracked'
|
|
36
|
+
: s.startsWith(' D')
|
|
37
|
+
? 'deleted'
|
|
38
|
+
: null,
|
|
39
39
|
] as const
|
|
40
|
-
})
|
|
40
|
+
}),
|
|
41
41
|
)
|
|
42
42
|
}
|
package/src/index.ts
CHANGED
|
@@ -58,9 +58,9 @@ void yargs
|
|
|
58
58
|
FIGMA_TOKEN,
|
|
59
59
|
OUTPUT_ROOT_DIR,
|
|
60
60
|
format as 'svg' | 'pdf',
|
|
61
|
-
layout as 'v1' | 'v2'
|
|
61
|
+
layout as 'v1' | 'v2',
|
|
62
62
|
)
|
|
63
|
-
}
|
|
63
|
+
},
|
|
64
64
|
)
|
|
65
65
|
.command(
|
|
66
66
|
'svg:optimize',
|
|
@@ -81,7 +81,7 @@ void yargs
|
|
|
81
81
|
mustBeDefined(OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')
|
|
82
82
|
|
|
83
83
|
await optimizeSvgInDirectory(OUTPUT_ROOT_DIR, color, ignoreFile)
|
|
84
|
-
}
|
|
84
|
+
},
|
|
85
85
|
)
|
|
86
86
|
.command(
|
|
87
87
|
'files:generate',
|
|
@@ -95,7 +95,7 @@ void yargs
|
|
|
95
95
|
console.error(e)
|
|
96
96
|
process.exit(1)
|
|
97
97
|
})
|
|
98
|
-
}
|
|
98
|
+
},
|
|
99
99
|
)
|
|
100
100
|
.command(
|
|
101
101
|
'gitlab:mr',
|
|
@@ -111,9 +111,9 @@ void yargs
|
|
|
111
111
|
Number(GITLAB_PROJECT_ID),
|
|
112
112
|
GITLAB_ACCESS_TOKEN,
|
|
113
113
|
GITLAB_DEFAULT_BRANCH ?? 'main',
|
|
114
|
-
OUTPUT_ROOT_DIR
|
|
114
|
+
OUTPUT_ROOT_DIR,
|
|
115
115
|
)
|
|
116
|
-
}
|
|
116
|
+
},
|
|
117
117
|
)
|
|
118
118
|
.command(
|
|
119
119
|
'github:pr',
|
|
@@ -128,9 +128,9 @@ void yargs
|
|
|
128
128
|
GITHUB_REPO_NAME ?? 'charcoal',
|
|
129
129
|
GITHUB_ACCESS_TOKEN,
|
|
130
130
|
GITHUB_DEFAULT_BRANCH ?? 'main',
|
|
131
|
-
OUTPUT_ROOT_DIR
|
|
131
|
+
OUTPUT_ROOT_DIR,
|
|
132
132
|
)
|
|
133
|
-
}
|
|
133
|
+
},
|
|
134
134
|
)
|
|
135
135
|
.demandCommand()
|
|
136
136
|
.strict()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
-
import glob from '
|
|
2
|
+
import { glob } from 'fs/promises'
|
|
3
3
|
import fs from 'fs-extra'
|
|
4
4
|
import { concurrently } from '../concurrently'
|
|
5
5
|
import { optimizeSvg } from './optimizeSvg'
|
|
@@ -9,7 +9,7 @@ import { optimizeSvg } from './optimizeSvg'
|
|
|
9
9
|
export const optimizeSvgInDirectory = async (
|
|
10
10
|
outputDir: string,
|
|
11
11
|
replaceColor: string,
|
|
12
|
-
ignoreFile?: string
|
|
12
|
+
ignoreFile?: string,
|
|
13
13
|
) => {
|
|
14
14
|
const rootDir = path.join(outputDir, 'svg')
|
|
15
15
|
|
|
@@ -18,9 +18,11 @@ export const optimizeSvgInDirectory = async (
|
|
|
18
18
|
? (await fs.readFile(ignoreFile, 'utf8')).trim().split(/\r?\n/u)
|
|
19
19
|
: []
|
|
20
20
|
|
|
21
|
-
const files = await
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const files = await Array.fromAsync(
|
|
22
|
+
glob('**/*.svg', {
|
|
23
|
+
cwd: rootDir,
|
|
24
|
+
}),
|
|
25
|
+
)
|
|
24
26
|
|
|
25
27
|
await concurrently(
|
|
26
28
|
files.map((file) => async () => {
|
|
@@ -33,6 +35,6 @@ export const optimizeSvgInDirectory = async (
|
|
|
33
35
|
withoutOptimizeBySVGO: ignorePatterns.includes(file),
|
|
34
36
|
})
|
|
35
37
|
await fs.writeFile(fullPath, optimizedSvg)
|
|
36
|
-
})
|
|
38
|
+
}),
|
|
37
39
|
)
|
|
38
40
|
}
|
package/src/utils.ts
CHANGED
package/src/v2/transformCSS.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mustBeDefined } from '../utils'
|
|
2
|
-
import glob from '
|
|
3
|
-
import {
|
|
2
|
+
import { glob, readFile, writeFile } from 'fs/promises'
|
|
3
|
+
import { ensureDir } from 'fs-extra'
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import { escape } from 'querystring'
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ async function transformV2(filePath: string, fileName: string) {
|
|
|
8
8
|
const content = await readFile(filePath, 'utf-8')
|
|
9
9
|
const [size, variant, name] = fileName.split('/')
|
|
10
10
|
const cssName = [
|
|
11
|
-
'charcoal-icon',
|
|
11
|
+
'charcoal-icon-v2',
|
|
12
12
|
name.toLowerCase().replace('.svg', '').replaceAll('.', '-'),
|
|
13
13
|
...(variant === 'regular' ? [] : [variant]),
|
|
14
14
|
...(size === '24' ? [] : [size]),
|
|
@@ -21,7 +21,7 @@ async function transformV2(filePath: string, fileName: string) {
|
|
|
21
21
|
height: 1em;
|
|
22
22
|
background: url('data:image/svg+xml;utf8,${escape(content).replace(
|
|
23
23
|
"'",
|
|
24
|
-
"\\'"
|
|
24
|
+
"\\'",
|
|
25
25
|
)}');
|
|
26
26
|
aspect-ratio: 1/1;
|
|
27
27
|
}`
|
|
@@ -32,7 +32,7 @@ async function transformV2(filePath: string, fileName: string) {
|
|
|
32
32
|
height: 1em;
|
|
33
33
|
mask-image: url('data:image/svg+xml;utf8,${escape(content).replace(
|
|
34
34
|
"'",
|
|
35
|
-
"\\'"
|
|
35
|
+
"\\'",
|
|
36
36
|
)}');
|
|
37
37
|
mask-size: 100% 100%;
|
|
38
38
|
background: currentColor;
|
|
@@ -62,7 +62,7 @@ async function transformV1(filePath: string, fileName: string) {
|
|
|
62
62
|
height: 1em;
|
|
63
63
|
background: url('data:image/svg+xml;utf8,${escape(content).replace(
|
|
64
64
|
"'",
|
|
65
|
-
"\\'"
|
|
65
|
+
"\\'",
|
|
66
66
|
)}');
|
|
67
67
|
aspect-ratio: 1/1;
|
|
68
68
|
}`
|
|
@@ -73,7 +73,7 @@ async function transformV1(filePath: string, fileName: string) {
|
|
|
73
73
|
height: 1em;
|
|
74
74
|
mask-image: url('data:image/svg+xml;utf8,${escape(content).replace(
|
|
75
75
|
"'",
|
|
76
|
-
"\\'"
|
|
76
|
+
"\\'",
|
|
77
77
|
)}');
|
|
78
78
|
mask-size: 100% 100%;
|
|
79
79
|
background: currentColor;
|
|
@@ -93,13 +93,13 @@ async function main() {
|
|
|
93
93
|
|
|
94
94
|
mustBeDefined(process.env.SOURCE_ROOT_DIR, 'SOURCE_ROOT_DIR')
|
|
95
95
|
const sourceDir = process.env.SOURCE_ROOT_DIR
|
|
96
|
-
const inputDir = path.join(
|
|
96
|
+
const inputDir = path.join(import.meta.dirname, sourceDir)
|
|
97
97
|
|
|
98
98
|
mustBeDefined(process.env.OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')
|
|
99
99
|
const outDir = process.env.OUTPUT_ROOT_DIR
|
|
100
100
|
|
|
101
101
|
await ensureDir(outDir)
|
|
102
|
-
const fileNames = await glob('**/*.svg', { cwd: inputDir })
|
|
102
|
+
const fileNames = await Array.fromAsync(glob('**/*.svg', { cwd: inputDir }))
|
|
103
103
|
|
|
104
104
|
let classNames: string[] = []
|
|
105
105
|
const filesWithContent = await Promise.all(
|
|
@@ -118,7 +118,7 @@ async function main() {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
throw new Error('VERSION received an unexpected value')
|
|
121
|
-
})
|
|
121
|
+
}),
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
const cssContent = filesWithContent
|
|
@@ -136,7 +136,7 @@ ${classNames
|
|
|
136
136
|
<div class="${icon}" aria-label=".${icon}" role="img" />
|
|
137
137
|
<code>.${icon}</code>
|
|
138
138
|
</div>
|
|
139
|
-
|
|
139
|
+
`,
|
|
140
140
|
)
|
|
141
141
|
.join('\n')}
|
|
142
142
|
</div>`
|
|
@@ -160,7 +160,7 @@ ${classNames
|
|
|
160
160
|
code {
|
|
161
161
|
font-size: 14px;
|
|
162
162
|
}
|
|
163
|
-
</style>${html}
|
|
163
|
+
</style>${html}`,
|
|
164
164
|
)
|
|
165
165
|
await writeFile(
|
|
166
166
|
path.join(outDir, 'index.story.tsx'),
|
|
@@ -205,7 +205,7 @@ export default {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
export const Default = {}
|
|
208
|
-
|
|
208
|
+
`,
|
|
209
209
|
)
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { glob } from '
|
|
2
|
-
import { ensureDir
|
|
1
|
+
import { glob, readFile, writeFile } from 'fs/promises'
|
|
2
|
+
import { ensureDir } from 'fs-extra'
|
|
3
3
|
import path from 'path'
|
|
4
4
|
import { mustBeDefined } from '../utils'
|
|
5
5
|
import { escape } from 'querystring'
|
|
@@ -7,13 +7,13 @@ import { escape } from 'querystring'
|
|
|
7
7
|
async function main() {
|
|
8
8
|
mustBeDefined(process.env.SOURCE_ROOT_DIR, 'SOURCE_ROOT_DIR')
|
|
9
9
|
const sourceDir = process.env.SOURCE_ROOT_DIR
|
|
10
|
-
const inputDir = path.join(
|
|
10
|
+
const inputDir = path.join(import.meta.dirname, sourceDir)
|
|
11
11
|
|
|
12
12
|
mustBeDefined(process.env.OUTPUT_ROOT_DIR, 'OUTPUT_ROOT_DIR')
|
|
13
13
|
const outDir = process.env.OUTPUT_ROOT_DIR
|
|
14
14
|
|
|
15
15
|
await ensureDir(outDir)
|
|
16
|
-
const fileNames = await glob('**/*.svg', { cwd: inputDir })
|
|
16
|
+
const fileNames = await Array.fromAsync(glob('**/*.svg', { cwd: inputDir }))
|
|
17
17
|
const dataUris = await Promise.all(
|
|
18
18
|
fileNames.map(async (fileName) => {
|
|
19
19
|
const filePath = path.join(inputDir, fileName)
|
|
@@ -24,7 +24,7 @@ async function main() {
|
|
|
24
24
|
uri: `data:image/svg+xml;utf8,${escape(content).replace("'", "\\'")}`,
|
|
25
25
|
isSetCurrentcolor: !content.includes('<def'),
|
|
26
26
|
}
|
|
27
|
-
})
|
|
27
|
+
}),
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
const js = `/** This file is auto generated. DO NOT EDIT BY HAND. */
|
|
@@ -35,7 +35,7 @@ ${dataUris
|
|
|
35
35
|
(it) =>
|
|
36
36
|
`'${it.iconName}': {uri: '${it.uri}', isSetCurrentcolor: ${
|
|
37
37
|
it.isSetCurrentcolor ? 'true' : 'false'
|
|
38
|
-
}}
|
|
38
|
+
}}`,
|
|
39
39
|
)
|
|
40
40
|
.join(',\n')}
|
|
41
41
|
}`
|
|
@@ -49,7 +49,7 @@ ${dataUris
|
|
|
49
49
|
(it) =>
|
|
50
50
|
`'${it.iconName}': {uri: '${it.uri}', isSetCurrentcolor: ${
|
|
51
51
|
it.isSetCurrentcolor ? 'true' : 'false'
|
|
52
|
-
}}
|
|
52
|
+
}}`,
|
|
53
53
|
)
|
|
54
54
|
.join(',\n')}
|
|
55
55
|
}`
|
package/src/v2/transformReact.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { mustBeDefined } from '../utils'
|
|
2
2
|
import ts from 'typescript'
|
|
3
|
-
import glob from '
|
|
4
|
-
import { readFile, writeFile } from 'fs-extra'
|
|
3
|
+
import { glob, readFile, writeFile } from 'fs/promises'
|
|
5
4
|
import path from 'path'
|
|
6
5
|
|
|
7
6
|
async function main() {
|
|
@@ -10,7 +9,7 @@ async function main() {
|
|
|
10
9
|
const workDir = process.env.OUTPUT_ROOT_DIR
|
|
11
10
|
const version = process.env.VERSION
|
|
12
11
|
|
|
13
|
-
const fileNames = await glob('*/**/*.tsx', { cwd: workDir })
|
|
12
|
+
const fileNames = await Array.fromAsync(glob('*/**/*.tsx', { cwd: workDir }))
|
|
14
13
|
const filesWithContent = await Promise.all(
|
|
15
14
|
fileNames.map(async (fileName) => {
|
|
16
15
|
const filePath = path.join(workDir, fileName)
|
|
@@ -20,13 +19,13 @@ async function main() {
|
|
|
20
19
|
fileName,
|
|
21
20
|
content,
|
|
22
21
|
}
|
|
23
|
-
})
|
|
22
|
+
}),
|
|
24
23
|
)
|
|
25
24
|
const { transformed, catalog } = rewrite(filesWithContent)
|
|
26
25
|
await Promise.all(
|
|
27
26
|
transformed.map(async (file) => {
|
|
28
27
|
return writeFile(file.filePath, file.content)
|
|
29
|
-
})
|
|
28
|
+
}),
|
|
30
29
|
)
|
|
31
30
|
const icons = Object.entries(catalog)
|
|
32
31
|
|
|
@@ -41,7 +40,7 @@ async function main() {
|
|
|
41
40
|
path.join(workDir, 'index.tsx'),
|
|
42
41
|
`${iconsPair
|
|
43
42
|
.map(([iconName, iconPath]) => `export {${iconName}} from '${iconPath}'`)
|
|
44
|
-
.join('\n')}
|
|
43
|
+
.join('\n')}`,
|
|
45
44
|
)
|
|
46
45
|
|
|
47
46
|
await writeFile(
|
|
@@ -73,7 +72,7 @@ ${icons
|
|
|
73
72
|
<div>
|
|
74
73
|
<${iconName} />
|
|
75
74
|
<code>${`<${iconName} />`}</code>
|
|
76
|
-
</div
|
|
75
|
+
</div>`,
|
|
77
76
|
)
|
|
78
77
|
.join('\n')}
|
|
79
78
|
</div>
|
|
@@ -99,7 +98,7 @@ const Global = createGlobalStyle\`
|
|
|
99
98
|
gap: 8px;
|
|
100
99
|
}
|
|
101
100
|
\`
|
|
102
|
-
|
|
101
|
+
`,
|
|
103
102
|
)
|
|
104
103
|
}
|
|
105
104
|
interface FileWithContent {
|
|
@@ -149,12 +148,12 @@ function rewrite(tsxSourceTexts: FileWithContent[]): {
|
|
|
149
148
|
node.declarationList.declarations[0].name,
|
|
150
149
|
node.declarationList.declarations[0].exclamationToken,
|
|
151
150
|
CreateSvgReturnType(ctx.factory),
|
|
152
|
-
node.declarationList.declarations[0].initializer
|
|
151
|
+
node.declarationList.declarations[0].initializer,
|
|
153
152
|
),
|
|
154
|
-
])
|
|
153
|
+
]),
|
|
155
154
|
),
|
|
156
155
|
visitor,
|
|
157
|
-
ctx
|
|
156
|
+
ctx,
|
|
158
157
|
)
|
|
159
158
|
}
|
|
160
159
|
}
|
|
@@ -179,7 +178,7 @@ function rewrite(tsxSourceTexts: FileWithContent[]): {
|
|
|
179
178
|
sourceText.content,
|
|
180
179
|
ts.ScriptTarget.ESNext,
|
|
181
180
|
undefined,
|
|
182
|
-
ts.ScriptKind.TSX
|
|
181
|
+
ts.ScriptKind.TSX,
|
|
183
182
|
)
|
|
184
183
|
})
|
|
185
184
|
const { transformed } = ts.transform(sources, [updateJSX])
|
|
@@ -200,28 +199,28 @@ function CreateSvgReturnType(factory: typeof ts.factory) {
|
|
|
200
199
|
factory.createTypeQueryNode(
|
|
201
200
|
factory.createQualifiedName(
|
|
202
201
|
factory.createIdentifier('React'),
|
|
203
|
-
factory.createIdentifier('forwardRef')
|
|
202
|
+
factory.createIdentifier('forwardRef'),
|
|
204
203
|
),
|
|
205
204
|
[
|
|
206
205
|
factory.createTypeReferenceNode(
|
|
207
206
|
factory.createIdentifier('SVGSVGElement'),
|
|
208
|
-
undefined
|
|
207
|
+
undefined,
|
|
209
208
|
),
|
|
210
209
|
factory.createTypeReferenceNode(
|
|
211
210
|
factory.createQualifiedName(
|
|
212
211
|
factory.createIdentifier('React'),
|
|
213
|
-
factory.createIdentifier('SVGProps')
|
|
212
|
+
factory.createIdentifier('SVGProps'),
|
|
214
213
|
),
|
|
215
214
|
[
|
|
216
215
|
factory.createTypeReferenceNode(
|
|
217
216
|
factory.createIdentifier('SVGSVGElement'),
|
|
218
|
-
undefined
|
|
217
|
+
undefined,
|
|
219
218
|
),
|
|
220
|
-
]
|
|
219
|
+
],
|
|
221
220
|
),
|
|
222
|
-
]
|
|
221
|
+
],
|
|
223
222
|
),
|
|
224
|
-
]
|
|
223
|
+
],
|
|
225
224
|
)
|
|
226
225
|
}
|
|
227
226
|
void main()
|