Commit dd968d7f authored by Philipp Nowinski's avatar Philipp Nowinski

[FEATURE] initial implementation

parents
# http://editorconfig.org
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[test/fixtures/*]
insert_final_newline = false
trim_trailing_whitespace = false
* text=auto
\ No newline at end of file
.DS_Store
node_modules/
temp/
coverage
.idea
*.iml
\ No newline at end of file
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 4,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "double",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"white": true
}
.DS_Store
node_modules/
temp/
coverage
.idea
*.iml
Copyright 2015
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# gulp-inline-svg
> inline-svg plugin for [gulp](https://github.com/wearefractal/gulp)
This plugin takes a couple of SVG files and provides them inside a Sass mixin as inlined background-images. By doing so, you can use them without having to touch you Markup.
## Compatibility
The inlined SVG gets URL encoded, so it is save to use starting with IE9.
## Important notes
The generated mixin contains width and height values for each SVG. Those values are taken from the width and height attribute inside the SVG. If it does not provide them, they will be set to 0px. You can still overwrite them in your CSS.
## Usage
First, install `gulp-inline-svg as a development dependency:
```shell
npm install --save-dev gulp-inline-svg
```
Then, add it to your `gulpfile.js`. I'd recommend to use it in conjunction with [gulp-svgmin](https://www.npmjs.com/package/gulp-svgmin) to clean the SVG before inlining them.
```javascript
var inlineSvg = require("gulp-inline-svg"),
svgMin = require('gulp-svgmin');
gulp.src("css/**/*.css")
.pipe(svgMin())
.pipe(inlineSvg())
.pipe(gulp.dest("sass"));
```
This will create a _svg.scss file inside your 'sass' folder.
### Usage inside you Sass code
The _svg.scss file will provide you with the following mixins and functions:
#### inline-svg mixin
```scss
.my-icon {
// will set the svg as background-image and width/height
@include inline-svg($icon-name);
}
```
#### inline-svg-width function
```scss
.my-icon {
margin-left: inline-svg-width($icon-name);
}
```
#### inline-svg-height function
```scss
.my-icon {
margin-bottom: inline-svg-height($icon-name);
}
```
## Configuration
If you want wo customize the default configuration, you can pass an options object to the task function:
´´´javascript
gulp.src("css/**/*.css")
.pipe(svgMin())
.pipe(inlineSvg({
filename: '_svg-file.scss',
template: 'mytemplate.mustache'
}))
.pipe(gulp.dest("sass"));
```
### filename
Specifies the name of the generated file.
### template
The plugin will generate an .scss-file by default, but you can easily adopt this for other languages, by using your own template. With this option, you can specify the path to a [mustache](https://github.com/janl/mustache.js/) template.
You can use the default template as a blueprint to create your own. And please don't hesitate to [share](http://gitlab.sgalinski.de/toolchain/gulp-inline-svg/fork/new) your template if you create one for an additional language.
## License
[MIT License](http://en.wikipedia.org/wiki/MIT_License)
var through = require("through2"),
gutil = gutil = require('gulp-util'),
File = gutil.File,
path = require('path'),
mustache = require('mustache'),
fs = require('fs'),
xml2js = require('xml2js'),
_ = require('underscore');
module.exports = function (_options) {
"use strict";
var files = {},
svgs = [],
options = {
filename: '_svg.scss',
template: __dirname + '/template.mustache'
};
// merge options
options = _.extend(options, _options);
function inlineSvg(file, enc, callback) {
/*jshint validthis:true*/
// Do nothing if no contents
if (file.isNull()) {
this.push(file);
return callback();
}
if (file.isStream()) {
// accepting streams is not supported
this.emit("error",
new gutil.PluginError("gulp-inline-svg", "Stream content is not supported"));
return callback();
}
// check if file.contents is a `Buffer`
if (file.isBuffer()) {
// store the new file for later usage
if (!files[file.base]) {
files[file.base] = new File({
cwd: "/",
base: "/",
path: "/" + options.filename,
contents: new Buffer("")
});
}
// get mustache template
var template = fs.readFileSync(options.template, 'utf-8');
var attrToLowerCase = function(name) {
return name.toLowerCase();
};
// parse the svg and extract dimensions
xml2js.parseString(String(file.contents), {strict: false, attrkey:'ATTR', attrNameProcessors:[attrToLowerCase]}, function (err, result) {
if (err) throw err;
var hasWidthHeightAttr = result.SVG.ATTR['width'] && result.SVG.ATTR['height'],
width,
height;
if (hasWidthHeightAttr) {
height = result.SVG.ATTR['height'];
width = result.SVG.ATTR['width'];
} else {
width = result.SVG.ATTR['viewbox'].toString().replace(/^\d+\s\d+\s(\d+\.?[\d])\s(\d+\.?[\d])/, "$1");
height = result.SVG.ATTR['viewbox'].toString().replace(/^\d+\s\d+\s(\d+\.?[\d])\s(\d+\.?[\d])/, "$2");
}
// store this svg data
svgs.push({
name: path.basename(file.path, '.svg'),
inline: 'data:image/svg+xml,' + encodeURIComponent(String(file.contents)),
width: parseInt(width) + 'px',
height: parseInt(height) + 'px'
});
// update template
files[file.base].contents = new Buffer(mustache.render(template, {svgs: svgs}));
// send new file back to stream
this.push(files[file.base]);
}.bind(this));
}
return callback();
}
return through.obj(inlineSvg);
};
{
"name": "gulp-inline-svg",
"version": "1.0.0",
"description": "A gulp plugin to use inline SVG as background-images",
"keywords": [
"gulpplugin, gulp, svg, inline"
],
"main": "index.js",
"directories": {
"test": "test"
},
"author": "",
"repository": {
"type": "git",
"url": "http://gitlab.sgalinski.de/toolchain/gulp-inline-svg.git"
},
"scripts": {
"test": "istanbul test _mocha --report html -- test/*.js --reporter spec",
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
},
"dependencies": {
"mustache": "^2.0.0",
"through2": "*",
"underscore": "^1.8.3",
"xml2js": "^0.4.9"
},
"devDependencies": {
"coveralls": "*",
"event-stream": "*",
"gulp-util": "^3.0.5",
"istanbul": "*",
"mocha": "*",
"mocha-lcov-reporter": "*",
"should": "~2.1.0"
},
"license": "MIT"
}
{{#svgs}}
${{{name}}}: '{{{inline}}}' {{width}} {{height}};
{{/svgs}}
@mixin inline-svg($name) {
background: transparent url(nth($name, 1)) no-repeat 50% 50%;
background-size: 100%;
width: nth($name, 2);
height: nth($name, 3);
}
@function inline-svg-width($name) {
@return nth($name, 2);
}
@function inline-svg-height($name) {
@return nth($name, 3);
}
\ No newline at end of file
$test: 'data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22350.471%22%20height%3D%22350.471%22%3E%3Cg%20stroke%3D%22%230091d4%22%20stroke-width%3D%221.9%22%3E%3Cpath%20d%3D%22M.95.95h234.286v225.714H.95z%22%2F%3E%3Cpath%20d%3D%22M349.52%20236.664c0%2062.33-50.526%20112.857-112.856%20112.857-62.33%200-112.857-50.526-112.857-112.856%200-62.33%2050.528-112.857%20112.857-112.857%2062.33%200%20112.857%2050.528%20112.857%20112.857z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A' 350px 350px;
@mixin inline-svg($name) {
background: transparent url(nth($name, 1)) no-repeat 50% 50%;
background-size: 100%;
width: nth($name, 2);
height: nth($name, 3);
}
@function inline-svg-width($name) {
@return nth($name, 2);
}
@function inline-svg-height($name) {
@return nth($name, 3);
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="350.471" height="350.471"><g stroke="#0091d4" stroke-width="1.9"><path d="M.95.95h234.286v225.714H.95z"/><path d="M349.52 236.664c0 62.33-50.526 112.857-112.856 112.857-62.33 0-112.857-50.526-112.857-112.856 0-62.33 50.528-112.857 112.857-112.857 62.33 0 112.857 50.528 112.857 112.857z"/></g></svg>
/*global describe, it*/
"use strict";
var fs = require("fs"),
es = require("event-stream"),
should = require("should");
require("mocha");
delete require.cache[require.resolve("../")];
var gutil = require("gulp-util"),
inlineSvg = require("../");
describe("gulp-inline-svg", function () {
var expectedFile = new gutil.File({
path: "test/expected/test.scss",
cwd: "test/",
base: "test/expected",
contents: fs.readFileSync("test/expected/test.scss")
});
it("should produce expected file via buffer", function (done) {
var srcFile = new gutil.File({
path: "test/fixtures/test.svg",
cwd: "test/",
base: "test/fixtures",
contents: fs.readFileSync("test/fixtures/test.svg")
});
var stream = inlineSvg();
stream.on("error", function(err) {
should.exist(err);
done(err);
});
stream.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
String(newFile.contents).should.equal(String(expectedFile.contents));
done();
});
stream.write(srcFile);
stream.end();
});
it("should error on stream", function (done) {
var srcFile = new gutil.File({
path: "test/fixtures/test.svg",
cwd: "test/",
base: "test/fixtures",
contents: fs.createReadStream("test/fixtures/test.svg")
});
var stream = inlineSvg();
stream.on("error", function(err) {
should.exist(err);
done();
});
stream.on("data", function (newFile) {
newFile.contents.pipe(es.wait(function(err, data) {
done(err);
}));
});
stream.write(srcFile);
stream.end();
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment