Skip to content

Instantly share code, notes, and snippets.

@stowball
Created October 24, 2017 09:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stowball/fbef3ad3744e09366e3b6eb8187f541e to your computer and use it in GitHub Desktop.
Save stowball/fbef3ad3744e09366e3b6eb8187f541e to your computer and use it in GitHub Desktop.
A node script to convert a a folder of SVGs in to React Native SVGs for https://github.com/stowball/react-native-svg-icon
/*
Usage: npm run convert-svgs <type:icons|logos>
*/
/* eslint-disable no-console, no-shadow */
const exec = require('child_process').exec;
const fs = require('fs');
const type = process.argv[2] || 'icons';
const path = `./src/assets/svg/${type}`;
const svgoOptions = {
plugins: [
{ collapseGroups: true },
{ convertPathData: true },
{ convertStyleToAttrs: true },
{ convertTransform: true },
{ removeDesc: true },
{ removeTitle: true },
],
};
const camelCase = (str) => str.replace(/(\w+)-(\w)/gi, (match, p1, p2) => `${p1}${p2.toUpperCase()}`);
const files = fs.readdirSync(`${path}`, 'utf8', (error, files) => files);
const jsFiles = files.filter((file) => file.indexOf('.js') > 0);
const svgFileNames = files
.filter((file) => file.indexOf('.svg') > 0)
.map((file) => file.replace(/\.svg/, ''));
jsFiles.forEach((file) => {
fs.unlink(`${path}/${file}`, (error) => {
if (error) {
console.log('error', error);
}
});
});
svgFileNames.forEach((file) => {
exec(`svgo ${path}/${file}.svg ${path}/${file}.min.svg --config='${JSON.stringify(svgoOptions)}'`, (error, stdout, stderror) => {
if (error) {
throw error;
}
if (stderror) {
console.log(stderror);
throw stderror;
}
fs.readFile(`${path}/${file}.min.svg`, 'utf8', (error, data) => {
if (error) {
throw error;
}
let svg = data
.replace(/(<\/?)([a-z])/gi, (match, p1, p2) => `${p1}${p2.toUpperCase()}`)
.replace(/(\s+[a-z]+?)-([a-z])/gi, (match, p1, p2) => `${p1}${p2.toUpperCase()}`)
.replace(/<\/?Svg.*?>/g, '')
.replace(/"\./g, '"0.')
.replace(/ fill="#0{3,6}"/g, '')
;
svg = `<G>${svg}</G>`;
const viewBox = data.match(/viewBox="(.*?)"/)[1];
let elems = svg.match(/<(\w+)/g);
elems = elems
.filter((elem, pos) => elems.indexOf(elem) === pos)
.map((elem) => elem.slice(1))
.sort();
let contents = 'import React from \'react\';\n';
contents += `import { ${elems.join(', ')} } from 'react-native-svg';\n\n`;
contents += 'export default';
if (viewBox !== '0 0 100 100') {
contents += ` {\n viewBox: '${viewBox}',\n svg: ${svg},\n}`;
} else {
contents += ` ${svg}`;
}
contents += ';\n';
fs.writeFile(`${path}/${file}.js`, contents, 'utf8', (error) => {
if (error) {
throw error;
}
console.log(`${file}.js created`);
fs.unlink(`${path}/${file}.min.svg`, (error) => {
if (error) {
console.log('error', error);
}
});
});
});
});
});
// eslint-disable-next-line arrow-body-style
let indexContents = svgFileNames.reduce((contents, fileName) => {
return `${contents}import ${camelCase(fileName)} from './${fileName}';\n`;
}, '');
indexContents += '\nexport default {\n';
// eslint-disable-next-line arrow-body-style
indexContents = svgFileNames.reduce((contents, fileName) => {
return `${contents} ${camelCase(fileName)},\n`;
}, indexContents);
indexContents += '};\n';
fs.writeFile(`${path}/index.js`, indexContents, 'utf8', (error) => {
if (error) {
throw error;
}
console.log('index.js created');
});
@thinklinux
Copy link

I had to change svgo ${path}/${file}.svg ${path}/${file}.min.svg to svgo ${path}/${file}.svg -o ${path}/${file}.min.svg in order for the script to work.

Thanks a lot! This script saves me soooo much time! Awesome work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment