Commit 45ad189a by Brett Wilkins

Adding new API

parent ed6fd4dc
...@@ -16,7 +16,7 @@ void WorkOnContext(uv_work_t* req) { ...@@ -16,7 +16,7 @@ void WorkOnContext(uv_work_t* req) {
sass_compile(ctx); sass_compile(ctx);
} }
void MakeCallback(uv_work_t* req) { void MakeOldCallback(uv_work_t* req) {
HandleScope scope; HandleScope scope;
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);
...@@ -46,7 +46,7 @@ void MakeCallback(uv_work_t* req) { ...@@ -46,7 +46,7 @@ void MakeCallback(uv_work_t* req) {
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
} }
Handle<Value> Render(const Arguments& args) { Handle<Value> OldRender(const Arguments& args) {
HandleScope scope; HandleScope scope;
sass_context* ctx = sass_new_context(); sass_context* ctx = sass_new_context();
sass_context_wrapper* ctx_w = sass_new_context_wrapper(); sass_context_wrapper* ctx_w = sass_new_context_wrapper();
...@@ -66,6 +66,63 @@ Handle<Value> Render(const Arguments& args) { ...@@ -66,6 +66,63 @@ Handle<Value> Render(const Arguments& args) {
ctx_w->callback = Persistent<Function>::New(callback); ctx_w->callback = Persistent<Function>::New(callback);
ctx_w->request.data = ctx_w; ctx_w->request.data = ctx_w;
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnContext, (uv_after_work_cb)MakeOldCallback);
assert(status == 0);
return scope.Close(Undefined());
}
void MakeCallback(uv_work_t* req) {
HandleScope scope;
TryCatch try_catch;
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
sass_context* ctx = static_cast<sass_context*>(ctx_w->ctx);
if (ctx->error_status == 0) {
// if no error, do callback(null, result)
const unsigned argc = 1;
Local<Value> argv[argc] = {
Local<Value>::New(String::New(ctx->output_string))
};
ctx_w->callback->Call(Context::GetCurrent()->Global(), argc, argv);
} else {
// if error, do callback(error)
const unsigned argc = 1;
Local<Value> argv[argc] = {
Local<Value>::New(String::New(ctx->error_message))
};
ctx_w->errorCallback->Call(Context::GetCurrent()->Global(), argc, argv);
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
sass_free_context_wrapper(ctx_w);
}
Handle<Value> Render(const Arguments& args) {
HandleScope scope;
sass_context* ctx = sass_new_context();
sass_context_wrapper* ctx_w = sass_new_context_wrapper();
char *source;
String::AsciiValue astr(args[0]);
Local<Function> callback = Local<Function>::Cast(args[1]);
Local<Function> errorCallback = Local<Function>::Cast(args[2]);
String::AsciiValue bstr(args[3]);
source = new char[strlen(*astr)+1];
strcpy(source, *astr);
ctx->source_string = source;
ctx->options.include_paths = new char[strlen(*bstr)+1];
strcpy(ctx->options.include_paths, *bstr);
// ctx->options.output_style = SASS_STYLE_NESTED;
ctx->options.output_style = args[4]->Int32Value();
ctx_w->ctx = ctx;
ctx_w->callback = Persistent<Function>::New(callback);
ctx_w->errorCallback = Persistent<Function>::New(errorCallback);
ctx_w->request.data = ctx_w;
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnContext, (uv_after_work_cb)MakeCallback); int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnContext, (uv_after_work_cb)MakeCallback);
assert(status == 0); assert(status == 0);
...@@ -95,9 +152,102 @@ Handle<Value> RenderSync(const Arguments& args) { ...@@ -95,9 +152,102 @@ Handle<Value> RenderSync(const Arguments& args) {
return scope.Close(Undefined()); return scope.Close(Undefined());
} }
/**
Rendering Files
**/
void WorkOnFileContext(uv_work_t* req) {
sass_file_context_wrapper* ctx_w = static_cast<sass_file_context_wrapper*>(req->data);
sass_file_context* ctx = static_cast<sass_file_context*>(ctx_w->ctx);
sass_compile_file(ctx);
}
void MakeFileCallback(uv_work_t* req) {
HandleScope scope;
TryCatch try_catch;
sass_file_context_wrapper* ctx_w = static_cast<sass_file_context_wrapper*>(req->data);
sass_file_context* ctx = static_cast<sass_file_context*>(ctx_w->ctx);
if (ctx->error_status == 0) {
// if no error, do callback(null, result)
const unsigned argc = 1;
Local<Value> argv[argc] = {
Local<Value>::New(String::New(ctx->output_string))
};
ctx_w->callback->Call(Context::GetCurrent()->Global(), argc, argv);
} else {
// if error, do callback(error)
const unsigned argc = 1;
Local<Value> argv[argc] = {
Local<Value>::New(String::New(ctx->error_message))
};
ctx_w->errorCallback->Call(Context::GetCurrent()->Global(), argc, argv);
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
sass_free_file_context_wrapper(ctx_w);
}
Handle<Value> RenderFile(const Arguments& args) {
HandleScope scope;
sass_file_context* ctx = sass_new_file_context();
sass_file_context_wrapper* ctx_w = sass_new_file_context_wrapper();
char *filename;
String::AsciiValue astr(args[0]);
Local<Function> callback = Local<Function>::Cast(args[1]);
Local<Function> errorCallback = Local<Function>::Cast(args[2]);
String::AsciiValue bstr(args[3]);
filename = new char[strlen(*astr)+1];
strcpy(filename, *astr);
ctx->input_path = filename;
ctx->options.include_paths = new char[strlen(*bstr)+1];
strcpy(ctx->options.include_paths, *bstr);
// ctx->options.output_style = SASS_STYLE_NESTED;
ctx->options.output_style = args[4]->Int32Value();
ctx_w->ctx = ctx;
ctx_w->callback = Persistent<Function>::New(callback);
ctx_w->errorCallback = Persistent<Function>::New(errorCallback);
ctx_w->request.data = ctx_w;
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, WorkOnFileContext, (uv_after_work_cb)MakeFileCallback);
assert(status == 0);
return scope.Close(Undefined());
}
Handle<Value> RenderFileSync(const Arguments& args) {
HandleScope scope;
sass_file_context* ctx = sass_new_file_context();
char *filename;
String::AsciiValue astr(args[0]);
String::AsciiValue bstr(args[1]);
filename = new char[strlen(*astr)+1];
strcpy(filename, *astr);
ctx->input_path = filename;
ctx->options.include_paths = new char[strlen(*bstr)+1];
strcpy(ctx->options.include_paths, *bstr);
ctx->options.output_style = args[2]->Int32Value();
sass_compile_file(ctx);
if (ctx->error_status == 0) {
return scope.Close(Local<Value>::New(String::New(ctx->output_string)));
}
ThrowException(Exception::Error(String::New(ctx->error_message)));
return scope.Close(Undefined());
}
void RegisterModule(v8::Handle<v8::Object> target) { void RegisterModule(v8::Handle<v8::Object> target) {
NODE_SET_METHOD(target, "oldRender", OldRender);
NODE_SET_METHOD(target, "render", Render); NODE_SET_METHOD(target, "render", Render);
NODE_SET_METHOD(target, "renderSync", RenderSync); NODE_SET_METHOD(target, "renderSync", RenderSync);
NODE_SET_METHOD(target, "renderFile", RenderFile);
NODE_SET_METHOD(target, "renderFileSync", RenderFileSync);
} }
NODE_MODULE(binding, RegisterModule); NODE_MODULE(binding, RegisterModule);
This diff was suppressed by a .gitattributes entry.
...@@ -21,20 +21,61 @@ var SASS_OUTPUT_STYLE = { ...@@ -21,20 +21,61 @@ var SASS_OUTPUT_STYLE = {
compressed: 3 compressed: 3
}; };
exports.render = function(css, callback, options) { var prepareOptions = function(options) {
var paths, style; var paths, style;
options = typeof options !== 'object' ? {} : options; options = typeof options !== 'object' ? {} : options;
paths = options.include_paths || options.includePaths || []; paths = options.include_paths || options.includePaths || [];
style = SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0; style = SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0;
return binding.render(css, callback, paths.join(':'), style);
return {
paths: paths,
style: style
};
}
var deprecatedRender = function(css, callback, options) {
options = prepareOptions(options);
return binding.oldRender(css, callback, options.paths.join(':'), options.style);
}; };
exports.renderSync = function(css, options) { var deprecatedRenderSync = function(css, options) {
var paths, style; options = prepareOptions(options);
options = typeof options !== 'object' ? {} : options; return binding.renderSync(css, options.paths.join(':'), options.style);
paths = options.include_paths || options.includePaths || []; };
style = SASS_OUTPUT_STYLE[options.output_style || options.outputStyle] || 0;
return binding.renderSync(css, paths.join(':'), style); exports.render = function(options) {
var newOptions;
if (typeof arguments[0] === 'string') {
return deprecatedRender.apply(this, arguments);
}
newOptions = prepareOptions(options);
options.error = options.error || function(){};
if (options.file !== undefined && options.file !== null) {
return binding.renderFile(options.file, options.success, options.error, newOptions.paths.join(':'), newOptions.style);
}
//Assume data is present if file is not. binding/libsass will tell the user otherwise!
return binding.render(options.data, options.success, options.error, newOptions.paths.join(":"), newOptions.style);
};
exports.renderSync = function(options) {
var newOptions;
if (typeof arguments[0] === 'string') {
return deprecatedRenderSync.apply(this, arguments);
}
newOptions = prepareOptions(options);
if (options.file !== undefined && options.file !== null) {
return binding.renderFileSync(options.file, newOptions.paths.join(':'), newOptions.style);
}
//Assume data is present if file is not. binding/libsass will tell the user otherwise!
return binding.renderSync(options.data, newOptions.paths.join(":"), newOptions.style);
}; };
exports.middleware = require('./lib/middleware'); exports.middleware = require('./lib/middleware');
...@@ -15,4 +15,16 @@ extern "C" { ...@@ -15,4 +15,16 @@ extern "C" {
free(ctx_w); free(ctx_w);
} }
sass_file_context_wrapper* sass_new_file_context_wrapper()
{
return (sass_file_context_wrapper*) calloc(1, sizeof(sass_file_context_wrapper));
}
void sass_free_file_context_wrapper(sass_file_context_wrapper* ctx_w)
{
if (ctx_w->ctx) sass_free_file_context(ctx_w->ctx);
free(ctx_w);
}
} }
...@@ -9,11 +9,22 @@ struct sass_context_wrapper { ...@@ -9,11 +9,22 @@ struct sass_context_wrapper {
sass_context* ctx; sass_context* ctx;
uv_work_t request; uv_work_t request;
v8::Persistent<v8::Function> callback; v8::Persistent<v8::Function> callback;
v8::Persistent<v8::Function> errorCallback;
}; };
struct sass_context_wrapper* sass_new_context_wrapper(void); struct sass_context_wrapper* sass_new_context_wrapper(void);
void sass_free_context_wrapper(struct sass_context_wrapper* ctx); void sass_free_context_wrapper(struct sass_context_wrapper* ctx);
struct sass_file_context_wrapper {
sass_file_context* ctx;
uv_work_t request;
v8::Persistent<v8::Function> callback;
v8::Persistent<v8::Function> errorCallback;
};
struct sass_file_context_wrapper* sass_new_file_context_wrapper(void);
void sass_free_file_context_wrapper(struct sass_file_context_wrapper* ctx);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#h1 { #navbar {
width: 100%; width: 80%;
span { height: 23px;
color: red; }
&.active { #navbar ul {
color: pink; list-style-type: none;
} }
#navbar li {
float: left;
a {
font-weight: bold;
} }
} }
...@@ -28,8 +28,11 @@ var expectedRender = '#navbar {\n\ ...@@ -28,8 +28,11 @@ var expectedRender = '#navbar {\n\
#navbar li a {\n\ #navbar li a {\n\
font-weight: bold; }\n'; font-weight: bold; }\n';
var badSampleFilename = 'sample.scss';
var sampleFilename = require('path').resolve(__dirname, 'sample.scss');
describe("compile scss", function() {
describe("DEPRECATED: compile scss", function() {
it("should compile with render", function(done) { it("should compile with render", function(done) {
sass.render(scssStr, function(err, css) { sass.render(scssStr, function(err, css) {
done(err); done(err);
...@@ -60,3 +63,80 @@ describe("compile scss", function() { ...@@ -60,3 +63,80 @@ describe("compile scss", function() {
})); }));
}); });
}); });
describe("compile scss", function() {
it("should compile with render", function(done) {
sass.render({
data: scssStr,
success: function(css) {
done(assert.ok(css));
}
});
});
it("should compile with renderSync", function(done) {
done(assert.ok(sass.renderSync({data: scssStr})));
});
it("should match compiled string with render", function(done) {
sass.render({
data: scssStr,
success: function(css) {
done(assert.equal(css, expectedRender));
},
error: function(error) {
done(error);
}
});
});
it("should match compiled string with renderSync", function(done) {
done(assert.equal(sass.renderSync({data: scssStr}), expectedRender));
});
it("should throw an exception for bad input", function(done) {
done(assert.throws(function() {
sass.renderSync({data: badInput});
}));
});
});
describe("compile file", function() {
it("should compile with render", function(done) {
sass.render({
file: sampleFilename,
success: function (css) {
done(assert.ok(css));
},
error: function (error) {
done(error);
}
});
});
it("should compile with renderSync", function(done) {
done(assert.ok(sass.renderSync({file: sampleFilename})));
});
it("should match compiled string with render", function(done) {
sass.render({
file: sampleFilename,
success: function(css) {
done(assert.equal(css, expectedRender));
},
error: function(error) {
done(error);
}
});
});
it("should match compiled string with renderSync", function(done) {
done(assert.equal(sass.renderSync({file: sampleFilename}), expectedRender));
});
it("should throw an exception for bad input", function(done) {
done(assert.throws(function() {
sass.renderSync({file: badSampleFilename});
}));
});
});
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