Skip to content
Snippets Groups Projects
index.js 2.41 KiB
Newer Older
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);
};