From 6fe62e90be534e6d5e324e525c5a3ed9971afb97 Mon Sep 17 00:00:00 2001 From: xzyfer Date: Sat, 24 Mar 2018 17:20:24 +1100 Subject: [PATCH] Add configuration for supporting additional extensions as .scss This is big step towards removing non-standard raw css imports. Using `sass_option_push_import_extension` implementors can choose to treat any extension they like as a `.scss` file. Closes #1964 --- include/sass/context.h | 3 +++ src/context.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- src/context.hpp | 3 +++ src/sass_context.cpp | 34 ++++++++++++++++++++++++++++++++-- src/sass_context.hpp | 5 ++++- 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/include/sass/context.h b/include/sass/context.h index 2f88d6888..29754b75f 100644 --- a/include/sass/context.h +++ b/include/sass/context.h @@ -149,6 +149,9 @@ ADDAPI size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler); ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx); +// Push function for import extenions +ADDAPI void ADDCALL sass_option_push_import_extension (struct Sass_Options* options, const char* ext); + // Push function for paths (no manipulation support for now) ADDAPI void ADDCALL sass_option_push_plugin_path (struct Sass_Options* options, const char* path); ADDAPI void ADDCALL sass_option_push_include_path (struct Sass_Options* options, const char* path); diff --git a/src/context.cpp b/src/context.cpp index dd6d74bfd..b199412cd 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -96,6 +96,8 @@ namespace Sass { // include_paths.push_back(CWD); // collect more paths from different options + collect_extensions(c_options.extension); + collect_extensions(c_options.extensions); collect_include_paths(c_options.include_path); collect_include_paths(c_options.include_paths); collect_plugin_paths(c_options.plugin_path); @@ -166,6 +168,37 @@ namespace Sass { { } + void Context::collect_extensions(const char* exts_str) + { + if (exts_str) { + const char* beg = exts_str; + const char* end = Prelexer::find_first(beg); + + while (end) { + std::string ext(beg, end - beg); + if (!ext.empty()) { + extensions.push_back(ext); + } + beg = end + 1; + end = Prelexer::find_first(beg); + } + + std::string ext(beg); + if (!ext.empty()) { + extensions.push_back(ext); + } + } + } + + void Context::collect_extensions(string_list* paths_array) + { + while (paths_array) + { + collect_extensions(paths_array->string); + paths_array = paths_array->next; + } + } + void Context::collect_include_paths(const char* paths_str) { if (paths_str) { @@ -236,15 +269,20 @@ namespace Sass { // looks for alternatives and returns a list from one directory std::vector Context::find_includes(const Importer& import) { + // include configured extensions + std::vector exts(File::defaultExtensions); + if (extensions.size() > 0) { + exts.insert(exts.end(), extensions.begin(), extensions.end()); + } // make sure we resolve against an absolute path std::string base_path(rel2abs(import.base_path)); // first try to resolve the load path relative to the base path - std::vector vec(resolve_includes(base_path, import.imp_path)); + std::vector vec(resolve_includes(base_path, import.imp_path, exts)); // then search in every include path (but only if nothing found yet) for (size_t i = 0, S = include_paths.size(); vec.size() == 0 && i < S; ++i) { // call resolve_includes and individual base path and append all results - std::vector resolved(resolve_includes(include_paths[i], import.imp_path)); + std::vector resolved(resolve_includes(include_paths[i], import.imp_path, exts)); if (resolved.size()) vec.insert(vec.end(), resolved.begin(), resolved.end()); } // return vector diff --git a/src/context.hpp b/src/context.hpp index d3caba13e..f14e69f6d 100644 --- a/src/context.hpp +++ b/src/context.hpp @@ -67,6 +67,7 @@ namespace Sass { std::vector plugin_paths; // relative paths to load plugins std::vector include_paths; // lookup paths for includes + std::vector extensions; // lookup extensions for imports` @@ -109,6 +110,8 @@ namespace Sass { void collect_plugin_paths(string_list* paths_array); void collect_include_paths(const char* paths_str); void collect_include_paths(string_list* paths_array); + void collect_extensions(const char* extensions_str); + void collect_extensions(string_list* extensions_array); std::string format_embedded_source_map(); std::string format_source_mapping_url(const std::string& out_path); diff --git a/src/sass_context.cpp b/src/sass_context.cpp index afadc66e1..7a0a49ce1 100644 --- a/src/sass_context.cpp +++ b/src/sass_context.cpp @@ -74,14 +74,14 @@ namespace Sass { // move line_beg pointer to line start while (line_beg && *line_beg && lines != 0) { if (*line_beg == '\n') --lines; - utf8::unchecked::next(line_beg); + utf8::unchecked::next(line_beg); } const char* line_end = line_beg; // move line_end before next newline character while (line_end && *line_end && *line_end != '\n') { if (*line_end == '\n') break; if (*line_end == '\r') break; - utf8::unchecked::next(line_end); + utf8::unchecked::next(line_end); } if (line_end && *line_end != 0) ++ line_end; size_t line_len = line_end - line_beg; @@ -524,6 +524,7 @@ extern "C" { options->c_headers = 0; options->plugin_paths = 0; options->include_paths = 0; + options->extensions = 0; } // helper function, not exported, only accessible locally @@ -558,6 +559,18 @@ extern "C" { cur = next; } } + // Deallocate extension + if (options->extensions) { + struct string_list* cur; + struct string_list* next; + cur = options->extensions; + while (cur) { + next = cur->next; + free(cur->string); + free(cur); + cur = next; + } + } // Free options strings free(options->input_path); free(options->output_path); @@ -577,6 +590,7 @@ extern "C" { options->c_headers = 0; options->plugin_paths = 0; options->include_paths = 0; + options->extensions = 0; } // helper function, not exported, only accessible locally @@ -713,6 +727,22 @@ extern "C" { IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string); IMPLEMENT_SASS_CONTEXT_TAKER(char**, included_files); + // Push function for import extenions + void ADDCALL sass_option_push_import_extension(struct Sass_Options* options, const char* ext) + { + struct string_list* extension = (struct string_list*) calloc(1, sizeof(struct string_list)); + if (extension == 0) return; + extension->string = ext ? sass_copy_c_string(ext) : 0; + struct string_list* last = options->extensions; + if (!options->extensions) { + options->extensions = extension; + } else { + while (last->next) + last = last->next; + last->next = extension; + } + } + // Push function for include paths (no manipulation support for now) void ADDCALL sass_option_push_include_path(struct Sass_Options* options, const char* path) { diff --git a/src/sass_context.hpp b/src/sass_context.hpp index 8ae1fb12c..9d192a301 100644 --- a/src/sass_context.hpp +++ b/src/sass_context.hpp @@ -40,9 +40,12 @@ struct Sass_Options : Sass_Output_Options { // Colon-separated list of paths // Semicolon-separated on Windows // Maybe use array interface instead? + char* extension; char* include_path; char* plugin_path; + // Extensions (linked string list) + struct string_list* extensions; // Include paths (linked string list) struct string_list* include_paths; // Plugin paths (linked string list) @@ -126,4 +129,4 @@ struct Sass_Compiler { Sass::Block_Obj root; }; -#endif \ No newline at end of file +#endif