init push
This commit is contained in:
124
web/packages/icons/scripts/generate.ts
Normal file
124
web/packages/icons/scripts/generate.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import prettier from 'prettier';
|
||||
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
async function downloadAndExtractSVGs(url) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
const svgString = await response.text();
|
||||
await extractSVGs(svgString);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch SVG string:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const toCamelCase = str => {
|
||||
return str
|
||||
.replace(/-./g, match => match.charAt(1).toUpperCase())
|
||||
.replace(/^./, match => match.toUpperCase());
|
||||
};
|
||||
|
||||
// 将SVG属性从短横线命名法转换为驼峰命名法
|
||||
const convertSvgAttributes = (content: string): string => {
|
||||
return content.replace(/(\w+)-(\w+)=/g, (match, p1, p2) => {
|
||||
const camelCase = p1 + p2.charAt(0).toUpperCase() + p2.slice(1);
|
||||
return `${camelCase}=`;
|
||||
});
|
||||
};
|
||||
|
||||
const extractSVGs = async svgString => {
|
||||
const svgMatch = svgString.match(
|
||||
/window\._iconfont_svg_string_.*?'(<svg>.*<\/svg>)'/,
|
||||
);
|
||||
|
||||
const prettierConfig = await prettier.resolveConfig(
|
||||
path.resolve(dirname, '../../../prettier.config.js'),
|
||||
);
|
||||
|
||||
if (!svgMatch || !svgMatch[1]) {
|
||||
console.error('无法提取SVG字符串。请检查输入是否正确。');
|
||||
return;
|
||||
}
|
||||
|
||||
const svgSpriteString = svgMatch[1];
|
||||
|
||||
const symbolRegex =
|
||||
/<symbol\s+id="([^"]+)"\s+viewBox="([^"]+)">([\s\S]*?)<\/symbol>/g;
|
||||
|
||||
let match;
|
||||
const icons: { id: string; viewBox: string; content: string }[] = [];
|
||||
|
||||
while ((match = symbolRegex.exec(svgSpriteString)) !== null) {
|
||||
const [fullMatch, id, viewBox, content] = match;
|
||||
icons.push({ id, viewBox, content });
|
||||
}
|
||||
|
||||
for (const icon of icons) {
|
||||
const { id, viewBox, content } = icon;
|
||||
const formattedName = toCamelCase(id);
|
||||
const fileName = `${formattedName}.tsx`;
|
||||
|
||||
// 转换SVG属性为驼峰命名法
|
||||
const convertedContent = convertSvgAttributes(content);
|
||||
|
||||
// 生成 React/JSX 组件代码
|
||||
const reactComponentCode = `import React from 'react';
|
||||
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
|
||||
|
||||
const ${formattedName} = (props: SvgIconProps) => (
|
||||
<SvgIcon
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
viewBox='${viewBox}'
|
||||
{...props}
|
||||
>
|
||||
${convertedContent}
|
||||
</SvgIcon>
|
||||
);
|
||||
|
||||
${formattedName}.displayName = '${id}';
|
||||
|
||||
export default ${formattedName};`;
|
||||
const targetDir = path.resolve(dirname, '../src');
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
}
|
||||
const prettierCode = await prettier.format(reactComponentCode, {
|
||||
parser: 'typescript',
|
||||
...prettierConfig,
|
||||
});
|
||||
fs.writeFileSync(path.resolve(targetDir, fileName), prettierCode);
|
||||
}
|
||||
};
|
||||
|
||||
async function start(url) {
|
||||
await downloadAndExtractSVGs(url);
|
||||
const srcDirname = path.resolve(dirname, '../src');
|
||||
const fileNames = fs.readdirSync(srcDirname);
|
||||
const newIndexContent = fileNames
|
||||
.map(fileName => {
|
||||
if (fileName === 'index.tsx') {
|
||||
return '';
|
||||
}
|
||||
const name = path.basename(fileName, '.tsx');
|
||||
return `export { default as ${name} } from './${name}';`;
|
||||
})
|
||||
.join('\n');
|
||||
fs.writeFileSync(path.resolve(srcDirname, 'index.tsx'), newIndexContent);
|
||||
|
||||
console.log('Generate Icon Success');
|
||||
}
|
||||
|
||||
let argument = process.argv.splice(2);
|
||||
|
||||
if (!argument[0]) {
|
||||
console.error('请输入 iconfont 的URL');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
start(argument[0]?.includes('http') ? argument[0] : `https:${argument[0]}`);
|
||||
Reference in New Issue
Block a user