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.1.0 to 0.2.0

test/fixtures/usingdef.svg

12

Gruntfile.js

@@ -80,8 +80,8 @@ /*

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

@@ -88,0 +88,0 @@ },

{
"name": "grunt-svgstore",
"description": "Merge SVGs from a folder.",
"version": "0.1.0",
"version": "0.2.0",
"homepage": "https://github.com/FWeinb/grunt-svgstore",

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

@@ -122,6 +122,25 @@ # 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)

## Release History
* 0.1.0 Always add `xmlns` namspace. Added the `includedemo` option. Fixed Issues [#20](https://github.com/FWeinb/grunt-svgstore/issues/20), [#19](https://github.com/FWeinb/grunt-svgstore/issues/19), [#18](https://github.com/FWeinb/grunt-svgstore/issues/18)
* 0.0.4 Fixed issue with referencing ids with `url()` (fix [#12](https://github.com/FWeinb/grunt-svgstore/issues/12))
* 0.0.3 Added `options.formatting` to format svg via [js-beautify](https://github.com/einars/js-beautify)
* 0.0.2 Fixed npm dependencies
* 0.0.1 Inital release
#### 0.2.0
* Use a `<symbol>`-tag for representing icons (See [TxHawks Comment](https://github.com/FWeinb/grunt-svgstore/issues/16#issuecomment-43786059).)
* Write the `viewBox` attribute to the `<symbol>`-tag,
* Include `title` and `desc` elements in the generated svg for each `<symbol>`
* use 'filename' as a fallback for `title`
* Fix issue [#1](https://github.com/FWeinb/grunt-svgstore/issues/1)
#### 0.1.0
* Always add `xmlns` namspace.
* Added the `includedemo` option.
* Fixed Issues [#20](https://github.com/FWeinb/grunt-svgstore/issues/20), [#19](https://github.com/FWeinb/grunt-svgstore/issues/19), [#18](https://github.com/FWeinb/grunt-svgstore/issues/18)
#### 0.0.4
* Fixed issue with referencing ids with `url()` (fix [#12](https://github.com/FWeinb/grunt-svgstore/issues/12))
#### 0.0.3
* Added `options.formatting` to format svg via [js-beautify](https://github.com/einars/js-beautify)
#### 0.0.2
* Fixed npm dependencies
#### 0.0.1
* Inital release

@@ -8,180 +8,205 @@ /*

*/
'use strict';
module.exports = function(grunt) {
var crypto = require('crypto'),
multiline= require('multiline'),
path = require('path'),
var genAttrStr = function ( attrs, allowed ) {
var result = '';
Object.keys(attrs).forEach(function (key) {
if ( allowed === undefined || allowed.indexOf(key) >= 0 ) {
result += ' ' + key + '="' + attrs[key] + '"';
}
});
return result;
};
beautify = require('js-beautify').html,
cheerio = require('cheerio'),
chalk = require('chalk');
module.exports = function (grunt) {
var md5 = function(str){
return crypto.createHash('md5').update(str).digest('hex');
};
var crypto = require('crypto');
var multiline = require('multiline');
var path = require('path');
// Matching an url() reference. To correct references broken by making ids unquie to the source svg
var urlPattern = /url\(\s*#([^ ]+?)\s*\)/g;
var beautify = require('js-beautify').html;
var cheerio = require('cheerio');
var chalk = require('chalk');
// Please see the Grunt documentation for more information regarding task
// creation: http://gruntjs.com/creating-tasks
var md5 = function (str) {
return crypto.createHash('md5').update(str).digest('hex');
};
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
});
// Matching an url() reference. To correct references broken by making ids unquie to the source svg
var urlPattern = /url\(\s*#([^ ]+?)\s*\)/g;
this.files.forEach(function(file) {
// Please see the Grunt documentation for more information regarding task
// creation: http://gruntjs.com/creating-tasks
var $resultDocument = cheerio.load('<svg><defs></defs></svg>'),
$resultSvg = $resultDocument('svg'),
$resultDefs = $resultDocument('defs').first(),
iconNameViewBoxArray = []; // Used to store information of all icons that are added
// { name : '', attribute : { 'data-viewBox' : ''}}
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
});
// Merge in SVG attributes
for ( var attr in options.svg ){
$resultSvg.attr(attr, options.svg[attr]);
}
this.files.forEach(function (file) {
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'),
contentStr = grunt.file.read(filepath),
uniqueId = md5(contentStr),
$ = cheerio.load(contentStr, {normalizeWhitespace : true, xmlMode: true});
var $resultDocument = cheerio.load('<svg><defs></defs></svg>'),
$resultSvg = $resultDocument('svg'),
$resultDefs = $resultDocument('defs').first(),
iconNameViewBoxArray = []; // Used to store information of all icons that are added
// { name : '', attribute : { 'data-viewBox' : ''}}
// Map to store references from id to uniqueId + id;
var mappedIds = {};
// Merge in SVG attributes from option
for (var attr in options.svg) {
$resultSvg.attr(attr, options.svg[attr]);
}
// 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);
});
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
});
// 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);
});
});
// Map to store references from id to uniqueId + id;
var mappedIds = {};
var $svg = $('svg'),
$children = $svg.children();
// 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);
});
// 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);
});
});
var resultStr;
var $svg = $('svg');
var $title = $('title');
var $desc = $('desc');
var $def = $('defs').first();
var attr = $svg.attr();
// Use the first element
if ( $children.length === 1){
resultStr = $svg.html();
} else { // Wrap the SVG in a <g>-Tag
resultStr = '<g>' + $svg.html() + '</g>';
}
var attrStr = genAttrStr(attr, ['viewBox']);
// Create a object
var $res = cheerio.load(resultStr);
// merge in the defs from this svg in the result defs block.
$resultDefs.append($def.html());
var graphicId = options.prefix + filename;
// Add ID to the first Element
$res('*').first().attr('id', graphicId);
var title = $title.first().html();
var desc = $desc.first().html();
// Append to resulting SVG
$resultDefs.append( $res.xml() );
// remove def, title, desc from this svg
$def.remove();
$title.remove();
$desc.remove();
// Add icon to the demo.html array
if ( options.includedemo ) {
iconNameViewBoxArray.push({
name : graphicId,
attributes : {
'viewBox' : $svg.attr('viewBox')
}
});
}
// If there is no title use the filename
title = title || filename;
});
var resultStr = '<symbol'+attrStr+'>' + '<title>' + title + '</title>';
var result = options.formatting ? beautify($resultDocument.xml(), options.formatting) : $resultDocument.xml();
var destName = path.basename(file.dest, '.svg');
// Only add desc if it was set
if ( desc ) { resultStr +='<desc>'+ desc +'</desc>'; }
grunt.file.write(file.dest, result);
resultStr += $svg.html() + '</symbol>';
grunt.log.writeln('File ' + chalk.cyan(file.dest) + ' created.');
// Create a object
var $res = cheerio.load(resultStr);
if ( options.includedemo ) {
var graphicId = options.prefix + filename;
// Add ID to the first Element
$res('*').first().attr('id', graphicId);
$resultSvg.attr('style', 'display:none');
// Append to resulting SVG
$resultDefs.append($res.xml());
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){
var attrStr = '';
// Add icon to the demo.html array
if (options.includedemo) {
iconNameViewBoxArray.push({
name: graphicId,
attributes: {
'viewBox': $svg.attr('viewBox')
}
});
}
Object.keys(item.attributes).forEach(function(key){
attrStr += ' ' +key+'="'+item.attributes[key]+'"';
});
});
useBlock += '\t\t<svg'+attrStr+'>\n\t\t\t<use xlink:href="#'+ item.name +'"></use>\n\t\t</svg>\n';
});
var result = options.formatting ? beautify($resultDocument.xml(), options.formatting) : $resultDocument.xml();
var destName = path.basename(file.dest, '.svg');
demoHTML = demoHTML.replace('{{svg}}', $resultDocument.xml());
demoHTML = demoHTML.replace('{{useBlock}}', useBlock);
grunt.file.write(file.dest, result);
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.');
}
grunt.log.writeln('File ' + chalk.cyan(file.dest) + ' created.');
if (options.includedemo) {
$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) {
//var attrStr = genAttrStr(item.attributes);
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.');
}
});
});
});
};
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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