Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
Support custom functions without signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
matryo committed Feb 2, 2015
1 parent f152b8c commit d6ce2d4
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 9 deletions.
65 changes: 56 additions & 9 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,45 @@ function tryCallback(callback, args) {
}
}

/**
* Normalizes the signature of custom functions to make it possible to just supply the
* function name and have the signature default to `fn(...)`. The callback is adjusted
* to transform the input sass list into discrete arguments.
*
* @param {String} signature
* @param {Function} callback
* @return {Object}
* @api private
*/

function normalizeFunctionSignature(signature, callback) {
if (!/^\*|@warn|@error|@debug|\w+\(.*\)$/.test(signature)) {
if (!/\w+/.test(signature)) {
throw new Error('Invalid function signature format "' + signature + '"');
}

return {
signature: signature + '(...)',
callback: function() {
var args = Array.prototype.slice.call(arguments),
list = args.shift(),
i;

for (i = list.getLength() - 1; i >= 0; i--) {
args.unshift(list.getValue(i));
}

return callback.apply(this, args);
}
};
}

return {
signature: signature,
callback: callback
};
}

/**
* Require binding
*/
Expand Down Expand Up @@ -242,19 +281,23 @@ module.exports.render = function(options) {
};
}

if (options.functions) {
Object.keys(options.functions).forEach(function(signature) {
var callback = options.functions[signature];
var functions = options.functions;

if (functions) {
options.functions = {};

options.functions[signature] = function() {
Object.keys(functions).forEach(function(signature) {
var cb = normalizeFunctionSignature(signature, functions[signature]);

options.functions[cb.signature] = function() {
var args = Array.prototype.slice.call(arguments),
bridge = args.pop();

function done(data) {
bridge.success(data);
}

var result = tryCallback(callback, args.concat(done));
var result = tryCallback(cb.callback, args.concat(done));

if (result) {
done(result);
Expand All @@ -277,12 +320,16 @@ module.exports.render = function(options) {
module.exports.renderSync = function(options) {
options = getOptions(options);

var functions = options.functions;

if (options.functions) {
Object.keys(options.functions).forEach(function(signature) {
var callback = options.functions[signature];
options.functions = {};

Object.keys(functions).forEach(function(signature) {
var cb = normalizeFunctionSignature(signature, functions[signature]);

options.functions[signature] = function() {
return tryCallback(callback, arguments);
options.functions[cb.signature] = function() {
return tryCallback(cb.callback, arguments);
};
});
}
Expand Down
29 changes: 29 additions & 0 deletions test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,21 @@ describe('api', function() {
});
});

it('should let us register custom functions without signatures', function(done) {
sass.render({
data: 'div { color: foo(20, 22); }',
success: function(result) {
assert.equal(result.css.trim(), 'div {\n color: 42em; }');
done();
},
functions: {
foo: function(a, b) {
return new sass.types.Number(a.getValue() + b.getValue(), 'em');
}
}
});
});

it('should fail when returning anything other than a sass value from a custom function', function(done) {
sass.render({
data: 'div { color: foo(); }',
Expand Down Expand Up @@ -706,6 +721,20 @@ describe('api', function() {
done();
});

it('should let us register custom functions without signatures', function(done) {
var result = sass.renderSync({
data: 'div { color: foo(20, 22); }',
functions: {
foo: function(a, b) {
return new sass.types.Number(a.getValue() + b.getValue(), 'em');
}
}
});

assert.equal(result.css.trim(), 'div {\n color: 42em; }');
done();
});

it('should fail when returning anything other than a sass value from a custom function', function(done) {
assert.throws(function() {
sass.renderSync({
Expand Down

0 comments on commit d6ce2d4

Please sign in to comment.