Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

grunt-svgstore

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-svgstore - npm Package Compare versions

Comparing version 0.2.5 to 0.2.6

test/expected/cleanup.svg

9

Gruntfile.js

@@ -104,2 +104,11 @@ /*

}
},
cleanup: {
options: {
cleanup: true
},
files: {
'tmp/cleanup.svg': ['test/fixtures/cleanup.svg']
}
}

@@ -106,0 +115,0 @@ },

2

package.json
{
"name": "grunt-svgstore",
"description": "Merge SVGs from a folder.",
"version": "0.2.5",
"version": "0.2.6",
"homepage": "https://github.com/FWeinb/grunt-svgstore",

@@ -6,0 +6,0 @@ "author": {

@@ -100,2 +100,8 @@ # grunt-svgstore [![NPM version](https://badge.fury.io/js/grunt-svgstore.svg)](http://badge.fury.io/js/grunt-svgstore) [![Build Status](https://travis-ci.org/FWeinb/grunt-svgstore.svg?branch=master)](https://travis-ci.org/FWeinb/grunt-svgstore)

#### options.cleanup (since 0.2.6)
Type: `boolean`
Default value: `false`
Clean up all inline style definitions that may jeopardise later stylesheet-based colouring (`fill`).
### Usage Examples

@@ -131,2 +137,6 @@

#### 0.2.6
* Add `options.clean` to remove inline styles from source svgs. (Thanks to [ain](https://github.com/FWeinb/grunt-svgstore/pull/37))
* Reformat source to use 2 spaces for indentation (Fix [#36](https://github.com/FWeinb/grunt-svgstore/issues/36))
#### 0.2.5

@@ -133,0 +143,0 @@ * To generate the id from the filename is now used as a title. (Fix [#33](https://github.com/FWeinb/grunt-svgstore/issues/33))

@@ -11,215 +11,211 @@ /*

module.exports = function (grunt) {
var crypto = require('crypto');
var multiline = require('multiline');
var path = require('path');
var crypto = require('crypto');
var multiline = require('multiline');
var path = require('path');
var beautify = require('js-beautify').html;
var cheerio = require('cheerio');
var chalk = require('chalk');
var beautify = require('js-beautify').html;
var cheerio = require('cheerio');
var chalk = require('chalk');
var md5 = function (str) {
return crypto.createHash('md5').update(str).digest('hex');
};
var md5 = function (str) {
return crypto.createHash('md5').update(str).digest('hex');
};
var symbolAttributes = function(attrs){
if (typeof attrs === 'undefined') {return '';}
var symbolAttributes = function(attrs){
if(typeof attrs === 'undefined') {return '';}
var result = '';
Object.keys(attrs).forEach(function (key) {
result += ' ' + key + '="' + attrs[key] + '"';
});
return result;
};
var result = '';
Object.keys(attrs).forEach(function (key) {
result += ' ' + key + '="' + attrs[key] + '"';
});
return result;
};
var convertNameToId = function( name ){
var dotPos = name.indexOf('.');
if ( dotPos > -1){
name = name.substring(0, dotPos);
}
return name;
};
var convertNameToId = function( name ){
var dotPos = name.indexOf('.');
if ( dotPos > -1){
name = name.substring(0, dotPos);
}
return name;
};
// Matching an url() reference. To correct references broken by making ids unquie to the source svg
var urlPattern = /url\(\s*#([^ ]+?)\s*\)/g;
// Matching an url() reference. To correct references broken by making ids unquie to the source svg
var urlPattern = /url\(\s*#([^ ]+?)\s*\)/g;
// Please see the Grunt documentation for more information regarding task
// creation: http://gruntjs.com/creating-tasks
// Please see the Grunt documentation for more information regarding task
// creation: http://gruntjs.com/creating-tasks
grunt.registerMultiTask('svgstore', 'Merge SVGs from a folder.', function () {
// Merge task-specific and/or target-specific options with these defaults.
var options = this.options({
prefix: '',
svg: {
'xmlns': "http://www.w3.org/2000/svg"
},
formatting: false,
includedemo: false,
symbol: {}
});
grunt.registerMultiTask('svgstore', 'Merge SVGs from a folder.', function () {
// Merge task-specific and/or target-specific options with these defaults.
var options = this.options({
prefix: '',
svg: {
'xmlns': "http://www.w3.org/2000/svg"
},
formatting: false,
includedemo: false,
symbol: {}
});
var symbolAttrs = symbolAttributes(options.symbol);
var symbolAttrs = symbolAttributes(options.symbol);
this.files.forEach(function (file) {
var $resultDocument = cheerio.load('<svg><defs></defs></svg>', { lowerCaseAttributeNames : false }),
$resultSvg = $resultDocument('svg'),
$resultDefs = $resultDocument('defs').first(),
iconNameViewBoxArray = []; // Used to store information of all icons that are added
// { name : '' }
this.files.forEach(function (file) {
// Merge in SVG attributes from option
for (var attr in options.svg) {
$resultSvg.attr(attr, options.svg[attr]);
}
var $resultDocument = cheerio.load('<svg><defs></defs></svg>', { lowerCaseAttributeNames : false }),
$resultSvg = $resultDocument('svg'),
$resultDefs = $resultDocument('defs').first(),
iconNameViewBoxArray = []; // Used to store information of all icons that are added
// { name : '' }
file.src.filter(function (filepath) {
if (!grunt.file.exists(filepath)) {
grunt.log.warn('File "' + filepath + '" not found.');
return false;
} else {
return true;
}
}).map(function (filepath) {
var filename = path.basename(filepath, '.svg');
var contentStr = grunt.file.read(filepath);
var uniqueId = md5(contentStr);
var $ = cheerio.load(contentStr, {
normalizeWhitespace: true,
xmlMode: true
});
// Merge in SVG attributes from option
for (var attr in options.svg) {
$resultSvg.attr(attr, options.svg[attr]);
}
// Map to store references from id to uniqueId + id;
var mappedIds = {};
file.src.filter(function (filepath) {
if (!grunt.file.exists(filepath)) {
grunt.log.warn('File "' + filepath + '" not found.');
return false;
} else {
return true;
}
}).map(function (filepath) {
var filename = path.basename(filepath, '.svg');
var contentStr = grunt.file.read(filepath);
var uniqueId = md5(contentStr);
var $ = cheerio.load(contentStr, {
normalizeWhitespace: true,
xmlMode: true
});
// Make IDs unique
$('[id]').each(function () {
var $elem = $(this);
var id = $elem.attr('id');
var newId = uniqueId + id;
mappedIds[id] = newId;
$elem.attr('id', newId);
});
// Map to store references from id to uniqueId + id;
var mappedIds = {};
// Search for an url() reference in every attribute of every tag
// replace the id with the unique one.
$('*').each(function () {
var $elem = $(this);
var attrs = $elem.attr();
Object.keys(attrs).forEach(function (key) {
var value = attrs[key];
var match;
while ((match = urlPattern.exec(value)) !== null) {
if (mappedIds[match[1]] !== undefined) {
value = value.replace(match[0], 'url(#' + mappedIds[match[1]] + ')');
} else {
grunt.log.warn('Can\'t reference to id "' + match[1] + '" from attribute "' + attr + '" in "' + this[0].name + '" because it is not defined.');
}
}
if (options.cleanup && key === 'style') {
value = null;
}
$elem.attr(key, value);
});
});
// Make IDs unique
$('[id]').each(function () {
var $elem = $(this);
var id = $elem.attr('id');
var newId = uniqueId + id;
mappedIds[id] = newId;
$elem.attr('id', newId);
});
var $svg = $('svg');
var $title = $('title');
var $desc = $('desc');
var $def = $('defs').first();
// Search for an url() reference in every attribute of every tag
// replace the id with the unique one.
$('*').each(function () {
var $elem = $(this);
var attrs = $elem.attr();
Object.keys(attrs).forEach(function (key) {
var value = attrs[key];
var match;
while ((match = urlPattern.exec(value)) !== null) {
if (mappedIds[match[1]] !== undefined) {
value = value.replace(match[0], 'url(#' + mappedIds[match[1]] + ')');
} else {
grunt.log.warn('Can\'t reference to id "' + match[1] + '" from attribute "' + attr + '" in "' + this[0].name + '" because it is not defined.');
}
}
$elem.attr(key, value);
});
});
// merge in the defs from this svg in the result defs block.
$resultDefs.append($def.html());
var $svg = $('svg');
var $title = $('title');
var $desc = $('desc');
var $def = $('defs').first();
var title = $title.first().html();
var desc = $desc.first().html();
// merge in the defs from this svg in the result defs block.
$resultDefs.append($def.html());
// remove def, title, desc from this svg
$def.remove();
$title.remove();
$desc.remove();
var title = $title.first().html();
var desc = $desc.first().html();
var id = convertNameToId(filename);
// remove def, title, desc from this svg
$def.remove();
$title.remove();
$desc.remove();
// If there is no title use the filename
title = title || id;
var id = convertNameToId(filename);
var resultStr = '<symbol' + symbolAttrs + '>' + '<title>' + title + '</title>';
// If there is no title use the filename
title = title || id;
// Only add desc if it was set
if ( desc ) { resultStr +='<desc>'+ desc +'</desc>'; }
var resultStr = '<symbol' + symbolAttrs + '>' + '<title>' + title + '</title>';
resultStr += $svg.html() + '</symbol>';
// Only add desc if it was set
if ( desc ) { resultStr +='<desc>'+ desc +'</desc>'; }
// Create a object
var $res = cheerio.load(resultStr, { lowerCaseAttributeNames : false });
resultStr += $svg.html() + '</symbol>';
$res('symbol').attr('viewBox', $svg.attr('viewBox'));
// Create a object
var $res = cheerio.load(resultStr, { lowerCaseAttributeNames : false });
var graphicId = options.prefix + id;
// Add ID to the first Element
$res('*').first().attr('id', graphicId);
$res('symbol').attr('viewBox', $svg.attr('viewBox'));
// Append <symbol> to resulting SVG
$resultSvg.append($res.html());
var graphicId = options.prefix + id;
// Add ID to the first Element
$res('*').first().attr('id', graphicId);
// Append <symbol> to resulting SVG
$resultSvg.append($res.html());
// Add icon to the demo.html array
if (options.includedemo) {
iconNameViewBoxArray.push({
name: graphicId
});
}
});
// remove defs block if empty
if ( $resultDefs.html().trim() === '' ) {
$resultDefs.remove();
}
// Add icon to the demo.html array
if (options.includedemo) {
iconNameViewBoxArray.push({
name: graphicId
});
}
var result = options.formatting ? beautify($resultDocument.xml(), options.formatting) : $resultDocument.xml();
var destName = path.basename(file.dest, '.svg');
});
grunt.file.write(file.dest, result);
// remove defs block if empty
if ( $resultDefs.html().trim() === '' ) {
$resultDefs.remove();
}
grunt.log.writeln('File ' + chalk.cyan(file.dest) + ' created.');
var result = options.formatting ? beautify($resultDocument.xml(), options.formatting) : $resultDocument.xml();
var destName = path.basename(file.dest, '.svg');
if (options.includedemo) {
$resultSvg.attr('style', 'width:0;height:0;visibility:hidden;');
grunt.file.write(file.dest, result);
var demoHTML = multiline.stripIndent(function () { /*
<!doctype html>
<html>
<head>
<style>
svg{
width:50px;
height:50px;
fill:black !important;
}
</style>
<head>
<body>
{{svg}}
{{useBlock}}
</body>
</html>
*/});
grunt.log.writeln('File ' + chalk.cyan(file.dest) + ' created.');
var useBlock = '';
iconNameViewBoxArray.forEach(function (item) {
useBlock += '\t\t<svg>\n\t\t\t<use xlink:href="#' + item.name + '"></use>\n\t\t</svg>\n';
});
if (options.includedemo) {
demoHTML = demoHTML.replace('{{svg}}', $resultDocument.xml());
demoHTML = demoHTML.replace('{{useBlock}}', useBlock);
$resultSvg.attr('style', 'width:0;height:0;visibility:hidden;');
var demoHTML = multiline.stripIndent(function () { /*
<!doctype html>
<html>
<head>
<style>
svg{
width:50px;
height:50px;
fill:black !important;
}
</style>
<head>
<body>
{{svg}}
{{useBlock}}
</body>
</html>
*/});
var useBlock = '';
iconNameViewBoxArray.forEach(function (item) {
useBlock += '\t\t<svg>\n\t\t\t<use xlink:href="#' + item.name + '"></use>\n\t\t</svg>\n';
});
demoHTML = demoHTML.replace('{{svg}}', $resultDocument.xml());
demoHTML = demoHTML.replace('{{useBlock}}', useBlock);
var demoPath = path.resolve(path.dirname(file.dest), destName + '-demo.html');
grunt.file.write(demoPath, demoHTML);
grunt.log.writeln('Demo file ' + chalk.cyan(demoPath) + ' created.');
}
});
var demoPath = path.resolve(path.dirname(file.dest), destName + '-demo.html');
grunt.file.write(demoPath, demoHTML);
grunt.log.writeln('Demo file ' + chalk.cyan(demoPath) + ' created.');
}
});
});
};

@@ -93,2 +93,12 @@ 'use strict';

withCleanup: function(test) {
test.expect(1);
var actual = grunt.file.read('tmp/cleanup.svg');
var expected = grunt.file.read('test/expected/cleanup.svg');
test.equal(actual, expected, 'All path inline style attributes should be removed');
test.done();
},
with_include_demo : function(test){

@@ -113,2 +123,3 @@ test.expect(1);

}
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc