Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export async function convertSvgToReact(
svgName: string,
svgData: string,
options: Options = DEFAULT_OPTIONS
): Promise {
const componentName = fileNameToComponentName(svgName);
// Convert the SVG into our ideal format
let svgDataCleaned = '';
try {
svgDataCleaned = await svgr(svgData, config, {componentName});
} catch (e) {
console.error(`Couldn't process svg data through SVGR: `, e);
}
// Remove the trailing semicolon from the generated SVG
// I use my own templating to solve for issues in theirs, which is why I need to do this
const noTrailingSemicolonSvg = removeLastCharacter(svgDataCleaned);
// Dump the SVG JSX into our template
let fileTemplate = options.useHooks ? fileTemplateReactHooks : fileTemplateReactDefault;
if (options.template != null) {
fileTemplate = options.template;
}
const templateJSX = fileTemplate({
componentName,
path.join(fullSvgDirectory, filename),
"utf-8"
);
// We have to use a custom svgo setup because the `svgr` one isn't
// configurable and will sometimes remove fills and strokes that we
// don't want removed.
const { data: svg } = await svgo.optimize(svgCode, {
path: path.join(fullSvgDirectory, filename),
});
const componentName = formatComponentName(
path.basename(filename, path.extname(filename))
);
const componentSource = await svgr(
svg,
{
dimensions: false,
template: function svgrTemplate(
{ template },
_opts,
{
imports,
componentName,
jsx,
}: {
imports: any;
componentName: string;
jsx: types.JSXElement;
}
) {
// Validate color attributes
['stroke', 'fill'].forEach(attr => {
const color = $el.attr(attr);
const validColors = ['currentColor', 'none', '#000'];
if (color && !validColors.includes(color)) {
throw new Error(`${svgName}: Invalid ${attr} color: ${$.html(el)}`);
}
});
});
const iconName = `Icon${pascalCase(svgName)}`;
const svgComponentName = `${iconName}${
variantName ? pascalCase(variantName) : ''
}Svg`;
const svgComponent = await svgr(optimisedSvg, svgrConfig, {
componentName: svgComponentName,
});
// Create icon directory if it's missing
const iconDir = path.join(iconComponentsDir, iconName);
await fs.mkdirp(iconDir);
// Write SVG React component
await fs.writeFile(
path.join(iconDir, `${svgComponentName}.tsx`),
svgComponent,
{ encoding: 'utf-8' },
);
// Bail out early if we're processing an icon variant (e.g. bookmark-active.svg)
// All subsequent steps should only happen once per icon component.
export const svg2jsx: FileDataTransformer = ({ fileData, filePath }) => {
/*
* There's no built-in SVGR template that works for both
* React Native and TypeScript. So it seems easier
* to use the React Native one and make some
* clunky manual replaces to the outputed content.
*/
const svgrData = svgr.sync(fileData, {
native: true,
// prettier plugin not working well.
// plugins: ['@svgr/plugin-prettier'],
});
/**/
return { fileData: svgrData, filePath };
};
module.exports.transform = function(src, filename, options) {
if (typeof src === "object") {
// handle RN >= 0.46
({ src, filename, options } = src);
}
if (filename.endsWith(".svg") || filename.endsWith(".svgx")) {
var config = resolveConfig.sync(resolveConfigDir(filename));
var svgrConfig = config
? Object.assign({}, defaultsvgrConfig, config)
: defaultsvgrConfig;
var jsCode = svgr.sync(src, svgrConfig);
return upstreamTransformer.transform({
src: fixRenderingBugs(jsCode),
filename,
options
});
}
return upstreamTransformer.transform({ src, filename, options });
};
files.forEach(fileName => {
const fileNameWithoutExtension = path.basename(fileName, iconFileExt);
const componentName = upperFirst(camelCase(fileNameWithoutExtension));
const svgCode = fs.readFileSync(fileName, 'UTF-8');
const jsCode = svgr.sync(
svgCode,
{
icon: false,
svgoConfig: {
plugins: [
{ removeViewBox: false },
{ prefixIds: true },
// same result as rollup plugin
{ prefixIds: { prefix: fileNameWithoutExtension } },
// Keeps ID's of svgs so they can be targeted with CSS
{ cleanupIDs: false },
],
},
// same as the rollup plugin
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
module.exports.transform = function(src, filename, options) {
if (typeof src === "object") {
// handle RN >= 0.46
({ src, filename, options } = src);
}
if (filename.endsWith(".svg") || filename.endsWith(".svgx")) {
var config = resolveConfig.sync(resolveConfigDir(filename));
var svgrConfig = config
? Object.assign({}, defaultsvgrConfig, config)
: defaultsvgrConfig;
var jsCode = svgr.sync(src, svgrConfig);
return upstreamTransformer.transform({
src: fixRenderingBugs(jsCode),
filename,
options
});
}
return upstreamTransformer.transform({ src, filename, options });
};
console.log(chalk.green(`[Generate SVG Component] Icon Amount: ${svgFileNames.length}`));
const componentNames = [];
const metaData = {};
const mirrorMetaData = {};
for (const svgPath of svgFilePaths) {
const svgCode = fs.readFileSync(svgPath);
const svgName = `${getComponentName({ filePath: svgPath })}`;
componentNames.push(svgName);
const kebabcaseName = kebabcase(svgName);
metaData[kebabcaseName] = svgName;
mirrorMetaData[svgName] = kebabcaseName;
if (shouldGenerateReactComponent) {
const componentCode = await svgr(svgCode, svgrConfig, { filePath: svgPath });
fs.writeFileSync(path.resolve(OUTPUT_DIR, `${svgName}.tsx`), componentCode);
}
}
if (shouldGenerateReactComponent) {
console.log(chalk.green(`[Generate SVG Component] Icon Components Generated!`));
}
fs.writeFileSync(OUTPUT_INDEX,
fs.readFileSync(path.resolve(__dirname, './index.ts.template'), { encoding: 'utf8' })
.replace('<% EXPORT_ALL_REACT_COMPONENTS %>', shouldGenerateReactComponent ? componentNames.map((name) => `export { default as ${name} } from './components/${name}';`).join('\n') : '')
);
console.log(chalk.green(`[Generate SVG Component] Entry Generated!`));
function createJs(file, component) {
const svgFile = fs.readFileSync(file, 'utf-8');
return svgr.default(
svgFile,
//this is where the rendered React component is customized:
unDrawConfig,
{ componentName: component }
)
.then (jsxFile => {
fs.writeFileSync(`${path}${component}/${component}.js`, jsxFile);
console.log(`Succesfully created component: ${component}` )
})
.catch (err => {
throw new Error("failed to generate React component, check svgr config and template")
})
}
await Promise.all(outputDirs.map((dir) => rimraf(dir)));
if (shouldGenerateReactComponent) {
await mkdirp(OUTPUT_DIR);
}
console.log(chalk.green(`[Generate SVG Component] Icon Amount: ${svgFileNames.length}`));
const componentNames = [];
const metaData = {};
const mirrorMetaData = {};
for (const svgPath of svgFilePaths) {
const svgCode = fs.readFileSync(svgPath);
const svgName = `${getComponentName({ filePath: svgPath })}`;
componentNames.push(svgName);
const kebabcaseName = kebabcase(svgName);
metaData[kebabcaseName] = svgName;
mirrorMetaData[svgName] = kebabcaseName;
if (shouldGenerateReactComponent) {
const componentCode = await svgr(svgCode, svgrConfig, { filePath: svgPath });
fs.writeFileSync(path.resolve(OUTPUT_DIR, `${svgName}.tsx`), componentCode);
}
}
if (shouldGenerateReactComponent) {
console.log(chalk.green(`[Generate SVG Component] Icon Components Generated!`));
}