Skip to content

Commit

Permalink
adds base64 support
Browse files Browse the repository at this point in the history
  • Loading branch information
aslansky committed Feb 13, 2014
1 parent 13b03e2 commit 8391a08
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 63 deletions.
5 changes: 5 additions & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ var opts = require('nomnom')
metavar: 'GLOB',
help: 'glob strings to find source images to put into the sprite'
})
.option('base64', {
abbr: 'b',
flag: true,
help: 'instead of creating a sprite, write base64 encoded images to css (css file will be written to <out>)'
})
.option('cssPath', {
abbr: 'c',
full: 'css-image-path',
Expand Down
65 changes: 37 additions & 28 deletions lib/css-sprite.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var lodash = require('lodash');
var path = require('path');
var json2css = require('json2css');
var File = require('vinyl');
var imageinfo = require('imageinfo');
var replaceExtension = require('./replace-extension');
var Image = Canvas.Image;

Expand All @@ -26,25 +27,29 @@ module.exports = function (opt) {

var queue = function (img) {
sprites.push({
'img': img,
'img': (!opt.base64) ? img : null,
'name': replaceExtension(file.relative, ''),
'x': opt.orientation === 'vertical' ? opt.margin : ctxWidth + opt.margin,
'y': opt.orientation === 'vertical' ? ctxHeight + opt.margin: opt.margin,
'x': (!opt.base64) ? (opt.orientation === 'vertical' ? opt.margin : ctxWidth + opt.margin) : 0,
'y': (!opt.base64) ? (opt.orientation === 'vertical' ? ctxHeight + opt.margin: opt.margin) : 0,
'width': img.width,
'height': img.height,
'image': path.join(opt.cssPath, opt.name)
'total_width': img.width,
'total_height': img.height,
'image': (!opt.base64) ? path.join(opt.cssPath, opt.name) : 'data:' + imageinfo(file.contents).mimeType + ';base64,' + file.contents.toString('base64')
});

if (opt.orientation === 'vertical') {
ctxHeight = ctxHeight + img.height + 2 * opt.margin;
if (img.width + 2 * opt.margin > ctxWidth) {
ctxWidth = img.width + 2 * opt.margin;
if (!opt.base64) {
if (opt.orientation === 'vertical') {
ctxHeight = ctxHeight + img.height + 2 * opt.margin;
if (img.width + 2 * opt.margin > ctxWidth) {
ctxWidth = img.width + 2 * opt.margin;
}
}
}
else {
ctxWidth = ctxWidth + img.width + 2 * opt.margin;
if (img.height + 2 * opt.margin > ctxHeight) {
ctxHeight = img.height + 2 * opt.margin;
else {
ctxWidth = ctxWidth + img.width + 2 * opt.margin;
if (img.height + 2 * opt.margin > ctxHeight) {
ctxHeight = img.height + 2 * opt.margin;
}
}
}
}
Expand All @@ -66,26 +71,30 @@ module.exports = function (opt) {
if (sprites.length === 0) {
return this.emit('end');
}
var canvas = new Canvas(ctxWidth, ctxHeight);
var ctx = canvas.getContext('2d');
lodash.each(sprites, function (sprite) {
sprite.total_width = ctxWidth;
sprite.total_height = ctxHeight;
ctx.drawImage(sprite.img, sprite.x, sprite.y, sprite.width, sprite.height);
});
if (opt.style) {
if (!opt.base64) {
var canvas = new Canvas(ctxWidth, ctxHeight);
var ctx = canvas.getContext('2d');
lodash.each(sprites, function (sprite) {
sprite.total_width = ctxWidth;
sprite.total_height = ctxHeight;
ctx.drawImage(sprite.img, sprite.x, sprite.y, sprite.width, sprite.height);
});
}
if (opt.style || opt.base64) {
var css = json2css(sprites, {'format': opt.processor});
this.emit('data', new File({
base: path.dirname(opt.style),
path: opt.style,
base: (!opt.base64) ? path.dirname(opt.style) : opt.out,
path: (!opt.base64 || (opt.base64 && opt.style)) ? opt.style : path.join(opt.out, replaceExtension(opt.name, '.' + opt.processor)),
contents: new Buffer(css)
}));
}
this.emit('data', new File({
base: opt.out,
path: path.join(opt.out, opt.name),
contents: new Buffer(canvas.toBuffer())
}));
if (!opt.base64) {
this.emit('data', new File({
base: opt.out,
path: path.join(opt.out, opt.name),
contents: new Buffer(canvas.toBuffer())
}));
}
this.emit('end');
}

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-sprite",
"version": "0.5.0",
"version": "0.6.0",
"description": "css sprite generator",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -57,7 +57,8 @@
"event-stream": "~3.1.0",
"graceful-fs": "~2.0.1",
"mkdirp": "~0.3.5",
"gaze": "~0.5.0"
"gaze": "~0.5.0",
"imageinfo": "~1.0.4"
},
"devDependencies": {
"mocha": "~1.17.0",
Expand Down
31 changes: 26 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

> A css sprite generator.
> Generates a sprite file and the propper css file out of a directory with images
> Generates a sprite file and the propper css file out of a directory with images. It can also generate style files with base64 encoded images.
## Requirements

Expand All @@ -20,7 +20,7 @@ Install with [npm](https://npmjs.org/package/css-sprite)
npm install css-sprite --save
```

If you want to use `css-sprite` on your cli use:
If you want to use `css-sprite` on your cli install with:

```
npm install css-sprite -g
Expand All @@ -35,6 +35,7 @@ out path of directory to write sprite file to
src glob strings to find source images to put into the sprite
Options:
-b, --base64 instead of creating a sprite, write base64 encoded images to css (css file will be written to <out>)
-c, --css-image-path http path to images on the web server (relative to css path or absolute path) [../images]
-n, --name name of the sprite file [sprite.png]
-p, --processor output format of the css. one of css, less, sass, scss or stylus [css]
Expand All @@ -59,6 +60,7 @@ sprite.create(options, cb);
* **processor:** output format of the css. one of css, less, sass, scss or stylus [css]
* **orientation:** orientation of the sprite image [vertical]
* **margin:** margin in px between tiles [5]
* **base64:** when true instead of creating a sprite writes base64 encoded images to css (css file will be written to ```<out>```)

### Example
```
Expand All @@ -81,17 +83,28 @@ var gulp = require('gulp');
var gulpif = require('gulp-if');
var sprite = require('css-sprite').stream;
// generate sprite.png and _sprite.scss
gulp.task('sprites', function () {
return gulp.src('./src/img/*.png')
.pipe(sprite({
name: 'sprites.png',
style: '_sprites.scss',
name: 'sprite.png',
style: '_sprite.scss',
cssPath: './img',
processor: 'scss'
}))
.pipe(gulpif('*.png', gulp.dest('./dist/img/')))
.pipe(gulpif('*.scss', gulp.dest('./dist/scss/')));
});
// generate scss with base64 encoded images
gulp.task('base64', function () {
return gulp.src('./src/img/*.png')
.pipe(sprite({
base64: true,
style: '_base64.scss',
processor: 'scss'
}))
.pipe(gulp.dest('./dist/scss/'));
});
```

Options to use `css-sprite` with [Gulp](http://gulpjs.com) are the same as for the `sprite.create` function with the exception of `src` and `out`.
Expand All @@ -112,12 +125,19 @@ module.exports = function(grunt) {
'orientation': 'vertical',
'margin': 5
},
build: {
sprite: {
options: {
'style': 'dest/css/sprite.css'
},
src: ['src/images/*', 'src/images2/*'],
dest: 'dest/images/sprite.png',
},
base64: {
options: {
'base64': true
},
src: ['src/images/*'],
dest: 'dest/scss/base64.css',
}
}
});
Expand All @@ -132,4 +152,5 @@ module.exports = function(grunt) {

Options to use `css-sprite` with [Grunt](http://gruntjs.com) are the same as for the `sprite.create` function with the exception of `src` and `out`.


[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/aslansky/css-sprite/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
9 changes: 4 additions & 5 deletions test/commandline.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@ describe('css-sprite cli (bin/cli.js)', function () {
function (error, stdout, stderr) {
stderr.should.be.empty;
stdout.should.containEql('Usage:');
stdout.should.containEql('css-sprite <src>');
stdout.should.containEql('--out DIR');
stdout.should.containEql('css-sprite <out> <src>');
done();
});
});
it('should generate sprite', function (done) {
exec('./bin/cli.js -o ./test/dist/ ./test/fixtures/*.png',
exec('./bin/cli.js ./test/dist/ ./test/fixtures/*.png',
function (error, stdout, stderr) {
stderr.should.be.empty;
fs.existsSync('./test/dist/sprite.png').should.be.true;
fs.readFile('./test/dist/sprite.png', function (err, png) {
var img = new Image();
img.src = png;
img.width.should.be.equal(56);
img.height.should.be.equal(125);
img.width.should.equal(56);
img.height.should.equal(125);
fs.unlinkSync('./test/dist/sprite.png');
fs.rmdirSync('./test/dist');
done();
Expand Down
49 changes: 31 additions & 18 deletions test/css-sprite.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ describe('css-sprite (lib/css-sprite.js)', function () {
.pipe(es.map(function (file, cb) {
var img = new Image();
img.src = file.contents;
file.path.should.be.equal('dist/img/sprites.png');
file.relative.should.be.equal('sprites.png');
img.width.should.be.equal(56);
img.height.should.be.equal(125);
file.path.should.equal('dist/img/sprites.png');
file.relative.should.equal('sprites.png');
img.width.should.equal(56);
img.height.should.equal(125);
cb();
}))
.on('end', done);
Expand All @@ -38,8 +38,8 @@ describe('css-sprite (lib/css-sprite.js)', function () {
.pipe(es.map(function (file, cb) {
var img = new Image();
img.src = file.contents;
img.width.should.be.equal(86);
img.height.should.be.equal(185);
img.width.should.equal(86);
img.height.should.equal(185);
cb();
}))
.on('end', done);
Expand All @@ -54,10 +54,10 @@ describe('css-sprite (lib/css-sprite.js)', function () {
.pipe(es.map(function (file, cb) {
var img = new Image();
img.src = file.contents;
file.path.should.be.equal('dist/img/sprites.png');
file.relative.should.be.equal('sprites.png');
img.width.should.be.equal(110);
img.height.should.be.equal(69);
file.path.should.equal('dist/img/sprites.png');
file.relative.should.equal('sprites.png');
img.width.should.equal(110);
img.height.should.equal(69);
cb();
}))
.on('end', done);
Expand All @@ -81,11 +81,11 @@ describe('css-sprite (lib/css-sprite.js)', function () {
}))
.on('end', function () {
png.should.be.ok;
png.path.should.be.equal('dist/img/sprites.png');
png.relative.should.be.equal('sprites.png');
png.path.should.equal('dist/img/sprites.png');
png.relative.should.equal('sprites.png');
css.should.be.ok;
css.path.should.be.equal('./dist/css/sprites.css');
css.relative.should.be.equal('sprites.css');
css.path.should.equal('./dist/css/sprites.css');
css.relative.should.equal('sprites.css');
css.contents.toString('utf-8').should.containEql('.icon-floppy-disk');
done();
});
Expand All @@ -110,15 +110,28 @@ describe('css-sprite (lib/css-sprite.js)', function () {
}))
.on('end', function () {
png.should.be.ok;
png.path.should.be.equal('dist/img/sprites.png');
png.relative.should.be.equal('sprites.png');
png.path.should.equal('dist/img/sprites.png');
png.relative.should.equal('sprites.png');
css.should.be.ok;
css.path.should.be.equal('./dist/css/sprites.scss');
css.relative.should.be.equal('sprites.scss');
css.path.should.equal('./dist/css/sprites.scss');
css.relative.should.equal('sprites.scss');
css.contents.toString('utf-8').should.containEql('$floppy-disk');
done();
});
});
it('should return a object stream with a css file with base64 encode images in it', function (done) {
vfs.src('./test/fixtures/**')
.pipe(sprite({
base64: true,
out: './dist/css'
}))
.pipe(es.map(function (file, cb) {
file.relative.should.equal('sprite.css');
file.contents.toString('utf-8').should.containEql('data:image/png;base64');
cb();
}))
.on('end', done);
});
it('should do nothing when no files match', function (done) {
var file = false;
vfs.src('./test/fixtures/empty/**')
Expand Down
10 changes: 5 additions & 5 deletions test/wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ describe('css-sprite wrapper (index.js)', function () {
fs.readFile('./test/dist/sprite.png', function (err, png) {
var img = new Image();
img.src = png;
img.width.should.be.equal(56);
img.height.should.be.equal(125);
img.width.should.equal(56);
img.height.should.equal(125);
fs.unlinkSync('./test/dist/sprite.png');
fs.rmdirSync('./test/dist');
done();
Expand Down Expand Up @@ -73,9 +73,9 @@ describe('css-sprite wrapper (index.js)', function () {
.pipe(es.map(function (file, cb) {
var img = new Image();
img.src = file.contents;
file.relative.should.be.equal('sprite.png');
img.width.should.be.equal(56);
img.height.should.be.equal(125);
file.relative.should.equal('sprite.png');
img.width.should.equal(56);
img.height.should.equal(125);
cb();
}))
.on('end', done);
Expand Down

0 comments on commit 8391a08

Please sign in to comment.