sassc 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)