|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include <string>
|
|
Packit Service |
7770af |
#include <cstdlib>
|
|
Packit Service |
7770af |
#include <cstring>
|
|
Packit Service |
7770af |
#include <iomanip>
|
|
Packit Service |
7770af |
#include <sstream>
|
|
Packit Service |
7770af |
#include <iostream>
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#include "ast.hpp"
|
|
Packit Service |
7770af |
#include "util.hpp"
|
|
Packit Service |
7770af |
#include "sass.h"
|
|
Packit Service |
7770af |
#include "context.hpp"
|
|
Packit Service |
7770af |
#include "plugins.hpp"
|
|
Packit Service |
7770af |
#include "constants.hpp"
|
|
Packit Service |
7770af |
#include "parser.hpp"
|
|
Packit Service |
7770af |
#include "file.hpp"
|
|
Packit Service |
7770af |
#include "inspect.hpp"
|
|
Packit Service |
7770af |
#include "output.hpp"
|
|
Packit Service |
7770af |
#include "expand.hpp"
|
|
Packit Service |
7770af |
#include "eval.hpp"
|
|
Packit Service |
7770af |
#include "check_nesting.hpp"
|
|
Packit Service |
7770af |
#include "cssize.hpp"
|
|
Packit Service |
7770af |
#include "listize.hpp"
|
|
Packit Service |
7770af |
#include "extend.hpp"
|
|
Packit Service |
7770af |
#include "remove_placeholders.hpp"
|
|
Packit Service |
7770af |
#include "functions.hpp"
|
|
Packit Service |
7770af |
#include "sass_functions.hpp"
|
|
Packit Service |
7770af |
#include "backtrace.hpp"
|
|
Packit Service |
7770af |
#include "sass2scss.h"
|
|
Packit Service |
7770af |
#include "prelexer.hpp"
|
|
Packit Service |
7770af |
#include "emitter.hpp"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
using namespace Constants;
|
|
Packit Service |
7770af |
using namespace File;
|
|
Packit Service |
7770af |
using namespace Sass;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j)
|
|
Packit Service |
7770af |
{ return sass_importer_get_priority(i) > sass_importer_get_priority(j); }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
static std::string safe_input(const char* in_path)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// enforce some safe defaults
|
|
Packit Service |
7770af |
// used to create relative file links
|
|
Packit Service |
7770af |
std::string safe_path(in_path ? in_path : "");
|
|
Packit Service |
7770af |
return safe_path == "" ? "stdin" : safe_path;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
static std::string safe_output(const char* out_path, const std::string& input_path = "")
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::string safe_path(out_path ? out_path : "");
|
|
Packit Service |
7770af |
// maybe we can extract an output path from input path
|
|
Packit Service |
7770af |
if (safe_path == "" && input_path != "") {
|
|
Packit Service |
7770af |
int lastindex = static_cast<int>(input_path.find_last_of("."));
|
|
Packit Service |
7770af |
return (lastindex > -1 ? input_path.substr(0, lastindex) : input_path) + ".css";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// enforce some safe defaults
|
|
Packit Service |
7770af |
// used to create relative file links
|
|
Packit Service |
7770af |
return safe_path == "" ? "stdout" : safe_path;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Context::Context(struct Sass_Context& c_ctx)
|
|
Packit Service |
7770af |
: CWD(File::get_cwd()),
|
|
Packit Service |
7770af |
c_options(c_ctx),
|
|
Packit Service |
7770af |
entry_path(""),
|
|
Packit Service |
7770af |
head_imports(0),
|
|
Packit Service |
7770af |
plugins(),
|
|
Packit Service |
7770af |
emitter(c_options),
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
ast_gc(),
|
|
Packit Service |
7770af |
strings(),
|
|
Packit Service |
7770af |
resources(),
|
|
Packit Service |
7770af |
sheets(),
|
|
Packit Service |
7770af |
subset_map(),
|
|
Packit Service |
7770af |
import_stack(),
|
|
Packit Service |
7770af |
callee_stack(),
|
|
Packit Service |
7770af |
c_compiler(NULL),
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
c_headers (std::vector<Sass_Importer_Entry>()),
|
|
Packit Service |
7770af |
c_importers (std::vector<Sass_Importer_Entry>()),
|
|
Packit Service |
7770af |
c_functions (std::vector<Sass_Function_Entry>()),
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
indent (safe_str(c_options.indent, " ")),
|
|
Packit Service |
7770af |
linefeed (safe_str(c_options.linefeed, "\n")),
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
input_path (make_canonical_path(safe_input(c_options.input_path))),
|
|
Packit Service |
7770af |
output_path (make_canonical_path(safe_output(c_options.output_path, input_path))),
|
|
Packit Service |
7770af |
source_map_file (make_canonical_path(safe_str(c_options.source_map_file, ""))),
|
|
Packit Service |
7770af |
source_map_root (make_canonical_path(safe_str(c_options.source_map_root, "")))
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Sass 3.4: The current working directory will no longer be placed onto the Sass load path by default.
|
|
Packit Service |
7770af |
// If you need the current working directory to be available, set SASS_PATH=. in your shell's environment.
|
|
Packit Service |
7770af |
// include_paths.push_back(CWD);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// collect more paths from different options
|
|
Packit Service |
7770af |
collect_include_paths(c_options.include_path);
|
|
Packit Service |
7770af |
collect_include_paths(c_options.include_paths);
|
|
Packit Service |
7770af |
collect_plugin_paths(c_options.plugin_path);
|
|
Packit Service |
7770af |
collect_plugin_paths(c_options.plugin_paths);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// load plugins and register custom behaviors
|
|
Packit Service |
7770af |
for(auto plug : plugin_paths) plugins.load_plugins(plug);
|
|
Packit Service |
7770af |
for(auto fn : plugins.get_headers()) c_headers.push_back(fn);
|
|
Packit Service |
7770af |
for(auto fn : plugins.get_importers()) c_importers.push_back(fn);
|
|
Packit Service |
7770af |
for(auto fn : plugins.get_functions()) c_functions.push_back(fn);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// sort the items by priority (lowest first)
|
|
Packit Service |
7770af |
sort (c_headers.begin(), c_headers.end(), sort_importers);
|
|
Packit Service |
7770af |
sort (c_importers.begin(), c_importers.end(), sort_importers);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
emitter.set_filename(abs2rel(output_path, source_map_file, CWD));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::add_c_function(Sass_Function_Entry function)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
c_functions.push_back(function);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
void Context::add_c_header(Sass_Importer_Entry header)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
c_headers.push_back(header);
|
|
Packit Service |
7770af |
// need to sort the array afterwards (no big deal)
|
|
Packit Service |
7770af |
sort (c_headers.begin(), c_headers.end(), sort_importers);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
void Context::add_c_importer(Sass_Importer_Entry importer)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
c_importers.push_back(importer);
|
|
Packit Service |
7770af |
// need to sort the array afterwards (no big deal)
|
|
Packit Service |
7770af |
sort (c_importers.begin(), c_importers.end(), sort_importers);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Context::~Context()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// resources were allocated by strdup or malloc
|
|
Packit Service |
7770af |
for (size_t i = 0; i < resources.size(); ++i) {
|
|
Packit Service |
7770af |
free(resources[i].contents);
|
|
Packit Service |
7770af |
free(resources[i].srcmap);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// free all strings we kept alive during compiler execution
|
|
Packit Service |
7770af |
for (size_t n = 0; n < strings.size(); ++n) free(strings[n]);
|
|
Packit Service |
7770af |
// everything that gets put into sources will be freed by us
|
|
Packit Service |
7770af |
// this shouldn't have anything in it anyway!?
|
|
Packit Service |
7770af |
for (size_t m = 0; m < import_stack.size(); ++m) {
|
|
Packit Service |
7770af |
sass_import_take_source(import_stack[m]);
|
|
Packit Service |
7770af |
sass_import_take_srcmap(import_stack[m]);
|
|
Packit Service |
7770af |
sass_delete_import(import_stack[m]);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// clear inner structures (vectors) and input source
|
|
Packit Service |
7770af |
resources.clear(); import_stack.clear();
|
|
Packit Service |
7770af |
subset_map.clear(), sheets.clear();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Data_Context::~Data_Context()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// --> this will be freed by resources
|
|
Packit Service |
7770af |
// make sure we free the source even if not processed!
|
|
Packit Service |
7770af |
// if (resources.size() == 0 && source_c_str) free(source_c_str);
|
|
Packit Service |
7770af |
// if (resources.size() == 0 && srcmap_c_str) free(srcmap_c_str);
|
|
Packit Service |
7770af |
// source_c_str = 0; srcmap_c_str = 0;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
File_Context::~File_Context()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::collect_include_paths(const char* paths_str)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (paths_str) {
|
|
Packit Service |
7770af |
const char* beg = paths_str;
|
|
Packit Service |
7770af |
const char* end = Prelexer::find_first<PATH_SEP>(beg);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
while (end) {
|
|
Packit Service |
7770af |
std::string path(beg, end - beg);
|
|
Packit Service |
7770af |
if (!path.empty()) {
|
|
Packit Service |
7770af |
if (*path.rbegin() != '/') path += '/';
|
|
Packit Service |
7770af |
include_paths.push_back(path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
beg = end + 1;
|
|
Packit Service |
7770af |
end = Prelexer::find_first<PATH_SEP>(beg);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string path(beg);
|
|
Packit Service |
7770af |
if (!path.empty()) {
|
|
Packit Service |
7770af |
if (*path.rbegin() != '/') path += '/';
|
|
Packit Service |
7770af |
include_paths.push_back(path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::collect_include_paths(string_list* paths_array)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
while (paths_array)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
collect_include_paths(paths_array->string);
|
|
Packit Service |
7770af |
paths_array = paths_array->next;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::collect_plugin_paths(const char* paths_str)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (paths_str) {
|
|
Packit Service |
7770af |
const char* beg = paths_str;
|
|
Packit Service |
7770af |
const char* end = Prelexer::find_first<PATH_SEP>(beg);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
while (end) {
|
|
Packit Service |
7770af |
std::string path(beg, end - beg);
|
|
Packit Service |
7770af |
if (!path.empty()) {
|
|
Packit Service |
7770af |
if (*path.rbegin() != '/') path += '/';
|
|
Packit Service |
7770af |
plugin_paths.push_back(path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
beg = end + 1;
|
|
Packit Service |
7770af |
end = Prelexer::find_first<PATH_SEP>(beg);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string path(beg);
|
|
Packit Service |
7770af |
if (!path.empty()) {
|
|
Packit Service |
7770af |
if (*path.rbegin() != '/') path += '/';
|
|
Packit Service |
7770af |
plugin_paths.push_back(path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::collect_plugin_paths(string_list* paths_array)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
while (paths_array)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
collect_plugin_paths(paths_array->string);
|
|
Packit Service |
7770af |
paths_array = paths_array->next;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// resolve the imp_path in base_path or include_paths
|
|
Packit Service |
7770af |
// looks for alternatives and returns a list from one directory
|
|
Packit Service |
7770af |
std::vector<Include> Context::find_includes(const Importer& import)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// make sure we resolve against an absolute path
|
|
Packit Service |
7770af |
std::string base_path(rel2abs(import.base_path));
|
|
Packit Service |
7770af |
// first try to resolve the load path relative to the base path
|
|
Packit Service |
7770af |
std::vector<Include> vec(resolve_includes(base_path, import.imp_path));
|
|
Packit Service |
7770af |
// then search in every include path (but only if nothing found yet)
|
|
Packit Service |
7770af |
for (size_t i = 0, S = include_paths.size(); vec.size() == 0 && i < S; ++i)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// call resolve_includes and individual base path and append all results
|
|
Packit Service |
7770af |
std::vector<Include> resolved(resolve_includes(include_paths[i], import.imp_path));
|
|
Packit Service |
7770af |
if (resolved.size()) vec.insert(vec.end(), resolved.begin(), resolved.end());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// return vector
|
|
Packit Service |
7770af |
return vec;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// register include with resolved path and its content
|
|
Packit Service |
7770af |
// memory of the resources will be freed by us on exit
|
|
Packit Service |
7770af |
void Context::register_resource(const Include& inc, const Resource& res, ParserState* prstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// do not parse same resource twice
|
|
Packit Service |
7770af |
// maybe raise an error in this case
|
|
Packit Service |
7770af |
// if (sheets.count(inc.abs_path)) {
|
|
Packit Service |
7770af |
// free(res.contents); free(res.srcmap);
|
|
Packit Service |
7770af |
// throw std::runtime_error("duplicate resource registered");
|
|
Packit Service |
7770af |
// return;
|
|
Packit Service |
7770af |
// }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// get index for this resource
|
|
Packit Service |
7770af |
size_t idx = resources.size();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// tell emitter about new resource
|
|
Packit Service |
7770af |
emitter.add_source_index(idx);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// put resources under our control
|
|
Packit Service |
7770af |
// the memory will be freed later
|
|
Packit Service |
7770af |
resources.push_back(res);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// add a relative link to the working directory
|
|
Packit Service |
7770af |
included_files.push_back(inc.abs_path);
|
|
Packit Service |
7770af |
// add a relative link to the source map output file
|
|
Packit Service |
7770af |
srcmap_links.push_back(abs2rel(inc.abs_path, source_map_file, CWD));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// get pointer to the loaded content
|
|
Packit Service |
7770af |
Sass_Import_Entry import = sass_make_import(
|
|
Packit Service |
7770af |
inc.imp_path.c_str(),
|
|
Packit Service |
7770af |
inc.abs_path.c_str(),
|
|
Packit Service |
7770af |
res.contents,
|
|
Packit Service |
7770af |
res.srcmap
|
|
Packit Service |
7770af |
);
|
|
Packit Service |
7770af |
// add the entry to the stack
|
|
Packit Service |
7770af |
import_stack.push_back(import);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// get pointer to the loaded content
|
|
Packit Service |
7770af |
const char* contents = resources[idx].contents;
|
|
Packit Service |
7770af |
// keep a copy of the path around (for parserstates)
|
|
Packit Service |
7770af |
// ToDo: we clean it, but still not very elegant!?
|
|
Packit Service |
7770af |
strings.push_back(sass_copy_c_string(inc.abs_path.c_str()));
|
|
Packit Service |
7770af |
// create the initial parser state from resource
|
|
Packit Service |
7770af |
ParserState pstate(strings.back(), contents, idx);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check existing import stack for possible recursion
|
|
Packit Service |
7770af |
for (size_t i = 0; i < import_stack.size() - 2; ++i) {
|
|
Packit Service |
7770af |
auto parent = import_stack[i];
|
|
Packit Service |
7770af |
if (std::strcmp(parent->abs_path, import->abs_path) == 0) {
|
|
Packit Service |
7770af |
std::string stack("An @import loop has been found:");
|
|
Packit Service |
7770af |
for (size_t n = 1; n < i + 2; ++n) {
|
|
Packit Service |
7770af |
stack += "\n " + std::string(import_stack[n]->imp_path) +
|
|
Packit Service |
7770af |
" imports " + std::string(import_stack[n+1]->imp_path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// implement error throw directly until we
|
|
Packit Service |
7770af |
// decided how to handle full stack traces
|
|
Packit Service |
7770af |
ParserState state = prstate ? *prstate : pstate;
|
|
Packit Service |
7770af |
throw Exception::InvalidSyntax(state, stack, &import_stack);
|
|
Packit Service |
7770af |
// error(stack, prstate ? *prstate : pstate, import_stack);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create a parser instance from the given c_str buffer
|
|
Packit Service |
7770af |
Parser p(Parser::from_c_str(contents, *this, pstate));
|
|
Packit Service |
7770af |
// do not yet dispose these buffers
|
|
Packit Service |
7770af |
sass_import_take_source(import);
|
|
Packit Service |
7770af |
sass_import_take_srcmap(import);
|
|
Packit Service |
7770af |
// then parse the root block
|
|
Packit Service |
7770af |
Block_Obj root = p.parse();
|
|
Packit Service |
7770af |
// delete memory of current stack frame
|
|
Packit Service |
7770af |
sass_delete_import(import_stack.back());
|
|
Packit Service |
7770af |
// remove current stack frame
|
|
Packit Service |
7770af |
import_stack.pop_back();
|
|
Packit Service |
7770af |
// create key/value pair for ast node
|
|
Packit Service |
7770af |
std::pair<const std::string, StyleSheet>
|
|
Packit Service |
7770af |
ast_pair(inc.abs_path, { res, root });
|
|
Packit Service |
7770af |
// register resulting resource
|
|
Packit Service |
7770af |
sheets.insert(ast_pair);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// Add a new import to the context (called from `import_url`)
|
|
Packit Service |
7770af |
Include Context::load_import(const Importer& imp, ParserState pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// search for valid imports (ie. partials) on the filesystem
|
|
Packit Service |
7770af |
// this may return more than one valid result (ambiguous imp_path)
|
|
Packit Service |
7770af |
const std::vector<Include> resolved(find_includes(imp));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// error nicely on ambiguous imp_path
|
|
Packit Service |
7770af |
if (resolved.size() > 1) {
|
|
Packit Service |
7770af |
std::stringstream msg_stream;
|
|
Packit Service |
7770af |
msg_stream << "It's not clear which file to import for ";
|
|
Packit Service |
7770af |
msg_stream << "'@import \"" << imp.imp_path << "\"'." << "\n";
|
|
Packit Service |
7770af |
msg_stream << "Candidates:" << "\n";
|
|
Packit Service |
7770af |
for (size_t i = 0, L = resolved.size(); i < L; ++i)
|
|
Packit Service |
7770af |
{ msg_stream << " " << resolved[i].imp_path << "\n"; }
|
|
Packit Service |
7770af |
msg_stream << "Please delete or rename all but one of these files." << "\n";
|
|
Packit Service |
7770af |
error(msg_stream.str(), pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// process the resolved entry
|
|
Packit Service |
7770af |
else if (resolved.size() == 1) {
|
|
Packit Service |
7770af |
bool use_cache = c_importers.size() == 0;
|
|
Packit Service |
7770af |
// use cache for the resource loading
|
|
Packit Service |
7770af |
if (use_cache && sheets.count(resolved[0].abs_path)) return resolved[0];
|
|
Packit Service |
7770af |
// try to read the content of the resolved file entry
|
|
Packit Service |
7770af |
// the memory buffer returned must be freed by us!
|
|
Packit Service |
7770af |
if (char* contents = read_file(resolved[0].abs_path)) {
|
|
Packit Service |
7770af |
// register the newly resolved file resource
|
|
Packit Service |
7770af |
register_resource(resolved[0], { contents, 0 }, &pstate);
|
|
Packit Service |
7770af |
// return resolved entry
|
|
Packit Service |
7770af |
return resolved[0];
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// nothing found
|
|
Packit Service |
7770af |
return { imp, "" };
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::import_url (Import_Ptr imp, std::string load_path, const std::string& ctx_path) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
ParserState pstate(imp->pstate());
|
|
Packit Service |
7770af |
std::string imp_path(unquote(load_path));
|
|
Packit Service |
7770af |
std::string protocol("file");
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
using namespace Prelexer;
|
|
Packit Service |
7770af |
if (const char* proto = sequence< identifier, exactly<':'>, exactly<'/'>, exactly<'/'> >(imp_path.c_str())) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
protocol = std::string(imp_path.c_str(), proto - 3);
|
|
Packit Service |
7770af |
// if (protocol.compare("file") && true) { }
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// add urls (protocol other than file) and urls without procotol to `urls` member
|
|
Packit Service |
7770af |
// ToDo: if ctx_path is already a file resource, we should not add it here?
|
|
Packit Service |
7770af |
if (imp->import_queries() || protocol != "file" || imp_path.substr(0, 2) == "//") {
|
|
Packit Service |
7770af |
imp->urls().push_back(SASS_MEMORY_NEW(String_Quoted, imp->pstate(), load_path));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (imp_path.length() > 4 && imp_path.substr(imp_path.length() - 4, 4) == ".css") {
|
|
Packit Service |
7770af |
String_Constant_Ptr loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path));
|
|
Packit Service |
7770af |
Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc);
|
|
Packit Service |
7770af |
Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate);
|
|
Packit Service |
7770af |
loc_args->append(loc_arg);
|
|
Packit Service |
7770af |
Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", loc_args);
|
|
Packit Service |
7770af |
imp->urls().push_back(new_url);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else {
|
|
Packit Service |
7770af |
const Importer importer(imp_path, ctx_path);
|
|
Packit Service |
7770af |
Include include(load_import(importer, pstate));
|
|
Packit Service |
7770af |
if (include.abs_path.empty()) {
|
|
Packit Service |
7770af |
error("File to import not found or unreadable: " + imp_path + ".\nParent style sheet: " + ctx_path, pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
imp->incs().push_back(include);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// call custom importers on the given (unquoted) load_path and eventually parse the resulting style_sheet
|
|
Packit Service |
7770af |
bool Context::call_loader(const std::string& load_path, const char* ctx_path, ParserState& pstate, Import_Ptr imp, std::vector<Sass_Importer_Entry> importers, bool only_one)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// unique counter
|
|
Packit Service |
7770af |
size_t count = 0;
|
|
Packit Service |
7770af |
// need one correct import
|
|
Packit Service |
7770af |
bool has_import = false;
|
|
Packit Service |
7770af |
// process all custom importers (or custom headers)
|
|
Packit Service |
7770af |
for (Sass_Importer_Entry& importer_ent : importers) {
|
|
Packit Service |
7770af |
// int priority = sass_importer_get_priority(importer);
|
|
Packit Service |
7770af |
Sass_Importer_Fn fn = sass_importer_get_function(importer_ent);
|
|
Packit Service |
7770af |
// skip importer if it returns NULL
|
|
Packit Service |
7770af |
if (Sass_Import_List includes =
|
|
Packit Service |
7770af |
fn(load_path.c_str(), importer_ent, c_compiler)
|
|
Packit Service |
7770af |
) {
|
|
Packit Service |
7770af |
// get c pointer copy to iterate over
|
|
Packit Service |
7770af |
Sass_Import_List it_includes = includes;
|
|
Packit Service |
7770af |
while (*it_includes) { ++count;
|
|
Packit Service |
7770af |
// create unique path to use as key
|
|
Packit Service |
7770af |
std::string uniq_path = load_path;
|
|
Packit Service |
7770af |
if (!only_one && count) {
|
|
Packit Service |
7770af |
std::stringstream path_strm;
|
|
Packit Service |
7770af |
path_strm << uniq_path << ":" << count;
|
|
Packit Service |
7770af |
uniq_path = path_strm.str();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// create the importer struct
|
|
Packit Service |
7770af |
Importer importer(uniq_path, ctx_path);
|
|
Packit Service |
7770af |
// query data from the current include
|
|
Packit Service |
7770af |
Sass_Import_Entry include_ent = *it_includes;
|
|
Packit Service |
7770af |
char* source = sass_import_take_source(include_ent);
|
|
Packit Service |
7770af |
char* srcmap = sass_import_take_srcmap(include_ent);
|
|
Packit Service |
7770af |
size_t line = sass_import_get_error_line(include_ent);
|
|
Packit Service |
7770af |
size_t column = sass_import_get_error_column(include_ent);
|
|
Packit Service |
7770af |
const char *abs_path = sass_import_get_abs_path(include_ent);
|
|
Packit Service |
7770af |
// handle error message passed back from custom importer
|
|
Packit Service |
7770af |
// it may (or may not) override the line and column info
|
|
Packit Service |
7770af |
if (const char* err_message = sass_import_get_error_message(include_ent)) {
|
|
Packit Service |
7770af |
if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, &pstate);
|
|
Packit Service |
7770af |
if (line == std::string::npos && column == std::string::npos) error(err_message, pstate);
|
|
Packit Service |
7770af |
else error(err_message, ParserState(ctx_path, source, Position(line, column)));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// content for import was set
|
|
Packit Service |
7770af |
else if (source) {
|
|
Packit Service |
7770af |
// resolved abs_path should be set by custom importer
|
|
Packit Service |
7770af |
// use the created uniq_path as fallback (maybe enforce)
|
|
Packit Service |
7770af |
std::string path_key(abs_path ? abs_path : uniq_path);
|
|
Packit Service |
7770af |
// create the importer struct
|
|
Packit Service |
7770af |
Include include(importer, path_key);
|
|
Packit Service |
7770af |
// attach information to AST node
|
|
Packit Service |
7770af |
imp->incs().push_back(include);
|
|
Packit Service |
7770af |
// register the resource buffers
|
|
Packit Service |
7770af |
register_resource(include, { source, srcmap }, &pstate);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// only a path was retuned
|
|
Packit Service |
7770af |
// try to load it like normal
|
|
Packit Service |
7770af |
else if(abs_path) {
|
|
Packit Service |
7770af |
// checks some urls to preserve
|
|
Packit Service |
7770af |
// `http://`, `https://` and `//`
|
|
Packit Service |
7770af |
// or dispatchs to `import_file`
|
|
Packit Service |
7770af |
// which will check for a `.css` extension
|
|
Packit Service |
7770af |
// or resolves the file on the filesystem
|
|
Packit Service |
7770af |
// added and resolved via `add_file`
|
|
Packit Service |
7770af |
// finally stores everything on `imp`
|
|
Packit Service |
7770af |
import_url(imp, abs_path, ctx_path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// move to next
|
|
Packit Service |
7770af |
++it_includes;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// deallocate the returned memory
|
|
Packit Service |
7770af |
sass_delete_import_list(includes);
|
|
Packit Service |
7770af |
// set success flag
|
|
Packit Service |
7770af |
has_import = true;
|
|
Packit Service |
7770af |
// break out of loop
|
|
Packit Service |
7770af |
if (only_one) break;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// return result
|
|
Packit Service |
7770af |
return has_import;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_function(Context&, Signature sig, Native_Function f, Env* env);
|
|
Packit Service |
7770af |
void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
|
|
Packit Service |
7770af |
void register_overload_stub(Context&, std::string name, Env* env);
|
|
Packit Service |
7770af |
void register_built_in_functions(Context&, Env* env);
|
|
Packit Service |
7770af |
void register_c_functions(Context&, Env* env, Sass_Function_List);
|
|
Packit Service |
7770af |
void register_c_function(Context&, Env* env, Sass_Function_Entry);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
char* Context::render(Block_Obj root)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// check for valid block
|
|
Packit Service |
7770af |
if (!root) return 0;
|
|
Packit Service |
7770af |
// start the render process
|
|
Packit Service |
7770af |
root->perform(&emitter);
|
|
Packit Service |
7770af |
// finish emitter stream
|
|
Packit Service |
7770af |
emitter.finalize();
|
|
Packit Service |
7770af |
// get the resulting buffer from stream
|
|
Packit Service |
7770af |
OutputBuffer emitted = emitter.get_buffer();
|
|
Packit Service |
7770af |
// should we append a source map url?
|
|
Packit Service |
7770af |
if (!c_options.omit_source_map_url) {
|
|
Packit Service |
7770af |
// generate an embeded source map
|
|
Packit Service |
7770af |
if (c_options.source_map_embed) {
|
|
Packit Service |
7770af |
emitted.buffer += linefeed;
|
|
Packit Service |
7770af |
emitted.buffer += format_embedded_source_map();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// or just link the generated one
|
|
Packit Service |
7770af |
else if (source_map_file != "") {
|
|
Packit Service |
7770af |
emitted.buffer += linefeed;
|
|
Packit Service |
7770af |
emitted.buffer += format_source_mapping_url(source_map_file);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// create a copy of the resulting buffer string
|
|
Packit Service |
7770af |
// this must be freed or taken over by implementor
|
|
Packit Service |
7770af |
return sass_copy_c_string(emitted.buffer.c_str());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void Context::apply_custom_headers(Block_Obj root, const char* ctx_path, ParserState pstate)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// create a custom import to resolve headers
|
|
Packit Service |
7770af |
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
|
|
Packit Service |
7770af |
// dispatch headers which will add custom functions
|
|
Packit Service |
7770af |
// custom headers are added to the import instance
|
|
Packit Service |
7770af |
call_headers(entry_path, ctx_path, pstate, imp);
|
|
Packit Service |
7770af |
// increase head count to skip later
|
|
Packit Service |
7770af |
head_imports += resources.size() - 1;
|
|
Packit Service |
7770af |
// add the statement if we have urls
|
|
Packit Service |
7770af |
if (!imp->urls().empty()) root->append(imp);
|
|
Packit Service |
7770af |
// process all other resources (add Import_Stub nodes)
|
|
Packit Service |
7770af |
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
|
|
Packit Service |
7770af |
root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Block_Obj File_Context::parse()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if entry file is given
|
|
Packit Service |
7770af |
if (input_path.empty()) return 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create absolute path from input filename
|
|
Packit Service |
7770af |
// ToDo: this should be resolved via custom importers
|
|
Packit Service |
7770af |
std::string abs_path(rel2abs(input_path, CWD));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// try to load the entry file
|
|
Packit Service |
7770af |
char* contents = read_file(abs_path);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// alternatively also look inside each include path folder
|
|
Packit Service |
7770af |
// I think this differs from ruby sass (IMO too late to remove)
|
|
Packit Service |
7770af |
for (size_t i = 0, S = include_paths.size(); contents == 0 && i < S; ++i) {
|
|
Packit Service |
7770af |
// build absolute path for this include path entry
|
|
Packit Service |
7770af |
abs_path = rel2abs(input_path, include_paths[i]);
|
|
Packit Service |
7770af |
// try to load the resulting path
|
|
Packit Service |
7770af |
contents = read_file(abs_path);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// abort early if no content could be loaded (various reasons)
|
|
Packit Service |
7770af |
if (!contents) throw std::runtime_error("File to read not found or unreadable: " + input_path);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// store entry path
|
|
Packit Service |
7770af |
entry_path = abs_path;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create entry only for import stack
|
|
Packit Service |
7770af |
Sass_Import_Entry import = sass_make_import(
|
|
Packit Service |
7770af |
input_path.c_str(),
|
|
Packit Service |
7770af |
entry_path.c_str(),
|
|
Packit Service |
7770af |
contents,
|
|
Packit Service |
7770af |
0
|
|
Packit Service |
7770af |
);
|
|
Packit Service |
7770af |
// add the entry to the stack
|
|
Packit Service |
7770af |
import_stack.push_back(import);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create the source entry for file entry
|
|
Packit Service |
7770af |
register_resource({{ input_path, "." }, abs_path }, { contents, 0 });
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create root ast tree node
|
|
Packit Service |
7770af |
return compile();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
Block_Obj Data_Context::parse()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// check if source string is given
|
|
Packit Service |
7770af |
if (!source_c_str) return 0;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// convert indented sass syntax
|
|
Packit Service |
7770af |
if(c_options.is_indented_syntax_src) {
|
|
Packit Service |
7770af |
// call sass2scss to convert the string
|
|
Packit Service |
7770af |
char * converted = sass2scss(source_c_str,
|
|
Packit Service |
7770af |
// preserve the structure as much as possible
|
|
Packit Service |
7770af |
SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
|
|
Packit Service |
7770af |
// replace old source_c_str with converted
|
|
Packit Service |
7770af |
free(source_c_str); source_c_str = converted;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// remember entry path (defaults to stdin for string)
|
|
Packit Service |
7770af |
entry_path = input_path.empty() ? "stdin" : input_path;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// ToDo: this may be resolved via custom importers
|
|
Packit Service |
7770af |
std::string abs_path(rel2abs(entry_path));
|
|
Packit Service |
7770af |
char* abs_path_c_str = sass_copy_c_string(abs_path.c_str());
|
|
Packit Service |
7770af |
strings.push_back(abs_path_c_str);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create entry only for the import stack
|
|
Packit Service |
7770af |
Sass_Import_Entry import = sass_make_import(
|
|
Packit Service |
7770af |
entry_path.c_str(),
|
|
Packit Service |
7770af |
abs_path_c_str,
|
|
Packit Service |
7770af |
source_c_str,
|
|
Packit Service |
7770af |
srcmap_c_str
|
|
Packit Service |
7770af |
);
|
|
Packit Service |
7770af |
// add the entry to the stack
|
|
Packit Service |
7770af |
import_stack.push_back(import);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// register a synthetic resource (path does not really exist, skip in includes)
|
|
Packit Service |
7770af |
register_resource({{ input_path, "." }, input_path }, { source_c_str, srcmap_c_str });
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// create root ast tree node
|
|
Packit Service |
7770af |
return compile();
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// parse root block from includes
|
|
Packit Service |
7770af |
Block_Obj Context::compile()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// abort if there is no data
|
|
Packit Service |
7770af |
if (resources.size() == 0) return 0;
|
|
Packit Service |
7770af |
// get root block from the first style sheet
|
|
Packit Service |
7770af |
Block_Obj root = sheets.at(entry_path).root;
|
|
Packit Service |
7770af |
// abort on invalid root
|
|
Packit Service |
7770af |
if (root.isNull()) return 0;
|
|
Packit Service |
7770af |
Env global; // create root environment
|
|
Packit Service |
7770af |
// register built-in functions on env
|
|
Packit Service |
7770af |
register_built_in_functions(*this, &global);
|
|
Packit Service |
7770af |
// register custom functions (defined via C-API)
|
|
Packit Service |
7770af |
for (size_t i = 0, S = c_functions.size(); i < S; ++i)
|
|
Packit Service |
7770af |
{ register_c_function(*this, &global, c_functions[i]); }
|
|
Packit Service |
7770af |
// create initial backtrace entry
|
|
Packit Service |
7770af |
Backtrace backtrace(0, ParserState("", 0), "");
|
|
Packit Service |
7770af |
// create crtp visitor objects
|
|
Packit Service |
7770af |
Expand expand(*this, &global, &backtrace);
|
|
Packit Service |
7770af |
Cssize cssize(*this, &backtrace);
|
|
Packit Service |
7770af |
CheckNesting check_nesting;
|
|
Packit Service |
7770af |
// check nesting
|
|
Packit Service |
7770af |
check_nesting(root);
|
|
Packit Service |
7770af |
// expand and eval the tree
|
|
Packit Service |
7770af |
root = expand(root);
|
|
Packit Service |
7770af |
// check nesting
|
|
Packit Service |
7770af |
check_nesting(root);
|
|
Packit Service |
7770af |
// merge and bubble certain rules
|
|
Packit Service |
7770af |
root = cssize(root);
|
|
Packit Service |
7770af |
// should we extend something?
|
|
Packit Service |
7770af |
if (!subset_map.empty()) {
|
|
Packit Service |
7770af |
// create crtp visitor object
|
|
Packit Service |
7770af |
Extend extend(subset_map);
|
|
Packit Service |
7770af |
// extend tree nodes
|
|
Packit Service |
7770af |
extend(root);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// clean up by removing empty placeholders
|
|
Packit Service |
7770af |
// ToDo: maybe we can do this somewhere else?
|
|
Packit Service |
7770af |
Remove_Placeholders remove_placeholders;
|
|
Packit Service |
7770af |
root->perform(&remove_placeholders);
|
|
Packit Service |
7770af |
// return processed tree
|
|
Packit Service |
7770af |
return root;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// EO compile
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string Context::format_embedded_source_map()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::string map = emitter.render_srcmap(*this);
|
|
Packit Service |
7770af |
std::istringstream is( map );
|
|
Packit Service |
7770af |
std::ostringstream buffer;
|
|
Packit Service |
7770af |
base64::encoder E;
|
|
Packit Service |
7770af |
E.encode(is, buffer);
|
|
Packit Service |
7770af |
std::string url = "data:application/json;base64," + buffer.str();
|
|
Packit Service |
7770af |
url.erase(url.size() - 1);
|
|
Packit Service |
7770af |
return "/*# sourceMappingURL=" + url + " */";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string Context::format_source_mapping_url(const std::string& file)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
std::string url = abs2rel(file, output_path, CWD);
|
|
Packit Service |
7770af |
return "/*# sourceMappingURL=" + url + " */";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
char* Context::render_srcmap()
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (source_map_file == "") return 0;
|
|
Packit Service |
7770af |
std::string map = emitter.render_srcmap(*this);
|
|
Packit Service |
7770af |
return sass_copy_c_string(map.c_str());
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// for data context we want to start after "stdin"
|
|
Packit Service |
7770af |
// we probably always want to skip the header includes?
|
|
Packit Service |
7770af |
std::vector<std::string> Context::get_included_files(bool skip, size_t headers)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
// create a copy of the vector for manipulations
|
|
Packit Service |
7770af |
std::vector<std::string> includes = included_files;
|
|
Packit Service |
7770af |
if (includes.size() == 0) return includes;
|
|
Packit Service |
7770af |
if (skip) { includes.erase( includes.begin(), includes.begin() + 1 + headers); }
|
|
Packit Service |
7770af |
else { includes.erase( includes.begin() + 1, includes.begin() + 1 + headers); }
|
|
Packit Service |
7770af |
includes.erase( std::unique( includes.begin(), includes.end() ), includes.end() );
|
|
Packit Service |
7770af |
std::sort( includes.begin() + (skip ? 0 : 1), includes.end() );
|
|
Packit Service |
7770af |
return includes;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_function(Context& ctx, Signature sig, Native_Function f, Env* env)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Definition_Ptr def = make_native_function(sig, f, ctx);
|
|
Packit Service |
7770af |
def->environment(env);
|
|
Packit Service |
7770af |
(*env)[def->name() + "[f]"] = def;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_function(Context& ctx, Signature sig, Native_Function f, size_t arity, Env* env)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Definition_Ptr def = make_native_function(sig, f, ctx);
|
|
Packit Service |
7770af |
std::stringstream ss;
|
|
Packit Service |
7770af |
ss << def->name() << "[f]" << arity;
|
|
Packit Service |
7770af |
def->environment(env);
|
|
Packit Service |
7770af |
(*env)[ss.str()] = def;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_overload_stub(Context& ctx, std::string name, Env* env)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Definition_Ptr stub = SASS_MEMORY_NEW(Definition,
|
|
Packit Service |
7770af |
ParserState("[built-in function]"),
|
|
Packit Service |
7770af |
0,
|
|
Packit Service |
7770af |
name,
|
|
Packit Service |
7770af |
0,
|
|
Packit Service |
7770af |
0,
|
|
Packit Service |
7770af |
true);
|
|
Packit Service |
7770af |
(*env)[name + "[f]"] = stub;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_built_in_functions(Context& ctx, Env* env)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
using namespace Functions;
|
|
Packit Service |
7770af |
// RGB Functions
|
|
Packit Service |
7770af |
register_function(ctx, rgb_sig, rgb, env);
|
|
Packit Service |
7770af |
register_overload_stub(ctx, "rgba", env);
|
|
Packit Service |
7770af |
register_function(ctx, rgba_4_sig, rgba_4, 4, env);
|
|
Packit Service |
7770af |
register_function(ctx, rgba_2_sig, rgba_2, 2, env);
|
|
Packit Service |
7770af |
register_function(ctx, red_sig, red, env);
|
|
Packit Service |
7770af |
register_function(ctx, green_sig, green, env);
|
|
Packit Service |
7770af |
register_function(ctx, blue_sig, blue, env);
|
|
Packit Service |
7770af |
register_function(ctx, mix_sig, mix, env);
|
|
Packit Service |
7770af |
// HSL Functions
|
|
Packit Service |
7770af |
register_function(ctx, hsl_sig, hsl, env);
|
|
Packit Service |
7770af |
register_function(ctx, hsla_sig, hsla, env);
|
|
Packit Service |
7770af |
register_function(ctx, hue_sig, hue, env);
|
|
Packit Service |
7770af |
register_function(ctx, saturation_sig, saturation, env);
|
|
Packit Service |
7770af |
register_function(ctx, lightness_sig, lightness, env);
|
|
Packit Service |
7770af |
register_function(ctx, adjust_hue_sig, adjust_hue, env);
|
|
Packit Service |
7770af |
register_function(ctx, lighten_sig, lighten, env);
|
|
Packit Service |
7770af |
register_function(ctx, darken_sig, darken, env);
|
|
Packit Service |
7770af |
register_function(ctx, saturate_sig, saturate, env);
|
|
Packit Service |
7770af |
register_function(ctx, desaturate_sig, desaturate, env);
|
|
Packit Service |
7770af |
register_function(ctx, grayscale_sig, grayscale, env);
|
|
Packit Service |
7770af |
register_function(ctx, complement_sig, complement, env);
|
|
Packit Service |
7770af |
register_function(ctx, invert_sig, invert, env);
|
|
Packit Service |
7770af |
// Opacity Functions
|
|
Packit Service |
7770af |
register_function(ctx, alpha_sig, alpha, env);
|
|
Packit Service |
7770af |
register_function(ctx, opacity_sig, alpha, env);
|
|
Packit Service |
7770af |
register_function(ctx, opacify_sig, opacify, env);
|
|
Packit Service |
7770af |
register_function(ctx, fade_in_sig, opacify, env);
|
|
Packit Service |
7770af |
register_function(ctx, transparentize_sig, transparentize, env);
|
|
Packit Service |
7770af |
register_function(ctx, fade_out_sig, transparentize, env);
|
|
Packit Service |
7770af |
// Other Color Functions
|
|
Packit Service |
7770af |
register_function(ctx, adjust_color_sig, adjust_color, env);
|
|
Packit Service |
7770af |
register_function(ctx, scale_color_sig, scale_color, env);
|
|
Packit Service |
7770af |
register_function(ctx, change_color_sig, change_color, env);
|
|
Packit Service |
7770af |
register_function(ctx, ie_hex_str_sig, ie_hex_str, env);
|
|
Packit Service |
7770af |
// String Functions
|
|
Packit Service |
7770af |
register_function(ctx, unquote_sig, sass_unquote, env);
|
|
Packit Service |
7770af |
register_function(ctx, quote_sig, sass_quote, env);
|
|
Packit Service |
7770af |
register_function(ctx, str_length_sig, str_length, env);
|
|
Packit Service |
7770af |
register_function(ctx, str_insert_sig, str_insert, env);
|
|
Packit Service |
7770af |
register_function(ctx, str_index_sig, str_index, env);
|
|
Packit Service |
7770af |
register_function(ctx, str_slice_sig, str_slice, env);
|
|
Packit Service |
7770af |
register_function(ctx, to_upper_case_sig, to_upper_case, env);
|
|
Packit Service |
7770af |
register_function(ctx, to_lower_case_sig, to_lower_case, env);
|
|
Packit Service |
7770af |
// Number Functions
|
|
Packit Service |
7770af |
register_function(ctx, percentage_sig, percentage, env);
|
|
Packit Service |
7770af |
register_function(ctx, round_sig, round, env);
|
|
Packit Service |
7770af |
register_function(ctx, ceil_sig, ceil, env);
|
|
Packit Service |
7770af |
register_function(ctx, floor_sig, floor, env);
|
|
Packit Service |
7770af |
register_function(ctx, abs_sig, abs, env);
|
|
Packit Service |
7770af |
register_function(ctx, min_sig, min, env);
|
|
Packit Service |
7770af |
register_function(ctx, max_sig, max, env);
|
|
Packit Service |
7770af |
register_function(ctx, random_sig, random, env);
|
|
Packit Service |
7770af |
// List Functions
|
|
Packit Service |
7770af |
register_function(ctx, length_sig, length, env);
|
|
Packit Service |
7770af |
register_function(ctx, nth_sig, nth, env);
|
|
Packit Service |
7770af |
register_function(ctx, set_nth_sig, set_nth, env);
|
|
Packit Service |
7770af |
register_function(ctx, index_sig, index, env);
|
|
Packit Service |
7770af |
register_function(ctx, join_sig, join, env);
|
|
Packit Service |
7770af |
register_function(ctx, append_sig, append, env);
|
|
Packit Service |
7770af |
register_function(ctx, zip_sig, zip, env);
|
|
Packit Service |
7770af |
register_function(ctx, list_separator_sig, list_separator, env);
|
|
Packit Service |
7770af |
// Map Functions
|
|
Packit Service |
7770af |
register_function(ctx, map_get_sig, map_get, env);
|
|
Packit Service |
7770af |
register_function(ctx, map_merge_sig, map_merge, env);
|
|
Packit Service |
7770af |
register_function(ctx, map_remove_sig, map_remove, env);
|
|
Packit Service |
7770af |
register_function(ctx, map_keys_sig, map_keys, env);
|
|
Packit Service |
7770af |
register_function(ctx, map_values_sig, map_values, env);
|
|
Packit Service |
7770af |
register_function(ctx, map_has_key_sig, map_has_key, env);
|
|
Packit Service |
7770af |
register_function(ctx, keywords_sig, keywords, env);
|
|
Packit Service |
7770af |
// Introspection Functions
|
|
Packit Service |
7770af |
register_function(ctx, type_of_sig, type_of, env);
|
|
Packit Service |
7770af |
register_function(ctx, unit_sig, unit, env);
|
|
Packit Service |
7770af |
register_function(ctx, unitless_sig, unitless, env);
|
|
Packit Service |
7770af |
register_function(ctx, comparable_sig, comparable, env);
|
|
Packit Service |
7770af |
register_function(ctx, variable_exists_sig, variable_exists, env);
|
|
Packit Service |
7770af |
register_function(ctx, global_variable_exists_sig, global_variable_exists, env);
|
|
Packit Service |
7770af |
register_function(ctx, function_exists_sig, function_exists, env);
|
|
Packit Service |
7770af |
register_function(ctx, mixin_exists_sig, mixin_exists, env);
|
|
Packit Service |
7770af |
register_function(ctx, feature_exists_sig, feature_exists, env);
|
|
Packit Service |
7770af |
register_function(ctx, call_sig, call, env);
|
|
Packit Service |
7770af |
// Boolean Functions
|
|
Packit Service |
7770af |
register_function(ctx, not_sig, sass_not, env);
|
|
Packit Service |
7770af |
register_function(ctx, if_sig, sass_if, env);
|
|
Packit Service |
7770af |
// Misc Functions
|
|
Packit Service |
7770af |
register_function(ctx, inspect_sig, inspect, env);
|
|
Packit Service |
7770af |
register_function(ctx, unique_id_sig, unique_id, env);
|
|
Packit Service |
7770af |
// Selector functions
|
|
Packit Service |
7770af |
register_function(ctx, selector_nest_sig, selector_nest, env);
|
|
Packit Service |
7770af |
register_function(ctx, selector_append_sig, selector_append, env);
|
|
Packit Service |
7770af |
register_function(ctx, selector_extend_sig, selector_extend, env);
|
|
Packit Service |
7770af |
register_function(ctx, selector_replace_sig, selector_replace, env);
|
|
Packit Service |
7770af |
register_function(ctx, selector_unify_sig, selector_unify, env);
|
|
Packit Service |
7770af |
register_function(ctx, is_superselector_sig, is_superselector, env);
|
|
Packit Service |
7770af |
register_function(ctx, simple_selectors_sig, simple_selectors, env);
|
|
Packit Service |
7770af |
register_function(ctx, selector_parse_sig, selector_parse, env);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
while (descrs && *descrs) {
|
|
Packit Service |
7770af |
register_c_function(ctx, env, *descrs);
|
|
Packit Service |
7770af |
++descrs;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
void register_c_function(Context& ctx, Env* env, Sass_Function_Entry descr)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Definition_Ptr def = make_c_function(descr, ctx);
|
|
Packit Service |
7770af |
def->environment(env);
|
|
Packit Service |
7770af |
(*env)[def->name() + "[f]"] = def;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|