From 21facf0a2ff04e8078a18e5d82f01c1a89a1887a Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Mon, 23 Mar 2015 21:48:50 +0100 Subject: [PATCH 1/3] Implement new output options for tool --- Build.PL | 1 + bin/psass.pl | 10 ++++++++-- lib/CSS/Sass.xs | 6 ++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Build.PL b/Build.PL index 68ceccf..ad4489e 100644 --- a/Build.PL +++ b/Build.PL @@ -211,6 +211,7 @@ my %config = ( extend.cpp file.cpp output.cpp parser.cpp prelexer.cpp emitter.cpp position.cpp sass.cpp sass_interface.cpp sass_functions.cpp sass_values.cpp sass_context.cpp source_map.cpp to_c.cpp to_string.cpp units.cpp utf8_string.cpp util.cpp cssize.cpp + contextualize_eval.cpp listize.cpp ) ] }, config => { ld => 'c++' }, # Need to link with a C++ linker since libsass is C++ (even though the .xs file is not) diff --git a/bin/psass.pl b/bin/psass.pl index 91f7a44..57a242a 100644 --- a/bin/psass.pl +++ b/bin/psass.pl @@ -18,8 +18,10 @@ use File::Slurp qw(write_file); # load constants from libsass +use CSS::Sass qw(SASS_STYLE_EXPANDED); use CSS::Sass qw(SASS_STYLE_NESTED); use CSS::Sass qw(SASS_STYLE_COMPRESSED); +use CSS::Sass qw(SASS_STYLE_COMPACT); use CSS::Sass::Watchdog qw(start_watchdog); #################################################################################################### @@ -84,8 +86,12 @@ sub version { # parse string to constant elsif ($output_style =~ m/^n/i) { $output_style = SASS_STYLE_NESTED } -elsif ($output_style =~ m/^c/i) +elsif ($output_style =~ m/^compa/i) +{ $output_style = SASS_STYLE_COMPACT } +elsif ($output_style =~ m/^compr/i) { $output_style = SASS_STYLE_COMPRESSED } +elsif ($output_style =~ m/^e/i) +{ $output_style = SASS_STYLE_EXPANDED } # die with message if style is unknown else { die "unknown output style: $output_style" } @@ -197,7 +203,7 @@ =head1 SYNOPSIS -w, --watch start watchdog mode -p, --precision precision for float output -o, --output-file=file output file to write result to - -t, --output-style=style output style [nested|compressed] + -t, --output-style=style output style [expanded|nested|compressed|compact] -L, --plugin-path=path plugin load path (repeatable) -I, --include-path=path sass include path (repeatable) -c, --source-comments enable source debug comments diff --git a/lib/CSS/Sass.xs b/lib/CSS/Sass.xs index 1087d80..dd1cf61 100644 --- a/lib/CSS/Sass.xs +++ b/lib/CSS/Sass.xs @@ -364,8 +364,8 @@ struct Sass_Import** sass_importer(const char* url, const char* prev, void* cook char* source = 0; char* mapjson = 0; char* error_msg = 0; - size_t error_line = 0; - size_t error_column = 0; + size_t error_line = -1; + size_t error_column = -1; // get the entry from the array // can either be another array or a path string @@ -579,6 +579,7 @@ void finalize_sass_context(struct Sass_Context* ctx, HV* RETVAL, SV* err) size_t error_column = sass_context_get_error_column(ctx); const char* error_text = sass_context_get_error_text(ctx); const char* error_message = sass_context_get_error_message(ctx); + const char* error_src = 0; // sass_context_get_error_src(ctx); const char* output_string = sass_context_get_output_string(ctx); const char* source_map_string = sass_context_get_source_map_string(ctx); char** included_files = sass_context_get_included_files(ctx); @@ -595,6 +596,7 @@ void finalize_sass_context(struct Sass_Context* ctx, HV* RETVAL, SV* err) hv_stores(RETVAL, "source_map_string", source_map_string ? newSVpv(source_map_string, 0) : newSV(0)); hv_stores(RETVAL, "error_line", SvOK(err) ? err : error_line ? newSViv(error_line) : newSViv(0)); hv_stores(RETVAL, "error_column", SvOK(err) ? err : error_column ? newSViv(error_column) : newSViv(0)); + hv_stores(RETVAL, "error_src", SvOK(err) ? err : error_src ? newSVpv(error_src, 0) : newSViv(0)); hv_stores(RETVAL, "error_text", SvOK(err) ? err : error_text ? newSVpv(error_text, 0) : newSV(0)); hv_stores(RETVAL, "error_message", SvOK(err) ? err : error_message ? newSVpv(error_message, 0) : newSV(0)); hv_stores(RETVAL, "error_json", SvOK(err) ? err : error_json ? newSVpv(error_json, 0) : newSV(0)); From e68673baefdc9ac0c83f2568d1372ff480660f1f Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Mon, 23 Mar 2015 22:29:03 +0100 Subject: [PATCH 2/3] Add indent and linefeed config options --- bin/psass.pl | 24 +++++++++++++++++++++++- lib/CSS/Sass.pm | 12 ++++++++++++ lib/CSS/Sass.xs | 9 ++++++++- libsass | 2 +- t/01_xs.t | 13 ++++++++++++- t/sass-spec | 2 +- 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/bin/psass.pl b/bin/psass.pl index 57a242a..fc92f77 100644 --- a/bin/psass.pl +++ b/bin/psass.pl @@ -62,11 +62,17 @@ sub version { my @plugin_paths; my @include_paths; +# output styles +my $indent = " "; +my $linefeed = "auto"; + # get options GetOptions ( 'help|h' => sub { pod2usage(1); }, 'watch|w' => \ $watchdog, 'version|v' => \ &version, + 'indent=s' => \ $indent, + 'linefeed=s' => \ $linefeed, 'precision|p=s' => \ $precision, 'output-file|o=s' => \ $output_file, 'output-style|t=s' => \ $output_style, @@ -95,6 +101,18 @@ sub version { # die with message if style is unknown else { die "unknown output style: $output_style" } +# resolve linefeed options +if ($linefeed =~ m/^a/i) +{ $linefeed = undef; } +elsif ($linefeed =~ m/^w/i) +{ $linefeed = "\r\n"; } +elsif ($linefeed =~ m/^[u]/i) +{ $linefeed = "\n"; } +elsif ($linefeed =~ m/^[n]/i) +{ $linefeed = ""; } +# die with message if linefeed type is unknown +else { die "unknown linefeed type: $linefeed" } + # do we have output path in second arg? if (defined $ARGV[1] && $ARGV[1] ne '-') { $output_file = $ARGV[1]; } @@ -108,6 +126,8 @@ () { return ( dont_die => $watchdog, + indent => $indent, + linefeed => $linefeed, precision => $precision, output_path => $output_file, output_style => $output_style, @@ -201,7 +221,9 @@ =head1 SYNOPSIS -v, --version print version -h, --help print this help -w, --watch start watchdog mode - -p, --precision precision for float output + -p, --precision=int precision for float output + --indent=string set indent string used for output + --linefeed=type linefeed used for output [auto|unix|win|none] -o, --output-file=file output file to write result to -t, --output-style=style output style [expanded|nested|compressed|compact] -L, --plugin-path=path plugin load path (repeatable) diff --git a/lib/CSS/Sass.pm b/lib/CSS/Sass.pm index 326703e..8c1b55f 100644 --- a/lib/CSS/Sass.pm +++ b/lib/CSS/Sass.pm @@ -283,6 +283,18 @@ C, but never both. The default is C. Set to C to eliminate all whitespace (for your production CSS). +=item C + +Set the floating point precision for output. + +=item C + +Set the linefeed string used for css output. + +=item C + +Set the indentation string used for css output. + =item C Set to C to get extra comments in the output, indicating what input diff --git a/lib/CSS/Sass.xs b/lib/CSS/Sass.xs index dd1cf61..6236298 100644 --- a/lib/CSS/Sass.xs +++ b/lib/CSS/Sass.xs @@ -17,6 +17,7 @@ #include "sass2scss.h" #include "sass_context.h" +#define isSafeSv(sv) sv && SvOK(*sv) #define Constant(c) newCONSTSUB(stash, #c, newSViv(c)) #undef free @@ -513,6 +514,8 @@ SV* init_sass_options(struct Sass_Options* sass_options, HV* perl_options) SV** include_paths_sv = hv_fetchs(perl_options, "include_paths", false); SV** plugin_paths_sv = hv_fetchs(perl_options, "plugin_paths", false); SV** precision_sv = hv_fetchs(perl_options, "precision", false); + SV** linefeed_sv = hv_fetchs(perl_options, "linefeed", false); + SV** indent_sv = hv_fetchs(perl_options, "indent", false); SV** source_map_root_sv = hv_fetchs(perl_options, "source_map_root", false); SV** source_map_file_sv = hv_fetchs(perl_options, "source_map_file", false); SV** sass_functions_sv = hv_fetchs(perl_options, "sass_functions", false); @@ -528,10 +531,14 @@ SV* init_sass_options(struct Sass_Options* sass_options, HV* perl_options) if (source_map_embed_sv) sass_option_set_source_map_embed (sass_options, SvTRUE(*source_map_embed_sv)); if (include_paths_sv) sass_option_set_include_path (sass_options, safe_svpv(*include_paths_sv, "")); if (plugin_paths_sv) sass_option_set_plugin_path (sass_options, safe_svpv(*plugin_paths_sv, "")); - if (precision_sv) sass_option_set_precision (sass_options, SvUV(*precision_sv)); if (source_map_root_sv) sass_option_set_source_map_root (sass_options, safe_svpv(*source_map_root_sv, "")); if (source_map_file_sv) sass_option_set_source_map_file (sass_options, safe_svpv(*source_map_file_sv, "")); + // do not set anything if the option is set to undef + if (isSafeSv(indent_sv)) sass_option_set_indent (sass_options, SvPV_nolen(*indent_sv)); + if (isSafeSv(linefeed_sv)) sass_option_set_linefeed (sass_options, SvPV_nolen(*linefeed_sv)); + if (isSafeSv(precision_sv)) sass_option_set_precision (sass_options, SvUV(*precision_sv)); + if (importer_sv) { sass_option_set_importer(sass_options, sass_make_importer(sass_importer, *importer_sv)); } if (sass_functions_sv) { diff --git a/libsass b/libsass index dea27e5..948854a 160000 --- a/libsass +++ b/libsass @@ -1 +1 @@ -Subproject commit dea27e5e3cc61a0d9f00ffa3f598a1080c6502d6 +Subproject commit 948854a3169dabc6a82349f4e15f7e910a704d8c diff --git a/t/01_xs.t b/t/01_xs.t index f77769f..599522a 100644 --- a/t/01_xs.t +++ b/t/01_xs.t @@ -6,7 +6,7 @@ use strict; use warnings; -use Test::More tests => 40; +use Test::More tests => 46; BEGIN { use_ok('CSS::Sass') }; my $r; @@ -53,6 +53,17 @@ $r = CSS::Sass::compile_sass("\n.valid {\n color: red; }", { source_comments => is ($r->{error_status}, 0, "source_comments=>[] no error_status and doesn't crash"); is ($r->{error_message}, undef, "source_comments=>[] error_message is undef"); +# $options->{indent} +$r = CSS::Sass::compile_sass('foo { color: red; }', { indent => '-äöü-' }); +is ($r->{error_status}, 0, "import no error_status"); +is ($r->{error_message}, undef, "import error_message is undef"); +like ($r->{output_string}, qr/foo {\r?\n-äöü-color: red; }/, "custom indent"); + +# $options->{linefeed} +$r = CSS::Sass::compile_sass('foo { color: red; }', { linefeed => "-äöü-\r" }); +is ($r->{error_status}, 0, "import no error_status"); +is ($r->{error_message}, undef, "import error_message is undef"); +like ($r->{output_string}, qr/foo {-äöü-\r color: red; }/, "custom linefeed"); # $options->{include_paths} $r = CSS::Sass::compile_sass('@import "colors"; .valid { color: $red; }', { }); diff --git a/t/sass-spec b/t/sass-spec index 4b5b1cf..9391485 160000 --- a/t/sass-spec +++ b/t/sass-spec @@ -1 +1 @@ -Subproject commit 4b5b1cf3ae940964a52a1b8f06560f7a3aaf6d16 +Subproject commit 9391485cd8edd4ae067e1574969a60eb1c61447a From 64559082d523fd9bf9cafac5a4a86f724be73d58 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Sat, 28 Mar 2015 14:08:13 +0100 Subject: [PATCH 3/3] Update for libsass 3.2.0 release --- Build.PL | 4 +- Changes | 12 +++++ bin/psass.pl | 16 +++++- lib/CSS/Sass.pm | 109 ++++++++++++++++++++++++++------------- lib/CSS/Sass.xs | 104 +++++++++++++++++++++++++++++++++---- lib/CSS/Sass/Watchdog.pm | 2 +- libsass | 2 +- t/01_xs.t | 1 - t/02_perl.t | 11 +++- t/04_xs_value_types.t | 4 +- t/07_custom_importer.t | 27 ++++++++-- t/99_sass_specs.t | 39 ++++++++++---- t/sass-spec | 2 +- 13 files changed, 265 insertions(+), 68 deletions(-) diff --git a/Build.PL b/Build.PL index ad4489e..bea9589 100644 --- a/Build.PL +++ b/Build.PL @@ -211,14 +211,12 @@ my %config = ( extend.cpp file.cpp output.cpp parser.cpp prelexer.cpp emitter.cpp position.cpp sass.cpp sass_interface.cpp sass_functions.cpp sass_values.cpp sass_context.cpp source_map.cpp to_c.cpp to_string.cpp units.cpp utf8_string.cpp util.cpp cssize.cpp - contextualize_eval.cpp listize.cpp + contextualize_eval.cpp listize.cpp lexer.cpp ) ] }, config => { ld => 'c++' }, # Need to link with a C++ linker since libsass is C++ (even though the .xs file is not) ); -$config{'requires'}->{'Win32::Unicode::File'} = 0 if ($^O eq "MSWin32"); - my $builder = Module::Build::Custom->new(%config); $builder->create_build_script(); diff --git a/Changes b/Changes index 9afce58..bba3495 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,15 @@ +CSS::Sass (3.2.0) + + * Update to latest libsass release (3.2.0) + * Add options for remaining output styles + * Add indent and linefeed config options + * Add benchmark option to command line tool + * Add watcher option to recompile on changes + * Refactor for libsass context option initializing + * Expose `resolve_file` function on the C-API + * Add experimental API for multiple importers + * Add highly experimental API for custom headers + CSS::Sass (3.1.0) * Updates to latest libsass version (3.1.0) diff --git a/bin/psass.pl b/bin/psass.pl index fc92f77..081f4af 100644 --- a/bin/psass.pl +++ b/bin/psass.pl @@ -41,6 +41,7 @@ # init options my $watchdog; +my $benchmark; my $precision; my $output_file; my $output_style; @@ -69,8 +70,9 @@ sub version { # get options GetOptions ( 'help|h' => sub { pod2usage(1); }, - 'watch|w' => \ $watchdog, + 'watch|w!' => \ $watchdog, 'version|v' => \ &version, + 'benchmark|b!' => \ $benchmark, 'indent=s' => \ $indent, 'linefeed=s' => \ $linefeed, 'precision|p=s' => \ $precision, @@ -117,6 +119,9 @@ sub version { if (defined $ARGV[1] && $ARGV[1] ne '-') { $output_file = $ARGV[1]; } +# check if the benchmark module is available +if ($benchmark && ! eval "use Benchmark; 1" ) +{ die "Error loading Benchmark module\n", $@; } #################################################################################################### # get sass standard option list @@ -154,6 +159,9 @@ () # variables my ($css, $err, $stats); + # get benchmark stamp before compiling + my $t0 = $benchmark ? Benchmark->new : 0; + # open filehandle if path is given if (defined $ARGV[0] && $ARGV[0] ne '-') { @@ -169,6 +177,11 @@ () ); } + # get benchmark stamp after compiling + my $t1 = $benchmark ? Benchmark->new : 0; + # only print benchmark result when module is available + if ($benchmark) { print timestr(timediff($t1, $t0)), "\n"; } + # process return status values if (defined $css) { @@ -233,6 +246,7 @@ =head1 SYNOPSIS -s, --source-map-contents include original contents -m, --source-map-file=file create and write source-map to file --no-source-map-url omit sourceMappingUrl from output + --benchmark print benchmark for compilation time =head1 OPTIONS diff --git a/lib/CSS/Sass.pm b/lib/CSS/Sass.pm index 8c1b55f..bac92d9 100644 --- a/lib/CSS/Sass.pm +++ b/lib/CSS/Sass.pm @@ -56,7 +56,8 @@ require XSLoader; XSLoader::load('CSS::Sass', $VERSION); require CSS::Sass::Type; -sub new { +sub new +{ my ($class, %options) = @_; # Ensure initial sub structures on options $options{plugin_paths} = [] unless exists $options{plugin_paths}; @@ -66,56 +67,91 @@ sub new { bless { options => \%options }, $class; }; -sub options { +sub options +{ shift->{options} } -sub last_error { +sub last_error +{ my ($self) = @_; $self->{last_error} } -sub sass_compile { +my @path_types = ( + 'plugin_paths', + 'include_paths' +); + +# directory delimiter according to platform +my $dir_delim = $^O eq 'MSWin32' ? ';' : ':'; + +# normalize option hash +my $normalize_options = sub +{ + my ($options) = @_; + # gather all functions + # they need to be hashes + my %functions = + ( + %{$options->{'functions'} || {}}, + %{$options->{'sass_functions'} || {}} + ); + # create functions array + # help the c code a little + my @functions = map { [ + $_, $functions{$_} + ] } keys %functions; + # gather all importers + # they need to be arrays + my @importers = + map { + ref($_) eq "ARRAY" ? + $_ : [ $_, 0 ]; + } + grep { defined } + ( + $options->{'importer'}, + @{$options->{'importers'} || []}, + @{$options->{'sass_importers'} || []} + ); + # gather all paths strings + foreach my $type (@path_types) + { + $options->{$type} = join $dir_delim, + map { split $dir_delim, $_ } + @{$options->{$type} || []}; + } + # now normalize the original hash + $options->{'functions'} = \@functions; + $options->{'importers'} = \@importers; + # remove importer from options + # it is now included in importers + delete $options->{'importer'}; + # return pointer + return $options; +}; + +sub sass_compile +{ my ($sass_code, %options) = @_; no warnings 'uninitialized'; - my $r = compile_sass($sass_code, { %options, - # Override sass_functions with the arrayref of arrayrefs that the XS expects. - !$options{sass_functions} ? () - : (sass_functions => [ map { [ $_ => $options{sass_functions}->{$_} ] - } keys %{$options{sass_functions}} ]), - # Override include_paths with a ':' separated list - !$options{include_paths} ? () - : (include_paths => join($^O eq 'MSWin32' ? ';' : ':', - @{$options{include_paths}})), - # Override plugin_paths with a ':' separated list - !$options{plugin_paths} ? () - : (plugin_paths => join($^O eq 'MSWin32' ? ';' : ':', - @{$options{plugin_paths}})), - }); + $normalize_options->(\%options); + my $r = compile_sass($sass_code, \%options); wantarray ? ($r->{output_string}, $r->{error_message}, $r) : $r->{output_string} } -sub sass_compile_file { +sub sass_compile_file +{ my ($input_path, %options) = @_; no warnings 'uninitialized'; - my $r = compile_sass_file($input_path, { %options, - # Override sass_functions with the arrayref of arrayrefs that the XS expects. - !$options{sass_functions} ? () - : (sass_functions => [ map { [ $_ => $options{sass_functions}->{$_} ] - } keys %{$options{sass_functions}} ]), - # Override include_paths with a ':' separated list - !$options{include_paths} ? () - : (include_paths => join($^O eq 'MSWin32' ? ';' : ':', - @{$options{include_paths}})), - # Override plugin_paths with a ':' separated list - !$options{plugin_paths} ? () - : (plugin_paths => join($^O eq 'MSWin32' ? ';' : ':', - @{$options{plugin_paths}})), - }); + $normalize_options->(\%options); + my $r = compile_sass_file($input_path, \%options); wantarray ? ($r->{output_string}, $r->{error_message}, $r) : $r->{output_string} } -sub compile { +sub compile +{ my ($self, $sass_code) = @_; my ($compiled, $stats); ($compiled, $self->{last_error}, $stats) = sass_compile($sass_code, %{$self->options}); @@ -123,7 +159,8 @@ sub compile { wantarray ? ($compiled, $stats) : $compiled } -sub compile_file { +sub compile_file +{ my ($self, $sass_file) = @_; my ($compiled, $stats); ($compiled, $self->{last_error}, $stats) = sass_compile_file($sass_file, %{$self->options}); @@ -494,7 +531,7 @@ L =head1 AUTHOR -David Caldwell Edavid@porkrind.orgE +David Caldwell Edavid@porkrind.orgE Marcel Greter Eperl-libsass@ocbnet.chE =head1 LICENSE diff --git a/lib/CSS/Sass.xs b/lib/CSS/Sass.xs index 6236298..5475f34 100644 --- a/lib/CSS/Sass.xs +++ b/lib/CSS/Sass.xs @@ -14,8 +14,11 @@ #include "ppport.h" +#include "sass.h" #include "sass2scss.h" +#include "sass_values.h" #include "sass_context.h" +#include "sass_functions.h" #define isSafeSv(sv) sv && SvOK(*sv) #define Constant(c) newCONSTSUB(stash, #c, newSViv(c)) @@ -293,7 +296,7 @@ SV* sass_value_to_sv(union Sass_Value* val) } -struct Sass_Import** sass_importer(const char* url, const char* prev, void* cookie) +Sass_Import_List sass_importer(const char* cur_path, Sass_Importer_Entry cb, struct Sass_Compiler* comp) { dSP; @@ -305,9 +308,13 @@ struct Sass_Import** sass_importer(const char* url, const char* prev, void* cook ENTER; SAVETMPS; + void* cookie = sass_importer_get_cookie(cb); + struct Sass_Import* previous = sass_compiler_get_last_import(comp); + const char* prev_path = sass_import_get_path(previous); + PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(url, 0))); - XPUSHs(sv_2mortal(newSVpv(prev, 0))); + XPUSHs(sv_2mortal(newSVpv(cur_path, 0))); + XPUSHs(sv_2mortal(newSVpv(prev_path, 0))); PUTBACK; // call the static function by soft name reference @@ -439,9 +446,8 @@ struct Sass_Import** sass_importer(const char* url, const char* prev, void* cook } - // we are called by libsass to dispatch to registered functions -union Sass_Value* call_sass_function(const union Sass_Value* s_args, void* cookie) +union Sass_Value* call_sass_function(const union Sass_Value* s_args, Sass_Function_Entry cb, struct Sass_Options* opts) { dSP; @@ -454,6 +460,8 @@ union Sass_Value* call_sass_function(const union Sass_Value* s_args, void* cooki ENTER; SAVETMPS; + void* cookie = sass_function_get_cookie(cb); + PUSHMARK(SP); for (i=0; i{error_status}, 0, "import no error_status"); is ($r->{error_message}, undef, "import error_message is undef"); like ($r->{output_string}, qr/0\.33333;/, "default float precision is 5"); -# has regression in https://github.com/sass/libsass/issues/364 $r = CSS::Sass::compile_sass('.valid { width: #{(1/3)}; }', { precision => 10 }); is ($r->{error_status}, 0, "import no error_status"); is ($r->{error_message}, undef, "import error_message is undef"); diff --git a/t/02_perl.t b/t/02_perl.t index df9be07..d19bad5 100644 --- a/t/02_perl.t +++ b/t/02_perl.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 39; +use Test::More tests => 41; BEGIN { use_ok('CSS::Sass', qw(:DEFAULT sass_compile sass_compile_file)) }; my $r; @@ -183,3 +183,12 @@ is ($err, undef, "custom precision works without error") like ($r, qr/padding\:0.3333333333\W/, "custom precision has correct output"); close($fh); + +# test quote and unquote helpers +my $quoted = CSS::Sass::quote("hello world"); +is ($quoted, "\"hello world\"", "test quote"); +my $unquoted = CSS::Sass::unquote($quoted); +is ($unquoted, "hello world", "test unquote"); + +# test file resolve helper +# die " hello [", CSS::Sass::resolve_file("bin/psass.pl"), "]"; diff --git a/t/04_xs_value_types.t b/t/04_xs_value_types.t index 27bae80..a70446b 100644 --- a/t/04_xs_value_types.t +++ b/t/04_xs_value_types.t @@ -375,11 +375,11 @@ is $css_str, "A{color:foo bar}\n", "function returned native string type"; $sass->options->{'sass_functions'}->{'var-pl-str-quote'} = sub { return "\"foo\\\"s\"" }; $css_str = $sass->compile('$str: var-pl-str-quote(); A { color: $str; }'); -is $css_str, "A{color:\"foo\\\"s\"}\n", "function returned native string type"; +is $css_str, "A{color:foo\"s}\n", "function returned native string type"; $sass->options->{'sass_functions'}->{'var-pl-str-quote'} = sub { return "\'foo\\'s\'" }; $css_str = $sass->compile('$str: var-pl-str-quote(); A { color: $str; }'); -is $css_str, "A{color:\'foo\\\'s\'}\n", "function returned native string type"; +is $css_str, "A{color:foo\'s}\n", "function returned native string type"; ################################################################################ # test if functions get passed correct var structures diff --git a/t/07_custom_importer.t b/t/07_custom_importer.t index ed83bf2..e3abe6d 100644 --- a/t/07_custom_importer.t +++ b/t/07_custom_importer.t @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 28; +use Test::More tests => 30; BEGIN { use_ok('CSS::Sass') }; @@ -11,7 +11,26 @@ my ($r, $err, $stat); ($r, $err, $stat) = CSS::Sass::sass_compile('@import "http://www.host.dom/red";', source_map_file => "test.css.map", - importer => sub { + headers => [ + [sub { return [['header-02', 'div { b: .5; }']]; }, .5], + [sub { return [['header-03', 'div { c: .1; }']]; }, .1], + [sub { return [['header-01', 'div { @include mixme; }']]; }, .9], + [sub { return [['mixin-01', '@mixin mixme { a: .9; }']]; }, 1009], + ], + importers => [[sub { + + if ($_[0] eq "http://www.host.dom/red") { + is ($_[1], "stdin", "import parent[0]"); + return [["red.css", '@import "brown";']]; + } + if ($_[0] eq "green") { + is ($_[1], "red.css", "import parent[1]"); + return [['http://www.host.dom/green', '@import "yellow";']]; + } + is ($_[1], "http://www.host.dom/green", "import parent[2]"); + return [['http://www.host.dom/final', 'A { color: ' . $_[0] . '; }']]; # yellow + }, 10], [sub { + if ($_[0] eq "http://www.host.dom/red") { is ($_[1], "stdin", "import parent[0]"); return [["red.css", '@import "green";']]; @@ -22,9 +41,10 @@ my ($r, $err, $stat); } is ($_[1], "http://www.host.dom/green", "import parent[2]"); return [['http://www.host.dom/final', 'A { color: ' . $_[0] . '; }']]; # yellow - } + }, 25]] ); +like ($r, qr/a:\s*\.9;.*b:\s*\.5;.*c:\s*\.1;/s, "Custom header works"); like ($r, qr/color:\s*yellow;/, "Custom importer works"); is ($err, undef, "Custom importer returns no errors"); @@ -33,6 +53,7 @@ is ($stat->{'included_files'}->[0], "green", "included_files[0] has correct u is ($stat->{'included_files'}->[1], "http://www.host.dom/red", "included_files[1] has correct url"); is ($stat->{'included_files'}->[2], "yellow", "included_files[2] has correct url"); +is (scalar(@{$stat->{'included_files'}}), 3, "included_files has correct size"); ## from https://github.com/sass/libsass/pull/691#issuecomment-67130937 diff --git a/t/99_sass_specs.t b/t/99_sass_specs.t index 2d26e07..dad074c 100644 --- a/t/99_sass_specs.t +++ b/t/99_sass_specs.t @@ -105,6 +105,8 @@ sub clean_output ($) { } sub norm_output ($) { $_[0] =~ s/\r//g; + $_[0] =~ s/\s+([{,])/$1/g; + # $_[0] =~ s/#ff0/yellow/g; $_[0] =~ s/(?:\r?\n)+/\n/g; $_[0] =~ s/(?:\r?\n)+$/\n/g; } @@ -128,10 +130,10 @@ foreach my $test (@tests) if ($redo_sass) { unless (-f join("/", $test->[0], 'redo.skip')) { - push @cmds, ["C:\\Ruby\\193\\bin\\sass --unix-newlines --sourcemap=none -t nested -C \"$input_file\" \"$output_nested\"", $input_file] if ($do_nested); - push @cmds, ["C:\\Ruby\\193\\bin\\sass --unix-newlines --sourcemap=none -t compact -C \"$input_file\" \"$output_compact\"", $input_file] if ($do_compact); - push @cmds, ["C:\\Ruby\\193\\bin\\sass --unix-newlines --sourcemap=none -t expanded -C \"$input_file\" \"$output_expanded\"", $input_file] if ($do_expanded); - push @cmds, ["C:\\Ruby\\193\\bin\\sass --unix-newlines --sourcemap=none -t compressed -C \"$input_file\" \"$output_compressed\"", $input_file] if ($do_compressed); + push @cmds, ["C:\\Ruby\\193\\bin\\sass -E utf-8 --unix-newlines --sourcemap=none -t nested -C \"$input_file\" \"$output_nested\"", $input_file] if ($do_nested); + push @cmds, ["C:\\Ruby\\193\\bin\\sass -E utf-8 --unix-newlines --sourcemap=none -t compact -C \"$input_file\" \"$output_compact\"", $input_file] if ($do_compact); + push @cmds, ["C:\\Ruby\\193\\bin\\sass -E utf-8 --unix-newlines --sourcemap=none -t expanded -C \"$input_file\" \"$output_expanded\"", $input_file] if ($do_expanded); + push @cmds, ["C:\\Ruby\\193\\bin\\sass -E utf-8 --unix-newlines --sourcemap=none -t compressed -C \"$input_file\" \"$output_compressed\"", $input_file] if ($do_compressed); } else { SKIP: { skip("dont redo expected_output.css", 1) if ($do_nested); } SKIP: { skip("dont redo expected.compact.css", 1) if ($do_compact); } @@ -176,6 +178,12 @@ while (scalar(@running)) { } @running; } +# check if the benchmark module is available +my $benchmark = eval "use Benchmark; 1" ; + +# get benchmark stamp before compiling +my $t0 = $benchmark ? Benchmark->new : 0; + foreach my $test (@tests) { @@ -246,6 +254,7 @@ foreach my $test (@tests) norm_output $css_nested; norm_output $sass_nested; norm_output $css_compact; norm_output $sass_compact; norm_output $css_expanded; norm_output $sass_expanded; + norm_output $css_compressed; norm_output $sass_compressed; unless ($input_file =~ m/todo/) { @@ -275,31 +284,43 @@ foreach my $test (@tests) else { + # warn "doing test spec " << $test->[0], "\n"; + my $surprise = sub { fail("suprprise in: " . $_[0]); push @surprises, [ @_ ]; }; if ($css_nested eq $sass_nested) - { $surprise->(join("/", $test->[0], 'expected.nested') . " unexpectely works"); } + { $surprise->(join("/", $test->[0], 'expected.nested')); } else { pass(join("/", $test->[0], 'expected.nested') . " is still failing"); } if ($css_compact eq $sass_compact) - { $surprise->(join("/", $test->[0], 'expected.compact') . " unexpectely works"); } + { $surprise->(join("/", $test->[0], 'expected.compact')); } else { pass(join("/", $test->[0], 'expected.compact') . " is still failing"); } if ($css_expanded eq $sass_expanded) - { $surprise->(join("/", $test->[0], 'expected.expanded') . " unexpectely works"); } + { $surprise->(join("/", $test->[0], 'expected.expanded')); } else { pass(join("/", $test->[0], 'expected.expanded') . " is still failing"); } if ($css_compressed eq $sass_compressed) - { $surprise->(join("/", $test->[0], 'expected.compressed') . " unexpectely works") } + { $surprise->(join("/", $test->[0], 'expected.compressed')) } else { pass(join("/", $test->[0], 'expected.compressed') . " is still failing"); } } } + +# get benchmark stamp after compiling +my $t1 = $benchmark ? Benchmark->new : 0; + END { + + # only print benchmark result when module is available + if ($benchmark) { warn "\nin ", timestr(timediff($t1, $t0)), "\n"; } + foreach my $surprise (@surprises) { - printf STDERR "surprise: %s\n", $surprise->[0]; + my $file = $surprise->[0]; + $file =~ s/\//\\/g if $^O eq 'MSWin32'; + printf STDERR "at %s\n", $file; } } diff --git a/t/sass-spec b/t/sass-spec index 9391485..b232b0f 160000 --- a/t/sass-spec +++ b/t/sass-spec @@ -1 +1 @@ -Subproject commit 9391485cd8edd4ae067e1574969a60eb1c61447a +Subproject commit b232b0fa720a6c2d583ae4ad71e50d18c277eaa6