diff --git a/packages/rollup-plugin-stdf-icon/README.md b/packages/rollup-plugin-stdf-icon/README.md index 193c362d..6757fd35 100644 --- a/packages/rollup-plugin-stdf-icon/README.md +++ b/packages/rollup-plugin-stdf-icon/README.md @@ -72,14 +72,14 @@ Note: **The parameter should be an array** representing the configuration for mu In general, the use of symbols is to combine a series of small, single-color SVG files into one symbol. This allows for easy modification of attributes such as color, size, and opacity when using SVG in a project. Therefore, when default configuring rollup-plugin-stdf-icon, the color attributes of the SVG files themselves are removed. If you need to use multi-color SVG files and want to preserve the colors in the generated symbol, you just need to set the `simple` parameter to `false`. -# Configuration - -| Parameter | Default | Description | -| --------- | ---------------- | ------------------------------------------------------------------------------------------------------------- | -| inFile | 'src/lib/symbol' | The folder where all the SVG files to be merged are located. | -| outFile | 'static/fonts' | The output path for the merged SVG symbol file. | -| fileName | '' | The filename of the merged SVG symbol file (if not passed, the last folder name of `inFile` will be used). | -| simple | true | Whether to use the simple mode, the simple mode will remove the color attributes of the SVG files themselves. | +# Array Configuration + +| Parameter | Type | Default | Description | +| --------- | ------ | ---------------- | ------------------------------------------------------------------------------------------------------------- | +| inFile | `string` | `'src/lib/symbol'` | The folder where all the SVG files to be merged are located. | +| outFile | `string` | `'static/fonts'` | The output path for the merged SVG symbol file. | +| fileName | `string` | `''` | The filename of the merged SVG symbol file (if not passed, the last folder name of `inFile` will be used). | +| simple | `boolean` | `true` | Whether to use the simple mode, the simple mode will remove the color attributes of the SVG files themselves. | # License diff --git a/packages/rollup-plugin-stdf-icon/README_CN.md b/packages/rollup-plugin-stdf-icon/README_CN.md index 1a784085..4df545ad 100644 --- a/packages/rollup-plugin-stdf-icon/README_CN.md +++ b/packages/rollup-plugin-stdf-icon/README_CN.md @@ -72,14 +72,14 @@ export default defineConfig({ 一般来说,使用 symbol 的场景是将一系列小的单色 svg 合并为一个 symbol,可以方便项目使用 svg 时修改颜色、大小、透明度等属性,所以默认配置下 rollup-plugin-stdf-icon 会去除掉 svg 本身的颜色属性。如果需要使用多色 svg,合成的 symbol 需要保留 svg 本身的颜色,只需要将 `simple` 参数设置为 `false`。 -# 配置 - -| 参数 | 默认 | 描述 | -| -------- | ---------------- | ------------------------------------------------------------------------------ | -| inFile | 'src/lib/symbol' | 将要被合并的所有 SVG 文件所在的文件夹。 | -| outFile | 'static/fonts' | 合并后的 SVG symbol 文件的输出路径。 | -| fileName | '' | 合并后的 SVG symbol 文件的文件名(如果不传则取 inFile 的最后一个文件夹名称)。 | -| simple | true | 是否使用简单模式,简单模式会将 svg 自带的颜色去除。 | +# 数组配置 + +| 参数 | 类型 | 默认 | 描述 | +| -------- | ------ | ---------------- | ------------------------------------------------------------------------------ | +| inFile | `string` | `'src/lib/symbol'` | 将要被合并的所有 SVG 文件所在的文件夹。 | +| outFile | `string` | `'static/fonts'` | 合并后的 SVG symbol 文件的输出路径。 | +| fileName | `string` | `''` | 合并后的 SVG symbol 文件的文件名(如果不传则取 inFile 的最后一个文件夹名称)。 | +| simple | `boolean` | `true` | 是否使用简单模式,简单模式会将 svg 自带的颜色去除。 | # 许可证 diff --git a/packages/rollup-plugin-stdf-icon/package.json b/packages/rollup-plugin-stdf-icon/package.json index 5fb69877..897d0972 100644 --- a/packages/rollup-plugin-stdf-icon/package.json +++ b/packages/rollup-plugin-stdf-icon/package.json @@ -1,8 +1,9 @@ { "name": "rollup-plugin-stdf-icon", - "version": "0.0.15", + "version": "0.1.0", "description": "A Rollup plugin that combines a series of svg into one symbol for use in the STDF project", "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { "build": "rollup -c", "test": "node test/index.js" @@ -26,13 +27,17 @@ "node": ">=14.14" }, "dependencies": { - "fs-extra": "^11.1.1", - "svgo": "^3.0.2", + "fs-extra": "^11.2.0", + "svgo": "^3.3.2", "svgstore": "^3.0.1" }, "devDependencies": { - "@rollup/plugin-terser": "^0.4.3", - "rollup": "^3.27.0" + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.1", + "@types/fs-extra": "^11.0.4", + "@types/node": "^22.10.2", + "rollup": "^4.28.1", + "typescript": "^5.7.2" }, "keywords": [ "stdf", diff --git a/packages/rollup-plugin-stdf-icon/rollup.config.js b/packages/rollup-plugin-stdf-icon/rollup.config.js index 365b0f7d..740ab5f0 100644 --- a/packages/rollup-plugin-stdf-icon/rollup.config.js +++ b/packages/rollup-plugin-stdf-icon/rollup.config.js @@ -1,8 +1,13 @@ +import typescript from '@rollup/plugin-typescript'; import terser from '@rollup/plugin-terser'; export default { - input: 'src/index.js', - output: [{ file: 'dist/index.js', format: 'es' }], - external: ['fs-extra', 'svgo', 'svgstore'], - plugins: [terser({ keep_fnames: true })], + input: 'src/index.ts', + output: { + file: 'dist/index.js', + format: 'esm', + sourcemap: true, + }, + plugins: [typescript(), terser()], + external: ['fs-extra', 'svgo', 'svgstore'], }; diff --git a/packages/rollup-plugin-stdf-icon/src/index.js b/packages/rollup-plugin-stdf-icon/src/index.js deleted file mode 100644 index 4e2eec08..00000000 --- a/packages/rollup-plugin-stdf-icon/src/index.js +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env node - -import fs from 'fs-extra'; -import { optimize } from 'svgo'; -import svgstore from 'svgstore'; - -export default function svgSprite(datas) { - // 可接收多组参数,处理多个文件夹内的文件 - // Multiple parameters can be accepted to process files in multiple folders - const data = datas ? datas : [{ inFile: 'src/lib/symbol', outFile: 'static/fonts', fileName: '', simple: true }]; - - // 循环处理每一组参数 - // Loop through each set of parameters - data.forEach(item => { - const { inFile, outFile, fileName, simple = true } = item; - // 如果 fileName 为默认 '',则将 inFile 的最后一个文件夹作为 fileName,注意不同操作系统的路径分隔符 - // If fileName is the default '', then the last folder of inFile is used as fileName, pay attention to the path separator of different operating systems - const fileNameInner = fileName ? fileName : inFile.split('/').pop(); - handleFile(inFile, outFile, fileNameInner, simple); - }); - - return { name: 'rollup-plugin-stdf-icon' }; -} - -// 处理一个文件夹内的文件 -// Process files in a folder -function handleFile(inFile, outFile, fileName, simple = true) { - // 如果 outFile 不存在, 则创建 - // If outFile does not exist, create it - if (!fs.existsSync(outFile)) { - fs.mkdirSync(outFile); - } - - // 创建一个空的 svgstore - // Create an empty svgstore - const sprites = svgstore({ cleanDefs: true }); - - // 循环 icons 目录下的所有 svg 文件 - // Loop through all svg files in the icons directory - const svgs = fs.readdirSync(inFile); - - svgs.forEach(svg => { - if (!svg.endsWith('.svg')) { - // 读取 svg 文件内容, 如果文件不是 svg 文件, 则给出提示并跳过 - // Read the contents of the svg file, if the file is not an svg file, give a prompt and skip - console.warn(`[rollup-plugin-stdf-icon]: ${inFile}/${svg} is not a svg file, skip it!`); - } else { - const code = fs.readFileSync(`${inFile}/${svg}`, 'utf8'); - - // 使用 SVGO 进行优化 - // Use SVGO for optimization - const result = optimize(code); - - // 删除 result 中的 p-id class 等属性 - // Delete p-id class and other attributes in result - result.data = result.data.replace(/p-id="[^"]*"/g, '').replace(/class="[^"]*"/g, ''); - - // 如果 result 中有 fill 属性,属性值不为 none, 则将 fill 属性值设置为 currentColor - // If there is a fill attribute in result, the attribute value is not none, then set the fill attribute value to currentColor - if (simple && result.data.indexOf('fill=') > -1 && result.data.indexOf('fill="none"') === -1) { - result.data = result.data.replace(/fill="[^"]*"/g, 'fill="currentColor"'); - } - - // 如果 result 中有 stroke 属性,属性值不为 none, 则将 stroke 属性值设置为 currentColor - // If there is a stroke attribute in result, the attribute value is not none, then set the stroke attribute value to currentColor - if (simple && result.data.indexOf('stroke=') > -1 && result.data.indexOf('stroke="none"') === -1) { - result.data = result.data.replace(/stroke="[^"]*"/g, 'stroke="currentColor"'); - } - - // 将优化后的 svg 添加到 sprites 中 - // Add the optimized svg to sprites - sprites.add(svg.replace('.svg', ''), result.data, { copyAttrs: ['fill', 'stroke'] }); - } - }); - - // 删除 sprites 的 标签和 标签 和 标签 - // Delete the tag and tag of sprites - const spritesStr = sprites - .toString() - .replace(/<\?xml[^>]*>/g, '') - .replace(/]*>/g, '') - .replace(//g, ''); - - // 写入到指定的文件中 - // Write to the specified file - fs.writeFileSync(outFile + '/' + fileName + '.svg', spritesStr); -} diff --git a/packages/rollup-plugin-stdf-icon/src/index.ts b/packages/rollup-plugin-stdf-icon/src/index.ts new file mode 100644 index 00000000..57f2d9e2 --- /dev/null +++ b/packages/rollup-plugin-stdf-icon/src/index.ts @@ -0,0 +1,103 @@ +import fs from 'fs-extra'; +import { optimize } from 'svgo'; +// @ts-expect-error svgstore no declaration file +import svgstore from 'svgstore'; + +interface StdfIconOptions { + inFile?: string; + outFile?: string; + fileName?: string; + simple?: boolean; +} + +export default function svgSprite(datas: StdfIconOptions[] = []) { + // 可接收多组参数,处理多个文件夹内的文件 + // Multiple parameters can be accepted to process files in multiple folders + const data = datas ? datas : [{ inFile: 'src/lib/symbol', outFile: 'static/fonts', fileName: '', simple: true }]; + + // 循环处理每一组参数 + // Loop through each set of parameters + if (Array.isArray(data)) { + // 给出提示,开始处理几个文件夹 + // Give a prompt, how many folders are being processed + console.log(`[rollup-plugin-stdf-icon]: ⌛ Start processing ${data.length} folders...`); + + data.forEach((item: any) => { + const { inFile, outFile, fileName, simple = true } = item; + // 如果 fileName 为默认 '',则将 inFile 的最后一个文件夹作为 fileName,注意不同操作系统的路径分隔符 + // If fileName is the default '', then the last folder of inFile is used as fileName, pay attention to the path separator of different operating systems + const fileNameInner = fileName ? fileName : inFile.split('/').pop(); + handleFile(inFile, outFile, fileNameInner, simple); + }); + } + + return { name: 'rollup-plugin-stdf-icon' }; +} + +// 处理一个文件夹内的文件 +// Process files in a folder +function handleFile(inFile: string, outFile: string, fileName: string, simple = true) { + // 如果 outFile 不存在, 则创建 + // If outFile does not exist, create it + if (!fs.existsSync(outFile)) { + fs.mkdirSync(outFile); + } + + // 创建一个空的 svgstore + // Create an empty svgstore + const sprites = svgstore({ cleanDefs: true }); + + // 循环 icons 目录下的所有 svg 文件 + // Loop through all svg files in the icons directory + const svgs = fs.readdirSync(inFile); + + svgs.forEach((svg: string) => { + if (!svg.endsWith('.svg')) { + // 读取 svg 文件内容, 如果文件不是 svg 文件, 则给出提示并跳过 + // Read the contents of the svg file, if the file is not an svg file, give a prompt and skip + console.warn(`[rollup-plugin-stdf-icon]: ⏭️ ${inFile}/${svg} is not a svg file, skip it!`); + } else { + const code = fs.readFileSync(`${inFile}/${svg}`, 'utf8'); + + // 使用 SVGO 进行优化 + // Use SVGO for optimization + const result = optimize(code); + + // 删除 result 中的 p-id class 等属性 + // Delete p-id class and other attributes in result + result.data = result.data.replace(/p-id="[^"]*"/g, '').replace(/class="[^"]*"/g, ''); + + // 如果 result 中有 fill 属性,属性值不为 none, 则将 fill 属性值设置为 currentColor + // If there is a fill attribute in result, the attribute value is not none, then set the fill attribute value to currentColor + if (simple && result.data.indexOf('fill=') > -1 && result.data.indexOf('fill="none"') === -1) { + result.data = result.data.replace(/fill="[^"]*"/g, 'fill="currentColor"'); + } + + // 如果 result 中有 stroke 属性,属性值不为 none, 则将 stroke 属性值设置为 currentColor + // If there is a stroke attribute in result, the attribute value is not none, then set the stroke attribute value to currentColor + if (simple && result.data.indexOf('stroke=') > -1 && result.data.indexOf('stroke="none"') === -1) { + result.data = result.data.replace(/stroke="[^"]*"/g, 'stroke="currentColor"'); + } + + // 将优化后的 svg 添加到 sprites 中 + // Add the optimized svg to sprites + sprites.add(svg.replace('.svg', ''), result.data, { copyAttrs: ['fill', 'stroke'] }); + } + }); + + // 已完成合并(inFile)中的多少个 svg 文件至 outFile/fileName.svg + // Have merged how many svg files in (inFile) to outFile/fileName.svg + console.log(`[rollup-plugin-stdf-icon]: ✅ ${inFile} has merged ${svgs.length} svg files to ${outFile}/${fileName}.svg`); + + // 删除 sprites 的 标签和 标签 和 标签 + // Delete the tag and tag of sprites + const spritesStr = sprites + .toString() + .replace(/<\?xml[^>]*>/g, '') + .replace(/]*>/g, '') + .replace(//g, ''); + + // 写入到指定的文件中 + // Write to the specified file + fs.writeFileSync(outFile + '/' + fileName + '.svg', spritesStr); +} diff --git a/packages/rollup-plugin-stdf-icon/test/index.js b/packages/rollup-plugin-stdf-icon/test/index.js index bdc7fe1c..2af6da4d 100644 --- a/packages/rollup-plugin-stdf-icon/test/index.js +++ b/packages/rollup-plugin-stdf-icon/test/index.js @@ -1,4 +1,4 @@ -import svgSprite from '../src/index.js'; +import svgSprite from '../dist/index.js'; // 将会在 test 目录下生成 symbol.svg 文件,内容为 test/icons 目录下所有 svg 文件的 symbol // Let the symbol.svg file be generated in the test directory, and the content is the symbol of all svg files in the test/icons directory diff --git a/packages/rollup-plugin-stdf-icon/tsconfig.json b/packages/rollup-plugin-stdf-icon/tsconfig.json new file mode 100644 index 00000000..7177817f --- /dev/null +++ b/packages/rollup-plugin-stdf-icon/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "node", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "declaration": true, + "declarationDir": "dist", + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test"] +} \ No newline at end of file