Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
aslansky committed Feb 9, 2014
0 parents commit d3ef253
Show file tree
Hide file tree
Showing 16 changed files with 690 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
coverage
.DS_Store
*.log
build
25 changes: 25 additions & 0 deletions .jscs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"requireCurlyBraces": [ "if", "else", "else if", "for", "while", "do", "switch" ],
"requireSpaceAfterKeywords": [ "if", "else", "else if", "for", "while", "do", "switch" ],
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"requireLineFeedAtFileEnd": true,
"requireRightStickedOperators": [ "!" ],
"requireLeftStickedOperators": [ "," ],
"requireKeywordsOnNewLine": ["else", "else if"],
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true,
"beforeOpeningRoundBrace": true
},
"disallowSpacesInsideParentheses": true,
"disallowSpaceAfterKeywords": [],
"disallowSpaceAfterObjectKeys": true,
"disallowLeftStickedOperators": [ "?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<=" ],
"disallowRightStickedOperators": [ "?", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<=" ],
"disallowImplicitTypeConversion": [],
"disallowMultipleLineBreaks": true,
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideObjectBrackets": true,
"disallowSpaceAfterPrefixUnaryOperators": [ "++", "--", "-", "+", "~", "!" ],
"disallowSpaceBeforePostfixUnaryOperators": [ "++", "--" ]
}
24 changes: 24 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"node": true,
"esnext": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"-W040": true,
"globals": {
"it": false,
"describe": false
}
}
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: node_js
node_js:
- '0.10'
before_install:
- sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
after_script:
- npm run coveralls
54 changes: 54 additions & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env node
'use strict';

var sprite = require('../index');
var opts = require('nomnom')
.option('src', {
position: 0,
abbr: 's',
required: true,
list: true,
metavar: 'GLOB',
help: 'glob strings to find source images to put into the sprite'
})
.option('out', {
abbr: 'o',
required: true,
metavar: 'DIR',
default: process.cwd(),
help: 'path of directory to write sprite file to'
})
.option('name', {
abbr: 'n',
default: 'sprite.png',
help: 'name of the sprite file'
})
.option('style', {
abbr: 'st',
help: 'file to write css to, if ommited no css is written'
})
.option('cssPath', {
abbr: 'c',
full: 'css-image-path',
default: '../images',
help: 'http path to images on the web server (relative to css path or absolute)'
})
.option('processor', {
abbr: 'p',
choices: ['css', 'less', 'sass', 'scss', 'stylus'],
default: 'css',
help: 'output format of the css. one of css, less, sass, scss or stylus'
})
.option('orientation', {
choices: ['vertical', 'horizontal'],
default: 'vertical',
help: 'orientation of the sprite image'
})
.option('margin', {
default: 5,
help: 'margin in px between tiles'
})
.script('css-sprite')
.parse();

sprite.create(opts);
58 changes: 58 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';

var sprite = require('./lib/css-sprite');
var es = require('event-stream');
var vfs = require('vinyl-fs');
var gfs = require('graceful-fs');
var mkdirp = require('mkdirp');
var _ = require('lodash');

var writeFile = function (file, cb) {
mkdirp(file.base, function () {
gfs.writeFile(file.path, file.contents, cb);
});
};

var defaults = {
src: null,
out: '',
name: 'sprite.png',
style: null,
cssPath: '../images',
processor: 'css',
orientation: 'vertical',
margin: 5
};

module.exports = {
/*
* Creates sprite and css file
*/
create: function (o, cb) {
if (!o.src) {
throw new Error('glob missing');
}
if (!o.out) {
throw new Error('output dir missing');
}

var opts = _.extend({}, defaults, o);

vfs.src(opts.src)
.pipe(sprite(opts))
.pipe(es.map(writeFile))
.on('end', function () {
if (_.isFunction(cb)) {
cb();
}
});
},
/*
* Takes a vinyl-fs Readable/Writable stream of images
* returns a Readable/Writable stream of vinyl files of the sprite and css file
*/
stream: function (o) {
var opts = _.extend({}, defaults, o);
return sprite(opts);
}
};
85 changes: 85 additions & 0 deletions lib/css-sprite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
'use strict';

var es = require('event-stream');
var Canvas = require('canvas');
var lodash = require('lodash');
var path = require('path');
var json2css = require('json2css');
var File = require('vinyl');
var Image = Canvas.Image;

function replaceExtension (npath, ext) {
var nFileName = path.basename(npath, path.extname(npath)) + ext;
return path.join(path.dirname(npath), nFileName);
}

module.exports = function (opt) {
opt = lodash.extend({}, {name: 'sprite.png', margin: 5, processor: 'css', cssPath: '../images', orientation: 'vertical'}, opt);
var sprites = [];
var ctxHeight = 0;
var ctxWidth = 0;

function queueImages (file) {
if (file.isNull()) {
return; // ignore
}

if (file.isStream()) {
return this.emit('error', new Error('Streaming not supported'));
}

var img = new Image();
img.src = file.contents;
sprites.push({
'img': img,
'name': replaceExtension(file.relative, ''),
'x': opt.orientation === 'vertical' ? opt.margin : ctxWidth + opt.margin,
'y': opt.orientation === 'vertical' ? ctxHeight + opt.margin: opt.margin,
'width': img.width,
'height': img.height,
'image': path.join(opt.cssPath, opt.name)
});

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;
}
}
}

function endStream () {
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) {
var css = json2css(sprites, {'format': opt.processor});
this.emit('data', new File({
base: path.dirname(opt.style),
path: opt.style,
contents: new Buffer(css)
}));
}
this.emit('data', new File({
base: opt.out,
path: path.join(opt.out, opt.name),
contents: new Buffer(canvas.toBuffer())
}));
this.emit('end');
}

return es.through(queueImages, endStream);
};
68 changes: 68 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "css-sprite",
"version": "0.4.0",
"description": "css sprite generator",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/aslansky/css-sprite.git"
},
"homepage": "https://github.com/aslansky/css-sprite",
"bugs": {
"url": "https://github.com/aslansky/css-sprite/issues"
},
"author": {
"name": "Alexander Slansky",
"email": "alexander@slansky.net",
"url": "http://slansky.net"
},
"engines": {
"node": ">=0.10.0"
},
"bin": {
"css-sprite": "./bin/cli.js"
},
"scripts": {
"test": "mocha --reporter spec",
"coveralls": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage",
"coverage": "istanbul cover _mocha --report html -- -R spec",
"hint": "jshint lib/*.js index.js",
"style": "jscs test/*.js lib/*.js index.js"
},
"main": "./index.js",
"files": [
"./index.js",
"lib",
"bin"
],
"keywords": [
"gulpfriendly",
"gruntfriendly",
"sprites",
"sprite",
"coordinates",
"css",
"scss",
"less",
"sass",
"stylus"
],
"dependencies": {
"vinyl-fs": "~0.0.2",
"canvas": "~1.1.1",
"json2css": "~4.2.1",
"lodash": "~2.4.1",
"nomnom": "~1.6.2",
"vinyl": "~0.2.3",
"event-stream": "~3.1.0",
"graceful-fs": "~2.0.1",
"mkdirp": "~0.3.5"
},
"devDependencies": {
"mocha": "~1.17.0",
"mocha-lcov-reporter": "~0.0.1",
"coveralls": "~2.7.0",
"istanbul": "~0.2.3",
"should": "~3.1.2"
}
}
Loading

0 comments on commit d3ef253

Please sign in to comment.