Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parsing and output of unknown at-rules (Fixes #855) #926

Merged
merged 3 commits into from
Mar 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,13 @@ namespace Sass {
At_Rule(ParserState pstate, string kwd, Selector* sel = 0, Block* b = 0)
: Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(0) // set value manually if needed
{ statement_type(DIRECTIVE); }
bool bubbles() { return true; }
bool bubbles() { return is_keyframes() || is_media(); }
bool is_media() {
return keyword_.compare("@-webkit-media") == 0 ||
keyword_.compare("@-moz-media") == 0 ||
keyword_.compare("@-o-media") == 0 ||
keyword_.compare("@media") == 0;
}
bool is_keyframes() {
return keyword_.compare("@-webkit-keyframes") == 0 ||
keyword_.compare("@-moz-keyframes") == 0 ||
Expand Down
1 change: 1 addition & 0 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ namespace Sass {
source_comments (initializers.source_comments()),
output_style (initializers.output_style()),
source_map_file (make_canonical_path(initializers.source_map_file())),
source_map_root (initializers.source_map_root()), // pass-through
source_map_embed (initializers.source_map_embed()),
source_map_contents (initializers.source_map_contents()),
omit_source_map_url (initializers.omit_source_map_url()),
Expand Down
2 changes: 2 additions & 0 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace Sass {
bool source_comments; // for inline debug comments in css output
Output_Style output_style; // output style for the generated css code
string source_map_file; // path to source map file (enables feature)
string source_map_root; // path for sourceRoot property (pass-through)
bool source_map_embed; // embed in sourceMappingUrl (as data-url)
bool source_map_contents; // insert included contents into source map
bool omit_source_map_url; // disable source map comment in css output
Expand Down Expand Up @@ -85,6 +86,7 @@ namespace Sass {
KWD_ARG(Data, bool, source_comments);
KWD_ARG(Data, Output_Style, output_style);
KWD_ARG(Data, string, source_map_file);
KWD_ARG(Data, string, source_map_root);
KWD_ARG(Data, bool, omit_source_map_url);
KWD_ARG(Data, bool, is_indented_syntax_src);
KWD_ARG(Data, size_t, precision);
Expand Down
4 changes: 2 additions & 2 deletions debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
" <" << prettyprint(selector->pstate().token.ws_before()) << "> X <" << prettyprint(selector->pstate().token.ws_after()) << ">" << endl;
} else if (dynamic_cast<Selector_Placeholder*>(node)) {
Selector_Placeholder* selector = dynamic_cast<Selector_Placeholder*>(node);
cerr << ind << "Selector_Placeholder " << selector << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
cerr << ind << "Selector_Placeholder [" << selector->name() << "] " << selector << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
} else if (dynamic_cast<Selector_Reference*>(node)) {
Selector_Reference* selector = dynamic_cast<Selector_Reference*>(node);
cerr << ind << "Selector_Reference " << selector << " @ref " << selector->selector() << endl;
Expand Down Expand Up @@ -161,7 +161,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
debug_ast(block->value(), ind + " value: ", env);
} else if (dynamic_cast<At_Rule*>(node)) {
At_Rule* block = dynamic_cast<At_Rule*>(node);
cerr << ind << "At_Rule " << block << " " << block->tabs() << endl;
cerr << ind << "At_Rule " << block << " [" << block->keyword() << "] " << block->tabs() << endl;
debug_ast(block->value(), ind + "+", env);
debug_ast(block->selector(), ind + "~", env);
if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
Expand Down
1 change: 1 addition & 0 deletions emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Sass {
scheduled_linefeed(0),
scheduled_delimiter(false),
in_comment(false),
in_at_rule(false),
in_media_block(false),
in_declaration(false),
in_declaration_list(false)
Expand Down
1 change: 1 addition & 0 deletions emitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace Sass {

public:
bool in_comment;
bool in_at_rule;
bool in_media_block;
bool in_declaration;
bool in_declaration_list;
Expand Down
4 changes: 3 additions & 1 deletion inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ namespace Sass {
append_token(at_rule->keyword(), at_rule);
if (at_rule->selector()) {
append_mandatory_space();
in_at_rule = true;
at_rule->selector()->perform(this);
in_at_rule = false;
}
if (at_rule->block()) {
at_rule->block()->perform(this);
Expand Down Expand Up @@ -836,7 +838,7 @@ namespace Sass {
{
if (g->empty()) return;
for (size_t i = 0, L = g->length(); i < L; ++i) {
if (i == 0) append_indentation();
if (!in_at_rule && i == 0) append_indentation();
(*g)[i]->perform(this);
if (i < L - 1) {
append_comma_separator();
Expand Down
2 changes: 2 additions & 0 deletions output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,9 @@ namespace Sass {
append_token(kwd, a);
if (s) {
append_mandatory_space();
in_at_rule = true;
s->perform(this);
in_at_rule = false;
}
else if (v) {
append_mandatory_space();
Expand Down
10 changes: 8 additions & 2 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,15 @@ namespace Sass {
while (*includes) {
struct Sass_Import* include = *includes;
const char *file = sass_import_get_path(include);
char *source = sass_import_take_source(include);
char* source = sass_import_take_source(include);
size_t line = sass_import_get_error_line(include);
size_t column = sass_import_get_error_column(include);
const char* message = sass_import_get_error_message(include);
// char *srcmap = sass_import_take_srcmap(include);
if (source) {
if (message) {
if (line == string::npos && column == string::npos) error(message, pstate);
else error(message, ParserState(message, Position(line, column)));
} else if (source) {
if (file) {
ctx.add_source(file, inc_path, source);
imp->files().push_back(file);
Expand Down
4 changes: 2 additions & 2 deletions position.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ namespace Sass {
public: // c-tor
ParserState(string path);
ParserState(string path, const size_t file);
ParserState(string path, Position position, Offset offset);
ParserState(string path, Token token, Position position, Offset offset);
ParserState(string path, Position position, Offset offset = Offset(0, 0));
ParserState(string path, Token token, Position position, Offset offset = Offset(0, 0));

public: // down casts
Offset off() { return *this; };
Expand Down
4 changes: 3 additions & 1 deletion prelexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace Sass {

// Match any single character.
const char* any_char(const char* src) { return *src ? src+1 : src; }
// Match word boundary (look ahead)
const char* word_boundary(const char* src) { return !*src || isspace(*src) || ispunct(*src) || !Sass::Util::isAscii(*src) ? src : 0 ; }

// Match a single character satisfying the ctype predicates.
const char* space(const char* src) { return std::isspace(*src) ? src+1 : 0; }
Expand Down Expand Up @@ -288,7 +290,7 @@ namespace Sass {
}

const char* extend(const char* src) {
return exactly<extend_kwd>(src);
return sequence < exactly<extend_kwd>, word_boundary >(src);
}


Expand Down
2 changes: 2 additions & 0 deletions prelexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ namespace Sass {
const char* any_char_except(const char* src) {
return (*src && *src != c) ? src+1 : 0;
}
// Match word boundary (look ahead)
const char* word_boundary(const char* src);

// Matches zero characters (always succeeds without consuming input).
// const char* epsilon(const char*);
Expand Down
9 changes: 9 additions & 0 deletions sass.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
#include <stddef.h>
#include <stdbool.h>

#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif

#ifdef _WIN32

/* You should define ADD_EXPORTS *only* when building the DLL. */
Expand Down
18 changes: 18 additions & 0 deletions sass_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ extern "C" {
// Used to create sourceMappingUrl
char* source_map_file;

// option for sourceRoot property
char* source_map_root;

// Custom functions that can be called from sccs code
Sass_C_Function_List c_functions;

Expand All @@ -115,6 +118,7 @@ extern "C" {
// error status
int error_status;
char* error_json;
char* error_text;
char* error_message;
// error position
char* error_file;
Expand Down Expand Up @@ -226,6 +230,7 @@ extern "C" {
msg_stream << e.pstate.path << ":" << e.pstate.line+1 << ": " << e.message << endl;
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.message.c_str());
c_ctx->error_status = 1;
c_ctx->error_file = copy_c_str(e.pstate.path.c_str());
c_ctx->error_line = e.pstate.line+1;
Expand All @@ -242,6 +247,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(ba.what()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(ba.what());
c_ctx->error_status = 2;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -255,6 +261,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(e.what()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.what());
c_ctx->error_status = 3;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -268,6 +275,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(e.c_str()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.c_str());
c_ctx->error_status = 4;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -281,6 +289,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring("unknown"));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup("unknown");
c_ctx->error_status = 5;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand Down Expand Up @@ -324,6 +333,7 @@ extern "C" {
.is_indented_syntax_src(c_ctx->is_indented_syntax_src)
.source_comments(c_ctx->source_comments)
.source_map_file(safe_str(c_ctx->source_map_file))
.source_map_root(safe_str(c_ctx->source_map_root))
.source_map_embed(c_ctx->source_map_embed)
.source_map_contents(c_ctx->source_map_contents)
.omit_source_map_url(c_ctx->omit_source_map_url)
Expand Down Expand Up @@ -351,6 +361,7 @@ extern "C" {

// reset error status
c_ctx->error_json = 0;
c_ctx->error_text = 0;
c_ctx->error_message = 0;
c_ctx->error_status = 0;
// reset error position
Expand Down Expand Up @@ -615,23 +626,27 @@ extern "C" {
if (ctx->output_string) free(ctx->output_string);
if (ctx->source_map_string) free(ctx->source_map_string);
if (ctx->error_message) free(ctx->error_message);
if (ctx->error_text) free(ctx->error_text);
if (ctx->error_json) free(ctx->error_json);
if (ctx->error_file) free(ctx->error_file);
if (ctx->input_path) free(ctx->input_path);
if (ctx->output_path) free(ctx->output_path);
if (ctx->include_path) free(ctx->include_path);
if (ctx->source_map_file) free(ctx->source_map_file);
if (ctx->source_map_root) free(ctx->source_map_root);
free_string_array(ctx->included_files);
// play safe and reset properties
ctx->output_string = 0;
ctx->source_map_string = 0;
ctx->error_message = 0;
ctx->error_text = 0;
ctx->error_json = 0;
ctx->error_file = 0;
ctx->input_path = 0;
ctx->output_path = 0;
ctx->include_path = 0;
ctx->source_map_file = 0;
ctx->source_map_root = 0;
ctx->included_files = 0;
// now clear the options
sass_clear_options(ctx);
Expand Down Expand Up @@ -677,11 +692,13 @@ extern "C" {
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root);

// Create getter and setters for context
IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file);
IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line);
IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column);
Expand All @@ -692,6 +709,7 @@ extern "C" {
// Take ownership of memory (value on context is set to 0)
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string);
Expand Down
4 changes: 4 additions & 0 deletions sass_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ ADDAPI const char* ADDCALL sass_option_get_input_path (struct Sass_Options* opti
ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_include_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_file (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_root (struct Sass_Options* options);
ADDAPI Sass_C_Function_List ADDCALL sass_option_get_c_functions (struct Sass_Options* options);
ADDAPI Sass_C_Import_Callback ADDCALL sass_option_get_importer (struct Sass_Options* options);

Expand All @@ -89,6 +90,7 @@ ADDAPI void ADDCALL sass_option_set_input_path (struct Sass_Options* options, co
ADDAPI void ADDCALL sass_option_set_output_path (struct Sass_Options* options, const char* output_path);
ADDAPI void ADDCALL sass_option_set_include_path (struct Sass_Options* options, const char* include_path);
ADDAPI void ADDCALL sass_option_set_source_map_file (struct Sass_Options* options, const char* source_map_file);
ADDAPI void ADDCALL sass_option_set_source_map_root (struct Sass_Options* options, const char* source_map_root);
ADDAPI void ADDCALL sass_option_set_c_functions (struct Sass_Options* options, Sass_C_Function_List c_functions);
ADDAPI void ADDCALL sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callback importer);

Expand All @@ -97,6 +99,7 @@ ADDAPI void ADDCALL sass_option_set_importer (struct Sass_Options* options, Sass
ADDAPI const char* ADDCALL sass_context_get_output_string (struct Sass_Context* ctx);
ADDAPI int ADDCALL sass_context_get_error_status (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_json (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_text (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_message (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_file (struct Sass_Context* ctx);
ADDAPI size_t ADDCALL sass_context_get_error_line (struct Sass_Context* ctx);
Expand All @@ -106,6 +109,7 @@ ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx)

// Take ownership of memory (value on context is set to 0)
ADDAPI char* ADDCALL sass_context_take_error_json (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_text (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_message (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_file (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_output_string (struct Sass_Context* ctx);
Expand Down
24 changes: 24 additions & 0 deletions sass_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ extern "C" {
char* base;
char* source;
char* srcmap;
// error handling
char* error;
size_t line;
size_t column;
};

// Struct to hold importer callback
Expand Down Expand Up @@ -90,6 +94,9 @@ extern "C" {
v->base = base ? Sass::copy_c_str(base) : 0;
v->source = source;
v->srcmap = srcmap;
v->error = 0;
v->line = -1;
v->column = -1;
return v;
}

Expand All @@ -99,6 +106,17 @@ extern "C" {
return sass_make_import(path, path, source, srcmap);
}

// Upgrade a normal import entry to throw an error (original path can be re-used by error reporting)
struct Sass_Import* ADDCALL sass_import_set_error(struct Sass_Import* import, const char* error, size_t line, size_t col)
{
if (import == 0) return 0;
if (import->error) free(import->error);
import->error = error ? strdup(error) : 0;
import->line = line ? line : -1;
import->column = col ? col : -1;
return import;
}

// Setters and getters for entries on the import list
void ADDCALL sass_import_set_list_entry(struct Sass_Import** list, size_t idx, struct Sass_Import* entry) { list[idx] = entry; }
struct Sass_Import* ADDCALL sass_import_get_list_entry(struct Sass_Import** list, size_t idx) { return list[idx]; }
Expand All @@ -122,6 +140,7 @@ extern "C" {
free(import->base);
free(import->source);
free(import->srcmap);
free(import->error);
free(import);
}

Expand All @@ -131,6 +150,11 @@ extern "C" {
const char* ADDCALL sass_import_get_source(struct Sass_Import* entry) { return entry->source; }
const char* ADDCALL sass_import_get_srcmap(struct Sass_Import* entry) { return entry->srcmap; }

// Getter for import error entry
size_t ADDCALL sass_import_get_error_line(struct Sass_Import* entry) { return entry->line; }
size_t ADDCALL sass_import_get_error_column(struct Sass_Import* entry) { return entry->column; }
const char* ADDCALL sass_import_get_error_message(struct Sass_Import* entry) { return entry->error; }

// Explicit functions to take ownership of the memory
// Resets our own property since we do not know if it is still alive
char* ADDCALL sass_import_take_source(struct Sass_Import* entry) { char* ptr = entry->source; entry->source = 0; return ptr; }
Expand Down
Loading