Skip to content

Commit

Permalink
Implement custom import overloading on parser
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Nov 10, 2014
1 parent 7bff8df commit 6cb2122
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 18 deletions.
1 change: 1 addition & 0 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace Sass {
source_map_contents (initializers.source_map_contents()),
omit_source_map_url (initializers.omit_source_map_url()),
is_indented_syntax_src (initializers.is_indented_syntax_src()),
importer (initializers.importer()),
names_to_colors (map<string, Color*>()),
colors_to_names (map<int, string>()),
precision (initializers.precision()),
Expand Down
4 changes: 4 additions & 0 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ namespace Sass {
bool omit_source_map_url; // disable source map comment in css output
bool is_indented_syntax_src; // treat source string as sass

// overload import calls
Sass_C_Import_Callback importer;

map<string, Color*> names_to_colors;
map<int, string> colors_to_names;

Expand All @@ -95,6 +98,7 @@ namespace Sass {
KWD_ARG(Data, bool, _skip_source_map_update);
KWD_ARG(Data, bool, source_map_embed);
KWD_ARG(Data, bool, source_map_contents);
KWD_ARG(Data, Sass_C_Import_Callback, importer);
};

Context(Data);
Expand Down
84 changes: 66 additions & 18 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,32 @@ namespace Sass {
return root;
}

void Parser::add_single_file (Import* imp, string import_path) {

string extension;
string unquoted(unquote(import_path));
if (unquoted.length() > 4) { // 2 quote marks + the 4 chars in .css
// a string constant is guaranteed to end with a quote mark, so make sure to skip it when indexing from the end
extension = unquoted.substr(unquoted.length() - 4, 4);
}

if (extension == ".css") {
String_Constant* loc = new (ctx.mem) String_Constant(path, source_position, import_path, true);
Argument* loc_arg = new (ctx.mem) Argument(path, source_position, loc);
Arguments* loc_args = new (ctx.mem) Arguments(path, source_position);
(*loc_args) << loc_arg;
Function_Call* new_url = new (ctx.mem) Function_Call(path, source_position, "url", loc_args);
imp->urls().push_back(new_url);
}
else {
string current_dir = File::dir_name(path);
string resolved(ctx.add_file(current_dir, unquoted));
if (resolved.empty()) error("file to import not found or unreadable: " + unquoted + "\nCurrent dir: " + current_dir);
imp->files().push_back(resolved);
}

}

Import* Parser::parse_import()
{
lex< import >();
Expand All @@ -127,25 +153,47 @@ namespace Sass {
do {
if (lex< string_constant >()) {
string import_path(lexed);
string extension;
if (import_path.length() > 6) { // 2 quote marks + the 4 chars in .css
// a string constant is guaranteed to end with a quote mark, so make sure to skip it when indexing from the end
extension = import_path.substr(import_path.length() - 5, 4);
}
if (extension == ".css") {
String_Constant* loc = new (ctx.mem) String_Constant(path, source_position, import_path, true);
Argument* loc_arg = new (ctx.mem) Argument(path, source_position, loc);
Arguments* loc_args = new (ctx.mem) Arguments(path, source_position);
(*loc_args) << loc_arg;
Function_Call* new_url = new (ctx.mem) Function_Call(path, source_position, "url", loc_args);
imp->urls().push_back(new_url);
}
else {
string current_dir = File::dir_name(path);
string resolved(ctx.add_file(current_dir, unquote(import_path)));
if (resolved.empty()) error("file to import not found or unreadable: " + import_path + "\nCurrent dir: " + current_dir);
imp->files().push_back(resolved);

// struct Sass_Options opt = sass_context_get_options(ctx)
Sass_C_Import_Callback importer = ctx.importer;
// custom importer
if (importer) {
Sass_C_Import_Fn fn = sass_import_get_function(importer);
void* cookie = sass_import_get_cookie(importer);
// get null delimited "array" of "external" imports
struct Sass_Import** imports = fn(import_path.c_str(), cookie);
struct Sass_Import** includes = imports;
if (includes) {
while (*includes) {
struct Sass_Import* include = *includes;
const char *file = sass_import_get_path(include);
const char *source = sass_import_get_source(include);
// const char *srcmap = sass_import_get_srcmap[include];
if (source) {
string inc_path = unquote(import_path);
if (file) {
ctx.add_source(file, import_path, strdup(source));
imp->files().push_back(file);
} else {
ctx.add_source(import_path, import_path, strdup(source));
imp->files().push_back(import_path);
}
} else if(file) {
add_single_file(imp, file);
}
++includes;
}
// deallocate returned memory
sass_delete_import_list(imports);
// go for next parse loop
continue;
}
// custom importer returned nothing
// means we should use default loader
}

add_single_file(imp, import_path);

}
else if (peek< uri_prefix >()) {
imp->urls().push_back(parse_value());
Expand Down
2 changes: 2 additions & 0 deletions parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ namespace Sass {
using namespace Prelexer;

class Parser {
private:
void add_single_file (Import* imp, string import_path);
public:
class AST_Node;

Expand Down
5 changes: 5 additions & 0 deletions sass_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ extern "C" {
// Custom functions that can be called from sccs code
Sass_C_Function_List c_functions;

// Custom functions to overload imports
Sass_C_Import_Callback importer;

};

// base for all contexts
Expand Down Expand Up @@ -214,6 +217,7 @@ extern "C" {
.omit_source_map_url(c_ctx->omit_source_map_url)
.image_path(safe_str(c_ctx->image_path))
.include_paths_c_str(c_ctx->include_path)
.importer(c_ctx->importer)
.include_paths_array(include_paths)
.include_paths(vector<string>())
.precision(c_ctx->precision ? c_ctx->precision : 5);
Expand Down Expand Up @@ -423,6 +427,7 @@ extern "C" {
IMPLEMENT_SASS_OPTION_SETTER(const char*, include_path);
IMPLEMENT_SASS_OPTION_SETTER(const char*, source_map_file);
IMPLEMENT_SASS_OPTION_SETTER(Sass_C_Function_List, c_functions);
IMPLEMENT_SASS_OPTION_SETTER(Sass_C_Import_Callback, importer);

// Create getter and setters for context
IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
Expand Down
2 changes: 2 additions & 0 deletions sass_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ void sass_option_set_include_path (struct Sass_Options* options, const char* inc
void sass_option_set_source_map_file (struct Sass_Options* options, const char* source_map_file);
// Sass_C_Function_List sass_option_get_c_functions (struct Sass_Options* options);
void sass_option_set_c_functions (struct Sass_Options* options, Sass_C_Function_List c_functions);
// Sass_C_Import_Callback sass_option_get_importer (struct Sass_Options* options);
void sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callback importer);

// Getter functions for context
const char* sass_context_get_output_string (struct Sass_Context* ctx);
Expand Down

0 comments on commit 6cb2122

Please sign in to comment.