Skip to content

Commit

Permalink
Implements embedding source contents in source maps
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Oct 29, 2014

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
1 parent 7e19bdc commit 66e1b4b
Showing 13 changed files with 339 additions and 73 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -56,9 +56,10 @@ SOURCES = \
to_string.cpp \
units.cpp \
utf8_string.cpp \
cencode.c \
util.cpp

OBJECTS = $(SOURCES:.cpp=.o)
OBJECTS = $(SOURCES:.cpp=.o) $(SOURCES:.c=.o)

DEBUG_LVL ?= NONE

@@ -81,7 +82,7 @@ libsass.a: $(OBJECTS)
libsass.so: $(OBJECTS)
$(CXX) -shared $(LDFLAGS) -o $@ $(OBJECTS)

%.o: %.cpp
%.o: %.cpp %.c
$(CXX) $(CXXFLAGS) -c -o $@ $<

%: %.o libsass.a
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ libsass_la_SOURCES = \
to_string.cpp \
units.cpp \
utf8_string.cpp \
cencode.c \
util.cpp

libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
32 changes: 32 additions & 0 deletions b64/cencode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/

#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H

typedef enum
{
step_A, step_B, step_C
} base64_encodestep;

typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;

void base64_init_encodestate(base64_encodestate* state_in);

char base64_encode_value(char value_in);

int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);

int base64_encode_blockend(char* code_out, base64_encodestate* state_in);

#endif /* BASE64_CENCODE_H */

77 changes: 77 additions & 0 deletions b64/encode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// :mode=c++:
/*
encode.h - c++ wrapper for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_ENCODE_H
#define BASE64_ENCODE_H

#include <iostream>

namespace base64
{
extern "C"
{
#include "cencode.h"
}

struct encoder
{
base64_encodestate _state;
int _buffersize;

encoder(int buffersize_in = BUFFERSIZE)
: _buffersize(buffersize_in)
{}

int encode(char value_in)
{
return base64_encode_value(value_in);
}

int encode(const char* code_in, const int length_in, char* plaintext_out)
{
return base64_encode_block(code_in, length_in, plaintext_out, &_state);
}

int encode_end(char* plaintext_out)
{
return base64_encode_blockend(plaintext_out, &_state);
}

void encode(std::istream& istream_in, std::ostream& ostream_in)
{
base64_init_encodestate(&_state);
//
const int N = _buffersize;
char* plaintext = new char[N];
char* code = new char[2*N];
int plainlength;
int codelength;

do
{
istream_in.read(plaintext, N);
plainlength = istream_in.gcount();
//
codelength = encode(plaintext, plainlength, code);
ostream_in.write(code, codelength);
}
while (istream_in.good() && plainlength > 0);

codelength = encode_end(code);
ostream_in.write(code, codelength);
//
base64_init_encodestate(&_state);

delete [] code;
delete [] plaintext;
}
};

} // namespace base64

#endif // BASE64_ENCODE_H

109 changes: 109 additions & 0 deletions cencode.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/

#include "b64/cencode.h"

const int CHARS_PER_LINE = 72;

void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}

char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}

int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;

result = state_in->result;

switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);

++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
state_in->stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}

int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;

switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
*codechar++ = '\n';

return codechar - code_out;
}

59 changes: 34 additions & 25 deletions context.cpp
Original file line number Diff line number Diff line change
@@ -58,13 +58,15 @@ namespace Sass {
source_comments (initializers.source_comments()),
output_style (initializers.output_style()),
source_map_file (make_canonical_path(initializers.source_map_file())),
source_map_embed (initializers.source_map_embed()),
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()),
names_to_colors (map<string, Color*>()),
colors_to_names (map<int, string>()),
precision (initializers.precision()),
subset_map (Subset_Map<string, pair<Complex_Selector*, Compound_Selector*> >()),
_skip_source_map_update (initializers._skip_source_map_update())
_skip_source_map_update (initializers._skip_source_map_update()),
subset_map (Subset_Map<string, pair<Complex_Selector*, Compound_Selector*> >())
{
cwd = get_cwd();

@@ -83,7 +85,10 @@ namespace Sass {
}

Context::~Context()
{ for (size_t i = 0; i < sources.size(); ++i) delete[] sources[i]; }
{
// everything that gets put into sources will be freed by us
for (size_t i = 0; i < sources.size(); ++i) delete[] sources[i];
}

void Context::setup_color_map()
{
@@ -145,6 +150,15 @@ namespace Sass {
// }
}

void Context::add_source(const string& load_path, const string& abs_path, const char* contents)
{
sources.push_back(contents);
included_files.push_back(abs_path);
queue.push_back(make_pair(load_path, contents));
source_map.source_index.push_back(sources.size() - 1);
include_links.push_back(resolve_relative_path(abs_path, source_map_file, cwd));
}

string Context::add_file(string path)
{
using namespace File;
@@ -153,14 +167,10 @@ namespace Sass {
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);
if (style_sheets.count(full_path)) return full_path;
contents = resolve_and_load(full_path, real_path);
if (contents) {
sources.push_back(contents);
included_files.push_back(real_path);
queue.push_back(make_pair(full_path, contents));
source_map.files.push_back(resolve_relative_path(real_path, source_map_file, cwd));
add_source(full_path, real_path, contents);
style_sheets[full_path] = 0;
return full_path;
}
@@ -178,10 +188,7 @@ namespace Sass {
if (style_sheets.count(full_path)) return full_path;
contents = resolve_and_load(full_path, real_path);
if (contents) {
sources.push_back(contents);
included_files.push_back(real_path);
queue.push_back(make_pair(full_path, contents));
source_map.files.push_back(resolve_relative_path(real_path, source_map_file, cwd));
add_source(full_path, real_path, contents);
style_sheets[full_path] = 0;
return full_path;
}
@@ -190,10 +197,7 @@ namespace Sass {
if (style_sheets.count(full_path)) return full_path;
contents = resolve_and_load(full_path, real_path);
if (contents) {
sources.push_back(contents);
included_files.push_back(real_path);
queue.push_back(make_pair(full_path, contents));
source_map.files.push_back(resolve_relative_path(real_path, source_map_file, cwd));
add_source(full_path, real_path, contents);
style_sheets[full_path] = 0;
return full_path;
}
@@ -267,14 +271,23 @@ namespace Sass {

string Context::format_source_mapping_url(const string& file) const
{
return "/*# sourceMappingURL=" + resolve_relative_path(file, output_path, cwd) + " */";
string url = resolve_relative_path(file, output_path, cwd);
if (source_map_embed) {
base64::encoder E;
istringstream is( sources[0] );
ostringstream buffer;
E.encode(is, buffer);
url = "data:text/css;base64," + buffer.str();
url.erase(url.size() - 1);
}
return "/*# sourceMappingURL=" + url + " */";
}

char* Context::generate_source_map()
{
if (source_map_file == "") return 0;
char* result = 0;
string map = source_map.generate_source_map();
string map = source_map.generate_source_map(*this);
result = copy_c_str(map.c_str());
return result;
}
@@ -288,14 +301,10 @@ namespace Sass {
queue.clear();
if(is_indented_syntax_src) {
char * contents = sass2scss(source_c_str, SASS2SCSS_PRETTIFY_1);
queue.push_back(make_pair(input_path, contents));
source_map.files.push_back(input_path);
char * compiled = compile_file();
delete[] contents;
return compiled;
add_source(input_path, input_path, contents);
return compile_file();
}
queue.push_back(make_pair(input_path, source_c_str));
source_map.files.push_back(input_path);
add_source(input_path, input_path, strdup(source_c_str));
return compile_file();
}

Loading

0 comments on commit 66e1b4b

Please sign in to comment.