Skip to content

Commit

Permalink
Added dimension CSS output for non-CSS sprites (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkphl committed Jan 24, 2015
1 parent 0190754 commit 62aaa3e
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 108 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,9 @@ Known problems / To-do
Release history
---------------

#### master (will become v1.0.12)
* Added dimension CSS output for non-CSS sprites ([#45](https://github.com/jkphl/svg-sprite/issues/45))

#### v1.0.11 Bugfix release
* Fixed coordinate distortion in CSS sprites ([#41](https://github.com/jkphl/svg-sprite/issues/41))

Expand Down
2 changes: 1 addition & 1 deletion lib/svg-sprite.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ SVGSpriter.prototype._getShapeFiles = function(dest) {
return new File({
base : dest,
path : path.join(dest, shape.id + '.svg'),
contents : new Buffer(shape.getSVG())
contents : new Buffer(shape.getSVG(false))
})
})
}
Expand Down
78 changes: 76 additions & 2 deletions lib/svg-sprite/mode/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
var path = require('path'),
_ = require('lodash'),
fs = require('fs'),
async = require('async'),
mustache = require('mustache'),
os = require('os'),
File = require('vinyl');

/**
Expand All @@ -31,7 +33,6 @@ function SVGSpriteBase(spriter, config, data, key) {
this.data = data;
this.data.mode = this.mode;
this.data.key = this.key;
this._render = [];

// Resolve file paths
this.config.dest = path.resolve(this._spriter.config.dest, this.config.dest);
Expand All @@ -41,6 +42,47 @@ function SVGSpriteBase(spriter, config, data, key) {
spriteName = spriteName.substring(0, spriteName.length - path.extname(spriteName).length) + '.svg';
this.config.sprite = path.resolve(this.config.dest, path.join(spritePath, spriteName));
}

// Prepare the rendering configurations
if (('render' in this.config) && _.isObject(this.config.render)) {
for (var extension in this.config.render) {
var renderConfig = {
template : path.resolve(path.dirname(path.dirname(path.dirname(__dirname))), path.join('tmpl', this.tmpl, 'sprite.' + extension)),
dest : path.join(this.config.dest, 'sprite.' + extension)
};
if (_.isObject(this.config.render[extension])) {
if ('template' in this.config.render[extension]) {
renderConfig.template = path.resolve(this.config.render[extension].template);
}
if ('dest' in this.config.render[extension]) {
renderConfig.dest = path.resolve(this.config.dest, this.config.render[extension].dest);
}
} else if (this.config.render[extension] !== true) {
continue;
}
this.config.render[extension] = renderConfig;
}
}

// Cache busting
this.config.bust = !!this.config.bust;

// Prepare the CSS prefix
this.config.prefix = this.config.prefix.trim();
if (!(this.config.prefix.match(/\s+/g) || []).length && (this.config.prefix.indexOf('.' !== 0))) {
this.config.prefix = '.' + this.config.prefix;
}
if (!/%s/g.test(this.config.prefix.split('%%').join(''))) {
this.config.prefix += '%s';
}

// Refine the base data
this.data = _.merge(this.data, this._initData({
padding : this._spriter.config.shape.spacing.padding,
sprite : path.relative(this.config.dest, this.config.sprite)
}));

this._init();
}

/**
Expand All @@ -53,7 +95,9 @@ SVGSpriteBase.prototype = {
MODE_DEFS : 'defs',
MODE_SYMBOL : 'symbol',
MODE_STACK : 'stack',
MODE_VIEW : 'view'
MODE_VIEW : 'view',

tmpl : 'common'
};

/**
Expand Down Expand Up @@ -101,6 +145,36 @@ SVGSpriteBase.prototype.layout = function(files, cb) {
cb(null);
}

/**
* Build the configured CSS resources
*
* @param {Array} files Files
* @param {Function} cb Callback
* @return {void}
*/
SVGSpriteBase.prototype._buildCSSResources = function(files, cb) {
var tasks = [];

for (var extension in this.config.render) {
tasks.push(function(renderConfig, data, spriter, ext){
return function(_cb) {
var out = mustache.render(fs.readFileSync(renderConfig.template, 'utf-8'), data);
if (out.length) {
files[ext] = new File({
base : spriter.config.dest,
path : renderConfig.dest,
contents : new Buffer(out)
});
spriter.verbose("Created «%s» stylesheet resource", ext);
}
_cb(null);
}
}(this.config.render[extension], this.data, this._spriter, extension));
}

async.parallelLimit(tasks, os.cpus().length * 2, cb);
}

/**
* Build the HTML example (non-CSS modes)
*
Expand Down
109 changes: 26 additions & 83 deletions lib/svg-sprite/mode/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ path = require('path'),
fs = require('fs'),
SVGSpriteBase = require('./base'),
SVGSprite = require('../sprite'),
async = require('async'),
os = require('os'),
mustache = require('mustache'),
File = require('vinyl'),
crypto = require('crypto');

Expand All @@ -32,56 +29,6 @@ crypto = require('crypto');
*/
function SVGSpriteCss(spriter, config, data, key) {
SVGSpriteBase.apply(this, arguments);

// Prepare the rendering configurations
if (('render' in this.config) && _.isObject(this.config.render)) {
for (var extension in this.config.render) {
var renderConfig = {
template : path.resolve(path.dirname(path.dirname(path.dirname(__dirname))), path.join('tmpl', 'css', 'sprite.' + extension)),
dest : path.join(this.config.dest, 'sprite.' + extension)
};
if (_.isObject(this.config.render[extension])) {
if ('template' in this.config.render[extension]) {
renderConfig.template = path.resolve(this.config.render[extension].template);
}
if ('dest' in this.config.render[extension]) {
renderConfig.dest = path.resolve(this.config.dest, this.config.render[extension].dest);
}
} else if (this.config.render[extension] !== true) {
continue;
}
this.config.render[extension] = renderConfig;
}
}

// Prepare the CSS prefix and dimension suffix
this.config.prefix = this.config.prefix.trim();
if (!(this.config.prefix.match(/\s+/g) || []).length && (this.config.prefix.indexOf('.' !== 0))) {
this.config.prefix = '.' + this.config.prefix;
}
if (!/%s/g.test(this.config.prefix.split('%%').join(''))) {
this.config.prefix += '%s';
}
if (this.config.dimensions && (this.config.dimensions !== true) && !/%s/g.test((this.config.dimensions || '').split('%%').join(''))) {
this.config.dimensions = this.config.prefix + this.config.dimensions;
}

// Cache busting
this.config.bust = !!this.config.bust;

// Refine the base data
this.data = _.merge(this.data, this._initData({
common : this.config.common,
mixin : this.config.common || 'svg-common',
includeDimensions : !!this.config.dimensions,
padding : this._spriter.config.shape.spacing.padding,
sprite : path.relative(this.config.dest, this.config.sprite),
spriteWidth : 0,
spriteHeight : 0
}));

// Determine if this sprite accepts displaced shape copies
this._displaceable = ([this.LAYOUT_VERTICAL, this.LAYOUT_HORIZONTAL].indexOf(this.config.layout) >= 0);
}

/**
Expand All @@ -92,13 +39,39 @@ function SVGSpriteCss(spriter, config, data, key) {
SVGSpriteCss.prototype = _.create(SVGSpriteBase.prototype, {
constructor : SVGSpriteCss,
mode : SVGSpriteBase.prototype.MODE_CSS,
tmpl : 'css',

LAYOUT_VERTICAL : 'vertical',
LAYOUT_HORIZONTAL : 'horizontal',
LAYOUT_DIAGONAL : 'diagonal',
LAYOUT_PACKED : 'packed'
});

/**
* Initialization (non-CSS modes)
*
* @return {void}
*/
SVGSpriteCss.prototype._init = function() {

// Prepare the dimension suffix
if (this.config.dimensions && (this.config.dimensions !== true) && !/%s/g.test((this.config.dimensions || '').split('%%').join(''))) {
this.config.dimensions = this.config.prefix + this.config.dimensions;
}

// Refine the base data
this.data = _.assign(this.data, {
common : this.config.common,
mixin : this.config.common || 'svg-common',
includeDimensions : !!this.config.dimensions,
spriteWidth : 0,
spriteHeight : 0
});

// Determine if this sprite accepts displaced shape copies
this._displaceable = ([this.LAYOUT_VERTICAL, this.LAYOUT_HORIZONTAL].indexOf(this.config.layout) >= 0);
}

/**
* Layout the sprite
*
Expand Down Expand Up @@ -450,36 +423,6 @@ SVGSpriteCss.prototype._buildSVG = function(xmlDeclaration, doctypeDeclaration)
return svg.toFile(this._spriter.config.dest, sprite);
}

/**
* Build the configured CSS resources
*
* @param {Array} files Files
* @param {Function} cb Callback
* @return {void}
*/
SVGSpriteCss.prototype._buildCSSResources = function(files, cb) {
var tasks = [];

for (var extension in this.config.render) {
tasks.push(function(renderConfig, data, spriter, ext){
return function(_cb) {
var out = mustache.render(fs.readFileSync(renderConfig.template, 'utf-8'), data);
if (out.length) {
files[ext] = new File({
base : spriter.config.dest,
path : renderConfig.dest,
contents : new Buffer(out)
});
spriter.verbose("Created «%s» stylesheet resource", ext);
}
_cb(null);
}
}(this.config.render[extension], this.data, this._spriter, extension));
}

async.parallelLimit(tasks, os.cpus().length * 2, cb);
}

/**
* Module export
*/
Expand Down
31 changes: 16 additions & 15 deletions lib/svg-sprite/mode/standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ SVGSpriteBase = require('./base');
*/
function SVGSpriteStandalone(spriter, config, data) {
SVGSpriteBase.apply(this, arguments);
this._init();
}

/**
Expand All @@ -43,24 +42,13 @@ SVGSpriteStandalone.prototype = _.create(SVGSpriteBase.prototype, {
*/
SVGSpriteStandalone.prototype._init = function() {

// Prepare the CSS prefix and dimension suffix
this.config.prefix = this.config.prefix.trim();
if (!(this.config.prefix.match(/\s+/g) || []).length && (this.config.prefix.indexOf('.' !== 0))) {
this.config.prefix = '.' + this.config.prefix;
}
if (!/%s/g.test(this.config.prefix.split('%%').join(''))) {
this.config.prefix += '%s';
}
// Prepare the dimension suffix
this.config.dimensions = _.isString(this.config.dimensions) ? this.config.dimensions.trim() : '-dims';
if (this.config.dimensions && !/%s/g.test((this.config.dimensions || '').split('%%').join(''))) {
this.config.dimensions = this.config.prefix + this.config.dimensions;
}

// Refine the base data
this.data = _.merge(this.data, this._initData({
padding : this._spriter.config.shape.spacing.padding,
sprite : path.relative(this.config.dest, this.config.sprite)
}));
this.data.inline = !!this.config.inline;
}

/**
Expand Down Expand Up @@ -121,7 +109,20 @@ SVGSpriteStandalone.prototype._layout = function(files, cb, extend) {
this._spriter.verbose("Created «%s» SVG sprite file («%s» mode)", this.key, this.mode);

// Build the HTML example
this._buildHTMLExample(files, cb);
// this._buildHTMLExample(files, cb);

// Build the configured CSS resources
this._buildCSSResources(files, function(error) {

// In case of errors: Break
if (error) {
cb(error);

// Else: Build the HTML example
} else {
this._buildHTMLExample(files, cb);
}
}.bind(this));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/svg-sprite/transform/svgo.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ module.exports = function(shape, config, spriter, cb) {
config.plugins.push({removeXMLProcInst: !!spriter.config.svg.xmlDeclaration});
config.plugins.push({removeDoctype: !!spriter.config.svg.doctypeDeclaration});

var svg = shape.getSVG(),
var svg = shape.getSVG(false),
svgLength = svg.length,
svgoInstance = new svgo(config);

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svg-sprite",
"version": "1.0.11",
"version": "1.0.12",
"author": {
"name": "Joschi Kuphal",
"email": "joschi@kuphal.net",
Expand Down Expand Up @@ -90,4 +90,4 @@
"mustache",
"gulpfriendly"
]
}
}
7 changes: 7 additions & 0 deletions tmpl/common/sprite.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#shapes}}{{#selector.dimensions}}{{expression}}{{^last}},
{{/last}}{{/selector.dimensions}} {
width: {{width.outer}}px;
height: {{height.outer}}px;
}

{{/shapes}}
7 changes: 7 additions & 0 deletions tmpl/common/sprite.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#shapes}}{{#selector.dimensions}}{{expression}}{{^last}},
{{/last}}{{/selector.dimensions}} {
width: {{width.outer}}px;
height: {{height.outer}}px;
}

{{/shapes}}
7 changes: 7 additions & 0 deletions tmpl/common/sprite.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#shapes}}{{#selector.dimensions}}{{expression}}{{^last}},
{{/last}}{{/selector.dimensions}} {
width: {{width.outer}}px;
height: {{height.outer}}px;
}

{{/shapes}}
5 changes: 5 additions & 0 deletions tmpl/common/sprite.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{#shapes}}{{#selector.dimensions}}{{#escape}}{{expression}}{{/escape}}{{^last}},{{/last}}
{{/selector.dimensions}} width {{width.outer}}px
height {{height.outer}}px

{{/shapes}}
Loading

0 comments on commit 62aaa3e

Please sign in to comment.