UNPKG

svg2vectordrawable

Version:

JavaScript module and command-line tools for convert SVG to Android vector drawable.

254 lines (231 loc) 8.29 kB
const fs = require('fs'); const path = require('path'); const pkg = require('../package.json'); const svg2vectordrawable = require('./svg-to-vectordrawable'); const { outputFile, convertFile } = require('./svg-file-to-vectordrawable-file'); let programName = process.argv[1]; let exampleText = '\n\n' + 'Example:\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -i input.svg -o output.xml\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -p 4 -i input.svg -o output.xml\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -i input.svg -o output_folder\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -f input_folder -o output_folder\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -s \'<svg>...</svg>\'\n' + ' \x1b[31m\x1b[1m' + path.basename(programName) + '\x1b[0m -s \'<svg>...</svg>\' -o output.xml'; // https://github.com/veged/coa module.exports = require('coa').Cmd() .helpful() .name(programName) .title(pkg.description + exampleText) .opt() .name('version') .title('Version') .short('v') .long('version') .only() .flag() .act(function(opts) { return pkg.version; }) .end() .opt() .name('input') .title('Input file, must be a SVG file.') .short('i') .long('input') .val(function(val) { return val || this.reject('Option "-i, --input" must have a value.'); }) .end() .opt() .name('folder') .title('Input folder, convert all *.svg files.') .short('f') .long('folder') .val(function(val) { return val || this.reject('Option "-f, --folder" must have a value.'); }) .end() .opt() .name('string') .title('Input full SVG code, or a SVG tag code.') .short('s') .long('string') .val(function(val) { val = val.replace(/\n/g, "").trim(); if (/^<.*>$/.test(val)) { return val; } else { return this.reject('Option "-s, --string" must be a SVG code.'); } }) .end() .opt() .name('output') .title('Output file or folder (by default the same as the input).') .short('o') .long('output') .val(function(val) { return val || this.reject('Option "-o, --output" must have a value.'); }) .end() .opt() .name('precision') .title('[optional] Set number of digits in the fractional part, default is 2.') .short('p') .long('precision') .val(function(val) { if (isNaN(val)) { return this.reject('Option "-p, --precision" must be an natural number.'); } else { val = Number(val); if (Number.isInteger(val) && val > 0) { return Math.min(val, 10); } else if (val === 0){ return this.reject('Option "-p, --precision" can\'t be 0.'); } else { return this.reject('Option "-p, --precision" must be an natural number.'); } } }) .end() .opt() .name('xmlTag') .title('[optional] Code with a XML tag.') .short('x') .long('xml') .val(function(val) { return true; }) .end() .opt() .name('tint') .title('[optional] Add tint color to vector drawable. -t "#FFF" ') .short('t') .long('tint') .val(function(val) { return val || this.reject('Option "-t, --tint", color value must inside quotes, like \'#FFF\' or "#FFF". ');; }) .end() .act(function(opts, args) { if (!opts.input && !opts.string && !opts.folder) { return this.usage(); } let input = opts.input || args.input; let options = { floatPrecision: opts.precision, strict: false, fillBlack: false, xmlTag: opts.xmlTag ? true : false, tint: opts.tint }; // -s '<...>' -o file if (opts.string) { svg2vectordrawable(opts.string, options).then(xml => { let output = opts.output; if (output) { if (!/\.xml$/i.test(output)) { output += '.xml'; } return outputFile(xml, output).then(() => { console.log(`Save to "${output}".`); }).catch(err => { showErrorAndExit(err.message); }); } else { return console.log(`\nAndroid Vector Drawable Code:\n\n${xml}`); } }).catch(err => { return showErrorAndExit(err.message); }); } else { let svgFiles = []; // -f if (opts.folder) { if (isDirectory(opts.folder)) { fs.readdirSync(opts.folder).forEach(file => { if (/\.svg$/i.test(file)) { svgFiles.push(path.join(opts.folder, file)); } }); if (svgFiles.length === 0) { return showErrorAndExit(`Folder "${opts.folder}" has not any SVG file.`); } } else if (isFile(opts.folder)) { return showErrorAndExit(`File "${opts.folder}" must be a folder.`); } else { return showErrorAndExit(`Folder "${opts.folder}" is not exists.`); } // -o if (!opts.output) { opts.output = opts.folder; } } // -i if (input) { if (isFile(input)) { if (/\.svg$/i.test(input)) { svgFiles.push(input); } else { return showErrorAndExit(`File "${input}" must be a SVG file.`); } } else if (isDirectory(input)) { return showErrorAndExit(`File "${input}" must be a file.`); } else { return showErrorAndExit(`File "${input}" is not exists.`); } // -o if (!opts.output) { opts.output = path.dirname(input); } } // output svgFiles.forEach(svgFile => { let filePath; if (input && /\.xml$/i.test(opts.output)) { let fileName = path.basename(opts.output, '.xml').replace(/[^a-z0-9]/gi, '_').replace(/^\d+/,'').toLowerCase(); filePath = path.join(path.dirname(opts.output), fileName + '.xml'); } else { let fileName = path.basename(svgFile, '.svg').replace(/[^a-z0-9]/gi, '_').replace(/^\d+/,'').toLowerCase(); filePath = path.join(opts.output, fileName + '.xml'); } return convertFile(svgFile, filePath, options).then(() => { console.log(`∙ ${svgFile}${filePath}`); }).catch(err => { showErrorAndExit(`Error ${err.message} while converting file ${svgFile}`); }); }); } }); function isFile(filePath) { if (fs.existsSync(filePath)) { if (fs.statSync(filePath).isFile()) { return true; } } return false; } function isDirectory(filePath) { if (fs.existsSync(filePath)) { if (fs.statSync(filePath).isDirectory()) { return true; } } return false; } function showErrorAndExit(message) { console.error(message); process.exit(1); }