Commit 9180b5c4 by Dean Mao

add callback support and add newlines at end of files

parent c4ce49a4
......@@ -6,13 +6,12 @@ Node bindings to libsass
## Install
cd libsass && make && cd ..
node-waf configure && node-waf build
npm install
## Usage
var sass = require('./sass');
sass.render('body{background:blue; a{color:black;}}', function(css){
sass.render('body{background:blue; a{color:black;}}', function(err, css){
console.log(css)
});
......@@ -40,4 +39,4 @@ Heavily inspired by <https://github.com/LearnBoost/stylus>
* publish npm
* use node-gyp for builds
* file context
* folder context
\ No newline at end of file
* folder context
#include <v8.h>
#include <node.h>
#include <string>
#include <cstdlib>
#include "libsass/sass_interface.h"
using namespace v8;
void WorkOnContext(uv_work_t* req) {
sass_context* ctx = static_cast<sass_context*>(req->data);
sass_compile(ctx);
}
void MakeCallback(uv_work_t* req) {
HandleScope scope;
TryCatch try_catch;
sass_context* ctx = static_cast<sass_context*>(req->data);
if (ctx->error_status == 0) {
// if no error, do callback(null, result)
const unsigned argc = 2;
Local<Value> argv[argc] = {
Local<Value>::New(Null()),
Local<Value>::New(String::New(ctx->output_string))
};
ctx->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->callback->Call(Context::GetCurrent()->Global(), argc, argv);
}
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}
Handle<Value> Render(const Arguments& args) {
HandleScope scope;
struct sass_context* ctx = sass_new_context();
String::AsciiValue astr(args[0]);
char * cs = *astr;
sass_context* ctx = sass_new_context();
String::AsciiValue astr(args[0]);
Local<Function> callback = Local<Function>::Cast(args[1]);
ctx->source_string = cs;
ctx->source_string = new char[strlen(*astr)+1];
strcpy(ctx->source_string, *astr);
ctx->options.include_paths = 0;
ctx->options.output_style = SASS_STYLE_NESTED;
ctx->callback = Persistent<Function>::New(callback);
ctx->request.data = ctx;
sass_compile(ctx);
int status = uv_queue_work(uv_default_loop(), &ctx->request, WorkOnContext, MakeCallback);
assert(status == 0);
return scope.Close(String::New(ctx->output_string));
return Undefined();
}
void RegisterModule(v8::Handle<v8::Object> target) {
......
......@@ -20,13 +20,13 @@ var imports = {};
* when undefined defaults to `src`.
*
* Examples:
*
*
* Pass the middleware to Connect, grabbing .scss files from this directory
* and saving .css files to _./public_.
*
*
* Following that we have a `staticProvider` layer setup to serve the .css
* files generated by Sass.
*
*
* var server = connect.createServer(
* sass.middleware({
* src: __dirname
......@@ -34,7 +34,7 @@ var imports = {};
* })
* , connect.static(__dirname + '/public')
* );
*
*
* @param {Object} options
* @return {Function}
* @api public
......@@ -99,8 +99,8 @@ module.exports = function(options){
var style = options.compile();
var paths = [];
delete imports[sassPath];
style.render(str, function(css){
// if (err) return next(err);
style.render(str, function(err, css){
if (err) return next(err);
if (debug) log('render', sassPath);
imports[sassPath] = paths;
mkdirp(dirname(cssPath), 0700, function(err){
......@@ -187,4 +187,4 @@ function checkImports(path, fn) {
function log(key, val) {
console.error(' \033[90m%s :\033[0m \033[36m%s\033[0m', key, val);
}
\ No newline at end of file
}
......@@ -6,7 +6,7 @@ using std::cerr; using std::endl;
namespace Sass {
using std::pair;
void Context::collect_include_paths(const char* paths_str)
{
const size_t wd_len = 1024;
......@@ -39,7 +39,7 @@ namespace Sass {
// cerr << include_paths[i] << endl;
// }
}
Context::Context(const char* paths_str)
: global_env(Environment()),
function_env(map<pair<string, size_t>, Function>()),
......@@ -54,7 +54,7 @@ namespace Sass {
register_functions();
collect_include_paths(paths_str);
}
Context::~Context()
{
for (size_t i = 0; i < source_refs.size(); ++i) {
......@@ -64,19 +64,19 @@ namespace Sass {
new_Node.free();
// cerr << "Deallocated " << i << " source string(s)." << endl;
}
inline void Context::register_function(Function_Descriptor d, Implementation ip)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, f.parameters.size())] = f;
}
inline void Context::register_function(Function_Descriptor d, Implementation ip, size_t arity)
{
Function f(d, ip);
function_env[pair<string, size_t>(f.name, arity)] = f;
}
void Context::register_functions()
{
using namespace Functions;
......@@ -122,5 +122,6 @@ namespace Sass {
// Boolean Functions
register_function(not_descriptor, not_impl);
}
}
......@@ -9,29 +9,29 @@
namespace Sass {
using std::pair;
using std::map;
struct Environment {
map<Token, Node> current_frame;
Environment* parent;
Environment* global;
Environment()
: current_frame(map<Token, Node>()), parent(0), global(0)
{ }
void link(Environment& env)
{
parent = &env;
global = parent->global ? parent->global : parent;
}
bool query(const Token& key) const
{
if (current_frame.count(key)) return true;
else if (parent) return parent->query(key);
else return false;
}
Node& operator[](const Token& key)
{
if (current_frame.count(key)) return current_frame[key];
......@@ -56,10 +56,11 @@ namespace Sass {
void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0);
~Context();
void register_function(Function_Descriptor d, Implementation ip);
void register_function(Function_Descriptor d, Implementation ip, size_t arity);
void register_functions();
};
}
......@@ -90,17 +90,17 @@ namespace Sass {
return doc;
}
void Document::throw_syntax_error(string message, size_t ln)
{ throw Error(Error::syntax, path, ln ? ln : line, message); }
void Document::throw_read_error(string message, size_t ln)
{ throw Error(Error::read, path, ln ? ln : line, message); }
using std::string;
using std::stringstream;
using std::endl;
string Document::emit_css(CSS_Style style) {
stringstream output;
switch (style) {
......@@ -121,3 +121,4 @@ namespace Sass {
return retval;
}
}
......@@ -25,7 +25,7 @@ namespace Sass {
struct Document {
enum CSS_Style { nested, expanded, compact, compressed, echo };
string path;
char* source;
const char* position;
......@@ -34,7 +34,7 @@ namespace Sass {
bool own_source;
Context& context;
Node root;
Token lexed;
......@@ -84,7 +84,7 @@ namespace Sass {
return 0;
}
}
template <prelexer mx>
const char* lex()
{
......@@ -123,7 +123,7 @@ namespace Sass {
return 0;
}
}
void parse_scss();
Node parse_import();
Node parse_include();
......@@ -163,13 +163,14 @@ namespace Sass {
Node parse_if_directive(Node surrounding_ruleset);
Node parse_for_directive(Node surrounding_ruleset);
Selector_Lookahead lookahead_for_selector(const char* start = 0);
void throw_syntax_error(string message, size_t ln = 0);
void throw_read_error(string message, size_t ln = 0);
string emit_css(CSS_Style style);
};
}
\ No newline at end of file
}
namespace Sass {
struct Error {
enum Type { read, write, syntax, evaluation };
Type type;
string path;
size_t line;
string message;
Error(Type type, string path, size_t line, string message)
: type(type), path(path), line(line), message(message)
{ }
};
}
\ No newline at end of file
}
......@@ -27,7 +27,7 @@ namespace Sass {
env[expr[0].token()] = expr;
return expr;
} break;
case Node::expansion: {
Token name(expr[0].token());
Node args(expr[1]);
......@@ -39,7 +39,7 @@ namespace Sass {
expr += expansion;
return expr;
} break;
case Node::propset: {
eval(expr[1], prefix, env, f_env, new_Node, ctx);
return expr;
......@@ -91,14 +91,14 @@ namespace Sass {
Node sel(needs_reparsing.parse_selector_group());
return sel;
} break;
case Node::root: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
expr[i] = eval(expr[i], prefix, env, f_env, new_Node, ctx);
}
return expr;
} break;
case Node::block: {
Environment new_frame;
new_frame.link(env);
......@@ -107,7 +107,7 @@ namespace Sass {
}
return expr;
} break;
case Node::assignment: {
Node val(expr[1]);
if (val.type() == Node::comma_list || val.type() == Node::space_list) {
......@@ -149,7 +149,7 @@ namespace Sass {
if (expr.should_eval()) expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
return expr;
} break;
case Node::disjunction: {
Node result;
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -159,7 +159,7 @@ namespace Sass {
}
return result;
} break;
case Node::conjunction: {
Node result;
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -168,16 +168,16 @@ namespace Sass {
}
return result;
} break;
case Node::relation: {
Node lhs(eval(expr[0], prefix, env, f_env, new_Node, ctx));
Node op(expr[1]);
Node rhs(eval(expr[2], prefix, env, f_env, new_Node, ctx));
// TO DO: don't allocate both T and F
Node T(new_Node(Node::boolean, lhs.path(), lhs.line(), true));
Node F(new_Node(Node::boolean, lhs.path(), lhs.line(), false));
switch (op.type())
{
case Node::eq: return (lhs == rhs) ? T : F;
......@@ -231,12 +231,12 @@ namespace Sass {
Token::make(Prelexer::number(expr.token().begin),
expr.token().end));
} break;
case Node::textual_number: {
return new_Node(expr.path(), expr.line(), std::atof(expr.token().begin));
} break;
case Node::textual_hex: {
case Node::textual_hex: {
Node triple(new_Node(Node::numeric_color, expr.path(), expr.line(), 4));
Token hext(Token::make(expr.token().begin+1, expr.token().end));
if (hext.length() == 6) {
......@@ -252,19 +252,19 @@ namespace Sass {
triple << new_Node(expr.path(), expr.line(), 1.0);
return triple;
} break;
case Node::variable: {
if (!env.query(expr.token())) throw_eval_error("reference to unbound variable " + expr.token().to_string(), expr.path(), expr.line());
return env[expr.token()];
} break;
case Node::function_call: {
// TO DO: default-constructed Function should be a generic callback (maybe)
pair<string, size_t> sig(expr[0].token().to_string(), expr[1].size());
if (!f_env.count(sig)) return expr;
return apply_function(f_env[sig], expr[1], prefix, env, f_env, new_Node, ctx);
} break;
case Node::unary_plus: {
Node arg(eval(expr[0], prefix, env, f_env, new_Node, ctx));
if (arg.is_numeric()) {
......@@ -275,7 +275,7 @@ namespace Sass {
return expr;
}
} break;
case Node::unary_minus: {
Node arg(eval(expr[0], prefix, env, f_env, new_Node, ctx));
if (arg.is_numeric()) {
......@@ -286,7 +286,7 @@ namespace Sass {
return expr;
}
} break;
case Node::string_schema:
case Node::value_schema: {
for (size_t i = 0, S = expr.size(); i < S; ++i) {
......@@ -294,7 +294,7 @@ namespace Sass {
}
return expr;
} break;
case Node::css_import: {
expr[0] = eval(expr[0], prefix, env, f_env, new_Node, ctx);
return expr;
......@@ -359,7 +359,7 @@ namespace Sass {
Node lhs(acc.back());
double lnum = lhs.numeric_value();
double rnum = rhs.numeric_value();
if (lhs.type() == Node::number && rhs.type() == Node::number) {
Node result(new_Node(acc.path(), acc.line(), operate(op, lnum, rnum)));
acc.pop_back();
......@@ -451,7 +451,7 @@ namespace Sass {
// Apply a mixin -- bind the arguments in a new environment, link the new
// environment to the current one, then copy the body and eval in the new
// environment.
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
Node params(mixin[1]);
......@@ -510,7 +510,7 @@ namespace Sass {
// Apply a function -- bind the arguments and pass them to the underlying
// primitive function implementation, then return its value.
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& ctx)
{
map<Token, Node> bindings;
......@@ -855,3 +855,4 @@ namespace Sass {
{ return selector_but(sel, new_Node, 0, 1); }
}
......@@ -10,11 +10,11 @@
namespace Sass {
using std::map;
Node eval(Node expr, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node::Type op, double lhs, double rhs);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<pair<string, size_t>, Function>& f_env, Node_Factory& new_Node, Context& src_refs);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
......@@ -28,4 +28,5 @@ namespace Sass {
Node selector_butfirst(Node sel, Node_Factory& new_Node);
Node selector_butlast(Node sel, Node_Factory& new_Node);
}
\ No newline at end of file
}
......@@ -7,20 +7,20 @@
namespace Sass {
using std::map;
typedef Node (*Implementation)(const vector<Token>&, map<Token, Node>&, Node_Factory& new_Node);
typedef const char* str;
typedef str Function_Descriptor[];
struct Function {
string name;
vector<Token> parameters;
Implementation implementation;
Function()
{ /* TO DO: set up the generic callback here */ }
Function(Function_Descriptor d, Implementation ip)
: name(d[0]),
parameters(vector<Token>()),
......@@ -28,7 +28,7 @@ namespace Sass {
{
size_t len = 0;
while (d[len+1]) ++len;
parameters.reserve(len);
for (size_t i = 0; i < len; ++i) {
const char* p = d[i+1];
......@@ -36,12 +36,12 @@ namespace Sass {
parameters.push_back(name);
}
}
Node operator()(map<Token, Node>& bindings, Node_Factory& new_Node) const
{ return implementation(parameters, bindings, new_Node); }
};
namespace Functions {
// RGB Functions ///////////////////////////////////////////////////////
......@@ -51,58 +51,58 @@ namespace Sass {
extern Function_Descriptor rgba_4_descriptor;
Node rgba_4(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor rgba_2_descriptor;
Node rgba_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor red_descriptor;
Node red(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor green_descriptor;
Node green(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor blue_descriptor;
Node blue(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_2_descriptor;
Node mix_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor mix_3_descriptor;
Node mix_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// HSL Functions ///////////////////////////////////////////////////////
extern Function_Descriptor hsla_descriptor;
Node hsla(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor hsl_descriptor;
Node hsl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor invert_descriptor;
Node invert(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Opacity Functions ///////////////////////////////////////////////////
extern Function_Descriptor alpha_descriptor;
extern Function_Descriptor opacity_descriptor;
Node alpha(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor opacify_descriptor;
extern Function_Descriptor fade_in_descriptor;
Node opacify(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor transparentize_descriptor;
extern Function_Descriptor fade_out_descriptor;
Node transparentize(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// String Functions ////////////////////////////////////////////////////
extern Function_Descriptor unquote_descriptor;
Node unquote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor quote_descriptor;
Node quote(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Number Functions ////////////////////////////////////////////////////
extern Function_Descriptor percentage_descriptor;
......@@ -117,42 +117,43 @@ namespace Sass {
extern Function_Descriptor floor_descriptor;
Node floor(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor abs_descriptor;
extern Function_Descriptor abs_descriptor;
Node abs(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// List Functions //////////////////////////////////////////////////////
extern Function_Descriptor length_descriptor;
Node length(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor nth_descriptor;
Node nth(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_2_descriptor;
extern Function_Descriptor join_2_descriptor;
Node join_2(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor join_3_descriptor;
extern Function_Descriptor join_3_descriptor;
Node join_3(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Introspection Functions /////////////////////////////////////////////
extern Function_Descriptor type_of_descriptor;
Node type_of(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unit_descriptor;
Node unit(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor unitless_descriptor;
extern Function_Descriptor unitless_descriptor;
Node unitless(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
extern Function_Descriptor comparable_descriptor;
extern Function_Descriptor comparable_descriptor;
Node comparable(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
// Boolean Functions ///////////////////////////////////////////////////
extern Function_Descriptor not_descriptor;
Node not_impl(const vector<Token>& parameters, map<Token, Node>& bindings, Node_Factory& new_Node);
}
}
......@@ -51,7 +51,7 @@ namespace Sass {
}
return true;
} break;
case variable:
case identifier:
case uri:
......@@ -62,12 +62,12 @@ namespace Sass {
case string_constant: {
return token().unquote() == rhs.token().unquote();
} break;
case number:
case numeric_percentage: {
return numeric_value() == rhs.numeric_value();
} break;
case numeric_dimension: {
if (unit() == rhs.unit()) {
return numeric_value() == rhs.numeric_value();
......@@ -76,26 +76,26 @@ namespace Sass {
return false;
}
} break;
case boolean: {
return boolean_value() == rhs.boolean_value();
} break;
default: {
return true;
} break;
}
return false;
}
bool Node::operator!=(Node rhs) const
{ return !(*this == rhs); }
bool Node::operator<(Node rhs) const
{
Type lhs_type = type();
Type rhs_type = rhs.type();
// comparing atomic numbers
if ((lhs_type == number && rhs_type == number) ||
(lhs_type == numeric_percentage && rhs_type == numeric_percentage)) {
......@@ -158,13 +158,13 @@ namespace Sass {
throw Error(Error::evaluation, path(), line(), "incomparable types");
}
}
bool Node::operator<=(Node rhs) const
{ return *this < rhs || *this == rhs; }
bool Node::operator>(Node rhs) const
{ return !(*this <= rhs); }
bool Node::operator>=(Node rhs) const
{ return !(*this < rhs); }
......@@ -172,7 +172,7 @@ namespace Sass {
// ------------------------------------------------------------------------
// Token method implementations
// ------------------------------------------------------------------------
string Token::unquote() const
{
string result;
......@@ -210,7 +210,7 @@ namespace Sass {
return result;
}
}
void Token::unquote_to_stream(std::stringstream& buf) const
{
const char* p = begin;
......@@ -247,7 +247,7 @@ namespace Sass {
return;
}
}
bool Token::operator<(const Token& rhs) const
{
const char* first1 = begin;
......@@ -262,15 +262,15 @@ namespace Sass {
}
return (first2 != last2);
}
bool Token::operator==(const Token& rhs) const
{
if (length() != rhs.length()) return false;
if ((begin[0] == '"' || begin[0] == '\'') &&
(rhs.begin[0] == '"' || rhs.begin[0] == '\''))
{ return unquote() == rhs.unquote(); }
const char* p = begin;
const char* q = rhs.begin;
for (; p < end; ++p, ++q) if (*p != *q) return false;
......@@ -298,7 +298,7 @@ namespace Sass {
// if you reach this point, you've got a logic error somewhere
return 0;
}
extern const char percent_str[] = "%";
extern const char empty_str[] = "";
Token Node_Impl::unit()
......@@ -308,14 +308,15 @@ namespace Sass {
case Node::numeric_percentage: {
return Token::make(percent_str);
} break;
case Node::numeric_dimension: {
return value.dimension.unit;
} break;
default: break;
}
return Token::make(empty_str);
}
}
\ No newline at end of file
}
......@@ -46,7 +46,7 @@ namespace Sass {
string unquote() const;
void unquote_to_stream(std::stringstream& buf) const;
operator bool()
{ return begin && end && begin >= end; }
......@@ -58,7 +58,7 @@ namespace Sass {
double numeric;
Token unit;
};
struct Node_Impl;
class Node {
......@@ -199,7 +199,7 @@ namespace Sass {
bool is_null_ptr() const;
void flatten();
bool operator==(Node rhs) const;
bool operator!=(Node rhs) const;
bool operator<(Node rhs) const;
......@@ -214,7 +214,7 @@ namespace Sass {
void emit_expanded_css(stringstream& buf, const string& prefix);
};
struct Node_Impl {
union value_t {
bool boolean;
......@@ -255,13 +255,13 @@ namespace Sass {
should_eval(false),
is_unquoted(false)
{ }
bool is_numeric()
{ return type >= Node::number && type <= Node::numeric_dimension; }
size_t size()
{ return children.size(); }
bool empty()
{ return children.empty(); }
......@@ -321,7 +321,7 @@ namespace Sass {
bool& boolean_value()
{ return value.boolean; }
double numeric_value();
Token unit();
};
......@@ -332,11 +332,11 @@ namespace Sass {
// -- in the header file so they can easily be declared inline
// -- outside of their class definition to get the right declaration order
// ------------------------------------------------------------------------
inline Node::Node(Node_Impl* ip) : ip_(ip) { }
inline Node::Type Node::type() const { return ip_->type; }
inline bool Node::has_children() const { return ip_->has_children; }
inline bool Node::has_statements() const { return ip_->has_statements; }
inline bool Node::has_blocks() const { return ip_->has_blocks; }
......@@ -346,12 +346,12 @@ namespace Sass {
inline bool& Node::should_eval() const { return ip_->should_eval; }
inline bool& Node::is_unquoted() const { return ip_->is_unquoted; }
inline bool Node::is_numeric() const { return ip_->is_numeric(); }
inline string& Node::path() const { return ip_->path; }
inline size_t Node::line() const { return ip_->line; }
inline size_t Node::size() const { return ip_->size(); }
inline bool Node::empty() const { return ip_->empty(); }
inline Node& Node::at(size_t i) const { return ip_->at(i); }
inline Node& Node::back() const { return ip_->back(); }
inline Node& Node::operator[](size_t i) const { return at(i); }
......@@ -390,3 +390,4 @@ namespace Sass {
inline bool Node::is_null_ptr() const { return !ip_; }
}
......@@ -27,10 +27,10 @@ namespace Sass {
}
return result;
} break;
case selector: {
string result;
result += at(0).to_string();
for (size_t i = 1, S = size(); i < S; ++i) {
result += " ";
......@@ -38,11 +38,11 @@ namespace Sass {
}
return result;
} break;
case selector_combinator: {
return token().to_string();
} break;
case simple_selector_sequence: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) {
......@@ -50,12 +50,12 @@ namespace Sass {
}
return result;
} break;
case pseudo:
case simple_selector: {
return token().to_string();
} break;
case pseudo_negation: {
string result;
result += at(0).to_string();
......@@ -63,7 +63,7 @@ namespace Sass {
result += ')';
return result;
} break;
case functional_pseudo: {
string result;
result += at(0).to_string();
......@@ -73,7 +73,7 @@ namespace Sass {
result += ')';
return result;
} break;
case attribute_selector: {
string result;
result += "[";
......@@ -93,7 +93,7 @@ namespace Sass {
}
return result;
} break;
case space_list: {
string result(at(0).to_string());
for (size_t i = 1, S = size(); i < S; ++i) {
......@@ -103,7 +103,7 @@ namespace Sass {
}
return result;
} break;
case expression:
case term: {
string result(at(0).to_string());
......@@ -116,16 +116,16 @@ namespace Sass {
}
return result;
} break;
//edge case
case sub: {
return "-";
} break;
case div: {
return "/";
} break;
case css_import: {
stringstream ss;
ss << "@import url(";
......@@ -134,7 +134,7 @@ namespace Sass {
ss << ")";
return ss.str();
}
case function_call: {
stringstream ss;
ss << at(0).to_string();
......@@ -143,7 +143,7 @@ namespace Sass {
ss << ")";
return ss.str();
}
case arguments: {
stringstream ss;
size_t S = size();
......@@ -156,40 +156,40 @@ namespace Sass {
}
return ss.str();
}
case unary_plus: {
stringstream ss;
ss << "+";
ss << at(0).to_string();
return ss.str();
}
case unary_minus: {
stringstream ss;
ss << "-";
ss << at(0).to_string();
return ss.str();
}
case numeric_percentage: {
stringstream ss;
ss << numeric_value();
ss << '%';
return ss.str();
}
case numeric_dimension: {
stringstream ss;
ss << numeric_value() << unit().to_string();
return ss.str();
} break;
case number: {
stringstream ss;
ss << numeric_value();
return ss.str();
} break;
case numeric_color: {
if (at(3).numeric_value() >= 1.0)
{
......@@ -201,7 +201,7 @@ namespace Sass {
else if (a >= 0xff && b >= 0xff && c == 0)
{ return "yellow"; }
else if (a == 0 && b >= 0xff && c >= 0xff)
{ return "aqua"; }
{ return "aqua"; }
else if (a >= 0xff && b == 0 && c >= 0xff)
{ return "fuchsia"; }
else if (a >= 0xff && b == 0 && c == 0)
......@@ -236,7 +236,7 @@ namespace Sass {
return ss.str();
}
} break;
case uri: {
string result("url(");
result += token().to_string();
......@@ -248,7 +248,7 @@ namespace Sass {
// ignore it
return "";
} break;
case string_constant: {
if (is_unquoted()) return token().unquote();
else {
......@@ -257,22 +257,22 @@ namespace Sass {
else return result;
}
} break;
case boolean: {
if (boolean_value()) return "true";
else return "false";
} break;
case important: {
return "!important";
} break;
case value_schema: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) result += at(i).to_string();
return result;
} break;
case string_schema: {
string result;
for (size_t i = 0, S = size(); i < S; ++i) {
......@@ -286,7 +286,7 @@ namespace Sass {
}
return result;
} break;
default: {
// return content.token.to_string();
if (!has_children()) return token().to_string();
......@@ -338,14 +338,14 @@ namespace Sass {
case propset: {
emit_propset(buf, depth, "");
} break;
case rule: {
buf << endl << string(2*depth, ' ');
at(0).emit_nested_css(buf, depth); // property
at(1).emit_nested_css(buf, depth); // values
buf << ";";
} break;
case css_import: {
buf << string(2*depth, ' ');
buf << to_string();
......@@ -373,7 +373,7 @@ namespace Sass {
} break;
}
}
void Node::emit_propset(stringstream& buf, size_t depth, const string& prefix)
{
string new_prefix(prefix);
......@@ -405,4 +405,5 @@ namespace Sass {
void Node::echo(stringstream& buf, size_t depth) { }
void Node::emit_expanded_css(stringstream& buf, const string& prefix) { }
}
\ No newline at end of file
}
#include "node_factory.hpp"
namespace Sass {
Node_Impl* Node_Factory::alloc_Node_Impl(Node::Type type, string path, size_t line)
{
Node_Impl* ip = new Node_Impl();
......@@ -69,7 +69,7 @@ namespace Sass {
ip->value.dimension.unit = t;
return Node(ip);
}
// for making nodes representing rgba color quads
Node Node_Factory::operator()(string path, size_t line, double r, double g, double b, double a)
{
......@@ -84,4 +84,5 @@ namespace Sass {
void Node_Factory::free()
{ for (size_t i = 0, S = pool_.size(); i < S; ++i) delete pool_[i]; }
}
\ No newline at end of file
}
......@@ -9,7 +9,7 @@ namespace Sass {
struct Token;
struct Node_Impl;
class Node_Factory {
vector<Node_Impl*> pool_;
Node_Impl* alloc_Node_Impl(Node::Type type, string file, size_t line);
......@@ -33,5 +33,6 @@ namespace Sass {
void free();
};
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@
namespace Sass {
namespace Prelexer {
// Matches zero characters (always succeeds without consuming input).
const char* epsilon(char *src) {
return src;
......@@ -12,10 +12,10 @@ namespace Sass {
const char* empty(char *src) {
return *src ? 0 : src;
}
// Match any single character.
const char* any_char(const char* src) { return *src ? src++ : src; }
// Match a single character satisfying the ctype predicates.
const char* space(const char* src) { return std::isspace(*src) ? src+1 : 0; }
const char* alpha(const char* src) { return std::isalpha(*src) ? src+1 : 0; }
......@@ -30,7 +30,7 @@ namespace Sass {
const char* xdigits(const char* src) { return one_plus<xdigit>(src); }
const char* alnums(const char* src) { return one_plus<alnum>(src); }
const char* puncts(const char* src) { return one_plus<punct>(src); }
// Match a line comment.
extern const char slash_slash[] = "//";
const char* line_comment(const char* src) { return to_endl<slash_slash>(src); }
......@@ -60,7 +60,7 @@ namespace Sass {
const char* interpolant(const char* src) {
return delimited_by<hash_lbrace, rbrace, false>(src);
}
// Whitespace handling.
const char* optional_spaces(const char* src) { return optional<spaces>(src); }
const char* optional_comment(const char* src) { return optional<comment>(src); }
......@@ -70,7 +70,7 @@ namespace Sass {
const char* no_spaces(const char* src) {
return negate< spaces >(src);
}
// Match CSS identifiers.
const char* identifier(const char* src) {
return sequence< optional< exactly<'-'> >,
......@@ -79,8 +79,8 @@ namespace Sass {
exactly<'-'>,
exactly<'_'> > > >(src);
}
// Match interpolant schemas
const char* identifier_schema(const char* src) {
// follows this pattern: (x*ix*)+
......@@ -94,7 +94,7 @@ namespace Sass {
interpolant,
zero_plus< alternatives< identifier, percentage, dimension, hex, number, string_constant > > > >(src);
}
// Match CSS '@' keywords.
const char* at_keyword(const char* src) {
return sequence<exactly<'@'>, identifier>(src);
......@@ -156,7 +156,7 @@ namespace Sass {
const char* while_directive(const char* src) {
return exactly<while_kwd>(src);
}
const char* name(const char* src) {
return one_plus< alternatives< alnum,
exactly<'-'>,
......@@ -305,12 +305,12 @@ namespace Sass {
const char* ancestor_of(const char* src) {
return sequence< spaces, negate< exactly<'{'> > >(src);
}
// Match SCSS variable names.
const char* variable(const char* src) {
return sequence<exactly<'$'>, name>(src);
}
// Match Sass boolean keywords.
extern const char and_chars[] = "and";
extern const char or_chars[] = "or";
......@@ -357,7 +357,7 @@ namespace Sass {
const char* lte_op(const char* src) {
return exactly<lte_chars>(src);
}
// Path matching functions.
const char* folder(const char* src) {
return sequence< zero_plus< any_char_except<'/'> >,
......@@ -367,4 +367,5 @@ namespace Sass {
return zero_plus< folder >(src);
}
}
}
\ No newline at end of file
}
......@@ -11,7 +11,7 @@ namespace Sass {
const char* exactly(const char* src) {
return *src == pre ? src + 1 : 0;
}
// Match a string constant.
template <const char* prefix>
const char* exactly(const char* src) {
......@@ -49,7 +49,7 @@ namespace Sass {
while (class_char<char_class>(p)) ++p;
return p == src ? 0 : p;
}
// Match a sequence of characters up to the next newline.
template <const char* prefix>
const char* to_endl(const char* src) {
......@@ -57,7 +57,7 @@ namespace Sass {
while (*src && *src != '\n') ++src;
return src;
}
// Match a sequence of characters delimited by the supplied chars.
template <char beg, char end, bool esc>
const char* delimited_by(const char* src) {
......@@ -71,7 +71,7 @@ namespace Sass {
src = stop ? stop : src + 1;
}
}
// Match a sequence of characters delimited by the supplied strings.
template <const char* beg, const char* end, bool esc>
const char* delimited_by(const char* src) {
......@@ -85,7 +85,7 @@ namespace Sass {
src = stop ? stop : src + 1;
}
}
// Match any single character.
const char* any_char(const char* src);
// Match any single character except the supplied one.
......@@ -93,19 +93,19 @@ namespace Sass {
const char* any_char_except(const char* src) {
return (*src && *src != c) ? src+1 : 0;
}
// Matches zero characters (always succeeds without consuming input).
const char* epsilon(const char*);
// Matches the empty string.
const char* empty(const char*);
// Succeeds of the supplied matcher fails, and vice versa.
template <prelexer mx>
const char* negate(const char* src) {
return mx(src) ? 0 : src;
}
// Tries the matchers in sequence and returns the first match (or none)
template <prelexer mx1, prelexer mx2>
const char* alternatives(const char* src) {
......@@ -113,7 +113,7 @@ namespace Sass {
(rslt = mx1(src)) || (rslt = mx2(src));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
const char* alternatives(const char* src) {
......@@ -121,7 +121,7 @@ namespace Sass {
(rslt = mx1(src)) || (rslt = mx2(src)) || (rslt = mx3(src));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
const char* alternatives(const char* src) {
......@@ -130,7 +130,7 @@ namespace Sass {
(rslt = mx3(src)) || (rslt = mx4(src));
return rslt;
}
// Same as above, but with 5 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3,
prelexer mx4, prelexer mx5>
......@@ -140,7 +140,7 @@ namespace Sass {
(rslt = mx4(src)) || (rslt = mx5(src));
return rslt;
}
// Same as above, but with 6 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3,
prelexer mx4, prelexer mx5, prelexer mx6>
......@@ -150,7 +150,7 @@ namespace Sass {
(rslt = mx4(src)) || (rslt = mx5(src)) || (rslt = mx6(src));
return rslt;
}
// Same as above, but with 7 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -164,7 +164,7 @@ namespace Sass {
(rslt = mx7(rslt));
return rslt;
}
// Same as above, but with 8 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -178,7 +178,7 @@ namespace Sass {
(rslt = mx7(rslt)) || (rslt = mx8(rslt));
return rslt;
}
// Tries the matchers in sequence and succeeds if they all succeed.
template <prelexer mx1, prelexer mx2>
const char* sequence(const char* src) {
......@@ -186,7 +186,7 @@ namespace Sass {
(rslt = mx1(rslt)) && (rslt = mx2(rslt));
return rslt;
}
// Same as above, but with 3 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3>
const char* sequence(const char* src) {
......@@ -194,7 +194,7 @@ namespace Sass {
(rslt = mx1(rslt)) && (rslt = mx2(rslt)) && (rslt = mx3(rslt));
return rslt;
}
// Same as above, but with 4 arguments.
template <prelexer mx1, prelexer mx2, prelexer mx3, prelexer mx4>
const char* sequence(const char* src) {
......@@ -203,7 +203,7 @@ namespace Sass {
(rslt = mx3(rslt)) && (rslt = mx4(rslt));
return rslt;
}
// Same as above, but with 5 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -215,7 +215,7 @@ namespace Sass {
(rslt = mx5(rslt));
return rslt;
}
// Same as above, but with 6 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -227,7 +227,7 @@ namespace Sass {
(rslt = mx5(rslt)) && (rslt = mx6(rslt));
return rslt;
}
// Same as above, but with 7 arguments.
template <prelexer mx1, prelexer mx2,
prelexer mx3, prelexer mx4,
......@@ -241,14 +241,14 @@ namespace Sass {
(rslt = mx7(rslt));
return rslt;
}
// Match a pattern or not. Always succeeds.
template <prelexer mx>
const char* optional(const char* src) {
const char* p = mx(src);
return p ? p : src;
}
// Match zero or more of the supplied pattern
template <prelexer mx>
const char* zero_plus(const char* src) {
......@@ -256,7 +256,7 @@ namespace Sass {
while (p) src = p, p = mx(src);
return src;
}
// Match one or more of the supplied pattern
template <prelexer mx>
const char* one_plus(const char* src) {
......@@ -265,7 +265,7 @@ namespace Sass {
while (p) src = p, p = mx(src);
return src;
}
// Match a single character satisfying the ctype predicates.
const char* space(const char* src);
const char* alpha(const char* src);
......@@ -280,7 +280,7 @@ namespace Sass {
const char* xdigits(const char* src);
const char* alnums(const char* src);
const char* puncts(const char* src);
// Match a line comment.
const char* line_comment(const char* src);
// Match a block comment.
......@@ -368,10 +368,10 @@ namespace Sass {
const char* precedes(const char* src);
const char* parent_of(const char* src);
const char* ancestor_of(const char* src);
// Match SCSS variable names.
const char* variable(const char* src);
// Match Sass boolean keywords.
const char* true_kwd(const char* src);
const char* false_kwd(const char* src);
......@@ -384,11 +384,11 @@ namespace Sass {
const char* gte_op(const char* src);
const char* lt_op(const char* src);
const char* lte_op(const char* src);
// Path matching functions.
const char* folder(const char* src);
const char* folders(const char* src);
// Utility functions for finding and counting characters in a string.
template<char c>
const char* find_first(const char* src) {
......@@ -433,6 +433,7 @@ namespace Sass {
}
return counter;
}
}
}
......@@ -14,9 +14,9 @@ extern "C" {
sass_context* sass_new_context()
{ return (sass_context*) calloc(1, sizeof(sass_context)); }
void sass_free_context(sass_context* ctx)
{
{
if (ctx->output_string)
free(ctx->output_string);
free(ctx);
......@@ -24,14 +24,14 @@ extern "C" {
sass_file_context* sass_new_file_context()
{ return (sass_file_context*) calloc(1, sizeof(sass_file_context)); }
void sass_free_file_context(sass_file_context* ctx)
{
{
if (ctx->output_string)
free(ctx->output_string);
free(ctx);
}
sass_folder_context* sass_new_folder_context()
{ return (sass_folder_context*) calloc(1, sizeof(sass_folder_context)); }
......@@ -86,7 +86,7 @@ extern "C" {
// TO DO: CATCH EVERYTHING ELSE
return 0;
}
int sass_compile_file(sass_file_context* c_ctx)
{
using namespace Sass;
......@@ -123,10 +123,11 @@ extern "C" {
// TO DO: CATCH EVERYTHING ELSE
return 0;
}
int sass_compile_folder(sass_folder_context* c_ctx)
{
return 1;
}
}
#include <node.h>
#ifdef __cplusplus
extern "C" {
#endif
......@@ -18,6 +20,8 @@ struct sass_context {
struct sass_options options;
int error_status;
char* error_message;
uv_work_t request;
v8::Persistent<v8::Function> callback;
};
struct sass_file_context {
......@@ -50,4 +54,5 @@ int sass_compile_folder (struct sass_folder_context* ctx);
#ifdef __cplusplus
}
#endif
\ No newline at end of file
#endif
......@@ -14,36 +14,36 @@ int main()
{
using namespace Sass;
using namespace std;
cout << sizeof(Node_Impl*) << endl;
cout << sizeof(Node) << endl;
cout << sizeof(Node_Impl) << endl << endl;
Node_Factory new_Node = Node_Factory();
Node interior(new_Node(Node::block, "", 0, 3));
cout << interior.size() << endl;
cout << interior.has_children() << endl;
cout << interior.should_eval() << endl << endl;
Node num(new_Node("", 0, 255, 123, 32));
Node num2(new_Node("", 0, 255, 123, 32));
Node num3(new_Node("", 0, 255, 122, 20, .75));
cout << num.size() << endl;
cout << num.has_children() << endl;
cout << num.has_statements() << endl << endl;
cout << num[1].is_numeric() << endl;
cout << num[1].numeric_value() << endl << endl;
cout << (num == num2) << endl;
cout << (num == num3) << endl << endl;
cout << (num3[2] < num2[2]) << endl;
cout << (num2[3] < num3[3]) << endl << endl;
cout << (num2[2] >= num3[2]) << endl;
cout << (num2[3] != num3[3]) << endl << endl;
......@@ -92,4 +92,5 @@ int main()
new_Node.free();
return 0;
}
\ No newline at end of file
}
var binding = require('./build/Release/binding')
var render = function(str, cb){
cb(binding.render(str))
}
exports.render = render
exports.middleware = require('./lib/middleware');
\ No newline at end of file
exports.render = binding.render
exports.middleware = require('./lib/middleware');
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