diff --git a/README.md b/README.md index 7b258a2..188ce91 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,17 @@ will generate } ```` +In svg files use no-sassvg class on elements where color, stroke or style should not be replaced: +````xml + + +```` +will generate +````xml + + +```` + ## Documentation Documentation may be generated using sassdoc. Otherwise, just read the _sassvg.scss file, should be clear how to use the provided sassvg() and the sassvg-list() functions. Here are some screeenshots of the essential sassdoc parts: diff --git a/index.js b/index.js index a914a27..5f334a9 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,10 @@ //require what we need var through = require('through2') -, PluginError = require('plugin-error') -, fs = require('fs') -, cheerio = require('cheerio') -, SVGO = require('svgo') -, svgo = new SVGO();; + , PluginError = require('plugin-error') + , fs = require('fs') + , cheerio = require('cheerio') + , SVGO = require('svgo') + , svgo = new SVGO();; // TODO rework with js classes/prototypes and promises, much less functions @@ -15,150 +15,148 @@ const DATA_PREFIX = "data:image/svg+xml;charset=US-ASCII,"; -function fileNameFromPath(filePath){ +function fileNameFromPath(filePath) { return filePath.split('\\').pop().split('/').pop().replace(/\.[^/.]+$/, ""); } -function folderNameFromPath(filePath){ +function folderNameFromPath(filePath) { var firstSplit = filePath.split('\\'); - if(firstSplit.length > 1){ + if (firstSplit.length > 1) { return firstSplit[firstSplit.length - 2]; } - + var secondSplit = filePath.split('/'); - if(secondSplit.length > 1){ + if (secondSplit.length > 1) { return secondSplit[secondSplit.length - 2]; } return ""; } -function sassVarRegex(variableName, optionalSuffix){ - var suffix = (optionalSuffix !== undefined) ? encodeURIComponent(optionalSuffix) : ""; +function sassVarRegex(variableName, optionalSuffix) { + var suffix = (optionalSuffix !== undefined) ? encodeURIComponent(optionalSuffix) : ""; return new RegExp(encodeURIComponent("#{$") + variableName + encodeURIComponent("}") + suffix, "gm"); // #{$variableName} } -function addVariables(filePath, fileContent){ - var $ = cheerio.load(fileContent, { - normalizeWhitespace: true, - xmlMode: true - }); - if($('svg').length !== 1){ - throw new PluginError(PLUGIN_NAME, "Wrong SVG-File at '" + filePath + "'."); - } - if($('[fill]').not('[fill=none]').length > 0){ - $('[fill]').not('[fill=none]').not('.no-sassvg').attr('fill', '#{$fillcolor}'); - }else{ - $('svg').attr('fill', '#{$fillcolor}'); - } - $('[style]').each(function(){ - var fillValue = $(this).css("fill"); - if(fillValue !== undefined && fillValue !== 'none'){ - $(this).css("fill", "#{$fillcolor}"); - } - var strokeValue = $(this).css("stroke"); - if(strokeValue !== undefined && strokeValue !== 'none'){ - $(this).css("stroke", "#{$strokecolor}"); - } - }); - $('svg').each(function(){ - var styles = $(this).attr("style"); - $(this).css("empty", "empty;#{$extrastyles}"); //not the very best solution, but makes it valid and works everytime - empty props will be regexed out again - }); - $('[stroke]').not('[stroke=none]').attr('stroke', '#{$strokecolor}'); - return $.html('svg'); //return only the svg +function addVariables(filePath, fileContent) { + var $ = cheerio.load(fileContent, { + normalizeWhitespace: true, + xmlMode: true + }); + if ($('svg').length !== 1) { + throw new PluginError(PLUGIN_NAME, "Wrong SVG-File at '" + filePath + "'."); + } + if ($('[fill]').not('[fill=none]').length > 0) { + $('[fill]').not('[fill=none]').not('.no-sassvg').attr('fill', '#{$fillcolor}'); + } else { + $('svg').attr('fill', '#{$fillcolor}'); + } + $('[style]').not('.no-sassvg').each(function () { + var fillValue = $(this).css("fill"); + if (fillValue !== undefined && fillValue !== 'none') { + $(this).css("fill", "#{$fillcolor}"); + } + var strokeValue = $(this).css("stroke"); + if (strokeValue !== undefined && strokeValue !== 'none') { + $(this).css("stroke", "#{$strokecolor}"); + } + }); + $('svg').each(function () { + var styles = $(this).attr("style"); + $(this).css("empty", "empty;#{$extrastyles}"); //not the very best solution, but makes it valid and works everytime - empty props will be regexed out again + }); + $('[stroke]').not('[stroke=none]').not('.no-sassvg').attr('stroke', '#{$strokecolor}'); + return $.html('svg'); //return only the svg } -function encodeSVG(dynamicContent){ +function encodeSVG(dynamicContent) { return encodeURIComponent(dynamicContent.replace(/[\t\n\r]/gmi, " ")) //replace tab, linefeed and carriage return .replace(/\(/g, "%28") // opening brackets .replace(/\)/g, "%29") // closing brackets .replace(/["']/g, "%22"); // double quotes - + } -function decodeVariables(encodedContent){ +function decodeVariables(encodedContent) { return encodedContent.replace(sassVarRegex("fillcolor"), "#{$fillcolor}") .replace(sassVarRegex("strokecolor"), "#{$strokecolor}") .replace(sassVarRegex("extrastyles", ";"), "#{$extrastyles}") - .replace(/empty%3A%20empty%3B/gm, "");//correct the empty styles props + .replace(/empty%3A%20empty%3B/gm, "");//correct the empty styles props } -function assembleDataString(fileName, finalContent){ +function assembleDataString(fileName, finalContent) { return "@function sassvg-" + fileName + "($fillcolor, $strokecolor, $extrastyles){ @return '" + DATA_PREFIX + finalContent + "'; }\n"; } -function optimizeSvg(writeStream, cb, filePath, svgString){ - svgo.optimize(svgString).then(function(result) { - var optimizedSvg; - if(result.error){ - throw new PluginError(PLUGIN_NAME, "SVG couldn't be optimized: '" + file.path + "', will try to SASSVG it without optimizing."); - optimizedSvg = String(file.contents); - }else{ - optimizedSvg = result.data; - } - sassvgIt(writeStream, cb, filePath, svgString); +function optimizeSvg(writeStream, cb, filePath, svgString) { + svgo.optimize(svgString).then(function (result) { + var optimizedSvg; + if (result.error) { + throw new PluginError(PLUGIN_NAME, "SVG couldn't be optimized: '" + file.path + "', will try to SASSVG it without optimizing."); + optimizedSvg = String(file.contents); + } else { + optimizedSvg = result.data; + } + sassvgIt(writeStream, cb, filePath, svgString); }); } -function sassvgIt(writeStream, cb, filePath, svgString){ - writeStream.write( - assembleDataString( - fileNameFromPath(filePath), - decodeVariables( - encodeSVG( - addVariables( - filePath, - svgString - ) - ) - ) - ) - ); - cb(); +function sassvgIt(writeStream, cb, filePath, svgString) { + writeStream.write( + assembleDataString( + fileNameFromPath(filePath), + decodeVariables( + encodeSVG( + addVariables( + filePath, + svgString + ) + ) + ) + ) + ); + cb(); } -var options -var gulpSassvg = function(optionsGiven){ +var options +var gulpSassvg = function (optionsGiven) { options = optionsGiven || {}; options.tmpDir = optionsGiven.tmpDir || "./.tmp-sassvg/"; //TODO still necessary? options.outputFolder = optionsGiven.outputFolder || "./scss/"; //TODO add some options - if( options.outputFolder.indexOf("/", options.outputFolder.length - 1) === -1 ){ - options.outputFolder = options.outputFolder + "/"; - } - options.outputMainFile = options.outputFolder + "_sassvg.scss"; - options.outputDataFile = options.outputFolder + "_sassvg-data.scss"; - options.optimizeSvg = (optionsGiven.optimizeSvg !== undefined) ? optionsGiven.optimizeSvg : true; //true = 25% less filesize, but 3 times as long to create the sass file - - var writeStreamMain = fs.createWriteStream(options.outputMainFile); - writeStreamMain.write(fs.readFileSync(__dirname + "/_sassvg.scss", "utf8")); - writeStreamMain.end(); - + if (options.outputFolder.indexOf("/", options.outputFolder.length - 1) === -1) { + options.outputFolder = options.outputFolder + "/"; + } + options.outputMainFile = options.outputFolder + "_sassvg.scss"; + options.outputDataFile = options.outputFolder + "_sassvg-data.scss"; + options.optimizeSvg = (optionsGiven.optimizeSvg !== undefined) ? optionsGiven.optimizeSvg : true; //true = 25% less filesize, but 3 times as long to create the sass file + + var writeStreamMain = fs.createWriteStream(options.outputMainFile); + writeStreamMain.write(fs.readFileSync(__dirname + "/_sassvg.scss", "utf8")); + writeStreamMain.end(); + var writeStream = fs.createWriteStream(options.outputDataFile); var sassvgMap = "\n\n$sassvg-map: ("; - - function listStream(file, enc, cb){ - var folderName = folderNameFromPath(file.path); - var fileName = fileNameFromPath(file.path); - sassvgMap += "'" + fileName + "': ('name': '" + fileName + "', 'folder': '" + folderName + "'),"; - if(options.optimizeSvg){ - optimizeSvg(writeStream, cb, file.path, String(file.contents)) - }else{ - sassvgIt(writeStream, cb, file.path, String(file.contents)); - } + + function listStream(file, enc, cb) { + var folderName = folderNameFromPath(file.path); + var fileName = fileNameFromPath(file.path); + sassvgMap += "'" + fileName + "': ('name': '" + fileName + "', 'folder': '" + folderName + "'),"; + if (options.optimizeSvg) { + optimizeSvg(writeStream, cb, file.path, String(file.contents)) + } else { + sassvgIt(writeStream, cb, file.path, String(file.contents)); + } } - - function endStream(cb){ - sassvgMap += ");"; - writeStream.write(sassvgMap); + + function endStream(cb) { + sassvgMap += ");"; + writeStream.write(sassvgMap); writeStream.end(); cb(); } return through.obj(listStream, endStream); } module.exports = gulpSassvg; - -