Skip to content

Commit

Permalink
Merge pull request #43 from ai/function
Browse files Browse the repository at this point in the history
Add common rework.function to clean function filter
  • Loading branch information
tj committed Mar 8, 2013
2 parents b851c9a + 201069b commit 0ceeae2
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 33 deletions.
34 changes: 34 additions & 0 deletions Readme.md
Expand Up @@ -480,6 +480,40 @@ h1 {
}
```

### .function(object)

Add user-defined CSS functions.

For example create `black(0.5)` shortcut, to replace
long `rgba(0, 0, 0, 0.5)`.

```js
var css = rework(css)
.use(rework.function({ black: black }))
.toString()

function black(opacity) {
return 'rgba(0, 0, 0, ' + opacity + ')';
}
```

User code will receive CSS arguments and replace user-defined function
by returned code.

```css
input {
box-shadow: 0 0 5px black(0.7);
}
```

yields:

```css
input {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.7);
}
```

### .references()

Add property reference support.
Expand Down
3 changes: 3 additions & 0 deletions examples/function.css
@@ -0,0 +1,3 @@
input {
box-shadow: 0 0 5px black(0.7);
}
15 changes: 15 additions & 0 deletions examples/function.js
@@ -0,0 +1,15 @@

var rework = require('..')
, read = require('fs').readFileSync;

var css = rework(read('examples/function.css', 'utf8'))
.use(rework.function({
black: black
}))
.toString()

function black(opacity) {
return 'rgba(0, 0, 0, ' + opacity + ')';
}

console.log(css);
49 changes: 49 additions & 0 deletions lib/plugins/function.js
@@ -0,0 +1,49 @@

/**
* Module dependencies.
*/

var visit = require('../visit');

/**
* Define custom function.
*/

module.exports = function(functions) {
if (!functions) throw new Error('functions object required');
return function(style, rework){
visit.declarations(style, function(declarations){
for (var name in functions) {
func(declarations, name, functions[name]);
}
});
}
};

/**
* Escape regexp codes in string.
*
* @param {String} s
* @api private
*/
function escape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

/**
* Visit declarations and apply functions.
*
* @param {Array} declarations
* @param {Object} functions
* @api private
*/
function func(declarations, name, func) {
var regexp = new RegExp(escape(name) + '\\(([^\)]+)\\)', 'g');
declarations.forEach(function(decl){
if (!~decl.value.indexOf(name + '(')) return;
decl.value = decl.value.replace(regexp, function(_, args){
args = args.split(/,\s*/);
return func.apply(decl, args);
});
});
}
36 changes: 15 additions & 21 deletions lib/plugins/inline.js
Expand Up @@ -3,7 +3,7 @@
* Module dependencies.
*/

var visit = require('../visit')
var func = require('./function')
, path = require('path')
, mime = require('mime')
, fs = require('fs')
Expand All @@ -29,25 +29,19 @@ module.exports = function(dirs) {
dirs = Array.prototype.slice.call(arguments);
}

return function(style, rework){
visit.declarations(style, function(declarations){
declarations.forEach(function(decl){
if (!~decl.value.indexOf('inline(')) return;
decl.value = decl.value.replace(/inline\(([^)]+)\)/g, function(_, name){

var file = dirs.map(function(dir) {
return path.join(dir, name);
}).filter(function(filePath){
return fs.existsSync(filePath)
})[0];

if (!file) throw new Error("Can't find `" + name + "` to inline");

var type = mime.lookup(file);
var base64 = new Buffer(read(file)).toString('base64');
return 'url("data:' + type + ';base64,' + base64 + '")';
});
});
});
return func({ inline: inline });

function inline(fileName){
var file = dirs.map(function(dir) {
return path.join(dir, fileName);
}).filter(function(filePath){
return fs.existsSync(filePath)
})[0];

if (!file) throw new Error("Can't find `" + fileName + "` to inline");

var type = mime.lookup(file);
var base64 = new Buffer(read(file)).toString('base64');
return 'url("data:' + type + ';base64,' + base64 + '")';
}
};
19 changes: 7 additions & 12 deletions lib/plugins/url.js
Expand Up @@ -4,7 +4,7 @@
*/

var utils = require('../utils')
, visit = require('../visit');
, func = require('./function');

/**
* Map `url()` calls.
Expand All @@ -22,15 +22,10 @@ var utils = require('../utils')
*/

module.exports = function(fn) {
return function(style, rework){
visit.declarations(style, function(declarations){
declarations.forEach(function(decl, i){
if (!~decl.value.indexOf('url(')) return;
decl.value = decl.value.replace(/url\(([^)]+)\)/g, function(_, url){
url = utils.stripQuotes(url);
return 'url("' + fn(url) + '")';
});
});
});
}
return func({ url: url });

function url(path){
path = utils.stripQuotes(path);
return 'url("' + fn(path) + '")';
};
};
1 change: 1 addition & 0 deletions lib/rework.js
Expand Up @@ -92,6 +92,7 @@ Rework.prototype.toString = function(options){

exports.media = require('./plugins/media');
exports.mixin = exports.mixins = require('./plugins/mixin');
exports.function = exports.functions = require('./plugins/function');
exports.prefix = require('./plugins/prefix');
exports.colors = require('./plugins/colors');
exports.extend = require('./plugins/extend');
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/function.css
@@ -0,0 +1,4 @@
@font-face {
scr: fonts(a.woff,a.ttf, a.otf);
font-family: A
}
4 changes: 4 additions & 0 deletions test/fixtures/function.out.css
@@ -0,0 +1,4 @@
@font-face {
scr: url(a.woff) format("woff"), url(a.ttf) format("truetype"), url(a.otf) format("opentype");
font-family: A
}
18 changes: 18 additions & 0 deletions test/rework.js
Expand Up @@ -112,6 +112,24 @@ describe('rework', function(){
})
})

describe('.function()', function(){
it('should add custom function', function(){
rework(fixture('function'))
.use(rework.function({ fonts: fonts }))
.toString()
.should.equal(fixture('function.out'));

function fonts() {
var files = Array.prototype.slice.call(arguments);
var types = { woff: 'woff', ttf: 'truetype', otf: 'opentype' };
return files.map(function(file){
var ext = file.replace(/^.*\./, '');
return 'url(' + file + ') format("' + types[ext] + '")';
}).join(', ');
}
})
})

describe('.references()', function(){
it('should substitute @<word> with property values', function(){
rework(fixture('references'))
Expand Down

0 comments on commit 0ceeae2

Please sign in to comment.