@fws/cli
Version:
This CLI is work in progress and it's meant to work together with other Forwardslash boilerplates. Please do not use it if you don't have access to other stuff.
211 lines (173 loc) • 7.45 kB
JavaScript
/**
* SVG Icons
*
* @description Run scripts for handling and creating SVG icons.
*/
const fs = require('fs');
const path = require('path');
const fancyLog = require('fancy-log');
const colors = require('ansi-colors');
const _template = require('lodash.template');
const _startCase = require('lodash.startcase');
const helpers = require('../helpers');
const store = require('../store');
const SHF = require('./svg-handle-files');
module.exports = {
optimizeSVGs: [],
starter: '',
init: function() {
this.starter = store.getters.getStarter();
const projectRoot = store.getters.getProjectRoot();
// todo - add support for starter_twig for wpThemeDir
const wpThemeDir = path.join(store.getters.getWpThemePath(), store.getters.getWpThemeName());
const assetsRoot = this.starter !== helpers.starterNuxt ? wpThemeDir : projectRoot;
const assetsDir = `${this.starter !== helpers.starterNuxt ? 'src/' : ''}assets/svg`;
const svgDirPath = path.join(assetsRoot, assetsDir);
this.handleSvgFiles(svgDirPath);
this.generateFiles(svgDirPath);
},
handleSvgFiles: function(svgDirPath) {
fs.readdirSync(svgDirPath).forEach((file, i, allFiles) => {
const filePath = path.join(svgDirPath, file);
// remove non svg files from folder
if (path.extname(file) !== '.svg') {
try {
fs.unlinkSync(filePath);
helpers.consoleLogWarning(`deleted '${path.relative(svgDirPath, filePath)}' as it is not an SVG file`, 'red');
} catch (err) {
fancyLog(colors.red(err));
}
} else {
// svgo optimization
const optimizeSVG = SHF.optimizeSvgFiles(filePath)
.then(result => {
// save optimized file
return SHF.saveSvgFiles(filePath, result.data);
})
.then(() => {
// clean file name and prefix it
return SHF.renameSvgFiles(file, filePath, allFiles, svgDirPath);
});
// store all optimization Promise functions
this.optimizeSVGs.push(optimizeSVG);
}
});
},
generateFiles: function(svgDirPath) {
const _this = this;
Promise.all(this.optimizeSVGs)
.then(() => {
let msg = 'SVGs are optimized and SvgIconGen.vue file is generated!';
_this.generateSvgIcon(svgDirPath);
if (this.starter !== helpers.starterS) {
_this.generateSvgJson(svgDirPath);
msg += '\n And svgIconList.json for stories is generated!';
} else {
_this.generateSvgScssVars(svgDirPath);
msg += '\n And SCSS _icons.scss is generated!';
}
helpers.consoleLogWarning(msg, 'cyan');
})
.catch(error => {
fancyLog(colors.red(error));
});
},
loopFiles: function(svgDirPath, callback) {
fs.readdirSync(svgDirPath).forEach(file => {
const name = path.basename(file, '.svg');
const relPath = path.relative('src/scss', path.join(svgDirPath, file)).replace(/\\/g, '/');
const svg = {
name,
relPath
};
callback(svg);
});
},
generateSvgJson: function(svgDirPath) {
let icons = [];
// set new array of icons
this.loopFiles(svgDirPath, function(svg) {
const componentName = _startCase(svg.name.replace('ico-', '')).replace(/ /g, '');
icons.push({
fileName: svg.name,
componentName
});
});
// convert to JSON format
icons = JSON.stringify(icons, null, '\t');
// generate new JSON file
fs.writeFileSync(`${this.starter !== helpers.starterNuxt ? 'src/' : ''}stories/base/svgIconList.json`, icons, 'utf8');
},
generateSvgScssVars: function(svgDirPath) {
// get template file
const svgScssGenTempFile = path.join(helpers.moduleDir, 'templates', 'temp-svg-gen-scss.txt');
const svgScssGenTemp = fs.readFileSync(svgScssGenTempFile, 'utf8');
// set full lodash template
const compiledSvgScssGenFile = _template(svgScssGenTemp);
// compile parts of lodash template
let scssImports = '';
// set scss imports
this.loopFiles(svgDirPath, function(svg) {
scssImports += `\t@if $icon == ${svg.name} {\n`;
scssImports += `\t\t$path: '${svg.relPath}'\n`;
scssImports += '\t}\n';
});
// compile full lodash template
const dataSvgScssGen = compiledSvgScssGenFile({
imports: scssImports
});
// generate new Vue file
fs.writeFileSync('src/scss/config/_icons.scss', dataSvgScssGen, 'utf8');
},
generateSvgIcon: function(svgDirPath) {
// set write/temp dir and src string
let writeDir;
let compiledImportSrc;
let tempFile;
switch (this.starter) {
case helpers.starterS:
writeDir = 'src/vue/components/base/SvgIcon/SvgIconGen.vue';
compiledImportSrc = '../../../../assets/svg/<%= fileName %>.svg';
tempFile = 'temp-svg-gen-vue-js.txt';
break;
case helpers.starterNuxt:
writeDir = 'components/plugins/SvgIcon/SvgIconGen.vue';
compiledImportSrc = '~/assets/svg/<%= fileName %>.svg?inline';
tempFile = 'temp-svg-gen-vue-js.txt';
break;
case helpers.starterVue:
writeDir = 'src/components/base/SvgIcon/SvgIconGen.vue';
compiledImportSrc = '@/assets/svg/<%= fileName %>.svg';
tempFile = 'temp-svg-gen-vue-ts.txt';
break;
}
// get template file
const svgIconGenTempFile = path.join(helpers.moduleDir, 'templates', tempFile);
const svgIconGenTemp = fs.readFileSync(svgIconGenTempFile, 'utf8');
// set parts of lodash template
const compiledImport = _template(` import <%= componentName %> from '${compiledImportSrc}';\n`);
const compiledComponent = _template(' <%= componentName %>,\n');
// set full lodash template
const compiledSvgIconGenFile = _template(svgIconGenTemp);
let importStrings = '';
let componentsStrings = '';
// compile parts of lodash template
this.loopFiles(svgDirPath, function(svg) {
const componentName = _startCase(svg.name.replace('ico-', '')).replace(/ /g, '');
importStrings += compiledImport({
fileName: svg.name,
componentName
});
componentsStrings += compiledComponent({
componentName
});
});
// compile full lodash template
const dataSvgIconGen = compiledSvgIconGenFile({
imports: importStrings,
components: componentsStrings
});
// generate new Vue file
fs.writeFileSync(writeDir, dataSvgIconGen, 'utf8');
}
};