Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.
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
27 changes: 19 additions & 8 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

namespace Sass {
using namespace Constants;
using namespace File;
using std::cerr;
using std::endl;

Expand All @@ -48,13 +49,14 @@ namespace Sass {
include_paths (initializers.include_paths()),
queue (vector<pair<string, const char*> >()),
style_sheets (map<string, Block*>()),
source_map (File::base_name(initializers.output_path())),
source_map (resolve_relative_path(initializers.output_path(), initializers.source_map_file(), get_cwd())),
c_functions (vector<Sass_C_Function_Descriptor>()),
image_path (initializers.image_path()),
image_path (make_canonical_path(initializers.image_path())),
output_path (make_canonical_path(initializers.output_path())),
source_comments (initializers.source_comments()),
source_maps (initializers.source_maps()),
output_style (initializers.output_style()),
source_map_file (initializers.source_map_file()),
source_map_file (make_canonical_path(initializers.source_map_file())),
omit_source_map_url (initializers.omit_source_map_url()),
names_to_colors (map<string, Color*>()),
colors_to_names (map<int, string>()),
Expand Down Expand Up @@ -146,6 +148,7 @@ namespace Sass {
using namespace File;
char* contents = 0;
string real_path;
path = make_canonical_path(path);
for (size_t i = 0, S = include_paths.size(); i < S; ++i) {
string full_path(join_paths(include_paths[i], path));
included_files.push_back(full_path);
Expand All @@ -168,6 +171,7 @@ namespace Sass {
using namespace File;
char* contents = 0;
string real_path;
rel_filepath = make_canonical_path(rel_filepath);
string full_path(join_paths(dir, rel_filepath));
if (style_sheets.count(full_path)) return full_path;
contents = resolve_and_load(full_path, real_path);
Expand Down Expand Up @@ -234,15 +238,19 @@ namespace Sass {
Output_Compressed output_compressed(this);
root->perform(&output_compressed);
string output = output_compressed.get_buffer();
if (!omit_source_map_url) output += format_source_mapping_url(source_map_file);
if (source_map_file != "" && !omit_source_map_url) {
output += format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());
} break;

default: {
Output_Nested output_nested(source_comments, this);
root->perform(&output_nested);
string output = output_nested.get_buffer();
if (!omit_source_map_url) output += "\n" + format_source_mapping_url(source_map_file);
if (source_map_file != "" && !omit_source_map_url) {
output += "\n" + format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());

} break;
Expand All @@ -253,7 +261,7 @@ namespace Sass {

string Context::format_source_mapping_url(const string& file) const
{
return "/*# sourceMappingURL=" + File::base_name(file) + " */";
return "/*# sourceMappingURL=" + resolve_relative_path(file, output_path, cwd) + " */";
}

char* Context::generate_source_map()
Expand All @@ -270,6 +278,8 @@ namespace Sass {
if (!source_c_str) return 0;
queue.clear();
queue.push_back(make_pair("source string", source_c_str));
// mimic google closure compiler
source_map.files.push_back("stdin");
return compile_file();
}

Expand All @@ -285,10 +295,11 @@ namespace Sass {
const size_t wd_len = 1024;
char wd[wd_len];
string cwd = getcwd(wd, wd_len);
if (cwd[cwd.length() - 1] != '/') cwd += '/';
#ifdef _WIN32
replace(cwd.begin(), cwd.end(), '\\', '/'); //convert Windows backslashes to URL forward slashes
//convert backslashes to forward slashes
replace(cwd.begin(), cwd.end(), '\\', '/');
#endif
if (cwd[cwd.length() - 1] != '/') cwd += '/';
return cwd;
}

Expand Down
1 change: 1 addition & 0 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace Sass {
vector<Sass_C_Function_Descriptor> c_functions;

string image_path; // for the image-url Sass function
string output_path; // for relative paths to the output
bool source_comments;
bool source_maps;
Output_Style output_style;
Expand Down
80 changes: 60 additions & 20 deletions file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif

#ifndef FS_CASE_SENSITIVE
#ifdef _WIN32
#define FS_CASE_SENSITIVE 0
#else
#define FS_CASE_SENSITIVE 1
#endif
#endif

#include <iostream>
#include <fstream>
#include <cctype>
Expand All @@ -15,6 +23,33 @@ namespace Sass {
namespace File {
using namespace std;

// no physical check on filesystem
// only a logical cleanup of a path
string make_canonical_path (string path)
{

// declarations
size_t pos;

#ifdef _WIN32
//convert backslashes to forward slashes
replace(path.begin(), path.end(), '\\', '/');
#endif

pos = 0; // remove all self references inside the path string
while((pos = path.find("/./", pos)) != string::npos) path.erase(pos, 2);

pos = 0; // remove all leading and trailing self references
while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2);
while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2);

pos = 0; // collapse multiple delimiters into a single one
while((pos = path.find("//", pos)) != string::npos) path.erase(pos, 1);

return path;

}

size_t find_last_folder_separator(const string& path, size_t limit = string::npos)
{
size_t pos = string::npos;
Expand Down Expand Up @@ -79,26 +114,11 @@ namespace Sass {

string make_absolute_path(const string& path, const string& cwd)
{
return (is_absolute_path(path) ? path : join_paths(cwd, path));
return make_canonical_path((is_absolute_path(path) ? path : join_paths(cwd, path)));
}

string resolve_relative_path(const string& uri, const string& base, const string& cwd, const bool recurse)
string resolve_relative_path(const string& uri, const string& base, const string& cwd)
{
if (!recurse) {
#ifdef _WIN32
// Convert all paths to lower case for Windows
string uri2(uri);
transform(uri.begin(), uri.end(), uri2.begin(), tolower);

string base2(base);
transform(base.begin(), base.end(), base2.begin(), tolower);

string cwd2(cwd);
transform(cwd.begin(), cwd.end(), cwd2.begin(), tolower);

return resolve_relative_path(uri2, base2, cwd2, true);
#endif
}

string absolute_uri = make_absolute_path(uri, cwd);
string absolute_base = make_absolute_path(base, cwd);
Expand All @@ -109,7 +129,13 @@ namespace Sass {
size_t index = 0;
size_t minSize = min(absolute_uri.size(), absolute_base.size());
for (size_t i = 0; i < minSize; ++i) {
if (absolute_uri[i] != absolute_base[i]) break;
#ifdef FS_CASE_SENSITIVE
if (absolute_uri[i] != absolute_base[i]) break;
#else
// compare the charactes in a case insensitive manner
// windows fs is only case insensitive in ascii ranges
if (tolower(absolute_uri[i]) != tolower(absolute_base[i])) break;
#endif
if (absolute_uri[i] == '/') index = i + 1;
}
for (size_t i = index; i < absolute_uri.size(); ++i) {
Expand All @@ -118,10 +144,24 @@ namespace Sass {
for (size_t i = index; i < absolute_base.size(); ++i) {
stripped_base += absolute_base[i];
}

size_t left = 0;
size_t directories = 0;
for (size_t i = 0; i < stripped_base.size(); ++i) {
if (stripped_base[i] == '/') ++directories;
for (size_t right = 0; right < stripped_base.size(); ++right) {
if (stripped_base[right] == '/') {
if (stripped_base.substr(left, 2) != "..") {
++directories;
}
else if (directories > 1) {
--directories;
}
else {
directories = 0;
}
left = right + 1;
}
}

string result = "";
for (size_t i = 0; i < directories; ++i) {
result += "../";
Expand Down
3 changes: 2 additions & 1 deletion file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ namespace Sass {
string dir_name(string);
string join_paths(string, string);
bool is_absolute_path(const string& path);
string make_canonical_path (string path);
string make_absolute_path(const string& path, const string& cwd);
string resolve_relative_path(const string& uri, const string& base, const string& cwd, const bool recurse=false);
string resolve_relative_path(const string& uri, const string& base, const string& cwd);
char* resolve_and_load(string path, string& real_path);
char* read_file(string path);
}
Expand Down
4 changes: 4 additions & 0 deletions sass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ extern "C" {
c_ctx->image_path :
"")

.output_path (c_ctx->output_path ?
c_ctx->output_path :
"")

.include_paths_c_str (c_ctx->include_paths_string)
.include_paths_array (/*c_ctx->include_paths_array*/0)
.include_paths (vector<string>())
Expand Down
1 change: 1 addition & 0 deletions sass.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct Sass_Context {
int source_comments;
int source_maps;
const char* image_path;
const char* output_path;
const char* include_paths_string;
const char** include_paths_array;
int precision;
Expand Down
2 changes: 2 additions & 0 deletions sass_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ extern "C" {
int lastindex = input_path.find_last_of(".");
string output_path;
if (!c_ctx->output_path) {
if (input_path != "") {
output_path = (lastindex > -1 ? input_path.substr(0, lastindex) : input_path) + ".css";
}
}
else {
output_path = c_ctx->output_path;
Expand Down