Commit 0e168812 by Adeel Mujahid

Merge pull request #577 from am11/simplified_api_2

API: Simplified code usage (#547)
parents 4bea0703 cfef58f3
...@@ -5,7 +5,8 @@ var Emitter = require('events').EventEmitter, ...@@ -5,7 +5,8 @@ var Emitter = require('events').EventEmitter,
meow = require('meow'), meow = require('meow'),
replaceExt = require('replace-ext'), replaceExt = require('replace-ext'),
stdin = require('get-stdin'), stdin = require('get-stdin'),
render = require('../lib/render'); render = require('../lib/render'),
fs = require('fs');
/** /**
* Initialize CLI * Initialize CLI
...@@ -14,6 +15,8 @@ var Emitter = require('events').EventEmitter, ...@@ -14,6 +15,8 @@ var Emitter = require('events').EventEmitter,
var cli = meow({ var cli = meow({
pkg: '../package.json', pkg: '../package.json',
help: [ help: [
require('../lib/').info(),
'',
'Usage', 'Usage',
' node-sass [options] <input.scss> [output.css]', ' node-sass [options] <input.scss> [output.css]',
' cat <input.scss> | node-sass > output.css', ' cat <input.scss> | node-sass > output.css',
...@@ -37,6 +40,7 @@ var cli = meow({ ...@@ -37,6 +40,7 @@ var cli = meow({
' --image-path Path to prepend when using the `image-url()` helper', ' --image-path Path to prepend when using the `image-url()` helper',
' --precision The amount of precision allowed in decimal numbers', ' --precision The amount of precision allowed in decimal numbers',
' --stdout Print the resulting CSS to stdout', ' --stdout Print the resulting CSS to stdout',
' --importer Path to custom importer',
' --help Print usage info' ' --help Print usage info'
].join('\n') ].join('\n')
}, { }, {
...@@ -105,6 +109,10 @@ function getEmitter() { ...@@ -105,6 +109,10 @@ function getEmitter() {
console.log(data); console.log(data);
}); });
emitter.on('done', function(){
process.exit(0);
});
return emitter; return emitter;
} }
...@@ -202,6 +210,15 @@ function run(options, emitter) { ...@@ -202,6 +210,15 @@ function run(options, emitter) {
} }
} }
if (options.importer) {
if (fs.existsSync(options.importer)) {
options.importer = require(options.importer);
} else {
console.error('Could not locate importer.');
process.exit(1);
}
}
if (options.watch) { if (options.watch) {
watch(options, emitter); watch(options, emitter);
} else { } else {
...@@ -240,6 +257,7 @@ if (options.src) { ...@@ -240,6 +257,7 @@ if (options.src) {
} else if (!process.stdin.isTTY) { } else if (!process.stdin.isTTY) {
stdin(function(data) { stdin(function(data) {
options.data = data; options.data = data;
options.stdin = true;
run(options, emitter); run(options, emitter);
}); });
} }
......
...@@ -54,7 +54,7 @@ function getOutFile(options) { ...@@ -54,7 +54,7 @@ function getOutFile(options) {
*/ */
function getStats(options) { function getStats(options) {
var stats = options.stats; var stats = {};
stats.entry = options.file || 'data'; stats.entry = options.file || 'data';
stats.start = Date.now(); stats.start = Date.now();
...@@ -65,17 +65,14 @@ function getStats(options) { ...@@ -65,17 +65,14 @@ function getStats(options) {
/** /**
* End stats * End stats
* *
* @param {Object} options * @param {Object} stats
* @param {Object} sourceMap * @param {Object} sourceMap
* @api private * @api private
*/ */
function endStats(options, sourceMap) { function endStats(stats) {
var stats = options.stats || {};
stats.end = Date.now(); stats.end = Date.now();
stats.duration = stats.end - stats.start; stats.duration = stats.end - stats.start;
stats.sourceMap = sourceMap;
return stats; return stats;
} }
...@@ -139,15 +136,12 @@ function getOptions(options) { ...@@ -139,15 +136,12 @@ function getOptions(options) {
options.paths = (options.include_paths || options.includePaths || []).join(path.delimiter); options.paths = (options.include_paths || options.includePaths || []).join(path.delimiter);
options.precision = parseInt(options.precision) || 5; options.precision = parseInt(options.precision) || 5;
options.sourceMap = getSourceMap(options); options.sourceMap = getSourceMap(options);
options.stats = options.stats || {};
options.style = getStyle(options) || 0; options.style = getStyle(options) || 0;
if (options.imagePath && typeof options.imagePath !== 'string') { if (options.imagePath && typeof options.imagePath !== 'string') {
throw new Error('`imagePath` needs to be a string'); throw new Error('`imagePath` needs to be a string');
} }
getStats(options);
var error = options.error; var error = options.error;
var success = options.success; var success = options.success;
var importer = options.importer; var importer = options.importer;
...@@ -159,29 +153,41 @@ function getOptions(options) { ...@@ -159,29 +153,41 @@ function getOptions(options) {
err = { message: err }; err = { message: err };
} }
err.code = code;
if (error) { if (error) {
error(err, code); error(err);
} }
}; };
options.success = function(css, sourceMap) { options.success = function() {
sourceMap = JSON.parse(sourceMap); options.result.sourceMap = JSON.parse(options.result.sourceMap);
endStats(options, sourceMap); var stats = endStats(options.result.stats);
if (success) { if (success) {
success(css, sourceMap); success({
css: options.result.css,
map: options.result.sourceMap,
stats: stats
});
} }
}; };
if (importer) { if (importer) {
options.importer = function(file, prev, key) { options.importer = function(file, prev, key) {
importer(file, prev, function(data) { var done = function(data) {
binding.importedCallback({ binding.importedCallback({
index: key, index: key,
objectLiteral: data objectLiteral: data
}); });
}); };
var result = importer(file, prev, done);
if (result) {
done(result);
}
}; };
} }
...@@ -191,6 +197,10 @@ function getOptions(options) { ...@@ -191,6 +197,10 @@ function getOptions(options) {
delete options.source_comments; delete options.source_comments;
delete options.sourceComments; delete options.sourceComments;
options.result = {
stats: getStats(options)
};
return options; return options;
} }
...@@ -201,41 +211,6 @@ function getOptions(options) { ...@@ -201,41 +211,6 @@ function getOptions(options) {
var binding = require(getBinding()); var binding = require(getBinding());
/** /**
* Render (deprecated)
*
* @param {String} css
* @param {Function} cb
* @param {Object} options
* @api private
*/
function deprecatedRender(css, cb, options) {
options = getOptions(options);
options.data = css;
options.error = cb;
options.success = function(css) {
cb(null, css);
};
binding.render(options);
}
/**
* Render sync (deprecated)
*
* @param {String} css
* @param {Object} options
* @api private
*/
function deprecatedRenderSync(css, options) {
options = getOptions(options);
options.data = css;
return binding.renderSync(options);
}
/**
* Render * Render
* *
* @param {Object} options * @param {Object} options
...@@ -243,12 +218,9 @@ function deprecatedRenderSync(css, options) { ...@@ -243,12 +218,9 @@ function deprecatedRenderSync(css, options) {
*/ */
module.exports.render = function(options) { module.exports.render = function(options) {
if (typeof arguments[0] === 'string') {
return deprecatedRender.apply(this, arguments);
}
options = getOptions(options); options = getOptions(options);
options.file ? binding.renderFile(options) : binding.render(options);
options.data ? binding.render(options) : binding.renderFile(options);
}; };
/** /**
...@@ -259,79 +231,27 @@ module.exports.render = function(options) { ...@@ -259,79 +231,27 @@ module.exports.render = function(options) {
*/ */
module.exports.renderSync = function(options) { module.exports.renderSync = function(options) {
if (typeof arguments[0] === 'string') {
return deprecatedRenderSync.apply(this, arguments);
}
var output;
options = getOptions(options); options = getOptions(options);
output = options.file ? binding.renderFileSync(options) : binding.renderSync(options);
endStats(options, JSON.parse(options.stats.sourceMap));
return output;
};
/** var result = options.data ? binding.renderSync(options) : binding.renderFileSync(options);
* Render file
*
* `options.sourceMap` can be used to specify that the source map should be saved:
*
* - If falsy the source map will not be saved
* - If `options.sourceMap === true` the source map will be saved to the
* standard location of `options.file + '.map'`
* - Else `options.sourceMap` specifies the path (relative to the `outFile`)
* where the source map should be saved
*
* @param {Object} options
* @api public
*/
module.exports.renderFile = function(options) { if(result) {
options = options || {}; options.result.stats = endStats(options.result.stats);
var outFile = options.outFile; return options.result;
var success = options.success;
if (options.sourceMap === true) {
options.sourceMap = outFile + '.map';
} }
options.success = function(css, sourceMap) {
fs.writeFile(outFile, css, function(err) {
if (err) {
return options.error(err);
}
if (!options.sourceMap) {
return success(outFile);
}
var dir = path.dirname(outFile);
var sourceMapFile = path.resolve(dir, options.sourceMap);
fs.writeFile(sourceMapFile, JSON.stringify(sourceMap), function(err) {
if (err) {
return options.error(err);
}
success(outFile, sourceMapFile);
});
});
};
module.exports.render(options);
}; };
/** /**
* Middleware * API Info
* *
* @api public
*/ */
module.exports.middleware = function() { module.exports.info = function() {
return new Error([ var package = require('../package.json');
'The middleware has been moved to',
'https://github.com/sass/node-sass-middleware' return [
].join(' ')); 'node-sass version: ' + package.version,
'libsass version: ' + package.libsass
].join('\n');
}; };
...@@ -22,7 +22,8 @@ module.exports = function(options, emitter) { ...@@ -22,7 +22,8 @@ module.exports = function(options, emitter) {
sourceComments: options.sourceComments, sourceComments: options.sourceComments,
sourceMapEmbed: options.sourceMapEmbed, sourceMapEmbed: options.sourceMapEmbed,
sourceMapContents: options.sourceMapContents, sourceMapContents: options.sourceMapContents,
sourceMap: options.sourceMap sourceMap: options.sourceMap,
importer: options.importer
}; };
if (options.src) { if (options.src) {
...@@ -31,7 +32,7 @@ module.exports = function(options, emitter) { ...@@ -31,7 +32,7 @@ module.exports = function(options, emitter) {
renderOptions.data = options.data; renderOptions.data = options.data;
} }
renderOptions.success = function(css, sourceMap) { renderOptions.success = function(result) {
var todo = 1; var todo = 1;
var done = function() { var done = function() {
if (--todo <= 0) { if (--todo <= 0) {
...@@ -39,38 +40,38 @@ module.exports = function(options, emitter) { ...@@ -39,38 +40,38 @@ module.exports = function(options, emitter) {
} }
}; };
if (options.stdout || (!options.dest && !process.stdout.isTTY)) { if (options.stdout || (!options.dest && !process.stdout.isTTY) || options.stdin) {
emitter.emit('log', css); emitter.emit('log', result.css);
return done(); return done();
} }
emitter.emit('warn', chalk.green('Rendering Complete, saving .css file...')); emitter.emit('warn', chalk.green('Rendering Complete, saving .css file...'));
fs.writeFile(options.dest, css, function(err) { fs.writeFile(options.dest, result.css, function(err) {
if (err) { if (err) {
return emitter.emit('error', chalk.red(err)); return emitter.emit('error', chalk.red(err));
} }
emitter.emit('warn', chalk.green('Wrote CSS to ' + options.dest)); emitter.emit('warn', chalk.green('Wrote CSS to ' + options.dest));
emitter.emit('write', err, options.dest, css); emitter.emit('write', err, options.dest, result.css);
done(); done();
}); });
if (options.sourceMap) { if (options.sourceMap) {
todo++; todo++;
fs.writeFile(options.sourceMap, sourceMap, function(err) { fs.writeFile(options.sourceMap, result.map, function(err) {
if (err) { if (err) {
return emitter.emit('error', chalk.red('Error' + err)); return emitter.emit('error', chalk.red('Error' + err));
} }
emitter.emit('warn', chalk.green('Wrote Source Map to ' + options.sourceMap)); emitter.emit('warn', chalk.green('Wrote Source Map to ' + options.sourceMap));
emitter.emit('write-source-map', err, options.sourceMap, sourceMap); emitter.emit('write-source-map', err, options.sourceMap, result.sourceMap);
done(); done();
}); });
} }
emitter.emit('render', css); emitter.emit('render', result.css);
}; };
renderOptions.error = function(error) { renderOptions.error = function(error) {
......
{ {
"name": "node-sass", "name": "node-sass",
"version": "1.2.3", "version": "2.0.0-beta",
"libsass": "3.1.0-beta",
"description": "Wrapper around libsass", "description": "Wrapper around libsass",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/sass/node-sass", "homepage": "https://github.com/sass/node-sass",
...@@ -50,7 +51,7 @@ ...@@ -50,7 +51,7 @@
"mkdirp": "^0.5.0", "mkdirp": "^0.5.0",
"mocha": "^2.0.1", "mocha": "^2.0.1",
"nan": "^1.3.0", "nan": "^1.3.0",
"object-assign": "^1.0.0", "object-assign": "^2.0.0",
"replace-ext": "0.0.1", "replace-ext": "0.0.1",
"request": "^2.48.0", "request": "^2.48.0",
"shelljs": "^0.3.0" "shelljs": "^0.3.0"
......
...@@ -15,7 +15,7 @@ char* CreateString(Local<Value> value) { ...@@ -15,7 +15,7 @@ char* CreateString(Local<Value> value) {
std::vector<sass_context_wrapper*> imports_collection; std::vector<sass_context_wrapper*> imports_collection;
void dispatched_async_uv_callback(uv_async_t *req){ void dispatched_async_uv_callback(uv_async_t *req) {
NanScope(); NanScope();
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data); sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
...@@ -24,8 +24,8 @@ void dispatched_async_uv_callback(uv_async_t *req){ ...@@ -24,8 +24,8 @@ void dispatched_async_uv_callback(uv_async_t *req){
imports_collection.push_back(ctx_w); imports_collection.push_back(ctx_w);
Handle<Value> argv[] = { Handle<Value> argv[] = {
NanNew<String>(strdup(ctx_w->file)), NanNew<String>(strdup(ctx_w->file ? ctx_w->file : 0)),
NanNew<String>(strdup(ctx_w->prev)), NanNew<String>(strdup(ctx_w->prev ? ctx_w->prev : 0)),
NanNew<Number>(imports_collection.size() - 1) NanNew<Number>(imports_collection.size() - 1)
}; };
...@@ -40,8 +40,8 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo ...@@ -40,8 +40,8 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo
{ {
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(cookie); sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(cookie);
ctx_w->file = strdup(file); ctx_w->file = file ? strdup(file) : 0;
ctx_w->prev = strdup(prev); ctx_w->prev = prev ? strdup(prev) : 0;
ctx_w->async.data = (void*)ctx_w; ctx_w->async.data = (void*)ctx_w;
uv_async_send(&ctx_w->async); uv_async_send(&ctx_w->async);
...@@ -52,7 +52,7 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo ...@@ -52,7 +52,7 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo
*/ */
uv_cond_wait(&ctx_w->importer_condition_variable, &ctx_w->importer_mutex); uv_cond_wait(&ctx_w->importer_condition_variable, &ctx_w->importer_mutex);
} }
else{ else {
/* that is sync: RenderSync() or RenderFileSync, /* that is sync: RenderSync() or RenderFileSync,
* we need to explicitly uv_run as the event loop * we need to explicitly uv_run as the event loop
* is blocked; waiting down the chain. * is blocked; waiting down the chain.
...@@ -66,6 +66,8 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo ...@@ -66,6 +66,8 @@ struct Sass_Import** sass_importer(const char* file, const char* prev, void* coo
void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx_w, bool isFile, bool isSync) { void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx_w, bool isFile, bool isSync) {
struct Sass_Context* ctx; struct Sass_Context* ctx;
NanAssignPersistent(ctx_w->result, options->Get(NanNew("result"))->ToObject());
if (isFile) { if (isFile) {
ctx = sass_file_context_get_context((struct Sass_File_Context*) cptr); ctx = sass_file_context_get_context((struct Sass_File_Context*) cptr);
ctx_w->fctx = (struct Sass_File_Context*) cptr; ctx_w->fctx = (struct Sass_File_Context*) cptr;
...@@ -78,8 +80,6 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -78,8 +80,6 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
struct Sass_Options* sass_options = sass_context_get_options(ctx); struct Sass_Options* sass_options = sass_context_get_options(ctx);
if (!isSync) { if (!isSync) {
NanAssignPersistent(ctx_w->stats, options->Get(NanNew("stats"))->ToObject());
ctx_w->request.data = ctx_w; ctx_w->request.data = ctx_w;
// async (callback) style // async (callback) style
...@@ -99,6 +99,7 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -99,6 +99,7 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
sass_option_set_importer(sass_options, sass_make_importer(sass_importer, ctx_w)); sass_option_set_importer(sass_options, sass_make_importer(sass_importer, ctx_w));
} }
sass_option_set_input_path(sass_options, CreateString(options->Get(NanNew("file"))));
sass_option_set_output_path(sass_options, CreateString(options->Get(NanNew("outFile")))); sass_option_set_output_path(sass_options, CreateString(options->Get(NanNew("outFile"))));
sass_option_set_image_path(sass_options, CreateString(options->Get(NanNew("imagePath")))); sass_option_set_image_path(sass_options, CreateString(options->Get(NanNew("imagePath"))));
sass_option_set_output_style(sass_options, (Sass_Output_Style)options->Get(NanNew("style"))->Int32Value()); sass_option_set_output_style(sass_options, (Sass_Output_Style)options->Get(NanNew("style"))->Int32Value());
...@@ -112,7 +113,7 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -112,7 +113,7 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
sass_option_set_precision(sass_options, options->Get(NanNew("precision"))->Int32Value()); sass_option_set_precision(sass_options, options->Get(NanNew("precision"))->Int32Value());
} }
void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) { void GetStats(Handle<Object> result, Sass_Context* ctx) {
char** included_files = sass_context_get_included_files(ctx); char** included_files = sass_context_get_included_files(ctx);
Handle<Array> arr = NanNew<Array>(); Handle<Array> arr = NanNew<Array>();
...@@ -122,8 +123,10 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) { ...@@ -122,8 +123,10 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) {
} }
} }
(*stats)->Set(NanNew("includedFiles"), arr); (*result)->Get(NanNew("stats"))->ToObject()->Set(NanNew("includedFiles"), arr);
}
void GetSourceMap(Handle<Object> result, Sass_Context* ctx) {
Handle<Value> source_map; Handle<Value> source_map;
if (sass_context_get_error_status(ctx)) { if (sass_context_get_error_status(ctx)) {
...@@ -137,7 +140,19 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) { ...@@ -137,7 +140,19 @@ void FillStatsObj(Handle<Object> stats, Sass_Context* ctx) {
source_map = NanNew<String>("{}"); source_map = NanNew<String>("{}");
} }
(*stats)->Set(NanNew("sourceMap"), source_map); (*result)->Set(NanNew("sourceMap"), source_map);
}
int GetResult(Handle<Object> result, Sass_Context* ctx) {
int status = sass_context_get_error_status(ctx);
if (status == 0) {
(*result)->Set(NanNew("css"), NanNew<String>(sass_context_get_output_string(ctx)));
GetStats(result, ctx);
GetSourceMap(result, ctx);
}
return status;
} }
void make_callback(uv_work_t* req) { void make_callback(uv_work_t* req) {
...@@ -145,35 +160,27 @@ void make_callback(uv_work_t* req) { ...@@ -145,35 +160,27 @@ void make_callback(uv_work_t* req) {
TryCatch try_catch; TryCatch try_catch;
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data); sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
int error_status;
struct Sass_Context* ctx; struct Sass_Context* ctx;
if (ctx_w->dctx) { if (ctx_w->dctx) {
ctx = sass_data_context_get_context(ctx_w->dctx); ctx = sass_data_context_get_context(ctx_w->dctx);
FillStatsObj(NanNew(ctx_w->stats), ctx);
error_status = sass_context_get_error_status(ctx);
} }
else { else {
ctx = sass_file_context_get_context(ctx_w->fctx); ctx = sass_file_context_get_context(ctx_w->fctx);
FillStatsObj(NanNew(ctx_w->stats), ctx);
error_status = sass_context_get_error_status(ctx);
} }
if (error_status == 0) { int status = GetResult(ctx_w->result, ctx);
if (status == 0) {
// if no error, do callback(null, result) // if no error, do callback(null, result)
const char* val = sass_context_get_output_string(ctx); ctx_w->success_callback->Call(0, 0);
Local<Value> argv[] = {
NanNew<String>(val),
NanNew(ctx_w->stats)->Get(NanNew("sourceMap"))
};
ctx_w->success_callback->Call(2, argv);
} }
else { else {
// if error, do callback(error) // if error, do callback(error)
const char* err = sass_context_get_error_json(ctx); const char* err = sass_context_get_error_json(ctx);
Local<Value> argv[] = { Local<Value> argv[] = {
NanNew<String>(err), NanNew<String>(err),
NanNew<Integer>(error_status) NanNew<Integer>(status)
}; };
ctx_w->error_callback->Call(2, argv); ctx_w->error_callback->Call(2, argv);
} }
...@@ -212,21 +219,22 @@ NAN_METHOD(RenderSync) { ...@@ -212,21 +219,22 @@ NAN_METHOD(RenderSync) {
ExtractOptions(options, dctx, ctx_w, false, true); ExtractOptions(options, dctx, ctx_w, false, true);
compile_data(dctx); compile_data(dctx);
FillStatsObj(options->Get(NanNew("stats"))->ToObject(), ctx);
if (sass_context_get_error_status(ctx) == 0) { int result = GetResult(ctx_w->result, ctx);
Local<String> output = NanNew<String>(sass_context_get_output_string(ctx)); Local<String> error;
sass_delete_data_context(dctx); if (result != 0) {
NanReturnValue(output); error = NanNew<String>(sass_context_get_error_json(ctx));
} }
Local<String> error = NanNew<String>(sass_context_get_error_json(ctx));
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
NanThrowError(error); free(source_string);
NanReturnUndefined(); if (result != 0) {
NanThrowError(error);
}
NanReturnValue(NanNew<Boolean>(result == 0));
} }
NAN_METHOD(RenderFile) { NAN_METHOD(RenderFile) {
...@@ -258,22 +266,22 @@ NAN_METHOD(RenderFileSync) { ...@@ -258,22 +266,22 @@ NAN_METHOD(RenderFileSync) {
ExtractOptions(options, fctx, ctx_w, true, true); ExtractOptions(options, fctx, ctx_w, true, true);
compile_file(fctx); compile_file(fctx);
FillStatsObj(options->Get(NanNew("stats"))->ToObject(), ctx);
free(input_path);
if (sass_context_get_error_status(ctx) == 0) { int result = GetResult(ctx_w->result, ctx);
Local<String> output = NanNew<String>(sass_context_get_output_string(ctx)); Local<String> error;
sass_delete_file_context(fctx); if (result != 0) {
NanReturnValue(output); error = NanNew<String>(sass_context_get_error_json(ctx));
} }
Local<String> error = NanNew<String>(sass_context_get_error_json(ctx));
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
NanThrowError(error); free(input_path);
NanReturnUndefined(); if (result != 0) {
NanThrowError(error);
}
NanReturnValue(NanNew<Boolean>(result == 0));
} }
NAN_METHOD(ImportedCallback) { NAN_METHOD(ImportedCallback) {
...@@ -282,9 +290,7 @@ NAN_METHOD(ImportedCallback) { ...@@ -282,9 +290,7 @@ NAN_METHOD(ImportedCallback) {
TryCatch try_catch; TryCatch try_catch;
Local<Object> options = args[0]->ToObject(); Local<Object> options = args[0]->ToObject();
char* source_string = CreateString(options->Get(NanNew("index")));
Local<Value> returned_value = options->Get(NanNew("objectLiteral")); Local<Value> returned_value = options->Get(NanNew("objectLiteral"));
size_t index = options->Get(NanNew("index"))->Int32Value(); size_t index = options->Get(NanNew("index"))->Int32Value();
if (index >= imports_collection.size()) { if (index >= imports_collection.size()) {
......
Subproject commit 7aaa45a979ce65d50b3158ff50bf9409f8955063 Subproject commit cf7c1d14fec91a66ab9c2a3050dcec5fab6198f5
...@@ -37,14 +37,13 @@ extern "C" { ...@@ -37,14 +37,13 @@ extern "C" {
sass_delete_file_context(ctx_w->fctx); sass_delete_file_context(ctx_w->fctx);
} }
NanDisposePersistent(ctx_w->stats); NanDisposePersistent(ctx_w->result);
delete ctx_w->success_callback; delete ctx_w->success_callback;
delete ctx_w->error_callback; delete ctx_w->error_callback;
delete ctx_w->importer_callback; delete ctx_w->importer_callback;
delete ctx_w->file; delete ctx_w->file;
delete ctx_w->prev; delete ctx_w->prev;
delete ctx_w->cookie;
uv_mutex_destroy(&ctx_w->importer_mutex); uv_mutex_destroy(&ctx_w->importer_mutex);
uv_cond_destroy(&ctx_w->importer_condition_variable); uv_cond_destroy(&ctx_w->importer_condition_variable);
......
...@@ -14,7 +14,7 @@ extern "C" { ...@@ -14,7 +14,7 @@ extern "C" {
struct sass_context_wrapper { struct sass_context_wrapper {
Sass_Data_Context* dctx; Sass_Data_Context* dctx;
Sass_File_Context* fctx; Sass_File_Context* fctx;
Persistent<Object> stats; Persistent<Object> result;
uv_work_t request; uv_work_t request;
uv_mutex_t importer_mutex; uv_mutex_t importer_mutex;
uv_cond_t importer_condition_variable; uv_cond_t importer_condition_variable;
......
...@@ -223,4 +223,106 @@ describe('cli', function() { ...@@ -223,4 +223,106 @@ describe('cli', function() {
}); });
}); });
}); });
describe('importer', function() {
var dest = fixture('include-files/index.css');
var src = fixture('include-files/index.scss');
var expected = read(fixture('include-files/expected-importer.css'), 'utf8').trim().replace(/\r\n/g, '\n');
it('should override imports and fire callback with file and contents', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_file_and_data_cb.js')
]);
bin.on('close', function () {
assert.equal(read(dest, 'utf8').trim(), expected);
fs.unlinkSync(dest);
done();
});
});
it('should override imports and fire callback with file', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_file_cb.js')
]);
bin.on('close', function () {
if (fs.existsSync(dest)) {
assert.equal(read(dest, 'utf8').trim(), '');
fs.unlinkSync(dest);
}
done();
});
});
it('should override imports and fire callback with data', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_data_cb.js')
]);
bin.on('close', function () {
assert.equal(read(dest, 'utf8').trim(), expected);
fs.unlinkSync(dest);
done();
});
});
it('should override imports and return file and contents', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_file_and_data.js')
]);
bin.on('close', function () {
assert.equal(read(dest, 'utf8').trim(), expected);
fs.unlinkSync(dest);
done();
});
});
it('should override imports and return file', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_file.js')
]);
bin.on('close', function () {
if (fs.existsSync(dest)) {
assert.equal(read(dest, 'utf8').trim(), '');
fs.unlinkSync(dest);
}
done();
});
});
it('should override imports and return data', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('extras/my_custom_importer_data.js')
]);
bin.on('close', function () {
assert.equal(read(dest, 'utf8').trim(), expected);
fs.unlinkSync(dest);
done();
});
});
it('should return error on for invalid importer file path', function(done) {
var bin = spawn(cli, [
src, '--output', path.dirname(dest),
'--importer', fixture('non/existing/path')
]);
bin.on('close', function (code) {
assert(code !== 0);
done();
});
});
});
}); });
module.exports = function() {
return {
contents: 'div {color: yellow;}'
};
};
module.exports = function(file, prev, done) {
done({
contents: 'div {color: yellow;}'
});
};
var path = require('path');
module.exports = function(file) {console.log('>>>>>>>>>>');console.log(path.resolve(path.join(process.cwd(), 'test/fixtures/include-files/', file + (path.extname(file) ? '' : '.scss'))));
return {
file: path.resolve(path.join(process.cwd(), 'test/fixtures/include-files/', file + (path.extname(file) ? '' : '.scss')))
};
};
module.exports = function() {
return {
file: '/some/random/path/file.scss',
contents: 'div {color: yellow;}'
};
};
module.exports = function(file, prev, done) {
done({
file: '/some/random/path/file.scss',
contents: 'div {color: yellow;}'
});
};
var path = require('path');
module.exports = function(file, /* jshint unused:false */ prev, done) {
done({
file: path.resolve(path.join(process.cwd(), 'test/fixtures/include-files/', file + (path.extname(file) ? '' : '.scss')))
});
};
div {
color: yellow; }
div {
color: yellow; }
Subproject commit 074ae3b24bfc3ff19a98efdec02415ed6fd5759a Subproject commit 00c6154dba85a38bb03b89d7279f439feb055821
...@@ -40,8 +40,8 @@ describe('spec', function () { ...@@ -40,8 +40,8 @@ describe('spec', function () {
sass.render({ sass.render({
file: t.src, file: t.src,
includePaths: t.paths, includePaths: t.paths,
success: function(css) { success: function(result) {
assert.equal(util.normalize(css), expected); assert.equal(util.normalize(result.css), expected);
done(); done();
}, },
error: function(err) { error: function(err) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment