zuora_connect_ui 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (449) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/zuora_connect_ui.js +1 -0
  3. data/app/assets/javascripts/zuora_connect_ui/util.js +51 -0
  4. data/app/assets/stylesheets/_zuora_connect_ui.scss +4 -6
  5. data/app/assets/stylesheets/zuora_connect_ui/datatables.scss +3 -3
  6. data/app/helpers/zuora_connect_ui/application_helper.rb +28 -4
  7. data/app/views/partials/_table.html.erb +16 -7
  8. data/lib/zuora_connect_ui/version.rb +1 -1
  9. data/vendor/ruby/2.6.0/cache/autoprefixer-rails-9.6.1.1.gem +0 -0
  10. data/vendor/ruby/2.6.0/cache/parser-2.6.4.1.gem +0 -0
  11. data/vendor/ruby/2.6.0/cache/sassc-2.2.0.gem +0 -0
  12. data/vendor/ruby/2.6.0/cache/zeitwerk-2.1.10.gem +0 -0
  13. data/vendor/ruby/2.6.0/extensions/x86_64-linux/2.6.0/sassc-2.2.0/gem.build_complete +0 -0
  14. data/vendor/ruby/2.6.0/extensions/x86_64-linux/2.6.0/sassc-2.2.0/gem_make.out +75 -0
  15. data/vendor/ruby/2.6.0/extensions/x86_64-linux/2.6.0/sassc-2.2.0/sassc/libsass.so +0 -0
  16. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/CHANGELOG.md +1085 -0
  17. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/Gemfile +10 -0
  18. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/LICENSE +20 -0
  19. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/README.md +237 -0
  20. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/Rakefile +53 -0
  21. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/autoprefixer-rails.gemspec +32 -0
  22. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails.rb +41 -0
  23. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails/processor.rb +194 -0
  24. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails/railtie.rb +50 -0
  25. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails/result.rb +24 -0
  26. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails/sprockets.rb +62 -0
  27. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/autoprefixer-rails/version.rb +3 -0
  28. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/lib/rake/autoprefixer_tasks.rb +28 -0
  29. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/Rakefile +2 -0
  30. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/config/manifest.js +0 -0
  31. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/stylesheets/evaluate.css.erb +1 -0
  32. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/stylesheets/loaded.sass +2 -0
  33. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/stylesheets/sass.sass +1 -0
  34. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/stylesheets/test.css +3 -0
  35. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/assets/stylesheets/wrong.css +2 -0
  36. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/controllers/application_controller.rb +2 -0
  37. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/app/controllers/css_controller.rb +6 -0
  38. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config.ru +2 -0
  39. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/application.rb +16 -0
  40. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/autoprefixer.yml +2 -0
  41. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/boot.rb +2 -0
  42. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/environment.rb +3 -0
  43. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/environments/test.rb +9 -0
  44. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/initializers/secret_token.rb +1 -0
  45. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/app/config/routes.rb +3 -0
  46. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/autoprefixer_spec.rb +121 -0
  47. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/processor_spec.rb +25 -0
  48. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/rails_spec.rb +40 -0
  49. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/railtie_spec.rb +29 -0
  50. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/spec/spec_helper.rb +16 -0
  51. data/vendor/ruby/2.6.0/gems/autoprefixer-rails-9.6.1.1/vendor/autoprefixer.js +67195 -0
  52. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/CHANGELOG.md +909 -0
  53. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/CONTRIBUTING.md +17 -0
  54. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/Gemfile +10 -0
  55. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/LICENSE.txt +25 -0
  56. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/README.md +301 -0
  57. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/Rakefile +166 -0
  58. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/bin/ruby-parse +7 -0
  59. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/bin/ruby-rewrite +7 -0
  60. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/ci/run_rubocop_specs +14 -0
  61. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/doc/AST_FORMAT.md +1816 -0
  62. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/doc/CUSTOMIZATION.md +37 -0
  63. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/doc/INTERNALS.md +21 -0
  64. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/doc/css/common.css +68 -0
  65. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/gauntlet_parser.rb +123 -0
  66. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser.rb +82 -0
  67. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/all.rb +12 -0
  68. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ast/node.rb +40 -0
  69. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ast/processor.rb +264 -0
  70. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/base.rb +270 -0
  71. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/builders/default.rb +1741 -0
  72. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/clobbering_error.rb +13 -0
  73. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/color.rb +32 -0
  74. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/context.rb +59 -0
  75. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/current.rb +92 -0
  76. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/deprecation.rb +13 -0
  77. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/diagnostic.rb +163 -0
  78. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/diagnostic/engine.rb +105 -0
  79. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer.rb +23546 -0
  80. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer.rl +2503 -0
  81. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer/dedenter.rb +79 -0
  82. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer/explanation.rb +55 -0
  83. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer/literal.rb +269 -0
  84. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer/max_numparam_stack.rb +42 -0
  85. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/lexer/stack_state.rb +49 -0
  86. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/macruby.rb +6124 -0
  87. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/macruby.y +2198 -0
  88. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/messages.rb +90 -0
  89. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/meta.rb +33 -0
  90. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/rewriter.rb +105 -0
  91. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby18.rb +5661 -0
  92. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby18.y +1934 -0
  93. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby19.rb +6084 -0
  94. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby19.y +2175 -0
  95. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby20.rb +6511 -0
  96. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby20.y +2353 -0
  97. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby21.rb +6570 -0
  98. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby21.y +2357 -0
  99. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby22.rb +6605 -0
  100. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby22.y +2364 -0
  101. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby23.rb +6624 -0
  102. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby23.y +2370 -0
  103. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby24.rb +6689 -0
  104. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby24.y +2408 -0
  105. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby25.rb +6656 -0
  106. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby25.y +2405 -0
  107. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby26.rb +6670 -0
  108. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby26.y +2413 -0
  109. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby27.rb +6893 -0
  110. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/ruby27.y +2470 -0
  111. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/rubymotion.rb +6078 -0
  112. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/rubymotion.y +2182 -0
  113. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/runner.rb +253 -0
  114. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/runner/ruby_parse.rb +157 -0
  115. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/runner/ruby_rewrite.rb +101 -0
  116. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/buffer.rb +330 -0
  117. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/comment.rb +121 -0
  118. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/comment/associator.rb +210 -0
  119. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map.rb +186 -0
  120. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/collection.rb +18 -0
  121. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/condition.rb +21 -0
  122. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/constant.rb +32 -0
  123. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/definition.rb +23 -0
  124. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/for.rb +19 -0
  125. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/heredoc.rb +19 -0
  126. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/index.rb +33 -0
  127. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/keyword.rb +20 -0
  128. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/objc_kwarg.rb +19 -0
  129. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/operator.rb +17 -0
  130. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/rescue_body.rb +21 -0
  131. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/send.rb +36 -0
  132. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/ternary.rb +18 -0
  133. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/map/variable.rb +31 -0
  134. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/range.rb +310 -0
  135. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/rewriter.rb +513 -0
  136. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/rewriter/action.rb +44 -0
  137. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/tree_rewriter.rb +301 -0
  138. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/source/tree_rewriter/action.rb +133 -0
  139. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/static_environment.rb +46 -0
  140. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/syntax_error.rb +21 -0
  141. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/tree_rewriter.rb +134 -0
  142. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/lib/parser/version.rb +5 -0
  143. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/parser.gemspec +51 -0
  144. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/bug_163/fixtures/input.rb +5 -0
  145. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/bug_163/fixtures/output.rb +5 -0
  146. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/bug_163/rewriter.rb +20 -0
  147. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/helper.rb +59 -0
  148. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/parse_helper.rb +316 -0
  149. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/racc_coverage_helper.rb +133 -0
  150. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_base.rb +31 -0
  151. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_current.rb +29 -0
  152. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_diagnostic.rb +96 -0
  153. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_diagnostic_engine.rb +62 -0
  154. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_encoding.rb +99 -0
  155. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_lexer.rb +3659 -0
  156. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_lexer_stack_state.rb +78 -0
  157. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_parse_helper.rb +80 -0
  158. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_parser.rb +7579 -0
  159. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_runner_parse.rb +35 -0
  160. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_runner_rewrite.rb +47 -0
  161. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_buffer.rb +162 -0
  162. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_comment.rb +36 -0
  163. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_comment_associator.rb +367 -0
  164. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_map.rb +15 -0
  165. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_range.rb +172 -0
  166. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_rewriter.rb +541 -0
  167. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_rewriter_action.rb +46 -0
  168. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_source_tree_rewriter.rb +173 -0
  169. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/test_static_environment.rb +45 -0
  170. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/using_tree_rewriter/fixtures/input.rb +3 -0
  171. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/using_tree_rewriter/fixtures/output.rb +3 -0
  172. data/vendor/ruby/2.6.0/gems/parser-2.6.4.1/test/using_tree_rewriter/using_tree_rewriter.rb +9 -0
  173. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/CHANGELOG.md +77 -0
  174. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/CODE_OF_CONDUCT.md +10 -0
  175. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/Gemfile +2 -0
  176. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/LICENSE.txt +22 -0
  177. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/README.md +68 -0
  178. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/Rakefile +53 -0
  179. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/Makefile +271 -0
  180. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/SharedPtr.o +0 -0
  181. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast.o +0 -0
  182. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast2c.o +0 -0
  183. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_fwd_decl.o +0 -0
  184. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_sel_cmp.o +0 -0
  185. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_sel_unify.o +0 -0
  186. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_selectors.o +0 -0
  187. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_supports.o +0 -0
  188. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/ast_values.o +0 -0
  189. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/backtrace.o +0 -0
  190. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/base64vlq.o +0 -0
  191. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/bind.o +0 -0
  192. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/c2ast.o +0 -0
  193. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/c99func.o +0 -0
  194. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/cencode.o +0 -0
  195. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/check_nesting.o +0 -0
  196. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/color_maps.o +0 -0
  197. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/constants.o +0 -0
  198. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/context.o +0 -0
  199. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/cssize.o +0 -0
  200. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/depend +4 -0
  201. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/emitter.o +0 -0
  202. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/environment.o +0 -0
  203. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/error_handling.o +0 -0
  204. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/eval.o +0 -0
  205. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/expand.o +0 -0
  206. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/extconf.rb +84 -0
  207. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/extend.o +0 -0
  208. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/file.o +0 -0
  209. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_colors.o +0 -0
  210. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_lists.o +0 -0
  211. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_maps.o +0 -0
  212. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_miscs.o +0 -0
  213. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_numbers.o +0 -0
  214. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_selectors.o +0 -0
  215. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_strings.o +0 -0
  216. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/fn_utils.o +0 -0
  217. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/inspect.o +0 -0
  218. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/json.o +0 -0
  219. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/lexer.o +0 -0
  220. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass.so +0 -0
  221. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/VERSION +1 -0
  222. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/contrib/plugin.cpp +60 -0
  223. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass.h +15 -0
  224. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass/base.h +96 -0
  225. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass/context.h +170 -0
  226. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass/functions.h +139 -0
  227. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass/values.h +145 -0
  228. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass/version.h +12 -0
  229. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/include/sass2scss.h +120 -0
  230. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast.cpp +963 -0
  231. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast.hpp +905 -0
  232. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast2c.cpp +80 -0
  233. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast2c.hpp +39 -0
  234. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_def_macros.hpp +132 -0
  235. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_fwd_decl.cpp +30 -0
  236. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_fwd_decl.hpp +341 -0
  237. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_sel_cmp.cpp +909 -0
  238. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_sel_unify.cpp +280 -0
  239. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_selectors.cpp +1475 -0
  240. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_selectors.hpp +568 -0
  241. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_supports.cpp +130 -0
  242. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_supports.hpp +121 -0
  243. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_values.cpp +967 -0
  244. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/ast_values.hpp +489 -0
  245. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/b64/cencode.h +32 -0
  246. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/b64/encode.h +79 -0
  247. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/backtrace.cpp +50 -0
  248. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/backtrace.hpp +29 -0
  249. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/base64vlq.cpp +47 -0
  250. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/base64vlq.hpp +30 -0
  251. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/bind.cpp +312 -0
  252. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/bind.hpp +15 -0
  253. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/c2ast.cpp +64 -0
  254. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/c2ast.hpp +14 -0
  255. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/c99func.c +54 -0
  256. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/cencode.c +108 -0
  257. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/check_nesting.cpp +394 -0
  258. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/check_nesting.hpp +66 -0
  259. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/color_maps.cpp +651 -0
  260. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/color_maps.hpp +331 -0
  261. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/constants.cpp +194 -0
  262. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/constants.hpp +194 -0
  263. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/context.cpp +890 -0
  264. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/context.hpp +152 -0
  265. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/cssize.cpp +604 -0
  266. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/cssize.hpp +77 -0
  267. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/debug.hpp +43 -0
  268. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/debugger.hpp +807 -0
  269. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/emitter.cpp +298 -0
  270. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/emitter.hpp +103 -0
  271. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/environment.cpp +260 -0
  272. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/environment.hpp +119 -0
  273. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/error_handling.cpp +212 -0
  274. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/error_handling.hpp +229 -0
  275. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/eval.cpp +1657 -0
  276. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/eval.hpp +112 -0
  277. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/expand.cpp +822 -0
  278. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/expand.hpp +78 -0
  279. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/extend.cpp +2132 -0
  280. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/extend.hpp +86 -0
  281. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/file.cpp +522 -0
  282. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/file.hpp +133 -0
  283. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_colors.cpp +594 -0
  284. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_colors.hpp +85 -0
  285. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_lists.cpp +284 -0
  286. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_lists.hpp +34 -0
  287. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_maps.cpp +94 -0
  288. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_maps.hpp +30 -0
  289. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_miscs.cpp +256 -0
  290. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_miscs.hpp +40 -0
  291. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_numbers.cpp +220 -0
  292. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_numbers.hpp +45 -0
  293. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_selectors.cpp +235 -0
  294. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_selectors.hpp +35 -0
  295. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_strings.cpp +254 -0
  296. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_strings.hpp +34 -0
  297. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_utils.cpp +156 -0
  298. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/fn_utils.hpp +56 -0
  299. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/inspect.cpp +1087 -0
  300. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/inspect.hpp +99 -0
  301. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/json.cpp +1436 -0
  302. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/json.hpp +117 -0
  303. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/kwd_arg_macros.hpp +28 -0
  304. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/lexer.cpp +184 -0
  305. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/lexer.hpp +315 -0
  306. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/listize.cpp +84 -0
  307. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/listize.hpp +38 -0
  308. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/mapping.hpp +18 -0
  309. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/memory/SharedPtr.cpp +33 -0
  310. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/memory/SharedPtr.hpp +286 -0
  311. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/node.cpp +322 -0
  312. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/node.hpp +118 -0
  313. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/operation.hpp +213 -0
  314. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/operators.cpp +266 -0
  315. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/operators.hpp +30 -0
  316. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/output.cpp +339 -0
  317. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/output.hpp +47 -0
  318. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/parser.cpp +3153 -0
  319. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/parser.hpp +402 -0
  320. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/paths.hpp +71 -0
  321. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/plugins.cpp +188 -0
  322. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/plugins.hpp +57 -0
  323. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/position.cpp +184 -0
  324. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/position.hpp +124 -0
  325. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/prelexer.cpp +1780 -0
  326. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/prelexer.hpp +484 -0
  327. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/remove_placeholders.cpp +87 -0
  328. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/remove_placeholders.hpp +34 -0
  329. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass.cpp +155 -0
  330. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass.hpp +142 -0
  331. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass2scss.cpp +895 -0
  332. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_context.cpp +772 -0
  333. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_context.hpp +129 -0
  334. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_functions.cpp +210 -0
  335. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_functions.hpp +50 -0
  336. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_util.cpp +152 -0
  337. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_util.hpp +256 -0
  338. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_values.cpp +365 -0
  339. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/sass_values.hpp +82 -0
  340. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/source_map.cpp +198 -0
  341. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/source_map.hpp +62 -0
  342. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/subset_map.cpp +58 -0
  343. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/subset_map.hpp +76 -0
  344. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/to_value.cpp +114 -0
  345. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/to_value.hpp +46 -0
  346. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/units.cpp +505 -0
  347. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/units.hpp +110 -0
  348. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8.h +34 -0
  349. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8/checked.h +336 -0
  350. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8/core.h +332 -0
  351. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8/unchecked.h +235 -0
  352. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8_string.cpp +105 -0
  353. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/utf8_string.hpp +37 -0
  354. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/util.cpp +725 -0
  355. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/util.hpp +106 -0
  356. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/util_string.cpp +75 -0
  357. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/util_string.hpp +19 -0
  358. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/values.cpp +140 -0
  359. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/libsass/src/values.hpp +12 -0
  360. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/listize.o +0 -0
  361. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/node.o +0 -0
  362. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/operators.o +0 -0
  363. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/output.o +0 -0
  364. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/parser.o +0 -0
  365. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/plugins.o +0 -0
  366. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/position.o +0 -0
  367. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/prelexer.o +0 -0
  368. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/remove_placeholders.o +0 -0
  369. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass.o +0 -0
  370. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass2scss.o +0 -0
  371. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass_context.o +0 -0
  372. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass_functions.o +0 -0
  373. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass_util.o +0 -0
  374. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/sass_values.o +0 -0
  375. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/source_map.o +0 -0
  376. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/subset_map.o +0 -0
  377. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/to_value.o +0 -0
  378. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/units.o +0 -0
  379. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/utf8_string.o +0 -0
  380. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/util.o +0 -0
  381. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/util_string.o +0 -0
  382. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/ext/values.o +0 -0
  383. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc.rb +57 -0
  384. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/dependency.rb +17 -0
  385. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/engine.rb +139 -0
  386. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/error.rb +37 -0
  387. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/functions_handler.rb +73 -0
  388. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/import_handler.rb +50 -0
  389. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/importer.rb +31 -0
  390. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/libsass.so +0 -0
  391. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native.rb +62 -0
  392. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/lib_c.rb +21 -0
  393. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/native_context_api.rb +147 -0
  394. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/native_functions_api.rb +159 -0
  395. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/sass2scss_api.rb +10 -0
  396. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/sass_input_style.rb +13 -0
  397. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/sass_output_style.rb +12 -0
  398. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/sass_value.rb +97 -0
  399. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/native/string_list.rb +10 -0
  400. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/sass_2_scss.rb +9 -0
  401. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script.rb +17 -0
  402. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/functions.rb +8 -0
  403. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value.rb +137 -0
  404. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/bool.rb +32 -0
  405. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/color.rb +95 -0
  406. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/list.rb +136 -0
  407. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/map.rb +69 -0
  408. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/number.rb +389 -0
  409. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value/string.rb +96 -0
  410. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion.rb +69 -0
  411. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/base.rb +13 -0
  412. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/bool.rb +13 -0
  413. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/color.rb +18 -0
  414. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/list.rb +25 -0
  415. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/map.rb +21 -0
  416. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/number.rb +13 -0
  417. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/script/value_conversion/string.rb +17 -0
  418. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/util.rb +231 -0
  419. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/util/normalized_map.rb +117 -0
  420. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/lib/sassc/version.rb +5 -0
  421. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/sassc.gemspec +69 -0
  422. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/custom_importer_test.rb +127 -0
  423. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/engine_test.rb +314 -0
  424. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/error_test.rb +29 -0
  425. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/fixtures/paths.scss +10 -0
  426. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/functions_test.rb +323 -0
  427. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/native_test.rb +213 -0
  428. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/output_style_test.rb +107 -0
  429. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/sass_2_scss_test.rb +14 -0
  430. data/vendor/ruby/2.6.0/gems/sassc-2.2.0/test/test_helper.rb +45 -0
  431. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/README.md +533 -0
  432. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk.rb +12 -0
  433. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/error.rb +10 -0
  434. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/explicit_namespace.rb +80 -0
  435. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/gem_inflector.rb +19 -0
  436. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/inflector.rb +19 -0
  437. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/kernel.rb +33 -0
  438. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/loader.rb +759 -0
  439. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/loader/callbacks.rb +71 -0
  440. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/real_mod_name.rb +15 -0
  441. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/registry.rb +147 -0
  442. data/vendor/ruby/2.6.0/gems/zeitwerk-2.1.10/lib/zeitwerk/version.rb +5 -0
  443. data/vendor/ruby/2.6.0/specifications/autoprefixer-rails-9.6.1.1.gemspec +47 -0
  444. data/vendor/ruby/2.6.0/specifications/parser-2.6.4.1.gemspec +62 -0
  445. data/vendor/ruby/2.6.0/specifications/sassc-2.2.0.gemspec +60 -0
  446. data/vendor/ruby/2.6.0/specifications/zeitwerk-2.1.10.gemspec +21 -0
  447. metadata +441 -4
  448. data/vendor/assets/anjuna/css/anjuna-application.css +0 -2
  449. data/vendor/assets/anjuna/css/anjuna-theme.css +0 -2
@@ -0,0 +1,78 @@
1
+ #ifndef SASS_EXPAND_H
2
+ #define SASS_EXPAND_H
3
+
4
+ #include <vector>
5
+
6
+ #include "ast.hpp"
7
+ #include "eval.hpp"
8
+ #include "operation.hpp"
9
+ #include "environment.hpp"
10
+
11
+ namespace Sass {
12
+
13
+ class Listize;
14
+ class Context;
15
+ class Eval;
16
+ struct Backtrace;
17
+
18
+ class Expand : public Operation_CRTP<Statement*, Expand> {
19
+ public:
20
+
21
+ Env* environment();
22
+ Selector_List_Obj selector();
23
+
24
+ Context& ctx;
25
+ Backtraces& traces;
26
+ Eval eval;
27
+ size_t recursions;
28
+ bool in_keyframes;
29
+ bool at_root_without_rule;
30
+ bool old_at_root_without_rule;
31
+
32
+ // it's easier to work with vectors
33
+ EnvStack env_stack;
34
+ BlockStack block_stack;
35
+ CallStack call_stack;
36
+ SelectorStack selector_stack;
37
+ MediaStack media_stack;
38
+
39
+ Boolean_Obj bool_true;
40
+
41
+ private:
42
+ void expand_selector_list(Selector_Obj, Selector_List_Obj extender);
43
+
44
+ public:
45
+ Expand(Context&, Env*, SelectorStack* stack = NULL);
46
+ ~Expand() { }
47
+
48
+ Block* operator()(Block*);
49
+ Statement* operator()(Ruleset*);
50
+ Statement* operator()(Media_Block*);
51
+ Statement* operator()(Supports_Block*);
52
+ Statement* operator()(At_Root_Block*);
53
+ Statement* operator()(Directive*);
54
+ Statement* operator()(Declaration*);
55
+ Statement* operator()(Assignment*);
56
+ Statement* operator()(Import*);
57
+ Statement* operator()(Import_Stub*);
58
+ Statement* operator()(Warning*);
59
+ Statement* operator()(Error*);
60
+ Statement* operator()(Debug*);
61
+ Statement* operator()(Comment*);
62
+ Statement* operator()(If*);
63
+ Statement* operator()(For*);
64
+ Statement* operator()(Each*);
65
+ Statement* operator()(While*);
66
+ Statement* operator()(Return*);
67
+ Statement* operator()(Extension*);
68
+ Statement* operator()(Definition*);
69
+ Statement* operator()(Mixin_Call*);
70
+ Statement* operator()(Content*);
71
+
72
+ void append_block(Block*);
73
+
74
+ };
75
+
76
+ }
77
+
78
+ #endif
@@ -0,0 +1,2132 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include "extend.hpp"
6
+ #include "context.hpp"
7
+ #include "backtrace.hpp"
8
+ #include "paths.hpp"
9
+ #include "parser.hpp"
10
+ #include "expand.hpp"
11
+ #include "node.hpp"
12
+ #include "sass_util.hpp"
13
+ #include "remove_placeholders.hpp"
14
+ #include "debug.hpp"
15
+ #include <iostream>
16
+ #include <deque>
17
+ #include <set>
18
+
19
+ /*
20
+ NOTES:
21
+
22
+ - The print* functions print to cerr. This allows our testing frameworks (like sass-spec) to ignore the output, which
23
+ is very helpful when debugging. The format of the output is mainly to wrap things in square brackets to match what
24
+ ruby already outputs (to make comparisons easier).
25
+
26
+ - For the direct porting effort, we're trying to port method-for-method until we get all the tests passing.
27
+ Where applicable, I've tried to include the ruby code above the function for reference until all our tests pass.
28
+ The ruby code isn't always directly portable, so I've tried to include any modified ruby code that was actually
29
+ used for the porting.
30
+
31
+ - DO NOT try to optimize yet. We get a tremendous benefit out of comparing the output of each stage of the extend to the ruby
32
+ output at the same stage. This makes it much easier to determine where problems are. Try to keep as close to
33
+ the ruby code as you can until we have all the sass-spec tests passing. Then, we should optimize. However, if you see
34
+ something that could probably be optimized, let's not forget it. Add a // TODO: or // IMPROVEMENT: comment.
35
+
36
+ - Coding conventions in this file (these may need to be changed before merging back into master)
37
+ - Very basic hungarian notation:
38
+ p prefix for pointers (pSelector)
39
+ no prefix for value types and references (selector)
40
+ - Use STL iterators where possible
41
+ - prefer verbose naming over terse naming
42
+ - use typedefs for STL container types for make maintenance easier
43
+
44
+ - You may see a lot of comments that say "// TODO: is this the correct combinator?". See the comment referring to combinators
45
+ in extendCompoundSelector for a more extensive explanation of my confusion. I think our divergence in data model from ruby
46
+ sass causes this to be necessary.
47
+
48
+
49
+ GLOBAL TODOS:
50
+
51
+ - wrap the contents of the print functions in DEBUG preprocesser conditionals so they will be optimized away in non-debug mode.
52
+
53
+ - consider making the extend* functions member functions to avoid passing around ctx and subset_map map around. This has the
54
+ drawback that the implementation details of the operator are then exposed to the outside world, which is not ideal and
55
+ can cause additional compile time dependencies.
56
+
57
+ - mark the helper methods in this file static to given them compilation unit linkage.
58
+
59
+ - implement parent directive matching
60
+
61
+ - fix compilation warnings for unused Extend members if we really don't need those references anymore.
62
+ */
63
+
64
+
65
+ namespace Sass {
66
+
67
+
68
+
69
+ #ifdef DEBUG
70
+
71
+ // TODO: move the ast specific ostream operators into ast.hpp/ast.cpp
72
+ std::ostream& operator<<(std::ostream& os, const Complex_Selector::Combinator combinator) {
73
+ switch (combinator) {
74
+ case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
75
+ case Complex_Selector::PARENT_OF: os << "\">\""; break;
76
+ case Complex_Selector::PRECEDES: os << "\"~\""; break;
77
+ case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
78
+ case Complex_Selector::REFERENCE: os << "\"/\""; break;
79
+ }
80
+
81
+ return os;
82
+ }
83
+
84
+
85
+ std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
86
+ for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
87
+ if (i > 0) os << ", ";
88
+ os << compoundSelector[i]->to_string();
89
+ }
90
+ return os;
91
+ }
92
+
93
+ std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) {
94
+ os << simpleSelector.to_string();
95
+ return os;
96
+ }
97
+
98
+ // Print a string representation of a Compound_Selector
99
+ static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
100
+
101
+ if (message) {
102
+ std::cerr << message;
103
+ }
104
+
105
+ if (pSimpleSelector) {
106
+ std::cerr << "[" << *pSimpleSelector << "]";
107
+ } else {
108
+ std::cerr << "NULL";
109
+ }
110
+
111
+ if (newline) {
112
+ std::cerr << std::endl;
113
+ }
114
+ }
115
+
116
+ // Print a string representation of a Compound_Selector
117
+ static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
118
+
119
+ if (message) {
120
+ std::cerr << message;
121
+ }
122
+
123
+ if (pCompoundSelector) {
124
+ std::cerr << "[" << *pCompoundSelector << "]";
125
+ } else {
126
+ std::cerr << "NULL";
127
+ }
128
+
129
+ if (newline) {
130
+ std::cerr << std::endl;
131
+ }
132
+ }
133
+
134
+
135
+ std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) {
136
+
137
+ os << "[";
138
+ Complex_Selector* pIter = &complexSelector;
139
+ bool first = true;
140
+ while (pIter) {
141
+ if (pIter->combinator() != Complex_Selector::ANCESTOR_OF) {
142
+ if (!first) {
143
+ os << ", ";
144
+ }
145
+ first = false;
146
+ os << pIter->combinator();
147
+ }
148
+
149
+ if (!first) {
150
+ os << ", ";
151
+ }
152
+ first = false;
153
+
154
+ if (pIter->head()) {
155
+ os << pIter->head()->to_string();
156
+ } else {
157
+ os << "NULL_HEAD";
158
+ }
159
+
160
+ pIter = pIter->tail();
161
+ }
162
+ os << "]";
163
+
164
+ return os;
165
+ }
166
+
167
+
168
+ // Print a string representation of a Complex_Selector
169
+ static void printComplexSelector(Complex_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
170
+
171
+ if (message) {
172
+ std::cerr << message;
173
+ }
174
+
175
+ if (pComplexSelector) {
176
+ std::cerr << *pComplexSelector;
177
+ } else {
178
+ std::cerr << "NULL";
179
+ }
180
+
181
+ if (newline) {
182
+ std::cerr << std::endl;
183
+ }
184
+ }
185
+
186
+ static void printSelsNewSeqPairCollection(SubSetMapLookups& collection, const char* message=NULL, bool newline=true) {
187
+
188
+ if (message) {
189
+ std::cerr << message;
190
+ }
191
+ bool first = true;
192
+ std::cerr << "[";
193
+ for(SubSetMapLookup& pair : collection) {
194
+ if (first) {
195
+ first = false;
196
+ } else {
197
+ std::cerr << ", ";
198
+ }
199
+ std::cerr << "[";
200
+ Compound_Selector* pSels = pair.first;
201
+ Complex_Selector* pNewSelector = pair.second;
202
+ std::cerr << "[" << *pSels << "], ";
203
+ printComplexSelector(pNewSelector, NULL, false);
204
+ }
205
+ std::cerr << "]";
206
+
207
+ if (newline) {
208
+ std::cerr << std::endl;
209
+ }
210
+ }
211
+
212
+ // Print a string representation of a ComplexSelectorSet
213
+ static void printSourcesSet(ComplexSelectorSet& sources, const char* message=NULL, bool newline=true) {
214
+
215
+ if (message) {
216
+ std::cerr << message;
217
+ }
218
+
219
+ // Convert to a deque of strings so we can sort since order doesn't matter in a set. This should cut down on
220
+ // the differences we see when debug printing.
221
+ typedef std::deque<std::string> SourceStrings;
222
+ SourceStrings sourceStrings;
223
+ for (ComplexSelectorSet::iterator iterator = sources.begin(), iteratorEnd = sources.end(); iterator != iteratorEnd; ++iterator) {
224
+ Complex_Selector* pSource = *iterator;
225
+ std::stringstream sstream;
226
+ sstream << complexSelectorToNode(pSource);
227
+ sourceStrings.push_back(sstream.str());
228
+ }
229
+
230
+ // Sort to get consistent output
231
+ std::sort(sourceStrings.begin(), sourceStrings.end());
232
+
233
+ std::cerr << "ComplexSelectorSet[";
234
+ for (SourceStrings::iterator iterator = sourceStrings.begin(), iteratorEnd = sourceStrings.end(); iterator != iteratorEnd; ++iterator) {
235
+ std::string source = *iterator;
236
+ if (iterator != sourceStrings.begin()) {
237
+ std::cerr << ", ";
238
+ }
239
+ std::cerr << source;
240
+ }
241
+ std::cerr << "]";
242
+
243
+ if (newline) {
244
+ std::cerr << std::endl;
245
+ }
246
+ }
247
+
248
+
249
+ std::ostream& operator<<(std::ostream& os, SubSetMapPairs& entries) {
250
+ os << "SUBSET_MAP_ENTRIES[";
251
+
252
+ for (SubSetMapPairs::iterator iterator = entries.begin(), endIterator = entries.end(); iterator != endIterator; ++iterator) {
253
+ Complex_Selector_Obj pExtComplexSelector = iterator->first; // The selector up to where the @extend is (ie, the thing to merge)
254
+ Compound_Selector_Obj pExtCompoundSelector = iterator->second; // The stuff after the @extend
255
+
256
+ if (iterator != entries.begin()) {
257
+ os << ", ";
258
+ }
259
+
260
+ os << "(";
261
+
262
+ if (pExtComplexSelector) {
263
+ std::cerr << *pExtComplexSelector;
264
+ } else {
265
+ std::cerr << "NULL";
266
+ }
267
+
268
+ os << " -> ";
269
+
270
+ if (pExtCompoundSelector) {
271
+ std::cerr << *pExtCompoundSelector;
272
+ } else {
273
+ std::cerr << "NULL";
274
+ }
275
+
276
+ os << ")";
277
+
278
+ }
279
+
280
+ os << "]";
281
+
282
+ return os;
283
+ }
284
+ #endif
285
+
286
+ static bool parentSuperselector(Complex_Selector* pOne, Complex_Selector* pTwo) {
287
+ // TODO: figure out a better way to create a Complex_Selector from scratch
288
+ // TODO: There's got to be a better way. This got ugly quick...
289
+ Type_Selector_Obj fakeParent = SASS_MEMORY_NEW(Type_Selector, ParserState("[FAKE]"), "temp");
290
+ Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
291
+ fakeHead->elements().push_back(fakeParent);
292
+ Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, {} /*tail*/);
293
+
294
+ pOne->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
295
+ pTwo->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
296
+
297
+ bool isSuperselector = pOne->is_superselector_of(pTwo);
298
+
299
+ pOne->clear_innermost();
300
+ pTwo->clear_innermost();
301
+
302
+ return isSuperselector;
303
+ }
304
+
305
+ void nodeToComplexSelectorDeque(const Node& node, ComplexSelectorDeque& out) {
306
+ for (NodeDeque::iterator iter = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
307
+ Node& child = *iter;
308
+ out.push_back(nodeToComplexSelector(child));
309
+ }
310
+ }
311
+
312
+ Node complexSelectorDequeToNode(const ComplexSelectorDeque& deque) {
313
+ Node result = Node::createCollection();
314
+
315
+ for (ComplexSelectorDeque::const_iterator iter = deque.begin(), iterEnd = deque.end(); iter != iterEnd; iter++) {
316
+ Complex_Selector_Obj pChild = *iter;
317
+ result.collection()->push_back(complexSelectorToNode(pChild));
318
+ }
319
+
320
+ return result;
321
+ }
322
+
323
+ class LcsCollectionComparator {
324
+ public:
325
+ LcsCollectionComparator() {}
326
+
327
+ bool operator()(Complex_Selector_Obj pOne, Complex_Selector_Obj pTwo, Complex_Selector_Obj& pOut) const {
328
+ /*
329
+ This code is based on the following block from ruby sass' subweave
330
+ do |s1, s2|
331
+ next s1 if s1 == s2
332
+ next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
333
+ next s2 if parent_superselector?(s1, s2)
334
+ next s1 if parent_superselector?(s2, s1)
335
+ end
336
+ */
337
+
338
+ if (*pOne == *pTwo) {
339
+ pOut = pOne;
340
+ return true;
341
+ }
342
+
343
+ if (pOne->combinator() != Complex_Selector::ANCESTOR_OF || pTwo->combinator() != Complex_Selector::ANCESTOR_OF) {
344
+ return false;
345
+ }
346
+
347
+ if (parentSuperselector(pOne, pTwo)) {
348
+ pOut = pTwo;
349
+ return true;
350
+ }
351
+
352
+ if (parentSuperselector(pTwo, pOne)) {
353
+ pOut = pOne;
354
+ return true;
355
+ }
356
+
357
+ return false;
358
+ }
359
+ };
360
+
361
+
362
+ /*
363
+ This is the equivalent of ruby's Sass::Util.lcs_backtrace.
364
+
365
+ # Computes a single longest common subsequence for arrays x and y.
366
+ # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS
367
+ */
368
+ void lcs_backtrace(const LCSTable& c, ComplexSelectorDeque& x, ComplexSelectorDeque& y, int i, int j, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) {
369
+ //DEBUG_PRINTLN(LCS, "LCSBACK: X=" << x << " Y=" << y << " I=" << i << " J=" << j)
370
+ // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
371
+
372
+ if (i == 0 || j == 0) {
373
+ DEBUG_PRINTLN(LCS, "RETURNING EMPTY")
374
+ return;
375
+ }
376
+
377
+
378
+ Complex_Selector_Obj pCompareOut;
379
+ if (comparator(x[i], y[j], pCompareOut)) {
380
+ DEBUG_PRINTLN(LCS, "RETURNING AFTER ELEM COMPARE")
381
+ lcs_backtrace(c, x, y, i - 1, j - 1, comparator, out);
382
+ out.push_back(pCompareOut);
383
+ return;
384
+ }
385
+
386
+ if (c[i][j - 1] > c[i - 1][j]) {
387
+ DEBUG_PRINTLN(LCS, "RETURNING AFTER TABLE COMPARE")
388
+ lcs_backtrace(c, x, y, i, j - 1, comparator, out);
389
+ return;
390
+ }
391
+
392
+ DEBUG_PRINTLN(LCS, "FINAL RETURN")
393
+ lcs_backtrace(c, x, y, i - 1, j, comparator, out);
394
+ return;
395
+ }
396
+
397
+ /*
398
+ This is the equivalent of ruby's Sass::Util.lcs_table.
399
+
400
+ # Calculates the memoization table for the Least Common Subsequence algorithm.
401
+ # Algorithm from http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS
402
+ */
403
+ void lcs_table(const ComplexSelectorDeque& x, const ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, LCSTable& out) {
404
+ //DEBUG_PRINTLN(LCS, "LCSTABLE: X=" << x << " Y=" << y)
405
+ // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
406
+
407
+ LCSTable c(x.size(), std::vector<int>(y.size()));
408
+
409
+ // These shouldn't be necessary since the vector will be initialized to 0 already.
410
+ // x.size.times {|i| c[i][0] = 0}
411
+ // y.size.times {|j| c[0][j] = 0}
412
+
413
+ for (size_t i = 1; i < x.size(); i++) {
414
+ for (size_t j = 1; j < y.size(); j++) {
415
+ Complex_Selector_Obj pCompareOut;
416
+
417
+ if (comparator(x[i], y[j], pCompareOut)) {
418
+ c[i][j] = c[i - 1][j - 1] + 1;
419
+ } else {
420
+ c[i][j] = std::max(c[i][j - 1], c[i - 1][j]);
421
+ }
422
+ }
423
+ }
424
+
425
+ out = c;
426
+ }
427
+
428
+ /*
429
+ This is the equivalent of ruby's Sass::Util.lcs.
430
+
431
+ # Computes a single longest common subsequence for `x` and `y`.
432
+ # If there are more than one longest common subsequences,
433
+ # the one returned is that which starts first in `x`.
434
+
435
+ # @param x [NodeCollection]
436
+ # @param y [NodeCollection]
437
+ # @comparator An equality check between elements of `x` and `y`.
438
+ # @return [NodeCollection] The LCS
439
+
440
+ http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
441
+ */
442
+ void lcs(ComplexSelectorDeque& x, ComplexSelectorDeque& y, const LcsCollectionComparator& comparator, ComplexSelectorDeque& out) {
443
+ //DEBUG_PRINTLN(LCS, "LCS: X=" << x << " Y=" << y)
444
+ // TODO: make printComplexSelectorDeque and use DEBUG_EXEC AND DEBUG_PRINTLN HERE to get equivalent output
445
+
446
+ x.push_front({});
447
+ y.push_front({});
448
+
449
+ LCSTable table;
450
+ lcs_table(x, y, comparator, table);
451
+
452
+ return lcs_backtrace(table, x, y, static_cast<int>(x.size()) - 1, static_cast<int>(y.size()) - 1, comparator, out);
453
+ }
454
+
455
+
456
+ /*
457
+ This is the equivalent of ruby's Sequence.trim.
458
+
459
+ The following is the modified version of the ruby code that was more portable to C++. You
460
+ should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
461
+
462
+ # Avoid truly horrific quadratic behavior. TODO: I think there
463
+ # may be a way to get perfect trimming without going quadratic.
464
+ return seqses if seqses.size > 100
465
+
466
+ # Keep the results in a separate array so we can be sure we aren't
467
+ # comparing against an already-trimmed selector. This ensures that two
468
+ # identical selectors don't mutually trim one another.
469
+ result = seqses.dup
470
+
471
+ # This is n^2 on the sequences, but only comparing between
472
+ # separate sequences should limit the quadratic behavior.
473
+ seqses.each_with_index do |seqs1, i|
474
+ tempResult = []
475
+
476
+ for seq1 in seqs1 do
477
+ max_spec = 0
478
+ for seq in _sources(seq1) do
479
+ max_spec = [max_spec, seq.specificity].max
480
+ end
481
+
482
+
483
+ isMoreSpecificOuter = false
484
+ for seqs2 in result do
485
+ if seqs1.equal?(seqs2) then
486
+ next
487
+ end
488
+
489
+ # Second Law of Extend: the specificity of a generated selector
490
+ # should never be less than the specificity of the extending
491
+ # selector.
492
+ #
493
+ # See https://github.com/nex3/sass/issues/324.
494
+ isMoreSpecificInner = false
495
+ for seq2 in seqs2 do
496
+ isMoreSpecificInner = _specificity(seq2) >= max_spec && _superselector?(seq2, seq1)
497
+ if isMoreSpecificInner then
498
+ break
499
+ end
500
+ end
501
+
502
+ if isMoreSpecificInner then
503
+ isMoreSpecificOuter = true
504
+ break
505
+ end
506
+ end
507
+
508
+ if !isMoreSpecificOuter then
509
+ tempResult.push(seq1)
510
+ end
511
+ end
512
+
513
+ result[i] = tempResult
514
+
515
+ end
516
+
517
+ result
518
+ */
519
+ /*
520
+ - IMPROVEMENT: We could probably work directly in the output trimmed deque.
521
+ */
522
+ Node Extend::trim(Node& seqses, bool isReplace) {
523
+ // See the comments in the above ruby code before embarking on understanding this function.
524
+
525
+ // Avoid poor performance in extreme cases.
526
+ if (seqses.collection()->size() > 100) {
527
+ return seqses;
528
+ }
529
+
530
+
531
+ DEBUG_PRINTLN(TRIM, "TRIM: " << seqses)
532
+
533
+
534
+ Node result = Node::createCollection();
535
+ result.plus(seqses);
536
+
537
+ DEBUG_PRINTLN(TRIM, "RESULT INITIAL: " << result)
538
+
539
+ // Normally we use the standard STL iterators, but in this case, we need to access the result collection by index since we're
540
+ // iterating the input collection, computing a value, and then setting the result in the output collection. We have to keep track
541
+ // of the index manually.
542
+ int toTrimIndex = 0;
543
+
544
+ for (NodeDeque::iterator seqsesIter = seqses.collection()->begin(), seqsesIterEnd = seqses.collection()->end(); seqsesIter != seqsesIterEnd; ++seqsesIter) {
545
+ Node& seqs1 = *seqsesIter;
546
+
547
+ DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1 << " " << toTrimIndex)
548
+
549
+ Node tempResult = Node::createCollection();
550
+ tempResult.got_line_feed = seqs1.got_line_feed;
551
+
552
+ for (NodeDeque::iterator seqs1Iter = seqs1.collection()->begin(), seqs1EndIter = seqs1.collection()->end(); seqs1Iter != seqs1EndIter; ++seqs1Iter) {
553
+ Node& seq1 = *seqs1Iter;
554
+
555
+ Complex_Selector_Obj pSeq1 = nodeToComplexSelector(seq1);
556
+
557
+ // Compute the maximum specificity. This requires looking at the "sources" of the sequence. See SimpleSequence.sources in the ruby code
558
+ // for a good description of sources.
559
+ //
560
+ // TODO: I'm pretty sure there's a bug in the sources code. It was implemented for sass-spec's 182_test_nested_extend_loop test.
561
+ // While the test passes, I compared the state of each trim call to verify correctness. The last trim call had incorrect sources. We
562
+ // had an extra source that the ruby version did not have. Without a failing test case, this is going to be extra hard to find. My
563
+ // best guess at this point is that we're cloning an object somewhere and maintaining the sources when we shouldn't be. This is purely
564
+ // a guess though.
565
+ unsigned long maxSpecificity = isReplace ? pSeq1->specificity() : 0;
566
+ ComplexSelectorSet sources = pSeq1->sources();
567
+
568
+ DEBUG_PRINTLN(TRIM, "TRIM SEQ1: " << seq1)
569
+ DEBUG_EXEC(TRIM, printSourcesSet(sources, "TRIM SOURCES: "))
570
+
571
+ for (ComplexSelectorSet::iterator sourcesSetIterator = sources.begin(), sourcesSetIteratorEnd = sources.end(); sourcesSetIterator != sourcesSetIteratorEnd; ++sourcesSetIterator) {
572
+ const Complex_Selector_Obj& pCurrentSelector = *sourcesSetIterator;
573
+ maxSpecificity = std::max(maxSpecificity, pCurrentSelector->specificity());
574
+ }
575
+
576
+ DEBUG_PRINTLN(TRIM, "MAX SPECIFICITY: " << maxSpecificity)
577
+
578
+ bool isMoreSpecificOuter = false;
579
+
580
+ int resultIndex = 0;
581
+
582
+ for (NodeDeque::iterator resultIter = result.collection()->begin(), resultIterEnd = result.collection()->end(); resultIter != resultIterEnd; ++resultIter) {
583
+ Node& seqs2 = *resultIter;
584
+
585
+ DEBUG_PRINTLN(TRIM, "SEQS1: " << seqs1)
586
+ DEBUG_PRINTLN(TRIM, "SEQS2: " << seqs2)
587
+
588
+ // Do not compare the same sequence to itself. The ruby call we're trying to
589
+ // emulate is: seqs1.equal?(seqs2). equal? is an object comparison, not an equivalency comparision.
590
+ // Since we have the same pointers in seqes and results, we can do a pointer comparision. seqs1 is
591
+ // derived from seqses and seqs2 is derived from result.
592
+ if (seqs1.collection() == seqs2.collection()) {
593
+ DEBUG_PRINTLN(TRIM, "CONTINUE")
594
+ continue;
595
+ }
596
+
597
+ bool isMoreSpecificInner = false;
598
+
599
+ for (NodeDeque::iterator seqs2Iter = seqs2.collection()->begin(), seqs2IterEnd = seqs2.collection()->end(); seqs2Iter != seqs2IterEnd; ++seqs2Iter) {
600
+ Node& seq2 = *seqs2Iter;
601
+
602
+ Complex_Selector_Obj pSeq2 = nodeToComplexSelector(seq2);
603
+
604
+ DEBUG_PRINTLN(TRIM, "SEQ2 SPEC: " << pSeq2->specificity())
605
+ DEBUG_PRINTLN(TRIM, "IS SPEC: " << pSeq2->specificity() << " >= " << maxSpecificity << " " << (pSeq2->specificity() >= maxSpecificity ? "true" : "false"))
606
+ DEBUG_PRINTLN(TRIM, "IS SUPER: " << (pSeq2->is_superselector_of(pSeq1) ? "true" : "false"))
607
+
608
+ isMoreSpecificInner = pSeq2->specificity() >= maxSpecificity && pSeq2->is_superselector_of(pSeq1);
609
+
610
+ if (isMoreSpecificInner) {
611
+ DEBUG_PRINTLN(TRIM, "FOUND MORE SPECIFIC")
612
+ break;
613
+ }
614
+ }
615
+
616
+ // If we found something more specific, we're done. Let the outer loop know and stop iterating.
617
+ if (isMoreSpecificInner) {
618
+ isMoreSpecificOuter = true;
619
+ break;
620
+ }
621
+
622
+ resultIndex++;
623
+ }
624
+
625
+ if (!isMoreSpecificOuter) {
626
+ DEBUG_PRINTLN(TRIM, "PUSHING: " << seq1)
627
+ tempResult.collection()->push_back(seq1);
628
+ }
629
+
630
+ }
631
+
632
+ DEBUG_PRINTLN(TRIM, "RESULT BEFORE ASSIGN: " << result)
633
+ DEBUG_PRINTLN(TRIM, "TEMP RESULT: " << toTrimIndex << " " << tempResult)
634
+ (*result.collection())[toTrimIndex] = tempResult;
635
+
636
+ toTrimIndex++;
637
+
638
+ DEBUG_PRINTLN(TRIM, "RESULT: " << result)
639
+ }
640
+
641
+ return result;
642
+ }
643
+
644
+
645
+
646
+ static bool parentSuperselector(const Node& one, const Node& two) {
647
+ // TODO: figure out a better way to create a Complex_Selector from scratch
648
+ // TODO: There's got to be a better way. This got ugly quick...
649
+ Type_Selector_Obj fakeParent = SASS_MEMORY_NEW(Type_Selector, ParserState("[FAKE]"), "temp");
650
+ Compound_Selector_Obj fakeHead = SASS_MEMORY_NEW(Compound_Selector, ParserState("[FAKE]"), 1 /*size*/);
651
+ fakeHead->elements().push_back(fakeParent);
652
+ Complex_Selector_Obj fakeParentContainer = SASS_MEMORY_NEW(Complex_Selector, ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, fakeHead /*head*/, {} /*tail*/);
653
+
654
+ Complex_Selector_Obj pOneWithFakeParent = nodeToComplexSelector(one);
655
+ pOneWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
656
+ Complex_Selector_Obj pTwoWithFakeParent = nodeToComplexSelector(two);
657
+ pTwoWithFakeParent->set_innermost(fakeParentContainer, Complex_Selector::ANCESTOR_OF);
658
+
659
+ return pOneWithFakeParent->is_superselector_of(pTwoWithFakeParent);
660
+ }
661
+
662
+
663
+ class ParentSuperselectorChunker {
664
+ public:
665
+ ParentSuperselectorChunker(Node& lcs) : mLcs(lcs) {}
666
+ Node& mLcs;
667
+
668
+ bool operator()(const Node& seq) const {
669
+ // {|s| parent_superselector?(s.first, lcs.first)}
670
+ if (seq.collection()->size() == 0) return false;
671
+ return parentSuperselector(seq.collection()->front(), mLcs.collection()->front());
672
+ }
673
+ };
674
+
675
+ class SubweaveEmptyChunker {
676
+ public:
677
+ bool operator()(const Node& seq) const {
678
+ // {|s| s.empty?}
679
+
680
+ return seq.collection()->empty();
681
+ }
682
+ };
683
+
684
+ /*
685
+ # Takes initial subsequences of `seq1` and `seq2` and returns all
686
+ # orderings of those subsequences. The initial subsequences are determined
687
+ # by a block.
688
+ #
689
+ # Destructively removes the initial subsequences of `seq1` and `seq2`.
690
+ #
691
+ # For example, given `(A B C | D E)` and `(1 2 | 3 4 5)` (with `|`
692
+ # denoting the boundary of the initial subsequence), this would return
693
+ # `[(A B C 1 2), (1 2 A B C)]`. The sequences would then be `(D E)` and
694
+ # `(3 4 5)`.
695
+ #
696
+ # @param seq1 [Array]
697
+ # @param seq2 [Array]
698
+ # @yield [a] Used to determine when to cut off the initial subsequences.
699
+ # Called repeatedly for each sequence until it returns true.
700
+ # @yieldparam a [Array] A final subsequence of one input sequence after
701
+ # cutting off some initial subsequence.
702
+ # @yieldreturn [Boolean] Whether or not to cut off the initial subsequence
703
+ # here.
704
+ # @return [Array<Array>] All possible orderings of the initial subsequences.
705
+ def chunks(seq1, seq2)
706
+ chunk1 = []
707
+ chunk1 << seq1.shift until yield seq1
708
+ chunk2 = []
709
+ chunk2 << seq2.shift until yield seq2
710
+ return [] if chunk1.empty? && chunk2.empty?
711
+ return [chunk2] if chunk1.empty?
712
+ return [chunk1] if chunk2.empty?
713
+ [chunk1 + chunk2, chunk2 + chunk1]
714
+ end
715
+ */
716
+ template<typename ChunkerType>
717
+ static Node chunks(Node& seq1, Node& seq2, const ChunkerType& chunker) {
718
+ Node chunk1 = Node::createCollection();
719
+ while (seq1.collection()->size() && !chunker(seq1)) {
720
+ chunk1.collection()->push_back(seq1.collection()->front());
721
+ seq1.collection()->pop_front();
722
+ }
723
+
724
+ Node chunk2 = Node::createCollection();
725
+ while (!seq2.collection()->empty() && !chunker(seq2)) {
726
+ chunk2.collection()->push_back(seq2.collection()->front());
727
+ seq2.collection()->pop_front();
728
+ }
729
+
730
+ if (chunk1.collection()->empty() && chunk2.collection()->empty()) {
731
+ DEBUG_PRINTLN(CHUNKS, "RETURNING BOTH EMPTY")
732
+ return Node::createCollection();
733
+ }
734
+
735
+ if (chunk1.collection()->empty()) {
736
+ Node chunk2Wrapper = Node::createCollection();
737
+ chunk2Wrapper.collection()->push_back(chunk2);
738
+ DEBUG_PRINTLN(CHUNKS, "RETURNING ONE EMPTY")
739
+ return chunk2Wrapper;
740
+ }
741
+
742
+ if (chunk2.collection()->empty()) {
743
+ Node chunk1Wrapper = Node::createCollection();
744
+ chunk1Wrapper.collection()->push_back(chunk1);
745
+ DEBUG_PRINTLN(CHUNKS, "RETURNING TWO EMPTY")
746
+ return chunk1Wrapper;
747
+ }
748
+
749
+ Node perms = Node::createCollection();
750
+
751
+ Node firstPermutation = Node::createCollection();
752
+ firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
753
+ firstPermutation.collection()->insert(firstPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
754
+ perms.collection()->push_back(firstPermutation);
755
+
756
+ Node secondPermutation = Node::createCollection();
757
+ secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk2.collection()->begin(), chunk2.collection()->end());
758
+ secondPermutation.collection()->insert(secondPermutation.collection()->end(), chunk1.collection()->begin(), chunk1.collection()->end());
759
+ perms.collection()->push_back(secondPermutation);
760
+
761
+ DEBUG_PRINTLN(CHUNKS, "RETURNING PERM")
762
+
763
+ return perms;
764
+ }
765
+
766
+
767
+ static Node groupSelectors(Node& seq) {
768
+ Node newSeq = Node::createCollection();
769
+
770
+ Node tail = Node::createCollection();
771
+ tail.plus(seq);
772
+
773
+ while (!tail.collection()->empty()) {
774
+ Node head = Node::createCollection();
775
+
776
+ do {
777
+ head.collection()->push_back(tail.collection()->front());
778
+ tail.collection()->pop_front();
779
+ } while (!tail.collection()->empty() && (head.collection()->back().isCombinator() || tail.collection()->front().isCombinator()));
780
+
781
+ newSeq.collection()->push_back(head);
782
+ }
783
+
784
+ return newSeq;
785
+ }
786
+
787
+
788
+ static void getAndRemoveInitialOps(Node& seq, Node& ops) {
789
+ NodeDeque& seqCollection = *(seq.collection());
790
+ NodeDeque& opsCollection = *(ops.collection());
791
+
792
+ while (seqCollection.size() > 0 && seqCollection.front().isCombinator()) {
793
+ opsCollection.push_back(seqCollection.front());
794
+ seqCollection.pop_front();
795
+ }
796
+ }
797
+
798
+
799
+ static void getAndRemoveFinalOps(Node& seq, Node& ops) {
800
+ NodeDeque& seqCollection = *(seq.collection());
801
+ NodeDeque& opsCollection = *(ops.collection());
802
+
803
+ while (seqCollection.size() > 0 && seqCollection.back().isCombinator()) {
804
+ opsCollection.push_back(seqCollection.back()); // Purposefully reversed to match ruby code
805
+ seqCollection.pop_back();
806
+ }
807
+ }
808
+
809
+
810
+ /*
811
+ def merge_initial_ops(seq1, seq2)
812
+ ops1, ops2 = [], []
813
+ ops1 << seq1.shift while seq1.first.is_a?(String)
814
+ ops2 << seq2.shift while seq2.first.is_a?(String)
815
+
816
+ newline = false
817
+ newline ||= !!ops1.shift if ops1.first == "\n"
818
+ newline ||= !!ops2.shift if ops2.first == "\n"
819
+
820
+ # If neither sequence is a subsequence of the other, they cannot be
821
+ # merged successfully
822
+ lcs = Sass::Util.lcs(ops1, ops2)
823
+ return unless lcs == ops1 || lcs == ops2
824
+ return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
825
+ end
826
+ */
827
+ static Node mergeInitialOps(Node& seq1, Node& seq2) {
828
+ Node ops1 = Node::createCollection();
829
+ Node ops2 = Node::createCollection();
830
+
831
+ getAndRemoveInitialOps(seq1, ops1);
832
+ getAndRemoveInitialOps(seq2, ops2);
833
+
834
+ // TODO: Do we have this information available to us?
835
+ // newline = false
836
+ // newline ||= !!ops1.shift if ops1.first == "\n"
837
+ // newline ||= !!ops2.shift if ops2.first == "\n"
838
+
839
+ // If neither sequence is a subsequence of the other, they cannot be merged successfully
840
+ DefaultLcsComparator lcsDefaultComparator;
841
+ Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator);
842
+
843
+ if (!(opsLcs == ops1 || opsLcs == ops2)) {
844
+ return Node::createNil();
845
+ }
846
+
847
+ // TODO: more newline logic
848
+ // return (newline ? ["\n"] : []) + (ops1.size > ops2.size ? ops1 : ops2)
849
+
850
+ return (ops1.collection()->size() > ops2.collection()->size() ? ops1 : ops2);
851
+ }
852
+
853
+
854
+ /*
855
+ def merge_final_ops(seq1, seq2, res = [])
856
+
857
+
858
+ # This code looks complicated, but it's actually just a bunch of special
859
+ # cases for interactions between different combinators.
860
+ op1, op2 = ops1.first, ops2.first
861
+ if op1 && op2
862
+ sel1 = seq1.pop
863
+ sel2 = seq2.pop
864
+ if op1 == '~' && op2 == '~'
865
+ if sel1.superselector?(sel2)
866
+ res.unshift sel2, '~'
867
+ elsif sel2.superselector?(sel1)
868
+ res.unshift sel1, '~'
869
+ else
870
+ merged = sel1.unify(sel2.members, sel2.subject?)
871
+ res.unshift [
872
+ [sel1, '~', sel2, '~'],
873
+ [sel2, '~', sel1, '~'],
874
+ ([merged, '~'] if merged)
875
+ ].compact
876
+ end
877
+ elsif (op1 == '~' && op2 == '+') || (op1 == '+' && op2 == '~')
878
+ if op1 == '~'
879
+ tilde_sel, plus_sel = sel1, sel2
880
+ else
881
+ tilde_sel, plus_sel = sel2, sel1
882
+ end
883
+
884
+ if tilde_sel.superselector?(plus_sel)
885
+ res.unshift plus_sel, '+'
886
+ else
887
+ merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
888
+ res.unshift [
889
+ [tilde_sel, '~', plus_sel, '+'],
890
+ ([merged, '+'] if merged)
891
+ ].compact
892
+ end
893
+ elsif op1 == '>' && %w[~ +].include?(op2)
894
+ res.unshift sel2, op2
895
+ seq1.push sel1, op1
896
+ elsif op2 == '>' && %w[~ +].include?(op1)
897
+ res.unshift sel1, op1
898
+ seq2.push sel2, op2
899
+ elsif op1 == op2
900
+ return unless merged = sel1.unify(sel2.members, sel2.subject?)
901
+ res.unshift merged, op1
902
+ else
903
+ # Unknown selector combinators can't be unified
904
+ return
905
+ end
906
+ return merge_final_ops(seq1, seq2, res)
907
+ elsif op1
908
+ seq2.pop if op1 == '>' && seq2.last && seq2.last.superselector?(seq1.last)
909
+ res.unshift seq1.pop, op1
910
+ return merge_final_ops(seq1, seq2, res)
911
+ else # op2
912
+ seq1.pop if op2 == '>' && seq1.last && seq1.last.superselector?(seq2.last)
913
+ res.unshift seq2.pop, op2
914
+ return merge_final_ops(seq1, seq2, res)
915
+ end
916
+ end
917
+ */
918
+ static Node mergeFinalOps(Node& seq1, Node& seq2, Node& res) {
919
+
920
+ Node ops1 = Node::createCollection();
921
+ Node ops2 = Node::createCollection();
922
+
923
+ getAndRemoveFinalOps(seq1, ops1);
924
+ getAndRemoveFinalOps(seq2, ops2);
925
+
926
+ // TODO: do we have newlines to remove?
927
+ // ops1.reject! {|o| o == "\n"}
928
+ // ops2.reject! {|o| o == "\n"}
929
+
930
+ if (ops1.collection()->empty() && ops2.collection()->empty()) {
931
+ return res;
932
+ }
933
+
934
+ if (ops1.collection()->size() > 1 || ops2.collection()->size() > 1) {
935
+ DefaultLcsComparator lcsDefaultComparator;
936
+ Node opsLcs = lcs(ops1, ops2, lcsDefaultComparator);
937
+
938
+ // If there are multiple operators, something hacky's going on. If one is a supersequence of the other, use that, otherwise give up.
939
+
940
+ if (!(opsLcs == ops1 || opsLcs == ops2)) {
941
+ return Node::createNil();
942
+ }
943
+
944
+ if (ops1.collection()->size() > ops2.collection()->size()) {
945
+ res.collection()->insert(res.collection()->begin(), ops1.collection()->rbegin(), ops1.collection()->rend());
946
+ } else {
947
+ res.collection()->insert(res.collection()->begin(), ops2.collection()->rbegin(), ops2.collection()->rend());
948
+ }
949
+
950
+ return res;
951
+ }
952
+
953
+ if (!ops1.collection()->empty() && !ops2.collection()->empty()) {
954
+
955
+ Node op1 = ops1.collection()->front();
956
+ Node op2 = ops2.collection()->front();
957
+
958
+ Node sel1 = seq1.collection()->back();
959
+ seq1.collection()->pop_back();
960
+
961
+ Node sel2 = seq2.collection()->back();
962
+ seq2.collection()->pop_back();
963
+
964
+ if (op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::PRECEDES) {
965
+
966
+ if (sel1.selector()->is_superselector_of(sel2.selector())) {
967
+
968
+ res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
969
+ res.collection()->push_front(sel2);
970
+
971
+ } else if (sel2.selector()->is_superselector_of(sel1.selector())) {
972
+
973
+ res.collection()->push_front(op1 /*PRECEDES - could have been op2 as well*/);
974
+ res.collection()->push_front(sel1);
975
+
976
+ } else {
977
+
978
+ DEBUG_PRINTLN(ALL, "sel1: " << sel1)
979
+ DEBUG_PRINTLN(ALL, "sel2: " << sel2)
980
+
981
+ Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
982
+ // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
983
+ Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head());
984
+ pMergedWrapper->head(pMerged);
985
+
986
+ DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
987
+
988
+ Node newRes = Node::createCollection();
989
+
990
+ Node firstPerm = Node::createCollection();
991
+ firstPerm.collection()->push_back(sel1);
992
+ firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
993
+ firstPerm.collection()->push_back(sel2);
994
+ firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
995
+ newRes.collection()->push_back(firstPerm);
996
+
997
+ Node secondPerm = Node::createCollection();
998
+ secondPerm.collection()->push_back(sel2);
999
+ secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1000
+ secondPerm.collection()->push_back(sel1);
1001
+ secondPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1002
+ newRes.collection()->push_back(secondPerm);
1003
+
1004
+ if (pMerged) {
1005
+ Node mergedPerm = Node::createCollection();
1006
+ mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper));
1007
+ mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1008
+ newRes.collection()->push_back(mergedPerm);
1009
+ }
1010
+
1011
+ res.collection()->push_front(newRes);
1012
+
1013
+ DEBUG_PRINTLN(ALL, "RESULT: " << res)
1014
+
1015
+ }
1016
+
1017
+ } else if (((op1.combinator() == Complex_Selector::PRECEDES && op2.combinator() == Complex_Selector::ADJACENT_TO)) || ((op1.combinator() == Complex_Selector::ADJACENT_TO && op2.combinator() == Complex_Selector::PRECEDES))) {
1018
+
1019
+ Node tildeSel = sel1;
1020
+ Node plusSel = sel2;
1021
+ Node plusOp = op2;
1022
+ if (op1.combinator() != Complex_Selector::PRECEDES) {
1023
+ tildeSel = sel2;
1024
+ plusSel = sel1;
1025
+ plusOp = op1;
1026
+ }
1027
+
1028
+ if (tildeSel.selector()->is_superselector_of(plusSel.selector())) {
1029
+
1030
+ res.collection()->push_front(plusOp);
1031
+ res.collection()->push_front(plusSel);
1032
+
1033
+ } else {
1034
+
1035
+ DEBUG_PRINTLN(ALL, "PLUS SEL: " << plusSel)
1036
+ DEBUG_PRINTLN(ALL, "TILDE SEL: " << tildeSel)
1037
+
1038
+ Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(plusSel.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1039
+ // TODO: does subject matter? Ruby: merged = plus_sel.unify(tilde_sel.members, tilde_sel.subject?)
1040
+ Compound_Selector* pMerged = plusSel.selector()->head()->unify_with(tildeSel.selector()->head());
1041
+ pMergedWrapper->head(pMerged);
1042
+
1043
+ DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
1044
+
1045
+ Node newRes = Node::createCollection();
1046
+
1047
+ Node firstPerm = Node::createCollection();
1048
+ firstPerm.collection()->push_back(tildeSel);
1049
+ firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::PRECEDES));
1050
+ firstPerm.collection()->push_back(plusSel);
1051
+ firstPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1052
+ newRes.collection()->push_back(firstPerm);
1053
+
1054
+ if (pMerged) {
1055
+ Node mergedPerm = Node::createCollection();
1056
+ mergedPerm.collection()->push_back(Node::createSelector(pMergedWrapper));
1057
+ mergedPerm.collection()->push_back(Node::createCombinator(Complex_Selector::ADJACENT_TO));
1058
+ newRes.collection()->push_back(mergedPerm);
1059
+ }
1060
+
1061
+ res.collection()->push_front(newRes);
1062
+
1063
+ DEBUG_PRINTLN(ALL, "RESULT: " << res)
1064
+
1065
+ }
1066
+ } else if (op1.combinator() == Complex_Selector::PARENT_OF && (op2.combinator() == Complex_Selector::PRECEDES || op2.combinator() == Complex_Selector::ADJACENT_TO)) {
1067
+
1068
+ res.collection()->push_front(op2);
1069
+ res.collection()->push_front(sel2);
1070
+
1071
+ seq1.collection()->push_back(sel1);
1072
+ seq1.collection()->push_back(op1);
1073
+
1074
+ } else if (op2.combinator() == Complex_Selector::PARENT_OF && (op1.combinator() == Complex_Selector::PRECEDES || op1.combinator() == Complex_Selector::ADJACENT_TO)) {
1075
+
1076
+ res.collection()->push_front(op1);
1077
+ res.collection()->push_front(sel1);
1078
+
1079
+ seq2.collection()->push_back(sel2);
1080
+ seq2.collection()->push_back(op2);
1081
+
1082
+ } else if (op1.combinator() == op2.combinator()) {
1083
+
1084
+ DEBUG_PRINTLN(ALL, "sel1: " << sel1)
1085
+ DEBUG_PRINTLN(ALL, "sel2: " << sel2)
1086
+
1087
+ Complex_Selector_Obj pMergedWrapper = SASS_MEMORY_CLONE(sel1.selector()); // Clone the Complex_Selector to get back to something we can transform to a node once we replace the head with the unification result
1088
+ // TODO: does subject matter? Ruby: return unless merged = sel1.unify(sel2.members, sel2.subject?)
1089
+ Compound_Selector* pMerged = sel1.selector()->head()->unify_with(sel2.selector()->head());
1090
+ pMergedWrapper->head(pMerged);
1091
+
1092
+ DEBUG_EXEC(ALL, printCompoundSelector(pMerged, "MERGED: "))
1093
+
1094
+ if (!pMerged) {
1095
+ return Node::createNil();
1096
+ }
1097
+
1098
+ res.collection()->push_front(op1);
1099
+ res.collection()->push_front(Node::createSelector(pMergedWrapper));
1100
+
1101
+ DEBUG_PRINTLN(ALL, "RESULT: " << res)
1102
+
1103
+ } else {
1104
+ return Node::createNil();
1105
+ }
1106
+
1107
+ return mergeFinalOps(seq1, seq2, res);
1108
+
1109
+ } else if (!ops1.collection()->empty()) {
1110
+
1111
+ Node op1 = ops1.collection()->front();
1112
+
1113
+ if (op1.combinator() == Complex_Selector::PARENT_OF && !seq2.collection()->empty() && seq2.collection()->back().selector()->is_superselector_of(seq1.collection()->back().selector())) {
1114
+ seq2.collection()->pop_back();
1115
+ }
1116
+
1117
+ // TODO: consider unshift(NodeCollection, Node)
1118
+ res.collection()->push_front(op1);
1119
+ res.collection()->push_front(seq1.collection()->back());
1120
+ seq1.collection()->pop_back();
1121
+
1122
+ return mergeFinalOps(seq1, seq2, res);
1123
+
1124
+ } else { // !ops2.collection()->empty()
1125
+
1126
+ Node op2 = ops2.collection()->front();
1127
+
1128
+ if (op2.combinator() == Complex_Selector::PARENT_OF && !seq1.collection()->empty() && seq1.collection()->back().selector()->is_superselector_of(seq2.collection()->back().selector())) {
1129
+ seq1.collection()->pop_back();
1130
+ }
1131
+
1132
+ res.collection()->push_front(op2);
1133
+ res.collection()->push_front(seq2.collection()->back());
1134
+ seq2.collection()->pop_back();
1135
+
1136
+ return mergeFinalOps(seq1, seq2, res);
1137
+
1138
+ }
1139
+
1140
+ }
1141
+
1142
+
1143
+ /*
1144
+ This is the equivalent of ruby's Sequence.subweave.
1145
+
1146
+ Here is the original subweave code for reference during porting.
1147
+
1148
+ def subweave(seq1, seq2)
1149
+ return [seq2] if seq1.empty?
1150
+ return [seq1] if seq2.empty?
1151
+
1152
+ seq1, seq2 = seq1.dup, seq2.dup
1153
+ return unless init = merge_initial_ops(seq1, seq2)
1154
+ return unless fin = merge_final_ops(seq1, seq2)
1155
+ seq1 = group_selectors(seq1)
1156
+ seq2 = group_selectors(seq2)
1157
+ lcs = Sass::Util.lcs(seq2, seq1) do |s1, s2|
1158
+ next s1 if s1 == s2
1159
+ next unless s1.first.is_a?(SimpleSequence) && s2.first.is_a?(SimpleSequence)
1160
+ next s2 if parent_superselector?(s1, s2)
1161
+ next s1 if parent_superselector?(s2, s1)
1162
+ end
1163
+
1164
+ diff = [[init]]
1165
+ until lcs.empty?
1166
+ diff << chunks(seq1, seq2) {|s| parent_superselector?(s.first, lcs.first)} << [lcs.shift]
1167
+ seq1.shift
1168
+ seq2.shift
1169
+ end
1170
+ diff << chunks(seq1, seq2) {|s| s.empty?}
1171
+ diff += fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
1172
+ diff.reject! {|c| c.empty?}
1173
+
1174
+ result = Sass::Util.paths(diff).map {|p| p.flatten}.reject {|p| path_has_two_subjects?(p)}
1175
+
1176
+ result
1177
+ end
1178
+ */
1179
+ Node subweave(Node& one, Node& two) {
1180
+ // Check for the simple cases
1181
+ if (one.collection()->size() == 0) {
1182
+ Node out = Node::createCollection();
1183
+ out.collection()->push_back(two);
1184
+ return out;
1185
+ }
1186
+ if (two.collection()->size() == 0) {
1187
+ Node out = Node::createCollection();
1188
+ out.collection()->push_back(one);
1189
+ return out;
1190
+ }
1191
+
1192
+ Node seq1 = Node::createCollection();
1193
+ seq1.plus(one);
1194
+ Node seq2 = Node::createCollection();
1195
+ seq2.plus(two);
1196
+
1197
+ DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE ONE: " << seq1)
1198
+ DEBUG_PRINTLN(SUBWEAVE, "SUBWEAVE TWO: " << seq2)
1199
+
1200
+ Node init = mergeInitialOps(seq1, seq2);
1201
+ if (init.isNil()) {
1202
+ return Node::createNil();
1203
+ }
1204
+
1205
+ DEBUG_PRINTLN(SUBWEAVE, "INIT: " << init)
1206
+
1207
+ Node res = Node::createCollection();
1208
+ Node fin = mergeFinalOps(seq1, seq2, res);
1209
+ if (fin.isNil()) {
1210
+ return Node::createNil();
1211
+ }
1212
+
1213
+ DEBUG_PRINTLN(SUBWEAVE, "FIN: " << fin)
1214
+
1215
+
1216
+ // Moving this line up since fin isn't modified between now and when it happened before
1217
+ // fin.map {|sel| sel.is_a?(Array) ? sel : [sel]}
1218
+
1219
+ for (NodeDeque::iterator finIter = fin.collection()->begin(), finEndIter = fin.collection()->end();
1220
+ finIter != finEndIter; ++finIter) {
1221
+
1222
+ Node& childNode = *finIter;
1223
+
1224
+ if (!childNode.isCollection()) {
1225
+ Node wrapper = Node::createCollection();
1226
+ wrapper.collection()->push_back(childNode);
1227
+ childNode = wrapper;
1228
+ }
1229
+
1230
+ }
1231
+
1232
+ DEBUG_PRINTLN(SUBWEAVE, "FIN MAPPED: " << fin)
1233
+
1234
+
1235
+
1236
+ Node groupSeq1 = groupSelectors(seq1);
1237
+ DEBUG_PRINTLN(SUBWEAVE, "SEQ1: " << groupSeq1)
1238
+
1239
+ Node groupSeq2 = groupSelectors(seq2);
1240
+ DEBUG_PRINTLN(SUBWEAVE, "SEQ2: " << groupSeq2)
1241
+
1242
+
1243
+ ComplexSelectorDeque groupSeq1Converted;
1244
+ nodeToComplexSelectorDeque(groupSeq1, groupSeq1Converted);
1245
+
1246
+ ComplexSelectorDeque groupSeq2Converted;
1247
+ nodeToComplexSelectorDeque(groupSeq2, groupSeq2Converted);
1248
+
1249
+ ComplexSelectorDeque out;
1250
+ LcsCollectionComparator collectionComparator;
1251
+ lcs(groupSeq2Converted, groupSeq1Converted, collectionComparator, out);
1252
+ Node seqLcs = complexSelectorDequeToNode(out);
1253
+
1254
+ DEBUG_PRINTLN(SUBWEAVE, "SEQLCS: " << seqLcs)
1255
+
1256
+
1257
+ Node initWrapper = Node::createCollection();
1258
+ initWrapper.collection()->push_back(init);
1259
+ Node diff = Node::createCollection();
1260
+ diff.collection()->push_back(initWrapper);
1261
+
1262
+ DEBUG_PRINTLN(SUBWEAVE, "DIFF INIT: " << diff)
1263
+
1264
+
1265
+ while (!seqLcs.collection()->empty()) {
1266
+ ParentSuperselectorChunker superselectorChunker(seqLcs);
1267
+ Node chunksResult = chunks(groupSeq1, groupSeq2, superselectorChunker);
1268
+ diff.collection()->push_back(chunksResult);
1269
+
1270
+ Node lcsWrapper = Node::createCollection();
1271
+ lcsWrapper.collection()->push_back(seqLcs.collection()->front());
1272
+ seqLcs.collection()->pop_front();
1273
+ diff.collection()->push_back(lcsWrapper);
1274
+
1275
+ if (groupSeq1.collection()->size()) groupSeq1.collection()->pop_front();
1276
+ if (groupSeq2.collection()->size()) groupSeq2.collection()->pop_front();
1277
+ }
1278
+
1279
+ DEBUG_PRINTLN(SUBWEAVE, "DIFF POST LCS: " << diff)
1280
+
1281
+
1282
+ DEBUG_PRINTLN(SUBWEAVE, "CHUNKS: ONE=" << groupSeq1 << " TWO=" << groupSeq2)
1283
+
1284
+
1285
+ SubweaveEmptyChunker emptyChunker;
1286
+ Node chunksResult = chunks(groupSeq1, groupSeq2, emptyChunker);
1287
+ diff.collection()->push_back(chunksResult);
1288
+
1289
+
1290
+ DEBUG_PRINTLN(SUBWEAVE, "DIFF POST CHUNKS: " << diff)
1291
+
1292
+
1293
+ diff.collection()->insert(diff.collection()->end(), fin.collection()->begin(), fin.collection()->end());
1294
+
1295
+ DEBUG_PRINTLN(SUBWEAVE, "DIFF POST FIN MAPPED: " << diff)
1296
+
1297
+ // JMA - filter out the empty nodes (use a new collection, since iterator erase() invalidates the old collection)
1298
+ Node diffFiltered = Node::createCollection();
1299
+ for (NodeDeque::iterator diffIter = diff.collection()->begin(), diffEndIter = diff.collection()->end();
1300
+ diffIter != diffEndIter; ++diffIter) {
1301
+ Node& node = *diffIter;
1302
+ if (node.collection() && !node.collection()->empty()) {
1303
+ diffFiltered.collection()->push_back(node);
1304
+ }
1305
+ }
1306
+ diff = diffFiltered;
1307
+
1308
+ DEBUG_PRINTLN(SUBWEAVE, "DIFF POST REJECT: " << diff)
1309
+
1310
+
1311
+ Node pathsResult = paths(diff);
1312
+
1313
+ DEBUG_PRINTLN(SUBWEAVE, "PATHS: " << pathsResult)
1314
+
1315
+
1316
+ // We're flattening in place
1317
+ for (NodeDeque::iterator pathsIter = pathsResult.collection()->begin(), pathsEndIter = pathsResult.collection()->end();
1318
+ pathsIter != pathsEndIter; ++pathsIter) {
1319
+
1320
+ Node& child = *pathsIter;
1321
+ child = flatten(child);
1322
+ }
1323
+
1324
+ DEBUG_PRINTLN(SUBWEAVE, "FLATTENED: " << pathsResult)
1325
+
1326
+
1327
+ /*
1328
+ TODO: implement
1329
+ rejected = mapped.reject {|p| path_has_two_subjects?(p)}
1330
+ $stderr.puts "REJECTED: #{rejected}"
1331
+ */
1332
+
1333
+
1334
+ return pathsResult;
1335
+
1336
+ }
1337
+ /*
1338
+ // disabled to avoid clang warning [-Wunused-function]
1339
+ static Node subweaveNaive(const Node& one, const Node& two) {
1340
+ Node out = Node::createCollection();
1341
+
1342
+ // Check for the simple cases
1343
+ if (one.isNil()) {
1344
+ out.collection()->push_back(two.klone());
1345
+ } else if (two.isNil()) {
1346
+ out.collection()->push_back(one.klone());
1347
+ } else {
1348
+ // Do the naive implementation. pOne = A B and pTwo = C D ...yields... A B C D and C D A B
1349
+ // See https://gist.github.com/nex3/7609394 for details.
1350
+
1351
+ Node firstPerm = one.klone();
1352
+ Node twoCloned = two.klone();
1353
+ firstPerm.plus(twoCloned);
1354
+ out.collection()->push_back(firstPerm);
1355
+
1356
+ Node secondPerm = two.klone();
1357
+ Node oneCloned = one.klone();
1358
+ secondPerm.plus(oneCloned );
1359
+ out.collection()->push_back(secondPerm);
1360
+ }
1361
+
1362
+ return out;
1363
+ }
1364
+ */
1365
+
1366
+
1367
+ /*
1368
+ This is the equivalent of ruby's Sequence.weave.
1369
+
1370
+ The following is the modified version of the ruby code that was more portable to C++. You
1371
+ should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
1372
+
1373
+ def weave(path)
1374
+ # This function works by moving through the selector path left-to-right,
1375
+ # building all possible prefixes simultaneously. These prefixes are
1376
+ # `befores`, while the remaining parenthesized suffixes is `afters`.
1377
+ befores = [[]]
1378
+ afters = path.dup
1379
+
1380
+ until afters.empty?
1381
+ current = afters.shift.dup
1382
+ last_current = [current.pop]
1383
+
1384
+ tempResult = []
1385
+
1386
+ for before in befores do
1387
+ sub = subweave(before, current)
1388
+ if sub.nil?
1389
+ next
1390
+ end
1391
+
1392
+ for seqs in sub do
1393
+ tempResult.push(seqs + last_current)
1394
+ end
1395
+ end
1396
+
1397
+ befores = tempResult
1398
+
1399
+ end
1400
+
1401
+ return befores
1402
+ end
1403
+ */
1404
+ /*
1405
+ def weave(path)
1406
+ befores = [[]]
1407
+ afters = path.dup
1408
+
1409
+ until afters.empty?
1410
+ current = afters.shift.dup
1411
+
1412
+ last_current = [current.pop]
1413
+
1414
+
1415
+ tempResult = []
1416
+
1417
+ for before in befores do
1418
+ sub = subweave(before, current)
1419
+
1420
+ if sub.nil?
1421
+ next []
1422
+ end
1423
+
1424
+
1425
+ for seqs in sub do
1426
+ toPush = seqs + last_current
1427
+
1428
+ tempResult.push(seqs + last_current)
1429
+ end
1430
+
1431
+ end
1432
+
1433
+ befores = tempResult
1434
+
1435
+ end
1436
+
1437
+ return befores
1438
+ end
1439
+ */
1440
+ Node Extend::weave(Node& path) {
1441
+
1442
+ DEBUG_PRINTLN(WEAVE, "WEAVE: " << path)
1443
+
1444
+ Node befores = Node::createCollection();
1445
+ befores.collection()->push_back(Node::createCollection());
1446
+
1447
+ Node afters = Node::createCollection();
1448
+ afters.plus(path);
1449
+
1450
+ while (!afters.collection()->empty()) {
1451
+ Node current = afters.collection()->front().klone();
1452
+ afters.collection()->pop_front();
1453
+ DEBUG_PRINTLN(WEAVE, "CURRENT: " << current)
1454
+ if (current.collection()->size() == 0) continue;
1455
+
1456
+ Node last_current = Node::createCollection();
1457
+ last_current.collection()->push_back(current.collection()->back());
1458
+ current.collection()->pop_back();
1459
+ DEBUG_PRINTLN(WEAVE, "CURRENT POST POP: " << current)
1460
+ DEBUG_PRINTLN(WEAVE, "LAST CURRENT: " << last_current)
1461
+
1462
+ Node tempResult = Node::createCollection();
1463
+
1464
+ for (NodeDeque::iterator beforesIter = befores.collection()->begin(), beforesEndIter = befores.collection()->end(); beforesIter != beforesEndIter; beforesIter++) {
1465
+ Node& before = *beforesIter;
1466
+
1467
+ Node sub = subweave(before, current);
1468
+
1469
+ DEBUG_PRINTLN(WEAVE, "SUB: " << sub)
1470
+
1471
+ if (sub.isNil()) {
1472
+ return Node::createCollection();
1473
+ }
1474
+
1475
+ for (NodeDeque::iterator subIter = sub.collection()->begin(), subEndIter = sub.collection()->end(); subIter != subEndIter; subIter++) {
1476
+ Node& seqs = *subIter;
1477
+
1478
+ Node toPush = Node::createCollection();
1479
+ toPush.plus(seqs);
1480
+ toPush.plus(last_current);
1481
+
1482
+ // move line feed from inner to outer selector (very hacky indeed)
1483
+ if (last_current.collection() && last_current.collection()->front().selector()) {
1484
+ toPush.got_line_feed = last_current.collection()->front().got_line_feed;
1485
+ last_current.collection()->front().selector()->has_line_feed(false);
1486
+ last_current.collection()->front().got_line_feed = false;
1487
+ }
1488
+
1489
+ tempResult.collection()->push_back(toPush);
1490
+
1491
+ }
1492
+ }
1493
+
1494
+ befores = tempResult;
1495
+
1496
+ }
1497
+
1498
+ return befores;
1499
+ }
1500
+
1501
+
1502
+
1503
+ /*
1504
+ This is the equivalent of ruby's SimpleSequence.do_extend.
1505
+
1506
+ // TODO: I think I have some modified ruby code to put here. Check.
1507
+ */
1508
+ /*
1509
+ ISSUES:
1510
+ - Previous TODO: Do we need to group the results by extender?
1511
+ - What does subject do in?: next unless unified = seq.members.last.unify(self_without_sel, subject?)
1512
+ - IMPROVEMENT: The search for uniqueness at the end is not ideal since it's has to loop over everything...
1513
+ - IMPROVEMENT: Check if the final search for uniqueness is doing anything that extendComplexSelector isn't already doing...
1514
+ */
1515
+ template<typename KeyType>
1516
+ class GroupByToAFunctor {
1517
+ public:
1518
+ KeyType operator()(SubSetMapPair& extPair) const {
1519
+ Complex_Selector_Obj pSelector = extPair.first;
1520
+ return pSelector;
1521
+ }
1522
+ };
1523
+ Node Extend::extendCompoundSelector(Compound_Selector* pSelector, CompoundSelectorSet& seen, bool isReplace) {
1524
+
1525
+ /* this turned out to be too much overhead
1526
+ probably due to holding a "Node" object
1527
+ // check if we already extended this selector
1528
+ // we can do this since subset_map is "static"
1529
+ auto memoized = memoizeCompound.find(pSelector);
1530
+ if (memoized != memoizeCompound.end()) {
1531
+ return memoized->second.klone();
1532
+ }
1533
+ */
1534
+
1535
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND: "))
1536
+ // TODO: Ruby has another loop here to skip certain members?
1537
+
1538
+ // let RESULTS be an empty list of complex selectors
1539
+ Node results = Node::createCollection();
1540
+ // extendedSelectors.got_line_feed = true;
1541
+
1542
+ SubSetMapPairs entries = subset_map.get_v(pSelector);
1543
+
1544
+ GroupByToAFunctor<Complex_Selector_Obj> extPairKeyFunctor;
1545
+ SubSetMapResults arr;
1546
+ group_by_to_a(entries, extPairKeyFunctor, arr);
1547
+
1548
+ SubSetMapLookups holder;
1549
+
1550
+ // for each (EXTENDER, TARGET) in MAP.get(COMPOUND):
1551
+ for (SubSetMapResult& groupedPair : arr) {
1552
+
1553
+ Complex_Selector_Obj seq = groupedPair.first;
1554
+ SubSetMapPairs& group = groupedPair.second;
1555
+
1556
+ DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(seq, "SEQ: "))
1557
+
1558
+ Compound_Selector_Obj pSels = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
1559
+ for (SubSetMapPair& pair : group) {
1560
+ pair.second->extended(true);
1561
+ pSels->concat(pair.second);
1562
+ }
1563
+
1564
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSels, "SELS: "))
1565
+
1566
+ // The selector up to where the @extend is (ie, the thing to merge)
1567
+ Complex_Selector* pExtComplexSelector = seq;
1568
+
1569
+ // TODO: This can return a Compound_Selector with no elements. Should that just be returning NULL?
1570
+ // RUBY: self_without_sel = Sass::Util.array_minus(members, sels)
1571
+ Compound_Selector_Obj pSelectorWithoutExtendSelectors = pSelector->minus(pSels);
1572
+
1573
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "MEMBERS: "))
1574
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "SELF_WO_SEL: "))
1575
+
1576
+ Compound_Selector_Obj pInnermostCompoundSelector = pExtComplexSelector->last()->head();
1577
+
1578
+ if (!pInnermostCompoundSelector) {
1579
+ pInnermostCompoundSelector = SASS_MEMORY_NEW(Compound_Selector, pSelector->pstate());
1580
+ }
1581
+ Compound_Selector_Obj pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors);
1582
+
1583
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pInnermostCompoundSelector, "LHS: "))
1584
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelectorWithoutExtendSelectors, "RHS: "))
1585
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pUnifiedSelector, "UNIFIED: "))
1586
+
1587
+ // RUBY: next unless unified
1588
+ if (!pUnifiedSelector || pUnifiedSelector->length() == 0) {
1589
+ continue;
1590
+ }
1591
+
1592
+ // TODO: implement the parent directive match (if necessary based on test failures)
1593
+ // next if group.map {|e, _| check_directives_match!(e, parent_directives)}.none?
1594
+
1595
+ // TODO: This seems a little fishy to me. See if it causes any problems. From the ruby, we should be able to just
1596
+ // get rid of the last Compound_Selector and replace it with this one. I think the reason this code is more
1597
+ // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered
1598
+ // out and aren't operated on.
1599
+ Complex_Selector_Obj pNewSelector = SASS_MEMORY_CLONE(pExtComplexSelector); // ->first();
1600
+
1601
+ Complex_Selector_Obj pNewInnerMost = SASS_MEMORY_NEW(Complex_Selector, pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, {});
1602
+
1603
+ Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
1604
+ pNewSelector->set_innermost(pNewInnerMost, combinator);
1605
+
1606
+ #ifdef DEBUG
1607
+ ComplexSelectorSet debugSet;
1608
+ debugSet = pNewSelector->sources();
1609
+ if (debugSet.size() > 0) {
1610
+ throw std::runtime_error("The new selector should start with no sources. Something needs to be cloned to fix this.");
1611
+ }
1612
+ debugSet = pExtComplexSelector->sources();
1613
+ if (debugSet.size() > 0) {
1614
+ throw std::runtime_error("The extension selector from our subset map should not have sources. These will bleed to the new selector. Something needs to be cloned to fix this.");
1615
+ }
1616
+ #endif
1617
+
1618
+
1619
+ // if (pSelector && pSelector->has_line_feed()) pNewInnerMost->has_line_feed(true);
1620
+ // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
1621
+ DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector))
1622
+
1623
+ DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet oldSet = pNewSelector->sources(); printSourcesSet(oldSet, "SOURCES NEW SEQ BEGIN: "))
1624
+
1625
+ // I actually want to create a copy here (performance!)
1626
+ ComplexSelectorSet newSourcesSet = pSelector->sources(); // XXX
1627
+ DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, "SOURCES THIS EXTEND: "))
1628
+
1629
+ newSourcesSet.insert(pExtComplexSelector);
1630
+ DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(newSourcesSet, "SOURCES WITH NEW SOURCE: "))
1631
+
1632
+ // RUBY: new_seq.add_sources!(sources + [seq])
1633
+ pNewSelector->addSources(newSourcesSet);
1634
+
1635
+ DEBUG_EXEC(EXTEND_COMPOUND, ComplexSelectorSet newSet = pNewSelector->sources(); printSourcesSet(newSet, "SOURCES ON NEW SELECTOR AFTER ADD: "))
1636
+ DEBUG_EXEC(EXTEND_COMPOUND, printSourcesSet(pSelector->sources(), "SOURCES THIS EXTEND WHICH SHOULD BE SAME STILL: "))
1637
+
1638
+
1639
+ if (pSels->has_line_feed()) pNewSelector->has_line_feed(true);
1640
+
1641
+ holder.push_back(std::make_pair(pSels, pNewSelector));
1642
+ }
1643
+
1644
+
1645
+ for (SubSetMapLookup& pair : holder) {
1646
+
1647
+ Compound_Selector_Obj pSels = pair.first;
1648
+ Complex_Selector_Obj pNewSelector = pair.second;
1649
+
1650
+
1651
+ // RUBY??: next [] if seen.include?(sels)
1652
+ if (seen.find(pSels) != seen.end()) {
1653
+ continue;
1654
+ }
1655
+
1656
+
1657
+ CompoundSelectorSet recurseSeen(seen);
1658
+ recurseSeen.insert(pSels);
1659
+
1660
+
1661
+ DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND: " << complexSelectorToNode(pNewSelector))
1662
+ Node recurseExtendedSelectors = extendComplexSelector(pNewSelector, recurseSeen, isReplace, false); // !:isOriginal
1663
+
1664
+ DEBUG_PRINTLN(EXTEND_COMPOUND, "RECURSING DO EXTEND RETURN: " << recurseExtendedSelectors)
1665
+
1666
+ for (NodeDeque::iterator iterator = recurseExtendedSelectors.collection()->begin(), endIterator = recurseExtendedSelectors.collection()->end();
1667
+ iterator != endIterator; ++iterator) {
1668
+ Node newSelector = *iterator;
1669
+
1670
+ // DEBUG_PRINTLN(EXTEND_COMPOUND, "EXTENDED AT THIS POINT: " << results)
1671
+ // DEBUG_PRINTLN(EXTEND_COMPOUND, "SELECTOR EXISTS ALREADY: " << newSelector << " " << results.contains(newSelector, false /*simpleSelectorOrderDependent*/));
1672
+
1673
+ if (!results.contains(newSelector)) {
1674
+ // DEBUG_PRINTLN(EXTEND_COMPOUND, "ADDING NEW SELECTOR")
1675
+ results.collection()->push_back(newSelector);
1676
+ }
1677
+ }
1678
+ }
1679
+
1680
+ DEBUG_EXEC(EXTEND_COMPOUND, printCompoundSelector(pSelector, "EXTEND COMPOUND END: "))
1681
+
1682
+ // this turned out to be too much overhead
1683
+ // memory results in a map table - since extending is very expensive
1684
+ // memoizeCompound.insert(std::pair<Compound_Selector_Obj, Node>(pSelector, results));
1685
+
1686
+ return results;
1687
+ }
1688
+
1689
+
1690
+ // check if selector has something to be extended by subset_map
1691
+ bool Extend::complexSelectorHasExtension(Complex_Selector* selector, CompoundSelectorSet& seen) {
1692
+
1693
+ bool hasExtension = false;
1694
+
1695
+ Complex_Selector_Obj pIter = selector;
1696
+
1697
+ while (!hasExtension && pIter) {
1698
+ Compound_Selector_Obj pHead = pIter->head();
1699
+
1700
+ if (pHead) {
1701
+ SubSetMapPairs entries = subset_map.get_v(pHead);
1702
+ for (SubSetMapPair ext : entries) {
1703
+ // check if both selectors have the same media block parent
1704
+ // if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1705
+ if (ext.second->media_block() == 0) continue;
1706
+ if (pHead->media_block() &&
1707
+ ext.second->media_block()->media_queries() &&
1708
+ pHead->media_block()->media_queries()
1709
+ ) {
1710
+ std::string query_left(ext.second->media_block()->media_queries()->to_string());
1711
+ std::string query_right(pHead->media_block()->media_queries()->to_string());
1712
+ if (query_left == query_right) continue;
1713
+ }
1714
+
1715
+ // fail if one goes across media block boundaries
1716
+ std::stringstream err;
1717
+ std::string cwd(Sass::File::get_cwd());
1718
+ ParserState pstate(ext.second->pstate());
1719
+ std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
1720
+ err << "You may not @extend an outer selector from within @media.\n";
1721
+ err << "You may only @extend selectors within the same directive.\n";
1722
+ err << "From \"@extend " << ext.second->to_string() << "\"";
1723
+ err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
1724
+ error(err.str(), selector->pstate(), eval->exp.traces);
1725
+ }
1726
+ if (entries.size() > 0) hasExtension = true;
1727
+ }
1728
+
1729
+ pIter = pIter->tail();
1730
+ }
1731
+
1732
+ return hasExtension;
1733
+ }
1734
+
1735
+
1736
+ /*
1737
+ This is the equivalent of ruby's Sequence.do_extend.
1738
+
1739
+ // TODO: I think I have some modified ruby code to put here. Check.
1740
+ */
1741
+ /*
1742
+ ISSUES:
1743
+ - check to automatically include combinators doesn't transfer over to libsass' data model where
1744
+ the combinator and compound selector are one unit
1745
+ next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1746
+ */
1747
+ Node Extend::extendComplexSelector(Complex_Selector* selector, CompoundSelectorSet& seen, bool isReplace, bool isOriginal) {
1748
+
1749
+ // check if we already extended this selector
1750
+ // we can do this since subset_map is "static"
1751
+ auto memoized = memoizeComplex.find(selector);
1752
+ if (memoized != memoizeComplex.end()) {
1753
+ return memoized->second;
1754
+ }
1755
+
1756
+ // convert the input selector to extend node format
1757
+ Node complexSelector = complexSelectorToNode(selector);
1758
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
1759
+
1760
+ // let CHOICES be an empty list of selector-lists
1761
+ // create new collection to hold the results
1762
+ Node choices = Node::createCollection();
1763
+
1764
+ // for each compound selector COMPOUND in COMPLEX:
1765
+ for (Node& sseqOrOp : *complexSelector.collection()) {
1766
+
1767
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "LOOP: " << sseqOrOp)
1768
+
1769
+ // If it's not a selector (meaning it's a combinator), just include it automatically
1770
+ // RUBY: next [[sseq_or_op]] unless sseq_or_op.is_a?(SimpleSequence)
1771
+ if (!sseqOrOp.isSelector()) {
1772
+ // Wrap our Combinator in two collections to match ruby. This is essentially making a collection Node
1773
+ // with one collection child. The collection child represents a Complex_Selector that is only a combinator.
1774
+ Node outer = Node::createCollection();
1775
+ Node inner = Node::createCollection();
1776
+ outer.collection()->push_back(inner);
1777
+ inner.collection()->push_back(sseqOrOp);
1778
+ choices.collection()->push_back(outer);
1779
+ continue;
1780
+ }
1781
+
1782
+ // verified now that node is a valid selector
1783
+ Complex_Selector_Obj sseqSel = sseqOrOp.selector();
1784
+ Compound_Selector_Obj sseqHead = sseqSel->head();
1785
+
1786
+ // let EXTENDED be extend_compound(COMPOUND, SEEN)
1787
+ // extend the compound selector against the given subset_map
1788
+ // RUBY: extended = sseq_or_op.do_extend(extends, parent_directives, replace, seen)
1789
+ Node extended = extendCompoundSelector(sseqHead, seen, isReplace); // slow(17%)!
1790
+ if (sseqOrOp.got_line_feed) extended.got_line_feed = true;
1791
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED: " << extended)
1792
+
1793
+ // Prepend the Compound_Selector based on the choices logic; choices seems to be extend but with a ruby
1794
+ // Array instead of a Sequence due to the member mapping: choices = extended.map {|seq| seq.members}
1795
+ // RUBY: extended.first.add_sources!([self]) if original && !has_placeholder?
1796
+ if (isOriginal && !selector->has_placeholder()) {
1797
+ ComplexSelectorSet srcset;
1798
+ srcset.insert(selector);
1799
+ sseqSel->addSources(srcset);
1800
+ // DEBUG_PRINTLN(EXTEND_COMPLEX, "ADD SOURCES: " << *pComplexSelector)
1801
+ }
1802
+
1803
+ bool isSuperselector = false;
1804
+ // if no complex selector in EXTENDED is a superselector of COMPOUND:
1805
+ for (Node& childNode : *extended.collection()) {
1806
+ Complex_Selector_Obj pExtensionSelector = nodeToComplexSelector(childNode);
1807
+ if (pExtensionSelector->is_superselector_of(sseqSel)) {
1808
+ isSuperselector = true;
1809
+ break;
1810
+ }
1811
+ }
1812
+
1813
+ if (!isSuperselector) {
1814
+ // add a complex selector composed only of COMPOUND to EXTENDED
1815
+ if (sseqOrOp.got_line_feed) sseqSel->has_line_feed(sseqOrOp.got_line_feed);
1816
+ extended.collection()->push_front(complexSelectorToNode(sseqSel));
1817
+ }
1818
+
1819
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "CHOICES UNSHIFTED: " << extended)
1820
+
1821
+ // add EXTENDED to CHOICES
1822
+ // Aggregate our current extensions
1823
+ choices.collection()->push_back(extended);
1824
+ }
1825
+
1826
+
1827
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTENDED NOT EXPANDED: " << choices)
1828
+
1829
+
1830
+
1831
+ // Ruby Equivalent: paths
1832
+ Node paths = Sass::paths(choices);
1833
+
1834
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "PATHS: " << paths)
1835
+
1836
+ // let WEAVES be an empty list of selector lists
1837
+ Node weaves = Node::createCollection();
1838
+
1839
+ // for each list of complex selectors PATH in paths(CHOICES):
1840
+ for (Node& path : *paths.collection()) {
1841
+ // add weave(PATH) to WEAVES
1842
+ Node weaved = weave(path); // slow(12%)!
1843
+ weaved.got_line_feed = path.got_line_feed;
1844
+ weaves.collection()->push_back(weaved);
1845
+ }
1846
+
1847
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "WEAVES: " << weaves)
1848
+
1849
+ // Ruby Equivalent: trim
1850
+ Node trimmed(trim(weaves, isReplace)); // slow(19%)!
1851
+
1852
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "TRIMMED: " << trimmed)
1853
+
1854
+ // Ruby Equivalent: flatten
1855
+ Node flattened(flatten(trimmed, 1));
1856
+
1857
+ DEBUG_PRINTLN(EXTEND_COMPLEX, "FLATTENED: " << flattened)
1858
+
1859
+ // memory results in a map table - since extending is very expensive
1860
+ memoizeComplex.insert(std::pair<Complex_Selector_Obj, Node>(selector, flattened));
1861
+
1862
+ // return trim(WEAVES)
1863
+ return flattened;
1864
+ }
1865
+
1866
+
1867
+
1868
+ /*
1869
+ This is the equivalent of ruby's CommaSequence.do_extend.
1870
+ */
1871
+ // We get a selector list with has something to extend and a subset_map with
1872
+ // all extenders. Pick the ones that match our selectors in the list.
1873
+ Selector_List* Extend::extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen) {
1874
+
1875
+ Selector_List_Obj pNewSelectors = SASS_MEMORY_NEW(Selector_List, pSelectorList->pstate(), pSelectorList->length());
1876
+
1877
+ // check if we already extended this selector
1878
+ // we can do this since subset_map is "static"
1879
+ auto memoized = memoizeList.find(pSelectorList);
1880
+ if (memoized != memoizeList.end()) {
1881
+ extendedSomething = true;
1882
+ return memoized->second;
1883
+ }
1884
+
1885
+ extendedSomething = false;
1886
+ // process each comlplex selector in the selector list.
1887
+ // Find the ones that can be extended by given subset_map.
1888
+ for (size_t index = 0, length = pSelectorList->length(); index < length; index++) {
1889
+ Complex_Selector_Obj pSelector = (*pSelectorList)[index];
1890
+
1891
+ // ruby sass seems to keep a list of things that have extensions and then only extend those. We don't currently do that.
1892
+ // Since it's not that expensive to check if an extension exists in the subset map and since it can be relatively expensive to
1893
+ // run through the extend code (which does a data model transformation), check if there is anything to extend before doing
1894
+ // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
1895
+ // when debugging).
1896
+ if (!complexSelectorHasExtension(pSelector, seen)) {
1897
+ pNewSelectors->append(pSelector);
1898
+ continue;
1899
+ }
1900
+
1901
+ // complexSelectorHasExtension was true!
1902
+ extendedSomething = true;
1903
+
1904
+ // now do the actual extension of the complex selector
1905
+ Node extendedSelectors = extendComplexSelector(pSelector, seen, isReplace, true);
1906
+
1907
+ if (!pSelector->has_placeholder()) {
1908
+ Node nSelector(complexSelectorToNode(pSelector));
1909
+ if (!extendedSelectors.contains(nSelector)) {
1910
+ pNewSelectors->append(pSelector);
1911
+ continue;
1912
+ }
1913
+ }
1914
+
1915
+ bool doReplace = isReplace;
1916
+ for (Node& childNode : *extendedSelectors.collection()) {
1917
+ // When it is a replace, skip the first one, unless there is only one
1918
+ if(doReplace && extendedSelectors.collection()->size() > 1 ) {
1919
+ doReplace = false;
1920
+ continue;
1921
+ }
1922
+ pNewSelectors->append(nodeToComplexSelector(childNode));
1923
+ }
1924
+ }
1925
+
1926
+ Remove_Placeholders remove_placeholders;
1927
+ // it seems that we have to remove the place holders early here
1928
+ // normally we do this as the very last step (compare to ruby sass)
1929
+ pNewSelectors = remove_placeholders.remove_placeholders(pNewSelectors);
1930
+
1931
+ // unwrap all wrapped selectors with inner lists
1932
+ for (Complex_Selector_Obj cur : pNewSelectors->elements()) {
1933
+ // process tails
1934
+ while (cur) {
1935
+ // process header
1936
+ if (cur->head() && seen.find(cur->head()) == seen.end()) {
1937
+ CompoundSelectorSet recseen(seen);
1938
+ recseen.insert(cur->head());
1939
+ // create a copy since we add multiple items if stuff get unwrapped
1940
+ Compound_Selector_Obj cpy_head = SASS_MEMORY_NEW(Compound_Selector, cur->pstate());
1941
+ for (Simple_Selector_Obj hs : *cur->head()) {
1942
+ if (Wrapped_Selector_Obj ws = Cast<Wrapped_Selector>(hs)) {
1943
+ ws->selector(SASS_MEMORY_CLONE(ws->selector()));
1944
+ if (Selector_List_Obj sl = Cast<Selector_List>(ws->selector())) {
1945
+ // special case for ruby ass
1946
+ if (sl->empty()) {
1947
+ // this seems inconsistent but it is how ruby sass seems to remove parentheses
1948
+ cpy_head->append(SASS_MEMORY_NEW(Type_Selector, hs->pstate(), ws->name()));
1949
+ }
1950
+ // has wrapped not selectors
1951
+ else if (ws->name() == ":not") {
1952
+ // extend the inner list of wrapped selector
1953
+ bool extended = false;
1954
+ Selector_List_Obj ext_sl = extendSelectorList(sl, false, extended, recseen);
1955
+ for (size_t i = 0; i < ext_sl->length(); i += 1) {
1956
+ if (Complex_Selector_Obj ext_cs = ext_sl->at(i)) {
1957
+ // create clones for wrapped selector and the inner list
1958
+ Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws);
1959
+ Selector_List_Obj cpy_ws_sl = SASS_MEMORY_NEW(Selector_List, sl->pstate());
1960
+ // remove parent selectors from inner selector
1961
+ Compound_Selector_Obj ext_head;
1962
+ if (ext_cs->first()) ext_head = ext_cs->first()->head();
1963
+ if (ext_head && ext_head && ext_head->length() > 0) {
1964
+ cpy_ws_sl->append(ext_cs->mutable_first());
1965
+ }
1966
+ // assign list to clone
1967
+ cpy_ws->selector(cpy_ws_sl);
1968
+ // append the clone
1969
+ cpy_head->append(cpy_ws);
1970
+ }
1971
+ }
1972
+ if (eval && extended) {
1973
+ eval->exp.selector_stack.push_back(pNewSelectors);
1974
+ cpy_head->perform(eval);
1975
+ eval->exp.selector_stack.pop_back();
1976
+ }
1977
+ }
1978
+ // has wrapped selectors
1979
+ else {
1980
+ Wrapped_Selector_Obj cpy_ws = SASS_MEMORY_COPY(ws);
1981
+ Selector_List_Obj ext_sl = extendSelectorList(sl, recseen);
1982
+ cpy_ws->selector(ext_sl);
1983
+ cpy_head->append(cpy_ws);
1984
+ }
1985
+ } else {
1986
+ cpy_head->append(hs);
1987
+ }
1988
+ } else {
1989
+ cpy_head->append(hs);
1990
+ }
1991
+ }
1992
+ // replace header
1993
+ cur->head(cpy_head);
1994
+ }
1995
+ // process tail
1996
+ cur = cur->tail();
1997
+ }
1998
+ }
1999
+
2000
+ // memory results in a map table - since extending is very expensive
2001
+ memoizeList.insert(std::pair<Selector_List_Obj, Selector_List_Obj>(pSelectorList, pNewSelectors));
2002
+
2003
+ return pNewSelectors.detach();
2004
+
2005
+ }
2006
+
2007
+
2008
+ bool shouldExtendBlock(Block_Obj b) {
2009
+
2010
+ // If a block is empty, there's no reason to extend it since any rules placed on this block
2011
+ // won't have any output. The main benefit of this is for structures like:
2012
+ //
2013
+ // .a {
2014
+ // .b {
2015
+ // x: y;
2016
+ // }
2017
+ // }
2018
+ //
2019
+ // We end up visiting two rulesets (one with the selector .a and the other with the selector .a .b).
2020
+ // In this case, we don't want to try to pull rules onto .a since they won't get output anyway since
2021
+ // there are no child statements. However .a .b should have extensions applied.
2022
+
2023
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
2024
+ Statement_Obj stm = b->at(i);
2025
+
2026
+ if (Cast<Ruleset>(stm)) {
2027
+ // Do nothing. This doesn't count as a statement that causes extension since we'll
2028
+ // iterate over this rule set in a future visit and try to extend it.
2029
+ }
2030
+ else {
2031
+ return true;
2032
+ }
2033
+ }
2034
+
2035
+ return false;
2036
+
2037
+ }
2038
+
2039
+
2040
+ // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
2041
+ // Every Ruleset in the whole tree is calling this function. We decide if there
2042
+ // was is @extend that matches our selector. If we find one, we will go further
2043
+ // and call the extend magic for our selector. The subset_map contains all blocks
2044
+ // where @extend was found. Pick the ones that match our selector!
2045
+ void Extend::extendObjectWithSelectorAndBlock(Ruleset* pObject) {
2046
+
2047
+ DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << Cast<Selector_List>(pObject->selector())->to_string())
2048
+
2049
+ // Ruby sass seems to filter nodes that don't have any content well before we get here.
2050
+ // I'm not sure the repercussions of doing so, so for now, let's just not extend things
2051
+ // that won't be output later. Profiling shows this may us 0.2% or so.
2052
+ if (!shouldExtendBlock(pObject->block())) {
2053
+ DEBUG_PRINTLN(EXTEND_OBJECT, "RETURNING WITHOUT EXTEND ATTEMPT")
2054
+ return;
2055
+ }
2056
+
2057
+ bool extendedSomething = false;
2058
+
2059
+ CompoundSelectorSet seen;
2060
+ Selector_List_Obj pNewSelectorList = extendSelectorList(pObject->selector(), false, extendedSomething, seen);
2061
+
2062
+ if (extendedSomething && pNewSelectorList) {
2063
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << pObject->selector()->to_string())
2064
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string())
2065
+ pNewSelectorList->remove_parent_selectors();
2066
+ pObject->selector(pNewSelectorList);
2067
+ } else {
2068
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND DID NOT TRY TO EXTEND ANYTHING")
2069
+ }
2070
+ }
2071
+
2072
+ Extend::Extend(Subset_Map& ssm)
2073
+ : subset_map(ssm), eval(NULL)
2074
+ { }
2075
+
2076
+ void Extend::setEval(Eval& e) {
2077
+ eval = &e;
2078
+ }
2079
+
2080
+ void Extend::operator()(Block* b)
2081
+ {
2082
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
2083
+ Statement_Obj stm = b->at(i);
2084
+ stm->perform(this);
2085
+ }
2086
+ // do final check if everything was extended
2087
+ // we set `extended` flag on extended selectors
2088
+ if (b->is_root()) {
2089
+ // debug_subset_map(subset_map);
2090
+ for(auto const &it : subset_map.values()) {
2091
+ const Complex_Selector* sel = nullptr;
2092
+ const Compound_Selector* ext = nullptr;
2093
+ if (it.first) sel = it.first->first();
2094
+ if (it.second) ext = it.second;
2095
+ if (ext && (ext->extended() || ext->is_optional())) continue;
2096
+ std::string str_sel(sel ? sel->to_string({ NESTED, 5 }) : "NULL");
2097
+ std::string str_ext(ext ? ext->to_string({ NESTED, 5 }) : "NULL");
2098
+ // debug_ast(sel, "sel: ");
2099
+ // debug_ast(ext, "ext: ");
2100
+ error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n"
2101
+ "The selector \"" + str_ext + "\" was not found.\n"
2102
+ "Use \"@extend " + str_ext + " !optional\" if the"
2103
+ " extend should be able to fail.", (ext ? ext->pstate() : NULL), eval->exp.traces);
2104
+ }
2105
+ }
2106
+
2107
+ }
2108
+
2109
+ void Extend::operator()(Ruleset* pRuleset)
2110
+ {
2111
+ extendObjectWithSelectorAndBlock( pRuleset );
2112
+ pRuleset->block()->perform(this);
2113
+ }
2114
+
2115
+ void Extend::operator()(Supports_Block* pFeatureBlock)
2116
+ {
2117
+ pFeatureBlock->block()->perform(this);
2118
+ }
2119
+
2120
+ void Extend::operator()(Media_Block* pMediaBlock)
2121
+ {
2122
+ pMediaBlock->block()->perform(this);
2123
+ }
2124
+
2125
+ void Extend::operator()(Directive* a)
2126
+ {
2127
+ // Selector_List* ls = Cast<Selector_List>(a->selector());
2128
+ // selector_stack.push_back(ls);
2129
+ if (a->block()) a->block()->perform(this);
2130
+ // exp.selector_stack.pop_back();
2131
+ }
2132
+ }