sassc 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Rakefile +1 -3
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +1 -0
  9. data/ext/libsass/src/ast.cpp +49 -59
  10. data/ext/libsass/src/ast.hpp +263 -102
  11. data/ext/libsass/src/ast_def_macros.hpp +8 -0
  12. data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
  13. data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
  14. data/ext/libsass/src/ast_helpers.hpp +292 -0
  15. data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
  16. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  17. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  18. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  19. data/ext/libsass/src/ast_selectors.cpp +559 -1001
  20. data/ext/libsass/src/ast_selectors.hpp +311 -367
  21. data/ext/libsass/src/ast_supports.cpp +1 -17
  22. data/ext/libsass/src/ast_values.cpp +216 -29
  23. data/ext/libsass/src/ast_values.hpp +42 -33
  24. data/ext/libsass/src/bind.cpp +1 -1
  25. data/ext/libsass/src/cencode.c +4 -6
  26. data/ext/libsass/src/check_nesting.cpp +5 -6
  27. data/ext/libsass/src/check_nesting.hpp +4 -0
  28. data/ext/libsass/src/color_maps.cpp +11 -10
  29. data/ext/libsass/src/color_maps.hpp +0 -8
  30. data/ext/libsass/src/constants.cpp +5 -0
  31. data/ext/libsass/src/constants.hpp +6 -0
  32. data/ext/libsass/src/context.cpp +30 -60
  33. data/ext/libsass/src/context.hpp +8 -20
  34. data/ext/libsass/src/cssize.cpp +36 -120
  35. data/ext/libsass/src/cssize.hpp +4 -10
  36. data/ext/libsass/src/dart_helpers.hpp +199 -0
  37. data/ext/libsass/src/debugger.hpp +364 -207
  38. data/ext/libsass/src/emitter.cpp +3 -4
  39. data/ext/libsass/src/emitter.hpp +0 -2
  40. data/ext/libsass/src/environment.hpp +5 -0
  41. data/ext/libsass/src/error_handling.cpp +21 -0
  42. data/ext/libsass/src/error_handling.hpp +25 -3
  43. data/ext/libsass/src/eval.cpp +33 -153
  44. data/ext/libsass/src/eval.hpp +11 -13
  45. data/ext/libsass/src/eval_selectors.cpp +75 -0
  46. data/ext/libsass/src/expand.cpp +214 -167
  47. data/ext/libsass/src/expand.hpp +26 -6
  48. data/ext/libsass/src/extender.cpp +1186 -0
  49. data/ext/libsass/src/extender.hpp +399 -0
  50. data/ext/libsass/src/extension.cpp +43 -0
  51. data/ext/libsass/src/extension.hpp +89 -0
  52. data/ext/libsass/src/file.cpp +15 -14
  53. data/ext/libsass/src/file.hpp +5 -12
  54. data/ext/libsass/src/fn_colors.cpp +12 -10
  55. data/ext/libsass/src/fn_lists.cpp +12 -11
  56. data/ext/libsass/src/fn_miscs.cpp +22 -34
  57. data/ext/libsass/src/fn_numbers.cpp +13 -6
  58. data/ext/libsass/src/fn_selectors.cpp +94 -124
  59. data/ext/libsass/src/fn_strings.cpp +16 -14
  60. data/ext/libsass/src/fn_utils.cpp +5 -6
  61. data/ext/libsass/src/fn_utils.hpp +9 -3
  62. data/ext/libsass/src/inspect.cpp +154 -117
  63. data/ext/libsass/src/inspect.hpp +10 -8
  64. data/ext/libsass/src/lexer.cpp +17 -81
  65. data/ext/libsass/src/lexer.hpp +5 -16
  66. data/ext/libsass/src/listize.cpp +22 -36
  67. data/ext/libsass/src/listize.hpp +8 -9
  68. data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
  69. data/ext/libsass/src/operation.hpp +27 -17
  70. data/ext/libsass/src/operators.cpp +1 -0
  71. data/ext/libsass/src/ordered_map.hpp +112 -0
  72. data/ext/libsass/src/output.cpp +30 -49
  73. data/ext/libsass/src/output.hpp +1 -1
  74. data/ext/libsass/src/parser.cpp +211 -381
  75. data/ext/libsass/src/parser.hpp +17 -15
  76. data/ext/libsass/src/parser_selectors.cpp +189 -0
  77. data/ext/libsass/src/permutate.hpp +140 -0
  78. data/ext/libsass/src/position.hpp +1 -1
  79. data/ext/libsass/src/prelexer.cpp +6 -6
  80. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  81. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  82. data/ext/libsass/src/sass.hpp +1 -0
  83. data/ext/libsass/src/sass2scss.cpp +4 -4
  84. data/ext/libsass/src/sass_context.cpp +42 -91
  85. data/ext/libsass/src/sass_context.hpp +2 -2
  86. data/ext/libsass/src/sass_functions.cpp +1 -1
  87. data/ext/libsass/src/sass_values.cpp +0 -1
  88. data/ext/libsass/src/stylesheet.cpp +22 -0
  89. data/ext/libsass/src/stylesheet.hpp +57 -0
  90. data/ext/libsass/src/to_value.cpp +2 -2
  91. data/ext/libsass/src/to_value.hpp +1 -1
  92. data/ext/libsass/src/units.cpp +5 -3
  93. data/ext/libsass/src/util.cpp +10 -12
  94. data/ext/libsass/src/util.hpp +2 -3
  95. data/ext/libsass/src/util_string.cpp +111 -61
  96. data/ext/libsass/src/util_string.hpp +61 -8
  97. data/lib/sassc/engine.rb +5 -3
  98. data/lib/sassc/functions_handler.rb +8 -8
  99. data/lib/sassc/native.rb +1 -1
  100. data/lib/sassc/script.rb +4 -4
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/functions_test.rb +18 -1
  103. data/test/native_test.rb +1 -1
  104. metadata +17 -12
  105. data/ext/libsass/src/extend.cpp +0 -2132
  106. data/ext/libsass/src/extend.hpp +0 -86
  107. data/ext/libsass/src/node.cpp +0 -322
  108. data/ext/libsass/src/node.hpp +0 -118
  109. data/ext/libsass/src/paths.hpp +0 -71
  110. data/ext/libsass/src/sass_util.cpp +0 -152
  111. data/ext/libsass/src/sass_util.hpp +0 -256
  112. data/ext/libsass/src/subset_map.cpp +0 -58
  113. data/ext/libsass/src/subset_map.hpp +0 -76
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9d02f93975945a28234a652a653c6f948c243e21367ac04fd47fe73c9b2ffb2
4
- data.tar.gz: 77e20a198347263cb2a5b94f63a452cbf2e19352a379d47f63861286cd008244
3
+ metadata.gz: aebf2c0084662833c589a03cd0de02b8b72d3968f4c33a27d1b37c330a692bf2
4
+ data.tar.gz: b828b00fb88f9ed8414cd7abfd86afdced6458f47e9560789690d8f9a3670c43
5
5
  SHA512:
6
- metadata.gz: f43ded03b2153ae363b32c0e95542bc2eb9e1e33f27a09e81b9225c6a055a0ac412ba0a8fe474cd58ed39b68c8fc34cbe3cf8dfd171e08a9b831c09b80d1c3e6
7
- data.tar.gz: c53a978dc54f799557f19dde249d17cf21346bc751c16fae7eadbd36e67f9ff8955ff764e3de6ab5f8206f6ab35324b2041972f98bc222a69930eb2f8d74aaab
6
+ metadata.gz: 802546b5350e0b550b8ba01a125e03dbe52ce9541003ae811782b4cf2c197e12b5056520376a5dbf5317a2b033f70808fafd1e62fe40ecd12cf2d56c52881c6e
7
+ data.tar.gz: 864f16c8f74351159107fb1ccfd3abf837447b41a846a1c990481e7b28732222c4abde988aebe953fb500db2424a0d7d7ce2fc1c351ed2711aa1fa5ea88e37c1
@@ -10,5 +10,6 @@ rvm:
10
10
  - 2.4.6
11
11
  - 2.5.5
12
12
  - 2.6.3
13
+ - truffleruby
13
14
  notifications:
14
15
  email: false
@@ -1,3 +1,16 @@
1
+ - **2.3.0**
2
+ - [Fix rake gem:native task](https://github.com/sass/sassc-ruby/pull/196)
3
+ - [disable lto flag for darwin + nix](https://github.com/sass/sassc-ruby/pull/166)
4
+ - [Sort input file list](https://github.com/sass/sassc-ruby/pull/178)
5
+ - [Set appropriate encoding for source_map](https://github.com/sass/sassc-ruby/pull/152)
6
+ - [allow passing functions directly](https://github.com/sass/sassc-ruby/pull/162)
7
+ - [always dispose data context](https://github.com/sass/sassc-ruby/pull/161)
8
+ - [Update libsass to 3.6.3](https://github.com/sass/sassc-ruby/pull/164)
9
+ - [Restore strip symbols](https://github.com/sass/sassc-ruby/pull/184)
10
+ - [Default --march-tune-native to false](https://github.com/sass/sassc-ruby/pull/158)
11
+ - [Fix compile issue on Mac OS X](https://github.com/sass/sassc-ruby/pull/174)
12
+ - [Test on TruffleRuby in TravisCI](https://github.com/sass/sassc-ruby/pull/171)
13
+ - [Use RbConfig::MAKEFILE_CONFIG['DLEXT'] instead of hardcoding extensions](https://github.com/sass/sassc-ruby/pull/173)
1
14
  - **2.2.1**
2
15
  - [Fix LoadError on some non-rvm environments](https://github.com/sass/sassc-ruby/pull/156)
3
16
  - **2.2.0**
data/Rakefile CHANGED
@@ -36,9 +36,7 @@ task 'gem:native' do
36
36
 
37
37
  # The RUBY_CC_VERSION here doesn't matter for the final package.
38
38
  # Only one version should be specified, as the shared library is Ruby-agnostic.
39
- #
40
- # g++-multilib is installed for 64->32-bit cross-compilation.
41
- RakeCompilerDock.sh "sudo apt-get install -y g++-multilib && gem i rake bundler --no-document && bundle && "\
39
+ RakeCompilerDock.sh "gem i rake bundler --no-document && bundle && "\
42
40
  "rake clean && rake cross native gem MAKE='nice make -j`nproc`' "\
43
41
  "RUBY_CC_VERSION=2.6.0 CLEAN=1"
44
42
  end
@@ -19,13 +19,17 @@ if enable_config('static-stdlib', false)
19
19
  $LDFLAGS << ' -static-libgcc -static-libstdc++'
20
20
  end
21
21
 
22
- # Set to false when building binary gems
23
- if enable_config('march-tune-native', true)
22
+ if enable_config('march-tune-native', false)
24
23
  $CFLAGS << ' -march=native -mtune=native'
25
24
  $CXXFLAGS << ' -march=native -mtune=native'
26
25
  end
27
26
 
28
- if enable_config('lto', true)
27
+ # darwin nix clang doesn't support lto
28
+ # disable -lto flag for darwin + nix
29
+ # see: https://github.com/sass/sassc-ruby/issues/148
30
+ enable_lto_by_default = (Gem::Platform.local.os == "darwin" && !ENV['NIX_CC'].nil?)
31
+
32
+ if enable_config('lto', enable_lto_by_default)
29
33
  $CFLAGS << ' -flto'
30
34
  $CXXFLAGS << ' -flto'
31
35
  $LDFLAGS << ' -flto'
@@ -56,10 +60,14 @@ $INCFLAGS << " -I$(srcdir)/libsass/include"
56
60
  $VPATH << "$(srcdir)/libsass/src"
57
61
  Dir.chdir(__dir__) do
58
62
  $VPATH += Dir['libsass/src/*/'].map { |p| "$(srcdir)/#{p}" }
59
- $srcs = Dir['libsass/src/**/*.{c,cpp}']
63
+ $srcs = Dir['libsass/src/**/*.{c,cpp}'].sort
60
64
  end
61
65
 
62
- MakeMakefile::LINK_SO << "\nstrip -x $@"
66
+ # libsass.bundle malformed object (unknown load command 7) on Mac OS X
67
+ # See https://github.com/sass/sassc-ruby/pull/174
68
+ if enable_config('strip', RbConfig::CONFIG['host_os'].downcase !~ /darwin/)
69
+ MakeMakefile::LINK_SO << "\nstrip -x $@"
70
+ end
63
71
 
64
72
  # Don't link libruby.
65
73
  $LIBRUBYARG = nil
@@ -1 +1 @@
1
- 3.6.1
1
+ 3.6.3
@@ -68,7 +68,8 @@ enum Sass_Output_Style {
68
68
  SASS_STYLE_COMPRESSED,
69
69
  // only used internaly
70
70
  SASS_STYLE_INSPECT,
71
- SASS_STYLE_TO_SASS
71
+ SASS_STYLE_TO_SASS,
72
+ SASS_STYLE_TO_CSS
72
73
  };
73
74
 
74
75
  // to allocate buffer to be filled
@@ -134,6 +134,7 @@ ADDAPI char* ADDCALL sass_context_take_error_json (struct Sass_Context* ctx);
134
134
  ADDAPI char* ADDCALL sass_context_take_error_text (struct Sass_Context* ctx);
135
135
  ADDAPI char* ADDCALL sass_context_take_error_message (struct Sass_Context* ctx);
136
136
  ADDAPI char* ADDCALL sass_context_take_error_file (struct Sass_Context* ctx);
137
+ ADDAPI char* ADDCALL sass_context_take_error_src (struct Sass_Context* ctx);
137
138
  ADDAPI char* ADDCALL sass_context_take_output_string (struct Sass_Context* ctx);
138
139
  ADDAPI char* ADDCALL sass_context_take_source_map_string (struct Sass_Context* ctx);
139
140
  ADDAPI char** ADDCALL sass_context_take_included_files (struct Sass_Context* ctx);
@@ -1,19 +1,8 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
4
+
2
5
  #include "ast.hpp"
3
- #include "context.hpp"
4
- #include "node.hpp"
5
- #include "eval.hpp"
6
- #include "extend.hpp"
7
- #include "emitter.hpp"
8
- #include "color_maps.hpp"
9
- #include "ast_fwd_decl.hpp"
10
- #include <set>
11
- #include <iomanip>
12
- #include <iostream>
13
- #include <algorithm>
14
- #include <functional>
15
- #include <cctype>
16
- #include <locale>
17
6
 
18
7
  namespace Sass {
19
8
 
@@ -69,7 +58,7 @@ namespace Sass {
69
58
  pstate_.offset += pstate - pstate_ + pstate.offset;
70
59
  }
71
60
 
72
- const std::string AST_Node::to_string(Sass_Inspect_Options opt) const
61
+ std::string AST_Node::to_string(Sass_Inspect_Options opt) const
73
62
  {
74
63
  Sass_Output_Options out(opt);
75
64
  Emitter emitter(out);
@@ -80,19 +69,21 @@ namespace Sass {
80
69
  return i.get_buffer();
81
70
  }
82
71
 
83
- const std::string AST_Node::to_string() const
72
+ std::string AST_Node::to_css(Sass_Inspect_Options opt) const
84
73
  {
85
- return to_string({ NESTED, 5 });
74
+ opt.output_style = TO_CSS;
75
+ Sass_Output_Options out(opt);
76
+ Emitter emitter(out);
77
+ Inspect i(emitter);
78
+ i.in_declaration = true;
79
+ // ToDo: inspect should be const
80
+ const_cast<AST_Node*>(this)->perform(&i);
81
+ return i.get_buffer();
86
82
  }
87
83
 
88
- /////////////////////////////////////////////////////////////////////////
89
- /////////////////////////////////////////////////////////////////////////
90
-
91
- Expression_Obj Hashed::at(Expression_Obj k) const
84
+ std::string AST_Node::to_string() const
92
85
  {
93
- if (elements_.count(k))
94
- { return elements_.at(k); }
95
- else { return {}; }
86
+ return to_string({ NESTED, 5 });
96
87
  }
97
88
 
98
89
  /////////////////////////////////////////////////////////////////////////
@@ -137,6 +128,14 @@ namespace Sass {
137
128
  is_root_(ptr->is_root_)
138
129
  { }
139
130
 
131
+ bool Block::isInvisible() const
132
+ {
133
+ for (auto& item : elements()) {
134
+ if (!item->is_invisible()) return false;
135
+ }
136
+ return true;
137
+ }
138
+
140
139
  bool Block::has_content()
141
140
  {
142
141
  for (size_t i = 0, L = elements().size(); i < L; ++i) {
@@ -163,19 +162,20 @@ namespace Sass {
163
162
  /////////////////////////////////////////////////////////////////////////
164
163
  /////////////////////////////////////////////////////////////////////////
165
164
 
166
- Ruleset::Ruleset(ParserState pstate, Selector_List_Obj s, Block_Obj b)
167
- : Has_Block(pstate, b), selector_(s), is_root_(false)
165
+ Ruleset::Ruleset(ParserState pstate, SelectorListObj s, Block_Obj b)
166
+ : Has_Block(pstate, b), selector_(s), schema_(), is_root_(false)
168
167
  { statement_type(RULESET); }
169
168
  Ruleset::Ruleset(const Ruleset* ptr)
170
169
  : Has_Block(ptr),
171
170
  selector_(ptr->selector_),
171
+ schema_(ptr->schema_),
172
172
  is_root_(ptr->is_root_)
173
173
  { statement_type(RULESET); }
174
174
 
175
175
  bool Ruleset::is_invisible() const {
176
- if (Selector_List* sl = Cast<Selector_List>(selector())) {
177
- for (size_t i = 0, L = sl->length(); i < L; ++i)
178
- if (!(*sl)[i]->has_placeholder()) return false;
176
+ if (const SelectorList * sl = Cast<SelectorList>(selector())) {
177
+ for (size_t i = 0, L = sl->length(); i < L; i += 1)
178
+ if (!(*sl)[i]->isInvisible()) return false;
179
179
  }
180
180
  return true;
181
181
  }
@@ -212,30 +212,7 @@ namespace Sass {
212
212
  /////////////////////////////////////////////////////////////////////////
213
213
  /////////////////////////////////////////////////////////////////////////
214
214
 
215
- Media_Block::Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b)
216
- : Has_Block(pstate, b), media_queries_(mqs)
217
- { statement_type(MEDIA); }
218
- Media_Block::Media_Block(const Media_Block* ptr)
219
- : Has_Block(ptr), media_queries_(ptr->media_queries_)
220
- { statement_type(MEDIA); }
221
-
222
- bool Media_Block::is_invisible() const {
223
- for (size_t i = 0, L = block()->length(); i < L; ++i) {
224
- Statement_Obj stm = block()->at(i);
225
- if (!stm->is_invisible()) return false;
226
- }
227
- return true;
228
- }
229
-
230
- bool Media_Block::bubbles()
231
- {
232
- return true;
233
- }
234
-
235
- /////////////////////////////////////////////////////////////////////////
236
- /////////////////////////////////////////////////////////////////////////
237
-
238
- Directive::Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel, Block_Obj b, Expression_Obj val)
215
+ Directive::Directive(ParserState pstate, std::string kwd, SelectorListObj sel, Block_Obj b, Expression_Obj val)
239
216
  : Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
240
217
  { statement_type(DIRECTIVE); }
241
218
  Directive::Directive(const Directive* ptr)
@@ -450,11 +427,19 @@ namespace Sass {
450
427
  /////////////////////////////////////////////////////////////////////////
451
428
  /////////////////////////////////////////////////////////////////////////
452
429
 
453
- Extension::Extension(ParserState pstate, Selector_List_Obj s)
454
- : Statement(pstate), selector_(s)
430
+ ExtendRule::ExtendRule(ParserState pstate, SelectorListObj s)
431
+ : Statement(pstate), isOptional_(false), selector_(s), schema_()
455
432
  { statement_type(EXTEND); }
456
- Extension::Extension(const Extension* ptr)
457
- : Statement(ptr), selector_(ptr->selector_)
433
+ ExtendRule::ExtendRule(ParserState pstate, Selector_Schema_Obj s)
434
+ : Statement(pstate), isOptional_(false), selector_(), schema_(s)
435
+ {
436
+ statement_type(EXTEND);
437
+ }
438
+ ExtendRule::ExtendRule(const ExtendRule* ptr)
439
+ : Statement(ptr),
440
+ isOptional_(ptr->isOptional_),
441
+ selector_(ptr->selector_),
442
+ schema_(ptr->schema_)
458
443
  { statement_type(EXTEND); }
459
444
 
460
445
  /////////////////////////////////////////////////////////////////////////
@@ -923,8 +908,13 @@ namespace Sass {
923
908
  /////////////////////////////////////////////////////////////////////////
924
909
  /////////////////////////////////////////////////////////////////////////
925
910
 
911
+ // If you forget to add a class here you will get
912
+ // undefined reference to `vtable for Sass::Class'
913
+
926
914
  IMPLEMENT_AST_OPERATORS(Ruleset);
927
- IMPLEMENT_AST_OPERATORS(Media_Block);
915
+ IMPLEMENT_AST_OPERATORS(MediaRule);
916
+ IMPLEMENT_AST_OPERATORS(CssMediaRule);
917
+ IMPLEMENT_AST_OPERATORS(CssMediaQuery);
928
918
  IMPLEMENT_AST_OPERATORS(Import);
929
919
  IMPLEMENT_AST_OPERATORS(Import_Stub);
930
920
  IMPLEMENT_AST_OPERATORS(Directive);
@@ -934,7 +924,7 @@ namespace Sass {
934
924
  IMPLEMENT_AST_OPERATORS(For);
935
925
  IMPLEMENT_AST_OPERATORS(If);
936
926
  IMPLEMENT_AST_OPERATORS(Mixin_Call);
937
- IMPLEMENT_AST_OPERATORS(Extension);
927
+ IMPLEMENT_AST_OPERATORS(ExtendRule);
938
928
  IMPLEMENT_AST_OPERATORS(Media_Query);
939
929
  IMPLEMENT_AST_OPERATORS(Media_Query_Expression);
940
930
  IMPLEMENT_AST_OPERATORS(Debug);
@@ -5,47 +5,22 @@
5
5
  // __EXTENSIONS__ fix on Solaris.
6
6
  #include "sass.hpp"
7
7
 
8
- #include <set>
9
- #include <deque>
10
- #include <vector>
11
- #include <string>
12
- #include <sstream>
13
- #include <iostream>
14
8
  #include <typeinfo>
15
- #include <algorithm>
9
+ #include <unordered_map>
10
+
16
11
  #include "sass/base.h"
12
+ #include "ast_helpers.hpp"
17
13
  #include "ast_fwd_decl.hpp"
14
+ #include "ast_def_macros.hpp"
18
15
 
19
- #include "util.hpp"
20
- #include "units.hpp"
21
- #include "context.hpp"
16
+ #include "file.hpp"
22
17
  #include "position.hpp"
23
- #include "constants.hpp"
24
18
  #include "operation.hpp"
25
- #include "position.hpp"
26
- #include "inspect.hpp"
27
- #include "source_map.hpp"
28
19
  #include "environment.hpp"
29
- #include "error_handling.hpp"
30
- #include "ast_def_macros.hpp"
31
- #include "ast_fwd_decl.hpp"
32
- #include "source_map.hpp"
33
20
  #include "fn_utils.hpp"
34
21
 
35
- #include "sass.h"
36
-
37
22
  namespace Sass {
38
23
 
39
- // easier to search with name
40
- const bool DELAYED = true;
41
-
42
- // ToDo: should this really be hardcoded
43
- // Note: most methods follow precision option
44
- const double NUMBER_EPSILON = 1e-12;
45
-
46
- // macro to test if numbers are equal within a small error margin
47
- #define NEAR_EQUAL(lhs, rhs) std::fabs(lhs - rhs) < NUMBER_EPSILON
48
-
49
24
  // ToDo: where does this fit best?
50
25
  // We don't share this with C-API?
51
26
  class Operand {
@@ -101,8 +76,9 @@ namespace Sass {
101
76
  virtual size_t hash() const { return 0; }
102
77
  virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
103
78
  virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
104
- virtual const std::string to_string(Sass_Inspect_Options opt) const;
105
- virtual const std::string to_string() const;
79
+ virtual std::string to_string(Sass_Inspect_Options opt) const;
80
+ virtual std::string to_css(Sass_Inspect_Options opt) const;
81
+ virtual std::string to_string() const;
106
82
  virtual void cloneChildren() {};
107
83
  // generic find function (not fully implemented yet)
108
84
  // ToDo: add specific implementions to all children
@@ -110,6 +86,20 @@ namespace Sass {
110
86
  void update_pstate(const ParserState& pstate);
111
87
  Offset off() { return pstate(); }
112
88
  Position pos() { return pstate(); }
89
+
90
+ // Some obects are not meant to be compared
91
+ // ToDo: maybe fallback to pointer comparison?
92
+ virtual bool operator== (const AST_Node& rhs) const {
93
+ throw std::runtime_error("operator== not implemented");
94
+ }
95
+
96
+ // We can give some reasonable implementations by using
97
+ // inverst operators on the specialized implementations
98
+ virtual bool operator!= (const AST_Node& rhs) const {
99
+ // Unequal if not equal
100
+ return !(*this == rhs);
101
+ }
102
+
113
103
  ATTACH_ABSTRACT_AST_OPERATIONS(AST_Node);
114
104
  ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()
115
105
  };
@@ -228,37 +218,112 @@ namespace Sass {
228
218
  public:
229
219
  Vectorized(size_t s = 0) : hash_(0)
230
220
  { elements_.reserve(s); }
221
+ Vectorized(std::vector<T> vec) :
222
+ elements_(std::move(vec)),
223
+ hash_(0)
224
+ {}
231
225
  virtual ~Vectorized() = 0;
232
226
  size_t length() const { return elements_.size(); }
233
227
  bool empty() const { return elements_.empty(); }
234
228
  void clear() { return elements_.clear(); }
235
- T last() const { return elements_.back(); }
236
- T first() const { return elements_.front(); }
229
+ T& last() { return elements_.back(); }
230
+ T& first() { return elements_.front(); }
231
+ const T& last() const { return elements_.back(); }
232
+ const T& first() const { return elements_.front(); }
233
+
234
+ bool operator== (const Vectorized<T>& rhs) const {
235
+ // Abort early if sizes do not match
236
+ if (length() != rhs.length()) return false;
237
+ // Otherwise test each node for object equalicy in order
238
+ return std::equal(begin(), end(), rhs.begin(), ObjEqualityFn<T>);
239
+ }
240
+
241
+ bool operator!= (const Vectorized<T>& rhs) const {
242
+ return !(*this == rhs);
243
+ }
244
+
237
245
  T& operator[](size_t i) { return elements_[i]; }
238
246
  virtual const T& at(size_t i) const { return elements_.at(i); }
239
247
  virtual T& at(size_t i) { return elements_.at(i); }
240
248
  const T& get(size_t i) const { return elements_[i]; }
241
249
  const T& operator[](size_t i) const { return elements_[i]; }
242
- virtual void append(T element)
250
+
251
+ // Implicitly get the std::vector from our object
252
+ // Makes the Vector directly assignable to std::vector
253
+ // You are responsible to make a copy if needed
254
+ // Note: since this returns the real object, we can't
255
+ // Note: guarantee that the hash will not get out of sync
256
+ operator std::vector<T>&() { return elements_; }
257
+ operator const std::vector<T>&() const { return elements_; }
258
+
259
+ // Explicitly request all elements as a real std::vector
260
+ // You are responsible to make a copy if needed
261
+ // Note: since this returns the real object, we can't
262
+ // Note: guarantee that the hash will not get out of sync
263
+ std::vector<T>& elements() { return elements_; }
264
+ const std::vector<T>& elements() const { return elements_; }
265
+
266
+ // Insert all items from compatible vector
267
+ void concat(const std::vector<T>& v)
268
+ {
269
+ if (!v.empty()) reset_hash();
270
+ elements().insert(end(), v.begin(), v.end());
271
+ }
272
+
273
+ // Syntatic sugar for pointers
274
+ void concat(const Vectorized<T>* v)
243
275
  {
244
- if (element) {
245
- reset_hash();
246
- elements_.push_back(element);
247
- adjust_after_pushing(element);
276
+ if (v != nullptr) {
277
+ return concat(*v);
248
278
  }
249
279
  }
250
- virtual void concat(Vectorized* v)
280
+
281
+ // Insert one item on the front
282
+ void unshift(T element)
251
283
  {
252
- for (size_t i = 0, L = v->length(); i < L; ++i) this->append((*v)[i]);
284
+ reset_hash();
285
+ elements_.insert(begin(), element);
253
286
  }
254
- Vectorized& unshift(T element)
287
+
288
+ // Remove and return item on the front
289
+ // ToDo: handle empty vectors
290
+ T shift() {
291
+ reset_hash();
292
+ T first = get(0);
293
+ elements_.erase(begin());
294
+ return first;
295
+ }
296
+
297
+ // Insert one item on the back
298
+ // ToDo: rename this to push
299
+ void append(T element)
255
300
  {
256
- elements_.insert(elements_.begin(), element);
257
- return *this;
301
+ reset_hash();
302
+ elements_.insert(end(), element);
303
+ // ToDo: Mostly used by parameters and arguments
304
+ // ToDo: Find a more elegant way to support this
305
+ adjust_after_pushing(element);
306
+ }
307
+
308
+ // Check if an item already exists
309
+ // Uses underlying object `operator==`
310
+ // E.g. compares the actual objects
311
+ bool contains(const T& el) const {
312
+ for (const T& rhs : elements_) {
313
+ // Test the underlying objects for equality
314
+ // A std::find checks for pointer equality
315
+ if (ObjEqualityFn(el, rhs)) {
316
+ return true;
317
+ }
318
+ }
319
+ return false;
320
+ }
321
+
322
+ // This might be better implemented as `operator=`?
323
+ void elements(std::vector<T> e) {
324
+ reset_hash();
325
+ elements_ = std::move(e);
258
326
  }
259
- std::vector<T>& elements() { return elements_; }
260
- const std::vector<T>& elements() const { return elements_; }
261
- std::vector<T>& elements(std::vector<T>& e) { elements_ = e; return elements_; }
262
327
 
263
328
  virtual size_t hash() const
264
329
  {
@@ -280,8 +345,8 @@ namespace Sass {
280
345
  typename std::vector<T>::iterator begin() { return elements_.begin(); }
281
346
  typename std::vector<T>::const_iterator end() const { return elements_.end(); }
282
347
  typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
283
- typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { return elements_.erase(el); }
284
- typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { return elements_.erase(el); }
348
+ typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { reset_hash(); return elements_.erase(el); }
349
+ typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { reset_hash(); return elements_.erase(el); }
285
350
 
286
351
  };
287
352
  template <typename T>
@@ -291,36 +356,61 @@ namespace Sass {
291
356
  // Mixin class for AST nodes that should behave like a hash table. Uses an
292
357
  // extra <std::vector> internally to maintain insertion order for interation.
293
358
  /////////////////////////////////////////////////////////////////////////////
359
+ template <typename K, typename T, typename U>
294
360
  class Hashed {
295
361
  private:
296
- ExpressionMap elements_;
297
- std::vector<Expression_Obj> list_;
362
+ std::unordered_map<
363
+ K, T, ObjHash, ObjEquality
364
+ > elements_;
365
+
366
+ std::vector<K> _keys;
367
+ std::vector<T> _values;
298
368
  protected:
299
369
  mutable size_t hash_;
300
- Expression_Obj duplicate_key_;
370
+ K duplicate_key_;
301
371
  void reset_hash() { hash_ = 0; }
302
372
  void reset_duplicate_key() { duplicate_key_ = {}; }
303
- virtual void adjust_after_pushing(std::pair<Expression_Obj, Expression_Obj> p) { }
373
+ virtual void adjust_after_pushing(std::pair<K, T> p) { }
304
374
  public:
305
375
  Hashed(size_t s = 0)
306
- : elements_(ExpressionMap(s)),
307
- list_(std::vector<Expression_Obj>()),
376
+ : elements_(),
377
+ _keys(),
378
+ _values(),
308
379
  hash_(0), duplicate_key_({})
309
- { elements_.reserve(s); list_.reserve(s); }
380
+ {
381
+ _keys.reserve(s);
382
+ _values.reserve(s);
383
+ elements_.reserve(s);
384
+ }
310
385
  virtual ~Hashed();
311
- size_t length() const { return list_.size(); }
312
- bool empty() const { return list_.empty(); }
313
- bool has(Expression_Obj k) const { return elements_.count(k) == 1; }
314
- Expression_Obj at(Expression_Obj k) const;
386
+ size_t length() const { return _keys.size(); }
387
+ bool empty() const { return _keys.empty(); }
388
+ bool has(K k) const {
389
+ return elements_.find(k) != elements_.end();
390
+ }
391
+ T at(K k) const {
392
+ if (elements_.count(k))
393
+ {
394
+ return elements_.at(k);
395
+ }
396
+ else { return {}; }
397
+ }
315
398
  bool has_duplicate_key() const { return duplicate_key_ != nullptr; }
316
- Expression_Obj get_duplicate_key() const { return duplicate_key_; }
317
- const ExpressionMap elements() { return elements_; }
318
- Hashed& operator<<(std::pair<Expression_Obj, Expression_Obj> p)
399
+ K get_duplicate_key() const { return duplicate_key_; }
400
+ const std::unordered_map<
401
+ K, T, ObjHash, ObjEquality
402
+ >& elements() { return elements_; }
403
+ Hashed& operator<<(std::pair<K, T> p)
319
404
  {
320
405
  reset_hash();
321
406
 
322
- if (!has(p.first)) list_.push_back(p.first);
323
- else if (!duplicate_key_) duplicate_key_ = p.first;
407
+ if (!has(p.first)) {
408
+ _keys.push_back(p.first);
409
+ _values.push_back(p.second);
410
+ }
411
+ else if (!duplicate_key_) {
412
+ duplicate_key_ = p.first;
413
+ }
324
414
 
325
415
  elements_[p.first] = p.second;
326
416
 
@@ -331,7 +421,8 @@ namespace Sass {
331
421
  {
332
422
  if (length() == 0) {
333
423
  this->elements_ = h->elements_;
334
- this->list_ = h->list_;
424
+ this->_values = h->_values;
425
+ this->_keys = h->_keys;
335
426
  return *this;
336
427
  }
337
428
 
@@ -342,8 +433,12 @@ namespace Sass {
342
433
  reset_duplicate_key();
343
434
  return *this;
344
435
  }
345
- const ExpressionMap& pairs() const { return elements_; }
346
- const std::vector<Expression_Obj>& keys() const { return list_; }
436
+ const std::unordered_map<
437
+ K, T, ObjHash, ObjEquality
438
+ >& pairs() const { return elements_; }
439
+
440
+ const std::vector<K>& keys() const { return _keys; }
441
+ const std::vector<T>& values() const { return _values; }
347
442
 
348
443
  // std::unordered_map<Expression_Obj, Expression_Obj>::iterator end() { return elements_.end(); }
349
444
  // std::unordered_map<Expression_Obj, Expression_Obj>::iterator begin() { return elements_.begin(); }
@@ -351,8 +446,8 @@ namespace Sass {
351
446
  // std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator begin() const { return elements_.begin(); }
352
447
 
353
448
  };
354
- inline Hashed::~Hashed() { }
355
-
449
+ template <typename K, typename T, typename U>
450
+ inline Hashed<K, T, U>::~Hashed() { }
356
451
 
357
452
  /////////////////////////////////////////////////////////////////////////
358
453
  // Abstract base class for statements. This side of the AST hierarchy
@@ -411,6 +506,7 @@ namespace Sass {
411
506
  void adjust_after_pushing(Statement_Obj s) override {}
412
507
  public:
413
508
  Block(ParserState pstate, size_t s = 0, bool r = false);
509
+ bool isInvisible() const;
414
510
  bool has_content() override;
415
511
  ATTACH_AST_OPERATIONS(Block)
416
512
  ATTACH_CRTP_PERFORM_METHODS()
@@ -434,10 +530,11 @@ namespace Sass {
434
530
  // of style declarations.
435
531
  /////////////////////////////////////////////////////////////////////////////
436
532
  class Ruleset final : public Has_Block {
437
- ADD_PROPERTY(Selector_List_Obj, selector)
533
+ ADD_PROPERTY(SelectorListObj, selector)
534
+ ADD_PROPERTY(Selector_Schema_Obj, schema)
438
535
  ADD_PROPERTY(bool, is_root);
439
536
  public:
440
- Ruleset(ParserState pstate, Selector_List_Obj s = {}, Block_Obj b = {});
537
+ Ruleset(ParserState pstate, SelectorListObj s = {}, Block_Obj b = {});
441
538
  bool is_invisible() const override;
442
539
  ATTACH_AST_OPERATIONS(Ruleset)
443
540
  ATTACH_CRTP_PERFORM_METHODS()
@@ -468,29 +565,16 @@ namespace Sass {
468
565
  ATTACH_CRTP_PERFORM_METHODS()
469
566
  };
470
567
 
471
- /////////////////
472
- // Media queries.
473
- /////////////////
474
- class Media_Block final : public Has_Block {
475
- ADD_PROPERTY(List_Obj, media_queries)
476
- public:
477
- Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b);
478
- bool bubbles() override;
479
- bool is_invisible() const override;
480
- ATTACH_AST_OPERATIONS(Media_Block)
481
- ATTACH_CRTP_PERFORM_METHODS()
482
- };
483
-
484
568
  ///////////////////////////////////////////////////////////////////////
485
569
  // At-rules -- arbitrary directives beginning with "@" that may have an
486
570
  // optional statement block.
487
571
  ///////////////////////////////////////////////////////////////////////
488
572
  class Directive final : public Has_Block {
489
573
  ADD_CONSTREF(std::string, keyword)
490
- ADD_PROPERTY(Selector_List_Obj, selector)
574
+ ADD_PROPERTY(SelectorListObj, selector)
491
575
  ADD_PROPERTY(Expression_Obj, value)
492
576
  public:
493
- Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel = {}, Block_Obj b = {}, Expression_Obj val = {});
577
+ Directive(ParserState pstate, std::string kwd, SelectorListObj sel = {}, Block_Obj b = {}, Expression_Obj val = {});
494
578
  bool bubbles() override;
495
579
  bool is_media();
496
580
  bool is_keyframes();
@@ -504,7 +588,7 @@ namespace Sass {
504
588
  class Keyframe_Rule final : public Has_Block {
505
589
  // according to css spec, this should be <keyframes-name>
506
590
  // <keyframes-name> = <custom-ident> | <string>
507
- ADD_PROPERTY(Selector_List_Obj, name)
591
+ ADD_PROPERTY(SelectorListObj, name)
508
592
  public:
509
593
  Keyframe_Rule(ParserState pstate, Block_Obj b);
510
594
  ATTACH_AST_OPERATIONS(Keyframe_Rule)
@@ -677,17 +761,6 @@ namespace Sass {
677
761
  ATTACH_CRTP_PERFORM_METHODS()
678
762
  };
679
763
 
680
- ////////////////////////////////
681
- // The Sass `@extend` directive.
682
- ////////////////////////////////
683
- class Extension final : public Statement {
684
- ADD_PROPERTY(Selector_List_Obj, selector)
685
- public:
686
- Extension(ParserState pstate, Selector_List_Obj s);
687
- ATTACH_AST_OPERATIONS(Extension)
688
- ATTACH_CRTP_PERFORM_METHODS()
689
- };
690
-
691
764
  /////////////////////////////////////////////////////////////////////////////
692
765
  // Definitions for both mixins and functions. The two cases are distinguished
693
766
  // by a type tag.
@@ -806,9 +879,96 @@ namespace Sass {
806
879
  ATTACH_CRTP_PERFORM_METHODS()
807
880
  };
808
881
 
809
- /////////////////
810
- // Media queries.
811
- /////////////////
882
+
883
+ // A Media Ruleset before it has been evaluated
884
+ // Could be already final or an interpolation
885
+ class MediaRule final : public Has_Block {
886
+ ADD_PROPERTY(List_Obj, schema)
887
+ public:
888
+ MediaRule(ParserState pstate, Block_Obj block = {});
889
+
890
+ bool bubbles() override { return true; };
891
+ bool is_invisible() const override { return false; };
892
+ ATTACH_AST_OPERATIONS(MediaRule)
893
+ ATTACH_CRTP_PERFORM_METHODS()
894
+ };
895
+
896
+ // A Media Ruleset after it has been evaluated
897
+ // Representing the static or resulting css
898
+ class CssMediaRule final : public Has_Block,
899
+ public Vectorized<CssMediaQuery_Obj> {
900
+ public:
901
+ CssMediaRule(ParserState pstate, Block_Obj b);
902
+ bool bubbles() override { return true; };
903
+ bool isInvisible() const { return empty(); }
904
+ bool is_invisible() const override { return false; };
905
+
906
+ public:
907
+ // Hash and equality implemtation from vector
908
+ size_t hash() const override { return Vectorized::hash(); }
909
+ // Check if two instances are considered equal
910
+ bool operator== (const CssMediaRule& rhs) const {
911
+ return Vectorized::operator== (rhs);
912
+ }
913
+ bool operator!=(const CssMediaRule& rhs) const {
914
+ // Invert from equality
915
+ return !(*this == rhs);
916
+ }
917
+
918
+ ATTACH_AST_OPERATIONS(CssMediaRule)
919
+ ATTACH_CRTP_PERFORM_METHODS()
920
+ };
921
+
922
+ // Media Queries after they have been evaluated
923
+ // Representing the static or resulting css
924
+ class CssMediaQuery final : public AST_Node {
925
+
926
+ // The modifier, probably either "not" or "only".
927
+ // This may be `null` if no modifier is in use.
928
+ ADD_PROPERTY(std::string, modifier);
929
+
930
+ // The media type, for example "screen" or "print".
931
+ // This may be `null`. If so, [features] will not be empty.
932
+ ADD_PROPERTY(std::string, type);
933
+
934
+ // Feature queries, including parentheses.
935
+ ADD_PROPERTY(std::vector<std::string>, features);
936
+
937
+ public:
938
+ CssMediaQuery(ParserState pstate);
939
+
940
+ // Check if two instances are considered equal
941
+ bool operator== (const CssMediaQuery& rhs) const;
942
+ bool operator!=(const CssMediaQuery& rhs) const {
943
+ // Invert from equality
944
+ return !(*this == rhs);
945
+ }
946
+
947
+ // Returns true if this query is empty
948
+ // Meaning it has no type and features
949
+ bool empty() const {
950
+ return type_.empty()
951
+ && modifier_.empty()
952
+ && features_.empty();
953
+ }
954
+
955
+ // Whether this media query matches all media types.
956
+ bool matchesAllTypes() const {
957
+ return type_.empty() || Util::equalsLiteral("all", type_);
958
+ }
959
+
960
+ // Merges this with [other] and adds a query that matches the intersection
961
+ // of both inputs to [result]. Returns false if the result is unrepresentable
962
+ CssMediaQuery_Obj merge(CssMediaQuery_Obj& other);
963
+
964
+ ATTACH_AST_OPERATIONS(CssMediaQuery)
965
+ ATTACH_CRTP_PERFORM_METHODS()
966
+ };
967
+
968
+ ////////////////////////////////////////////////////
969
+ // Media queries (replaced by MediaRule at al).
970
+ // ToDo: only used for interpolation case
971
+ ////////////////////////////////////////////////////
812
972
  class Media_Query final : public Expression,
813
973
  public Vectorized<Media_Query_Expression_Obj> {
814
974
  ADD_PROPERTY(String_Obj, media_type)
@@ -822,6 +982,7 @@ namespace Sass {
822
982
 
823
983
  ////////////////////////////////////////////////////
824
984
  // Media expressions (for use inside media queries).
985
+ // ToDo: only used for interpolation case
825
986
  ////////////////////////////////////////////////////
826
987
  class Media_Query_Expression final : public Expression {
827
988
  ADD_PROPERTY(Expression_Obj, feature)