sassc 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -3
  3. data/ext/libsass/.gitignore +3 -0
  4. data/ext/libsass/.travis.yml +1 -1
  5. data/ext/libsass/GNUmakefile.am +7 -7
  6. data/ext/libsass/Makefile +7 -4
  7. data/ext/libsass/Makefile.conf +0 -1
  8. data/ext/libsass/appveyor.yml +6 -2
  9. data/ext/libsass/docs/api-context.md +4 -4
  10. data/ext/libsass/docs/api-doc.md +29 -11
  11. data/ext/libsass/docs/api-importer-example.md +5 -5
  12. data/ext/libsass/docs/build-on-windows.md +1 -1
  13. data/ext/libsass/include/sass/base.h +10 -0
  14. data/ext/libsass/include/sass/version.h +4 -0
  15. data/ext/libsass/include/sass/version.h.in +4 -0
  16. data/ext/libsass/include/sass2scss.h +1 -1
  17. data/ext/libsass/script/ci-build-libsass +15 -3
  18. data/ext/libsass/src/ast.cpp +161 -6
  19. data/ext/libsass/src/ast.hpp +71 -44
  20. data/ext/libsass/src/ast_factory.hpp +1 -1
  21. data/ext/libsass/src/ast_fwd_decl.hpp +2 -2
  22. data/ext/libsass/src/constants.cpp +2 -4
  23. data/ext/libsass/src/constants.hpp +3 -4
  24. data/ext/libsass/src/context.cpp +16 -17
  25. data/ext/libsass/src/context.hpp +2 -2
  26. data/ext/libsass/src/cssize.cpp +19 -8
  27. data/ext/libsass/src/cssize.hpp +5 -2
  28. data/ext/libsass/src/debugger.hpp +6 -3
  29. data/ext/libsass/src/emitter.cpp +1 -1
  30. data/ext/libsass/src/environment.cpp +1 -1
  31. data/ext/libsass/src/eval.cpp +42 -14
  32. data/ext/libsass/src/eval.hpp +1 -1
  33. data/ext/libsass/src/expand.cpp +24 -8
  34. data/ext/libsass/src/expand.hpp +2 -1
  35. data/ext/libsass/src/extend.cpp +55 -15
  36. data/ext/libsass/src/extend.hpp +5 -1
  37. data/ext/libsass/src/functions.cpp +10 -5
  38. data/ext/libsass/src/inspect.cpp +25 -19
  39. data/ext/libsass/src/inspect.hpp +2 -2
  40. data/ext/libsass/src/json.cpp +20 -9
  41. data/ext/libsass/src/json.hpp +5 -5
  42. data/ext/libsass/src/lexer.cpp +4 -1
  43. data/ext/libsass/src/lexer.hpp +21 -0
  44. data/ext/libsass/src/listize.cpp +2 -1
  45. data/ext/libsass/src/operation.hpp +4 -4
  46. data/ext/libsass/src/output.cpp +1 -1
  47. data/ext/libsass/src/output.hpp +1 -1
  48. data/ext/libsass/src/parser.cpp +189 -90
  49. data/ext/libsass/src/parser.hpp +42 -2
  50. data/ext/libsass/src/prelexer.cpp +474 -7
  51. data/ext/libsass/src/prelexer.hpp +15 -2
  52. data/ext/libsass/src/remove_placeholders.cpp +5 -5
  53. data/ext/libsass/src/remove_placeholders.hpp +3 -2
  54. data/ext/libsass/src/sass.cpp +33 -3
  55. data/ext/libsass/src/sass2scss.cpp +7 -0
  56. data/ext/libsass/src/sass_context.cpp +32 -62
  57. data/ext/libsass/src/sass_functions.cpp +3 -3
  58. data/ext/libsass/src/sass_values.cpp +5 -5
  59. data/ext/libsass/src/utf8/unchecked.h +16 -16
  60. data/ext/libsass/src/util.cpp +51 -30
  61. data/ext/libsass/src/util.hpp +6 -1
  62. data/ext/libsass/win/libsass.targets +0 -2
  63. data/ext/libsass/win/libsass.vcxproj.filters +0 -6
  64. data/lib/sassc/engine.rb +4 -1
  65. data/lib/sassc/error.rb +23 -1
  66. data/lib/sassc/version.rb +1 -1
  67. data/test/error_test.rb +27 -0
  68. data/test/native_test.rb +1 -1
  69. metadata +5 -5
  70. data/ext/libsass/include/sass/interface.h +0 -105
  71. data/ext/libsass/src/sass_interface.cpp +0 -215
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4aafee4a5710a8ea851a5702e8a0cc565072af21
4
- data.tar.gz: 1971d63aab1fabbbf3354dcf3f4c722c37884e43
3
+ metadata.gz: b52db28344dd1103c3d9c82150b7670f31e040d6
4
+ data.tar.gz: 0ce1622190528f513b5460017c4033da8932fb4d
5
5
  SHA512:
6
- metadata.gz: da80b6d5c99d360c2a015b30a26758eb58823e44082532b058c159e36f0bffa2b5b0ebc95da828274874e1ed6182b9d9b2cfbff27cc22cc9d1c8b9a9c3523743
7
- data.tar.gz: 3f8022f8d73ea4ab6cced6b8bcb7c39a47ae1039c2919777d27f9bce7e7a9af763834bd05196c40fe1c5322c6ea5523d99836c062e72fa6a41604fa0d963adb7
6
+ metadata.gz: ca2d6b6f548d6c73c419dc6ba94c3d0a20fbed1af6a95862a8ff3c68fb55e583c9a51f33b5122e353d6514d9998fad8a388131a9b74b3a9d06433eacae5461e6
7
+ data.tar.gz: 06e7cb73e2e52f756aa0980c449b8f32d6f10c6be9a9e8a4e223d9f34603221e2859ae80a41eca0e9066e0d9e8cc0848ab259b0c03a0f20dd927542b50609d7a
data/README.md CHANGED
@@ -6,12 +6,36 @@ This gem combines the speed of `libsass`, the [Sass C implementation](https://gi
6
6
 
7
7
  ### libsass Version
8
8
 
9
- [3.3.3](https://github.com/sass/libsass/releases/tag/3.3.3)
9
+ [3.3.6](https://github.com/sass/libsass/releases/tag/3.3.6)
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'sassc'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ ```bash
22
+ bundle
23
+ ```
24
+
25
+ Or install it yourself as:
26
+
27
+ ```bash
28
+ gem install sassc
29
+ ```
10
30
 
11
31
  ## Usage
12
32
 
13
33
  This library utilizes `libsass` to allow you to compile SCSS or SASS syntax
14
- to CSS. To compile, use a `SassC::Engine`.
34
+ to CSS. To compile, use a `SassC::Engine`, e.g.:
35
+
36
+ ```ruby
37
+ SassC::Engine.new(sass, style: :compressed).render
38
+ ```
15
39
 
16
40
  **Note**: If you want to use this library with Rails/Sprockets, check out
17
41
  [sassc-rails](https://github.com/bolandrm/sassc-rails).
@@ -25,8 +49,11 @@ and [awesome contributors](https://github.com/bolandrm/sassc-ruby/graphs/contrib
25
49
 
26
50
  ## Changelog
27
51
 
52
+ - **1.10.0**
53
+ - [Improved error messages](https://github.com/sass/sassc-ruby/pull/34)
54
+ - Update to Libsass 3.3.6
28
55
  - **1.9.0**
29
- Support boolean script support
56
+ - Support boolean script support
30
57
  - **1.8.5**
31
58
  - Update to Libsass 3.3.4
32
59
  - **1.8.4**
@@ -1,5 +1,8 @@
1
1
  # Miscellaneous stuff
2
2
 
3
+ /sassc
4
+ /sass-spec
5
+
3
6
  VERSION
4
7
  .DS_Store
5
8
  .sass-cache
@@ -37,7 +37,7 @@ matrix:
37
37
  - os: osx
38
38
  compiler: gcc
39
39
  - os: osx
40
- env: AUTOTOOLS=no COVERAGE=yes BUILD=static
40
+ env: AUTOTOOLS=no BUILD=static
41
41
 
42
42
  script: ./script/ci-build-libsass
43
43
  before_install: ./script/ci-install-deps
@@ -57,9 +57,9 @@ TESTS = \
57
57
  $(SASS_SPEC_PATH)/spec/scss-tests \
58
58
  $(SASS_SPEC_PATH)/spec/types
59
59
 
60
- SASS_TEST_FLAGS =
60
+ SASS_TEST_FLAGS = -V 3.4 --impl libsass
61
61
  LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) ./script/tap-driver
62
- AM_LOG_FLAGS = -c ./tester --ignore-todo $(LOG_FLAGS)
62
+ AM_LOG_FLAGS = -c ./tester $(LOG_FLAGS)
63
63
  if USE_TAP
64
64
  AM_LOG_FLAGS += -t
65
65
  SASS_TEST_FLAGS += -t | tapout
@@ -72,16 +72,16 @@ SASS_TESTER = $(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb
72
72
  SASS_TESTER += -c $(SASS_LIBSASS_PATH)/tester$(EXEEXT)
73
73
 
74
74
  test:
75
- $(SASS_TESTER) --ignore-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
75
+ $(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
76
76
 
77
77
  test_build:
78
- $(SASS_TESTER) --ignore-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
78
+ $(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
79
79
 
80
80
  test_full:
81
- $(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
81
+ $(SASS_TESTER) --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
82
82
 
83
- test_issues:
84
- $(SASS_TESTER) $(LOG_FLAGS) $(SASS_SPEC_PATH)/spec/issues $(SASS_TEST_FLAGS)
83
+ test_probe:
84
+ $(SASS_TESTER) --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
85
85
 
86
86
  endif
87
87
 
@@ -300,13 +300,16 @@ version: $(SASSC_BIN)
300
300
  $(SASSC_BIN) -v
301
301
 
302
302
  test: $(SASSC_BIN)
303
- $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) -s $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
303
+ $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
304
304
 
305
305
  test_build: $(SASSC_BIN)
306
- $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) -s --ignore-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
306
+ $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
307
307
 
308
- test_issues: $(SASSC_BIN)
309
- $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) $(LOG_FLAGS) $(SASS_SPEC_PATH)/spec/issues
308
+ test_full: $(SASSC_BIN)
309
+ $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
310
+
311
+ test_probe: $(SASSC_BIN)
312
+ $(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
310
313
 
311
314
  clean-objects: lib
312
315
  -$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la
@@ -33,7 +33,6 @@ SOURCES = \
33
33
  sass_values.cpp \
34
34
  sass_context.cpp \
35
35
  sass_functions.cpp \
36
- sass_interface.cpp \
37
36
  sass2scss.cpp \
38
37
  source_map.cpp \
39
38
  to_c.cpp \
@@ -63,8 +63,11 @@ test_script:
63
63
  git -C sass-spec checkout -q --force ci-spec-pr-$SPEC_PR
64
64
  }
65
65
  }
66
- ruby sass-spec/sass-spec.rb -c $env:TargetPath -s --ignore-todo sass-spec/spec
67
-
66
+ ruby sass-spec/sass-spec.rb -V 3.4 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
67
+ if(-not($?)) {
68
+ echo "sass-spec tests failed"
69
+ exit 1
70
+ }
68
71
  Write-Host "Explicitly testing the case when cwd has Cyrillic characters: " -nonewline
69
72
  # See comments in gh-1774 for details.
70
73
  $env:TargetPath = Join-Path $pwd.Path $env:TargetPath
@@ -76,3 +79,4 @@ test_script:
76
79
  } else {
77
80
  echo "Success!"
78
81
  }
82
+
@@ -88,7 +88,7 @@ char* source_map_file;
88
88
  char* source_map_root;
89
89
  ```
90
90
  ```C
91
- // Custom functions that can be called from sccs code
91
+ // Custom functions that can be called from Sass code
92
92
  Sass_C_Function_List c_functions;
93
93
  ```
94
94
  ```C
@@ -168,12 +168,12 @@ struct Sass_Compiler* sass_make_data_compiler (struct Sass_Data_Context* data_ct
168
168
 
169
169
  // Execute the different compilation steps individually
170
170
  // Usefull if you only want to query the included files
171
- int sass_compiler_parse(struct Sass_Compiler* compiler);
172
- int sass_compiler_execute(struct Sass_Compiler* compiler);
171
+ int sass_compiler_parse (struct Sass_Compiler* compiler);
172
+ int sass_compiler_execute (struct Sass_Compiler* compiler);
173
173
 
174
174
  // Release all memory allocated with the compiler
175
175
  // This does _not_ include any contexts or options
176
- void sass_delete_compiler(struct Sass_Compiler* compiler);
176
+ void sass_delete_compiler (struct Sass_Compiler* compiler);
177
177
 
178
178
  // Release all memory allocated and also ourself
179
179
  void sass_delete_file_context (struct Sass_File_Context* ctx);
@@ -16,16 +16,6 @@ This will automatically load all other headers too!
16
16
  #include "sass/context.h"
17
17
  ```
18
18
 
19
- ### Deprecated usage
20
-
21
- The old API is kept in the source for backward compatibility.
22
- It's deprecated and incompatible with this documentation, use `sass/context.h`!
23
-
24
- ```C
25
- // deprecated interface
26
- #include "sass/interface.h"
27
- ```
28
-
29
19
  ## Basic C Example
30
20
 
31
21
  ```C
@@ -33,7 +23,7 @@ It's deprecated and incompatible with this documentation, use `sass/context.h`!
33
23
  #include "sass/context.h"
34
24
 
35
25
  int main() {
36
- puts(libsass_VERSION());
26
+ puts(libsass_version());
37
27
  return 0;
38
28
  }
39
29
  ```
@@ -114,6 +104,34 @@ This mirrors very well how `libsass` uses these structures.
114
104
 
115
105
  Structs can be down-casted to access `context` or `options`!
116
106
 
107
+ ## Memory handling and life-cycles
108
+
109
+ We keep memory around for as long as the main [context](api-context.md) object is not destroyed (`sass_delete_context`). LibSass will create copies of most inputs/options beside the main sass code.
110
+ You need to allocate and fill that buffer before passing it to LibSass. You may also overtake memory management from libsass for certain return values (i.e. `sass_context_take_output_string`).
111
+
112
+ ```C
113
+ // to allocate buffer to be filled
114
+ void* sass_alloc_memory(size_t size);
115
+ // to allocate a buffer from existing string
116
+ char* sass_copy_c_string(const char* str);
117
+ // to free overtaken memory when done
118
+ void sass_free_memory(void* ptr);
119
+ ```
120
+
121
+ ## Miscellaneous API functions
122
+
123
+ ```C
124
+ // Some convenient string helper function
125
+ char* sass_string_unquote (const char* str);
126
+ char* sass_string_quote (const char* str, const char quote_mark);
127
+
128
+ // Resolve a file via the given include paths in the include char* array
129
+ char* sass_resolve_file (const char* path, const char* incs[]);
130
+
131
+ // Get compiled libsass version
132
+ const char* libsass_version(void);
133
+ ```
134
+
117
135
  ## Common Pitfalls
118
136
 
119
137
  **input_path**
@@ -10,10 +10,10 @@ Sass_Import_List sass_importer(const char* path, Sass_Importer_Entry cb, struct
10
10
  // get the cookie from importer descriptor
11
11
  void* cookie = sass_importer_get_cookie(cb);
12
12
  Sass_Import_List list = sass_make_import_list(2);
13
- const char* local = "local { color: green; }";
14
- const char* remote = "remote { color: red; }";
15
- list[0] = sass_make_import_entry("/tmp/styles.scss", strdup(local), 0);
16
- list[1] = sass_make_import_entry("http://www.example.com", strdup(remote), 0);
13
+ char* local = sass_copy_c_string("local { color: green; }");
14
+ char* remote = sass_copy_c_string("remote { color: red; }");
15
+ list[0] = sass_make_import_entry("/tmp/styles.scss", local, 0);
16
+ list[1] = sass_make_import_entry("http://www.example.com", remote, 0);
17
17
  return list;
18
18
  }
19
19
 
@@ -84,7 +84,7 @@ Sass_Import_List importer(const char* path, Sass_Importer_Entry cb, struct Sass_
84
84
  Sass_Import_List list = sass_make_import_list(1);
85
85
  const char* message = "some error message";
86
86
  list[0] = sass_make_import_entry(path, 0, 0);
87
- sass_import_set_error(list[0], strdup(message), 0, 0);
87
+ sass_import_set_error(list[0], sass_copy_c_string(message), 0, 0);
88
88
  return list;
89
89
  }
90
90
 
@@ -130,7 +130,7 @@ cd libsass
130
130
  REM set PATH=%PATH%;%PROGRAMFILES%\MSBuild\12.0\Bin
131
131
  msbuild /m:4 /p:Configuration=Release win\libsass.sln
132
132
  REM running the spec test-suite manually (needs ruby and minitest gem)
133
- ruby sass-spec\sass-spec.rb -c win\bin\sassc.exe -s --ignore-todo sass-spec/spec
133
+ ruby sass-spec\sass-spec.rb -V 3.4 -c win\bin\sassc.exe -s --impl libsass sass-spec/spec
134
134
  cd ..
135
135
  ```
136
136
 
@@ -62,6 +62,13 @@ enum Sass_Output_Style {
62
62
  SASS_STYLE_TO_SASS
63
63
  };
64
64
 
65
+ // to allocate buffer to be filled
66
+ void* sass_alloc_memory(size_t size);
67
+ // to allocate a buffer from existing string
68
+ char* sass_copy_c_string(const char* str);
69
+ // to free overtaken memory when done
70
+ void sass_free_memory(void* ptr);
71
+
65
72
  // Some convenient string helper function
66
73
  ADDAPI char* ADDCALL sass_string_quote (const char* str, const char quote_mark);
67
74
  ADDAPI char* ADDCALL sass_string_unquote (const char* str);
@@ -72,6 +79,9 @@ ADDAPI char* ADDCALL sass_resolve_file (const char* path, const char* incs[]);
72
79
  // Get compiled libsass version
73
80
  ADDAPI const char* ADDCALL libsass_version(void);
74
81
 
82
+ // Get compiled libsass language
83
+ ADDAPI const char* ADDCALL libsass_language_version(void);
84
+
75
85
  #ifdef __cplusplus
76
86
  } // __cplusplus defined.
77
87
  #endif
@@ -5,4 +5,8 @@
5
5
  #define LIBSASS_VERSION "[NA]"
6
6
  #endif
7
7
 
8
+ #ifndef LIBSASS_LANGUAGE_VERSION
9
+ #define LIBSASS_LANGUAGE_VERSION "[NA]"
10
+ #endif
11
+
8
12
  #endif
@@ -5,4 +5,8 @@
5
5
  #define LIBSASS_VERSION "@PACKAGE_VERSION@"
6
6
  #endif
7
7
 
8
+ #ifndef LIBSASS_LANGUAGE_VERSION
9
+ #define LIBSASS_LANGUAGE_VERSION "3.4"
10
+ #endif
11
+
8
12
  #endif
@@ -37,7 +37,7 @@
37
37
  #ifndef SASS2SCSS_VERSION
38
38
  // Hardcode once the file is copied from
39
39
  // https://github.com/mgreter/sass2scss
40
- #define SASS2SCSS_VERSION "1.0.5"
40
+ #define SASS2SCSS_VERSION "1.0.6"
41
41
  #endif
42
42
 
43
43
  // add namespace for c++
@@ -48,6 +48,18 @@ if [ "x$PREFIX" == "x" ]; then
48
48
  fi
49
49
  fi
50
50
 
51
+ # enable address sanitation
52
+ # https://en.wikipedia.org/wiki/AddressSanitizer
53
+ if [ "x$CC" == "xclang" ]; then
54
+ if [ "x$COVERAGE" != "xyes" ]; then
55
+ if [ "$TRAVIS_OS_NAME" == "linux" ]; then
56
+ export EXTRA_CFLAGS="$EXTRA_CFLAGS -fsanitize=address"
57
+ export EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS -fsanitize=address"
58
+ export EXTRA_LDFLAGS="$EXTRA_LDFLAGS -fsanitize=address"
59
+ fi
60
+ fi
61
+ fi
62
+
51
63
  echo SASS_LIBSASS_PATH: $SASS_LIBSASS_PATH
52
64
  echo TRAVIS_BUILD_DIR: $TRAVIS_BUILD_DIR
53
65
  echo SASS_SASSC_PATH: $SASS_SASSC_PATH
@@ -108,10 +120,10 @@ then
108
120
  echo "Fetching Sass Spec PR $SPEC_PR"
109
121
  git -C sass-spec fetch -u origin pull/$SPEC_PR/head:ci-spec-pr-$SPEC_PR
110
122
  git -C sass-spec checkout --force ci-spec-pr-$SPEC_PR
111
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
123
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
112
124
  else
113
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
125
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
114
126
  fi
115
127
  else
116
- LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_build
128
+ LD_LIBRARY_PATH="$PREFIX/lib/" make $MAKE_OPTS test_probe
117
129
  fi
@@ -7,8 +7,11 @@
7
7
  #include "color_maps.hpp"
8
8
  #include <set>
9
9
  #include <iomanip>
10
- #include <algorithm>
11
10
  #include <iostream>
11
+ #include <algorithm>
12
+ #include <functional>
13
+ #include <cctype>
14
+ #include <locale>
12
15
 
13
16
  namespace Sass {
14
17
 
@@ -25,6 +28,80 @@ namespace Sass {
25
28
  dynamic_cast<Supports_Operator*>(cond);
26
29
  }
27
30
 
31
+ std::string & str_ltrim(std::string & str)
32
+ {
33
+ auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
34
+ str.erase( str.begin() , it2);
35
+ return str;
36
+ }
37
+
38
+ std::string & str_rtrim(std::string & str)
39
+ {
40
+ auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
41
+ str.erase( it1.base() , str.end() );
42
+ return str;
43
+ }
44
+
45
+ void String_Constant::rtrim()
46
+ {
47
+ value_ = str_rtrim(value_);
48
+ }
49
+ void String_Constant::ltrim()
50
+ {
51
+ value_ = str_ltrim(value_);
52
+ }
53
+ void String_Constant::trim()
54
+ {
55
+ rtrim();
56
+ ltrim();
57
+ }
58
+
59
+ void String_Schema::rtrim()
60
+ {
61
+ if (!empty()) {
62
+ if (String* str = dynamic_cast<String*>(last())) str->rtrim();
63
+ }
64
+ }
65
+ void String_Schema::ltrim()
66
+ {
67
+ if (!empty()) {
68
+ if (String* str = dynamic_cast<String*>(first())) str->ltrim();
69
+ }
70
+ }
71
+ void String_Schema::trim()
72
+ {
73
+ rtrim();
74
+ ltrim();
75
+ }
76
+
77
+ bool At_Root_Query::exclude(std::string str)
78
+ {
79
+ bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
80
+ List* l = static_cast<List*>(value());
81
+ std::string v;
82
+
83
+ if (with)
84
+ {
85
+ if (!l || l->length() == 0) return str.compare("rule") != 0;
86
+ for (size_t i = 0, L = l->length(); i < L; ++i)
87
+ {
88
+ v = unquote((*l)[i]->to_string());
89
+ if (v.compare("all") == 0 || v == str) return false;
90
+ }
91
+ return true;
92
+ }
93
+ else
94
+ {
95
+ if (!l || !l->length()) return str.compare("rule") == 0;
96
+ for (size_t i = 0, L = l->length(); i < L; ++i)
97
+ {
98
+ v = unquote((*l)[i]->to_string());
99
+ if (v.compare("all") == 0 || v == str) return true;
100
+ }
101
+ return false;
102
+ }
103
+ }
104
+
28
105
  void AST_Node::update_pstate(const ParserState& pstate)
29
106
  {
30
107
  pstate_.offset += pstate - pstate_ + pstate.offset;
@@ -60,7 +137,7 @@ namespace Sass {
60
137
  bool Compound_Selector::has_parent_ref()
61
138
  {
62
139
  for (Simple_Selector* s : *this) {
63
- if (s->has_parent_ref()) return true;
140
+ if (s && s->has_parent_ref()) return true;
64
141
  }
65
142
  return false;
66
143
  }
@@ -209,6 +286,7 @@ namespace Sass {
209
286
 
210
287
  bool Simple_Selector::operator== (const Simple_Selector& rhs) const
211
288
  {
289
+ if (const Pseudo_Selector* lp = dynamic_cast<const Pseudo_Selector*>(this)) return *lp == rhs;
212
290
  if (const Wrapped_Selector* lw = dynamic_cast<const Wrapped_Selector*>(this)) return *lw == rhs;
213
291
  if (const Attribute_Selector* la = dynamic_cast<const Attribute_Selector*>(this)) return *la == rhs;
214
292
  if (is_ns_eq(ns(), rhs.ns()))
@@ -218,6 +296,7 @@ namespace Sass {
218
296
 
219
297
  bool Simple_Selector::operator< (const Simple_Selector& rhs) const
220
298
  {
299
+ if (const Pseudo_Selector* lp = dynamic_cast<const Pseudo_Selector*>(this)) return *lp == rhs;
221
300
  if (const Wrapped_Selector* lw = dynamic_cast<const Wrapped_Selector*>(this)) return *lw < rhs;
222
301
  if (const Attribute_Selector* la = dynamic_cast<const Attribute_Selector*>(this)) return *la < rhs;
223
302
  if (is_ns_eq(ns(), rhs.ns()))
@@ -481,6 +560,49 @@ namespace Sass {
481
560
  return ns() == rhs.ns();
482
561
  }
483
562
 
563
+ bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
564
+ {
565
+ if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
566
+ {
567
+ Expression* lhs_ex = expression();
568
+ Expression* rhs_ex = rhs.expression();
569
+ if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex;
570
+ else return lhs_ex == rhs_ex;
571
+ }
572
+ else return false;
573
+ }
574
+
575
+ bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const
576
+ {
577
+ if (const Pseudo_Selector* w = dynamic_cast<const Pseudo_Selector*>(&rhs))
578
+ {
579
+ return *this == *w;
580
+ }
581
+ if (is_ns_eq(ns(), rhs.ns()))
582
+ { return name() == rhs.name(); }
583
+ return ns() == rhs.ns();
584
+ }
585
+
586
+ bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const
587
+ {
588
+ if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
589
+ { return *(expression()) < *(rhs.expression()); }
590
+ if (is_ns_eq(ns(), rhs.ns()))
591
+ { return name() < rhs.name(); }
592
+ return ns() < rhs.ns();
593
+ }
594
+
595
+ bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const
596
+ {
597
+ if (const Pseudo_Selector* w = dynamic_cast<const Pseudo_Selector*>(&rhs))
598
+ {
599
+ return *this < *w;
600
+ }
601
+ if (is_ns_eq(ns(), rhs.ns()))
602
+ { return name() < rhs.name(); }
603
+ return ns() < rhs.ns();
604
+ }
605
+
484
606
  bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const
485
607
  {
486
608
  if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
@@ -1230,10 +1352,12 @@ namespace Sass {
1230
1352
  if ((*this)[i]->head()->is_empty_reference()) {
1231
1353
  // simply move to the next tail if we have "no" combinator
1232
1354
  if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) {
1233
- if ((*this)[i]->tail() && (*this)[i]->has_line_feed()) {
1234
- (*this)[i]->tail()->has_line_feed(true);
1355
+ if ((*this)[i]->tail() != NULL) {
1356
+ if ((*this)[i]->has_line_feed()) {
1357
+ (*this)[i]->tail()->has_line_feed(true);
1358
+ }
1359
+ (*this)[i] = (*this)[i]->tail();
1235
1360
  }
1236
- (*this)[i] = (*this)[i]->tail();
1237
1361
  }
1238
1362
  // otherwise remove the first item from head
1239
1363
  else {
@@ -1246,7 +1370,15 @@ namespace Sass {
1246
1370
  bool Selector_List::has_parent_ref()
1247
1371
  {
1248
1372
  for (Complex_Selector* s : *this) {
1249
- if (s->has_parent_ref()) return true;
1373
+ if (s && s->has_parent_ref()) return true;
1374
+ }
1375
+ return false;
1376
+ }
1377
+
1378
+ bool Selector_Schema::has_parent_ref()
1379
+ {
1380
+ if (String_Schema* schema = dynamic_cast<String_Schema*>(contents())) {
1381
+ return schema->length() > 0 && dynamic_cast<Parent_Selector*>(schema->at(0)) != NULL;
1250
1382
  }
1251
1383
  return false;
1252
1384
  }
@@ -2017,6 +2149,29 @@ namespace Sass {
2017
2149
  return is_interpolant() || (right() && right()->is_right_interpolant());
2018
2150
  }
2019
2151
 
2152
+ // delay binary expressions in function arguments
2153
+ // https://github.com/sass/libsass/issues/1417
2154
+ bool Binary_Expression::can_delay(void) const
2155
+ {
2156
+ bool l_delay = false;
2157
+ bool r_delay = false;
2158
+ if (op().operand == Sass_OP::DIV) {
2159
+ if (Textual* tl = dynamic_cast<Textual*>(left())) {
2160
+ l_delay = tl->type() == Textual::NUMBER ||
2161
+ tl->type() == Textual::DIMENSION;
2162
+ } else {
2163
+ l_delay = dynamic_cast<Number*>(left()) != NULL;
2164
+ }
2165
+ if (Textual* tr = dynamic_cast<Textual*>(right())) {
2166
+ r_delay = tr->type() == Textual::NUMBER ||
2167
+ tr->type() == Textual::DIMENSION;
2168
+ } else {
2169
+ r_delay = dynamic_cast<Number*>(right()) != NULL;
2170
+ }
2171
+ }
2172
+ return l_delay && r_delay;
2173
+ }
2174
+
2020
2175
  std::string AST_Node::to_string(Sass_Inspect_Options opt) const
2021
2176
  {
2022
2177
  Sass_Output_Options out(opt);