sassc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +24 -0
  8. data/Rakefile +21 -0
  9. data/ext/libsass/.editorconfig +15 -0
  10. data/ext/libsass/.gitattributes +2 -0
  11. data/ext/libsass/.gitignore +61 -0
  12. data/ext/libsass/.travis.yml +38 -0
  13. data/ext/libsass/COPYING +25 -0
  14. data/ext/libsass/INSTALL +1 -0
  15. data/ext/libsass/LICENSE +25 -0
  16. data/ext/libsass/Makefile +223 -0
  17. data/ext/libsass/Makefile.am +145 -0
  18. data/ext/libsass/Readme.md +93 -0
  19. data/ext/libsass/appveyor.yml +76 -0
  20. data/ext/libsass/ast.cpp +581 -0
  21. data/ext/libsass/ast.hpp +1949 -0
  22. data/ext/libsass/ast_def_macros.hpp +16 -0
  23. data/ext/libsass/ast_factory.hpp +87 -0
  24. data/ext/libsass/ast_fwd_decl.hpp +72 -0
  25. data/ext/libsass/b64/cencode.h +32 -0
  26. data/ext/libsass/b64/encode.h +77 -0
  27. data/ext/libsass/backtrace.hpp +81 -0
  28. data/ext/libsass/base64vlq.cpp +43 -0
  29. data/ext/libsass/base64vlq.hpp +28 -0
  30. data/ext/libsass/bind.cpp +187 -0
  31. data/ext/libsass/bind.hpp +18 -0
  32. data/ext/libsass/cencode.c +102 -0
  33. data/ext/libsass/color_names.hpp +324 -0
  34. data/ext/libsass/configure.ac +130 -0
  35. data/ext/libsass/constants.cpp +144 -0
  36. data/ext/libsass/constants.hpp +145 -0
  37. data/ext/libsass/context.cpp +507 -0
  38. data/ext/libsass/context.hpp +150 -0
  39. data/ext/libsass/contextualize.cpp +157 -0
  40. data/ext/libsass/contextualize.hpp +65 -0
  41. data/ext/libsass/copy_c_str.cpp +13 -0
  42. data/ext/libsass/copy_c_str.hpp +5 -0
  43. data/ext/libsass/debug.hpp +39 -0
  44. data/ext/libsass/environment.hpp +75 -0
  45. data/ext/libsass/error_handling.cpp +28 -0
  46. data/ext/libsass/error_handling.hpp +28 -0
  47. data/ext/libsass/eval.cpp +1149 -0
  48. data/ext/libsass/eval.hpp +80 -0
  49. data/ext/libsass/expand.cpp +430 -0
  50. data/ext/libsass/expand.hpp +77 -0
  51. data/ext/libsass/extconf.rb +6 -0
  52. data/ext/libsass/extend.cpp +1962 -0
  53. data/ext/libsass/extend.hpp +50 -0
  54. data/ext/libsass/file.cpp +291 -0
  55. data/ext/libsass/file.hpp +18 -0
  56. data/ext/libsass/functions.cpp +1565 -0
  57. data/ext/libsass/functions.hpp +187 -0
  58. data/ext/libsass/inspect.cpp +727 -0
  59. data/ext/libsass/inspect.hpp +108 -0
  60. data/ext/libsass/json.cpp +1411 -0
  61. data/ext/libsass/json.hpp +117 -0
  62. data/ext/libsass/kwd_arg_macros.hpp +23 -0
  63. data/ext/libsass/m4/.gitkeep +0 -0
  64. data/ext/libsass/mapping.hpp +17 -0
  65. data/ext/libsass/memory_manager.hpp +54 -0
  66. data/ext/libsass/node.cpp +251 -0
  67. data/ext/libsass/node.hpp +122 -0
  68. data/ext/libsass/operation.hpp +153 -0
  69. data/ext/libsass/output_compressed.cpp +401 -0
  70. data/ext/libsass/output_compressed.hpp +95 -0
  71. data/ext/libsass/output_nested.cpp +364 -0
  72. data/ext/libsass/output_nested.hpp +108 -0
  73. data/ext/libsass/parser.cpp +2016 -0
  74. data/ext/libsass/parser.hpp +264 -0
  75. data/ext/libsass/paths.hpp +69 -0
  76. data/ext/libsass/position.hpp +22 -0
  77. data/ext/libsass/posix/getopt.c +562 -0
  78. data/ext/libsass/posix/getopt.h +95 -0
  79. data/ext/libsass/prelexer.cpp +688 -0
  80. data/ext/libsass/prelexer.hpp +513 -0
  81. data/ext/libsass/remove_placeholders.cpp +59 -0
  82. data/ext/libsass/remove_placeholders.hpp +43 -0
  83. data/ext/libsass/res/resource.rc +35 -0
  84. data/ext/libsass/sass.cpp +33 -0
  85. data/ext/libsass/sass.h +60 -0
  86. data/ext/libsass/sass2scss.cpp +834 -0
  87. data/ext/libsass/sass2scss.h +110 -0
  88. data/ext/libsass/sass_context.cpp +709 -0
  89. data/ext/libsass/sass_context.h +120 -0
  90. data/ext/libsass/sass_functions.cpp +137 -0
  91. data/ext/libsass/sass_functions.h +90 -0
  92. data/ext/libsass/sass_interface.cpp +277 -0
  93. data/ext/libsass/sass_interface.h +97 -0
  94. data/ext/libsass/sass_util.cpp +136 -0
  95. data/ext/libsass/sass_util.hpp +259 -0
  96. data/ext/libsass/sass_values.cpp +337 -0
  97. data/ext/libsass/sass_values.h +124 -0
  98. data/ext/libsass/script/bootstrap +10 -0
  99. data/ext/libsass/script/branding +10 -0
  100. data/ext/libsass/script/ci-build-libsass +72 -0
  101. data/ext/libsass/script/ci-install-compiler +4 -0
  102. data/ext/libsass/script/ci-install-deps +19 -0
  103. data/ext/libsass/script/ci-report-coverage +25 -0
  104. data/ext/libsass/script/coveralls-debug +32 -0
  105. data/ext/libsass/script/spec +5 -0
  106. data/ext/libsass/script/tap-driver +652 -0
  107. data/ext/libsass/script/tap-runner +1 -0
  108. data/ext/libsass/source_map.cpp +133 -0
  109. data/ext/libsass/source_map.hpp +46 -0
  110. data/ext/libsass/subset_map.hpp +145 -0
  111. data/ext/libsass/support/libsass.pc.in +11 -0
  112. data/ext/libsass/test-driver +127 -0
  113. data/ext/libsass/test/test_node.cpp +98 -0
  114. data/ext/libsass/test/test_paths.cpp +29 -0
  115. data/ext/libsass/test/test_selector_difference.cpp +28 -0
  116. data/ext/libsass/test/test_specificity.cpp +28 -0
  117. data/ext/libsass/test/test_subset_map.cpp +472 -0
  118. data/ext/libsass/test/test_superselector.cpp +71 -0
  119. data/ext/libsass/test/test_unification.cpp +33 -0
  120. data/ext/libsass/to_c.cpp +61 -0
  121. data/ext/libsass/to_c.hpp +44 -0
  122. data/ext/libsass/to_string.cpp +29 -0
  123. data/ext/libsass/to_string.hpp +32 -0
  124. data/ext/libsass/token.hpp +32 -0
  125. data/ext/libsass/units.cpp +54 -0
  126. data/ext/libsass/units.hpp +10 -0
  127. data/ext/libsass/utf8.h +34 -0
  128. data/ext/libsass/utf8/checked.h +327 -0
  129. data/ext/libsass/utf8/core.h +329 -0
  130. data/ext/libsass/utf8/unchecked.h +228 -0
  131. data/ext/libsass/utf8_string.cpp +102 -0
  132. data/ext/libsass/utf8_string.hpp +36 -0
  133. data/ext/libsass/util.cpp +189 -0
  134. data/ext/libsass/util.hpp +26 -0
  135. data/ext/libsass/win/libsass.filters +291 -0
  136. data/ext/libsass/win/libsass.sln +28 -0
  137. data/ext/libsass/win/libsass.vcxproj +255 -0
  138. data/lib/sassc.rb +6 -0
  139. data/lib/sassc/engine.rb +13 -0
  140. data/lib/sassc/native.rb +44 -0
  141. data/lib/sassc/native/native_context_api.rb +140 -0
  142. data/lib/sassc/native/native_functions_api.rb +41 -0
  143. data/lib/sassc/native/sass_input_style.rb +11 -0
  144. data/lib/sassc/native/sass_output_style.rb +10 -0
  145. data/lib/sassc/native/sass_value.rb +95 -0
  146. data/lib/sassc/native/string_list.rb +8 -0
  147. data/lib/sassc/version.rb +3 -0
  148. data/sassc.gemspec +43 -0
  149. data/test/smoke_test.rb +171 -0
  150. data/test/test_helper.rb +4 -0
  151. metadata +281 -0
@@ -0,0 +1,122 @@
1
+ #define SASS_NODE
2
+
3
+
4
+ #include <deque>
5
+ #include <iostream>
6
+ #include <memory>
7
+
8
+ #ifndef SASS_AST
9
+ #include "ast.hpp"
10
+ #endif
11
+
12
+
13
+ namespace Sass {
14
+
15
+
16
+ using namespace std;
17
+
18
+
19
+ struct Context;
20
+
21
+ /*
22
+ There are a lot of stumbling blocks when trying to port the ruby extend code to C++. The biggest is the choice of
23
+ data type. The ruby code will pretty seamlessly switch types between an Array<SimpleSequence or Op> (libsass'
24
+ equivalent is the Complex_Selector) to a Sequence, which contains more metadata about the sequence than just the
25
+ selector info. They also have the ability to have arbitrary nestings of arrays like [1, [2]], which is hard to
26
+ implement using Array equivalents in C++ (like the deque or vector). They also have the ability to include nil
27
+ in the arrays, like [1, nil, 3], which has potential semantic differences than an empty array [1, [], 3]. To be
28
+ able to represent all of these as unique cases, we need to create a tree of variant objects. The tree nature allows
29
+ the inconsistent nesting levels. The variant nature (while making some of the C++ code uglier) allows the code to
30
+ more closely match the ruby code, which is a huge benefit when attempting to implement an complex algorithm like
31
+ the Extend operator.
32
+
33
+ Note that the current libsass data model also pairs the combinator with the Complex_Selector that follows it, but
34
+ ruby sass has no such restriction, so we attempt to create a data structure that can handle them split apart.
35
+ */
36
+
37
+ class Node;
38
+ typedef deque<Node> NodeDeque;
39
+ typedef shared_ptr<NodeDeque> NodeDequePtr;
40
+
41
+ class Node {
42
+ public:
43
+ enum TYPE {
44
+ SELECTOR,
45
+ COMBINATOR,
46
+ COLLECTION,
47
+ NIL
48
+ };
49
+
50
+ TYPE type() const { return mType; }
51
+ bool isCombinator() const { return mType == COMBINATOR; }
52
+ bool isSelector() const { return mType == SELECTOR; }
53
+ bool isCollection() const { return mType == COLLECTION; }
54
+ bool isNil() const { return mType == NIL; }
55
+
56
+ Complex_Selector::Combinator combinator() const { return mCombinator; }
57
+
58
+ Complex_Selector* selector() { return mpSelector; }
59
+ const Complex_Selector* selector() const { return mpSelector; }
60
+
61
+ NodeDequePtr collection() { return mpCollection; }
62
+ const NodeDequePtr collection() const { return mpCollection; }
63
+
64
+ static Node createCombinator(const Complex_Selector::Combinator& combinator);
65
+
66
+ // This method will clone the selector, stripping off the tail and combinator
67
+ static Node createSelector(Complex_Selector* pSelector, Context& ctx);
68
+
69
+ static Node createCollection();
70
+ static Node createCollection(const NodeDeque& values);
71
+
72
+ static Node createNil();
73
+
74
+ Node clone(Context& ctx) const;
75
+
76
+ bool operator==(const Node& rhs) const;
77
+ inline bool operator!=(const Node& rhs) const { return !(*this == rhs); }
78
+
79
+
80
+ /*
81
+ COLLECTION FUNCTIONS
82
+
83
+ Most types don't need any helper methods (nil and combinator due to their simplicity and
84
+ selector due to the fact that we leverage the non-node selector code on the Complex_Selector
85
+ whereever possible). The following methods are intended to be called on Node objects whose
86
+ type is COLLECTION only.
87
+ */
88
+
89
+ // rhs and this must be node collections. Shallow copy the nodes from rhs to the end of this.
90
+ // This function DOES NOT remove the nodes from rhs.
91
+ void plus(Node& rhs);
92
+
93
+ // potentialChild must be a node collection of selectors/combinators. this must be a collection
94
+ // of collections of nodes/combinators. This method checks if potentialChild is a child of this
95
+ // Node.
96
+ bool contains(const Node& potentialChild, bool simpleSelectorOrderDependent) const;
97
+
98
+ private:
99
+ // Private constructor; Use the static methods (like createCombinator and createSelector)
100
+ // to instantiate this object. This is more expressive, and it allows us to break apart each
101
+ // case into separate functions.
102
+ Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection);
103
+
104
+ TYPE mType;
105
+
106
+ // TODO: can we union these to save on memory?
107
+ Complex_Selector::Combinator mCombinator;
108
+ Complex_Selector* mpSelector; // this is an AST_Node, so it will be handled by the Memory_Manager
109
+ NodeDequePtr mpCollection;
110
+ };
111
+
112
+
113
+ ostream& operator<<(ostream& os, const Node& node);
114
+
115
+
116
+ Node complexSelectorToNode(Complex_Selector* pToConvert, Context& ctx);
117
+ Complex_Selector* nodeToComplexSelector(const Node& toConvert, Context& ctx);
118
+
119
+
120
+ bool nodesEqual(const Node& one, const Node& two, bool simpleSelectorOrderDependent);
121
+
122
+ }
@@ -0,0 +1,153 @@
1
+ #define SASS_OPERATION
2
+
3
+ #include "ast_fwd_decl.hpp"
4
+
5
+ #include <iostream>
6
+ using namespace std;
7
+ #include <typeinfo>
8
+
9
+ namespace Sass {
10
+
11
+ template<typename T>
12
+ class Operation {
13
+ public:
14
+ virtual T operator()(AST_Node* x) = 0;
15
+ virtual ~Operation() { }
16
+ // statements
17
+ virtual T operator()(Block* x) = 0;
18
+ virtual T operator()(Ruleset* x) = 0;
19
+ virtual T operator()(Propset* x) = 0;
20
+ virtual T operator()(Feature_Block* x) = 0;
21
+ virtual T operator()(Media_Block* x) = 0;
22
+ virtual T operator()(At_Rule* x) = 0;
23
+ virtual T operator()(Declaration* x) = 0;
24
+ virtual T operator()(Assignment* x) = 0;
25
+ virtual T operator()(Import* x) = 0;
26
+ virtual T operator()(Import_Stub* x) = 0;
27
+ virtual T operator()(Warning* x) = 0;
28
+ virtual T operator()(Error* x) = 0;
29
+ virtual T operator()(Debug* x) = 0;
30
+ virtual T operator()(Comment* x) = 0;
31
+ virtual T operator()(If* x) = 0;
32
+ virtual T operator()(For* x) = 0;
33
+ virtual T operator()(Each* x) = 0;
34
+ virtual T operator()(While* x) = 0;
35
+ virtual T operator()(Return* x) = 0;
36
+ virtual T operator()(Content* x) = 0;
37
+ virtual T operator()(Extension* x) = 0;
38
+ virtual T operator()(Definition* x) = 0;
39
+ virtual T operator()(Mixin_Call* x) = 0;
40
+ // expressions
41
+ virtual T operator()(List* x) = 0;
42
+ virtual T operator()(Map* x) = 0;
43
+ virtual T operator()(Binary_Expression* x) = 0;
44
+ virtual T operator()(Unary_Expression* x) = 0;
45
+ virtual T operator()(Function_Call* x) = 0;
46
+ virtual T operator()(Function_Call_Schema* x) = 0;
47
+ virtual T operator()(Variable* x) = 0;
48
+ virtual T operator()(Textual* x) = 0;
49
+ virtual T operator()(Number* x) = 0;
50
+ virtual T operator()(Color* x) = 0;
51
+ virtual T operator()(Boolean* x) = 0;
52
+ virtual T operator()(String_Schema* x) = 0;
53
+ virtual T operator()(String_Constant* x) = 0;
54
+ virtual T operator()(Feature_Query* x) = 0;
55
+ virtual T operator()(Feature_Query_Condition* x)= 0;
56
+ virtual T operator()(Media_Query* x) = 0;
57
+ virtual T operator()(Media_Query_Expression* x) = 0;
58
+ virtual T operator()(Null* x) = 0;
59
+ // parameters and arguments
60
+ virtual T operator()(Parameter* x) = 0;
61
+ virtual T operator()(Parameters* x) = 0;
62
+ virtual T operator()(Argument* x) = 0;
63
+ virtual T operator()(Arguments* x) = 0;
64
+ // selectors
65
+ virtual T operator()(Selector_Schema* x) = 0;
66
+ virtual T operator()(Selector_Reference* x) = 0;
67
+ virtual T operator()(Selector_Placeholder* x) = 0;
68
+ virtual T operator()(Type_Selector* x) = 0;
69
+ virtual T operator()(Selector_Qualifier* x) = 0;
70
+ virtual T operator()(Attribute_Selector* x) = 0;
71
+ virtual T operator()(Pseudo_Selector* x) = 0;
72
+ virtual T operator()(Wrapped_Selector* x) = 0;
73
+ virtual T operator()(Compound_Selector* x) = 0;
74
+ virtual T operator()(Complex_Selector* x) = 0;
75
+ virtual T operator()(Selector_List* x) = 0;
76
+
77
+ template <typename U>
78
+ T fallback(U x) { return T(); }
79
+ };
80
+
81
+ template <typename T, typename D>
82
+ class Operation_CRTP : public Operation<T> {
83
+ public:
84
+ virtual T operator()(AST_Node* x) { return static_cast<D*>(this)->fallback(x); }
85
+ virtual ~Operation_CRTP() = 0;
86
+ // statements
87
+ virtual T operator()(Block* x) { return static_cast<D*>(this)->fallback(x); }
88
+ virtual T operator()(Ruleset* x) { return static_cast<D*>(this)->fallback(x); }
89
+ virtual T operator()(Propset* x) { return static_cast<D*>(this)->fallback(x); }
90
+ virtual T operator()(Feature_Block* x) { return static_cast<D*>(this)->fallback(x); }
91
+ virtual T operator()(Media_Block* x) { return static_cast<D*>(this)->fallback(x); }
92
+ virtual T operator()(At_Rule* x) { return static_cast<D*>(this)->fallback(x); }
93
+ virtual T operator()(Declaration* x) { return static_cast<D*>(this)->fallback(x); }
94
+ virtual T operator()(Assignment* x) { return static_cast<D*>(this)->fallback(x); }
95
+ virtual T operator()(Import* x) { return static_cast<D*>(this)->fallback(x); }
96
+ virtual T operator()(Import_Stub* x) { return static_cast<D*>(this)->fallback(x); }
97
+ virtual T operator()(Warning* x) { return static_cast<D*>(this)->fallback(x); }
98
+ virtual T operator()(Error* x) { return static_cast<D*>(this)->fallback(x); }
99
+ virtual T operator()(Debug* x) { return static_cast<D*>(this)->fallback(x); }
100
+ virtual T operator()(Comment* x) { return static_cast<D*>(this)->fallback(x); }
101
+ virtual T operator()(If* x) { return static_cast<D*>(this)->fallback(x); }
102
+ virtual T operator()(For* x) { return static_cast<D*>(this)->fallback(x); }
103
+ virtual T operator()(Each* x) { return static_cast<D*>(this)->fallback(x); }
104
+ virtual T operator()(While* x) { return static_cast<D*>(this)->fallback(x); }
105
+ virtual T operator()(Return* x) { return static_cast<D*>(this)->fallback(x); }
106
+ virtual T operator()(Content* x) { return static_cast<D*>(this)->fallback(x); }
107
+ virtual T operator()(Extension* x) { return static_cast<D*>(this)->fallback(x); }
108
+ virtual T operator()(Definition* x) { return static_cast<D*>(this)->fallback(x); }
109
+ virtual T operator()(Mixin_Call* x) { return static_cast<D*>(this)->fallback(x); }
110
+ // expressions
111
+ virtual T operator()(List* x) { return static_cast<D*>(this)->fallback(x); }
112
+ virtual T operator()(Map* x) { return static_cast<D*>(this)->fallback(x); }
113
+ virtual T operator()(Binary_Expression* x) { return static_cast<D*>(this)->fallback(x); }
114
+ virtual T operator()(Unary_Expression* x) { return static_cast<D*>(this)->fallback(x); }
115
+ virtual T operator()(Function_Call* x) { return static_cast<D*>(this)->fallback(x); }
116
+ virtual T operator()(Function_Call_Schema* x) { return static_cast<D*>(this)->fallback(x); }
117
+ virtual T operator()(Variable* x) { return static_cast<D*>(this)->fallback(x); }
118
+ virtual T operator()(Textual* x) { return static_cast<D*>(this)->fallback(x); }
119
+ virtual T operator()(Number* x) { return static_cast<D*>(this)->fallback(x); }
120
+ virtual T operator()(Color* x) { return static_cast<D*>(this)->fallback(x); }
121
+ virtual T operator()(Boolean* x) { return static_cast<D*>(this)->fallback(x); }
122
+ virtual T operator()(String_Schema* x) { return static_cast<D*>(this)->fallback(x); }
123
+ virtual T operator()(String_Constant* x) { return static_cast<D*>(this)->fallback(x); }
124
+ virtual T operator()(Feature_Query* x) { return static_cast<D*>(this)->fallback(x); }
125
+ virtual T operator()(Feature_Query_Condition* x){ return static_cast<D*>(this)->fallback(x); }
126
+ virtual T operator()(Media_Query* x) { return static_cast<D*>(this)->fallback(x); }
127
+ virtual T operator()(Media_Query_Expression* x) { return static_cast<D*>(this)->fallback(x); }
128
+ virtual T operator()(Null* x) { return static_cast<D*>(this)->fallback(x); }
129
+ // parameters and arguments
130
+ virtual T operator()(Parameter* x) { return static_cast<D*>(this)->fallback(x); }
131
+ virtual T operator()(Parameters* x) { return static_cast<D*>(this)->fallback(x); }
132
+ virtual T operator()(Argument* x) { return static_cast<D*>(this)->fallback(x); }
133
+ virtual T operator()(Arguments* x) { return static_cast<D*>(this)->fallback(x); }
134
+ // selectors
135
+ virtual T operator()(Selector_Schema* x) { return static_cast<D*>(this)->fallback(x); }
136
+ virtual T operator()(Selector_Reference* x) { return static_cast<D*>(this)->fallback(x); }
137
+ virtual T operator()(Selector_Placeholder* x) { return static_cast<D*>(this)->fallback(x); }
138
+ virtual T operator()(Type_Selector* x) { return static_cast<D*>(this)->fallback(x); }
139
+ virtual T operator()(Selector_Qualifier* x) { return static_cast<D*>(this)->fallback(x); }
140
+ virtual T operator()(Attribute_Selector* x) { return static_cast<D*>(this)->fallback(x); }
141
+ virtual T operator()(Pseudo_Selector* x) { return static_cast<D*>(this)->fallback(x); }
142
+ virtual T operator()(Wrapped_Selector* x) { return static_cast<D*>(this)->fallback(x); }
143
+ virtual T operator()(Compound_Selector* x) { return static_cast<D*>(this)->fallback(x); }
144
+ virtual T operator()(Complex_Selector* x) { return static_cast<D*>(this)->fallback(x); }
145
+ virtual T operator()(Selector_List* x) { return static_cast<D*>(this)->fallback(x); }
146
+
147
+ template <typename U>
148
+ T fallback(U x) { return T(); }
149
+ };
150
+ template<typename T, typename D>
151
+ inline Operation_CRTP<T, D>::~Operation_CRTP() { }
152
+
153
+ }
@@ -0,0 +1,401 @@
1
+ #include "output_compressed.hpp"
2
+ #include "inspect.hpp"
3
+ #include "ast.hpp"
4
+ #include "context.hpp"
5
+ #include "to_string.hpp"
6
+ #include "util.hpp"
7
+ #include <cmath>
8
+ #include <iomanip>
9
+
10
+ namespace Sass {
11
+ using namespace std;
12
+
13
+ Output_Compressed::Output_Compressed(Context* ctx) : buffer(""), rendered_imports(""), ctx(ctx), seen_utf8(false) { }
14
+ Output_Compressed::~Output_Compressed() { }
15
+
16
+ inline void Output_Compressed::fallback_impl(AST_Node* n)
17
+ {
18
+ Inspect i(ctx);
19
+ n->perform(&i);
20
+ const string& text = i.get_buffer();
21
+ for(const char& chr : text) {
22
+ // abort clause
23
+ if (seen_utf8) break;
24
+ // skip all normal ascii chars
25
+ if (Util::isAscii(chr)) continue;
26
+ // singleton
27
+ seen_utf8 = true;
28
+ }
29
+ buffer += text;
30
+ if (ctx && !ctx->_skip_source_map_update)
31
+ ctx->source_map.update_column(text);
32
+ }
33
+
34
+ void Output_Compressed::operator()(Import* imp)
35
+ {
36
+ Inspect insp(ctx);
37
+ imp->perform(&insp);
38
+ rendered_imports += insp.get_buffer();
39
+ }
40
+
41
+ void Output_Compressed::operator()(Block* b)
42
+ {
43
+ if (!b->is_root()) return;
44
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
45
+ (*b)[i]->perform(this);
46
+ }
47
+ }
48
+
49
+ void Output_Compressed::operator()(Ruleset* r)
50
+ {
51
+ Selector* s = r->selector();
52
+ Block* b = r->block();
53
+
54
+ // Filter out rulesets that aren't printable (process its children though)
55
+ if (!Util::isPrintable(r)) {
56
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
57
+ Statement* stm = (*b)[i];
58
+ if (dynamic_cast<Has_Block*>(stm)) {
59
+ stm->perform(this);
60
+ }
61
+ }
62
+ return;
63
+ }
64
+
65
+ if (b->has_non_hoistable()) {
66
+ s->perform(this);
67
+ append_singleline_part_to_buffer("{");
68
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
69
+ Statement* stm = (*b)[i];
70
+ if (!stm->is_hoistable()) {
71
+ stm->perform(this);
72
+ }
73
+ }
74
+ size_t l = buffer.length();
75
+ if (l > 0 && buffer.at(l - 1) == ';') buffer.erase(l - 1);
76
+ append_singleline_part_to_buffer("}");
77
+ }
78
+
79
+ if (b->has_hoistable()) {
80
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
81
+ Statement* stm = (*b)[i];
82
+ if (stm->is_hoistable()) {
83
+ stm->perform(this);
84
+ }
85
+ }
86
+ }
87
+ }
88
+
89
+ void Output_Compressed::operator()(Media_Block* m)
90
+ {
91
+ List* q = m->media_queries();
92
+ Block* b = m->block();
93
+
94
+ // Filter out media blocks that aren't printable (process its children though)
95
+ if (!Util::isPrintable(m)) {
96
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
97
+ Statement* stm = (*b)[i];
98
+ if (dynamic_cast<Has_Block*>(stm)) {
99
+ stm->perform(this);
100
+ }
101
+ }
102
+ return;
103
+ }
104
+
105
+ ctx->source_map.add_mapping(m);
106
+ append_singleline_part_to_buffer("@media ");
107
+ q->perform(this);
108
+ append_singleline_part_to_buffer("{");
109
+
110
+ Selector* e = m->selector();
111
+ if (e && b->has_non_hoistable()) {
112
+ // JMA - hoisted, output the non-hoistable in a nested block, followed by the hoistable
113
+ e->perform(this);
114
+ append_singleline_part_to_buffer("{");
115
+
116
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
117
+ Statement* stm = (*b)[i];
118
+ if (!stm->is_hoistable()) {
119
+ stm->perform(this);
120
+ }
121
+ }
122
+
123
+ append_singleline_part_to_buffer("}");
124
+
125
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
126
+ Statement* stm = (*b)[i];
127
+ if (stm->is_hoistable()) {
128
+ stm->perform(this);
129
+ }
130
+ }
131
+ }
132
+ else {
133
+ // JMA - not hoisted, just output in order
134
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
135
+ Statement* stm = (*b)[i];
136
+ stm->perform(this);
137
+ }
138
+ }
139
+
140
+ append_singleline_part_to_buffer("}");
141
+ }
142
+
143
+ void Output_Compressed::operator()(At_Rule* a)
144
+ {
145
+ string kwd = a->keyword();
146
+ Selector* s = a->selector();
147
+ Expression* v = a->value();
148
+ Block* b = a->block();
149
+
150
+ append_singleline_part_to_buffer(kwd);
151
+ if (s) {
152
+ append_singleline_part_to_buffer(" ");
153
+ s->perform(this);
154
+ }
155
+ else if (v) {
156
+ append_singleline_part_to_buffer(" ");
157
+ v->perform(this);
158
+ }
159
+
160
+ if (!b) {
161
+ append_singleline_part_to_buffer(";");
162
+ return;
163
+ }
164
+
165
+ append_singleline_part_to_buffer("{");
166
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
167
+ Statement* stm = (*b)[i];
168
+ if (!stm->is_hoistable()) {
169
+ stm->perform(this);
170
+ }
171
+ }
172
+
173
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
174
+ Statement* stm = (*b)[i];
175
+ if (stm->is_hoistable()) {
176
+ stm->perform(this);
177
+ }
178
+ }
179
+
180
+ append_singleline_part_to_buffer("}");
181
+ }
182
+
183
+ void Output_Compressed::operator()(Declaration* d)
184
+ {
185
+ bool bPrintExpression = true;
186
+ // Check print conditions
187
+ if (d->value()->concrete_type() == Expression::NULL_VAL) {
188
+ bPrintExpression = false;
189
+ }
190
+ if (d->value()->concrete_type() == Expression::STRING) {
191
+ String_Constant* valConst = static_cast<String_Constant*>(d->value());
192
+ string val(valConst->value());
193
+ if (val.empty()) {
194
+ bPrintExpression = false;
195
+ }
196
+ }
197
+ // Print if OK
198
+ if(bPrintExpression) {
199
+ if (ctx) ctx->source_map.add_mapping(d->property());
200
+ d->property()->perform(this);
201
+ append_singleline_part_to_buffer(":");
202
+ if (ctx) ctx->source_map.add_mapping(d->value());
203
+ d->value()->perform(this);
204
+ if (d->is_important()) append_singleline_part_to_buffer("!important");
205
+ append_singleline_part_to_buffer(";");
206
+ }
207
+ }
208
+
209
+ void Output_Compressed::operator()(Comment* c)
210
+ {
211
+ To_String to_string;
212
+ string txt = c->text()->perform(&to_string);
213
+ if(txt[2] != '!') {
214
+ return;
215
+ }
216
+ else {
217
+ Inspect i(ctx);
218
+ c->perform(&i);
219
+ const string& text = i.get_buffer();
220
+ for(const char& chr : text) {
221
+ // abort clause
222
+ if (seen_utf8) break;
223
+ // skip all normal ascii chars
224
+ if (Util::isAscii(chr)) continue;
225
+ // singleton
226
+ seen_utf8 = true;
227
+ }
228
+ buffer += text;
229
+ if (ctx && !ctx->_skip_source_map_update)
230
+ ctx->source_map.update_column(text);
231
+ }
232
+ }
233
+
234
+ void Output_Compressed::operator()(List* list)
235
+ {
236
+ string sep(list->separator() == List::SPACE ? " " : ",");
237
+ if (list->empty()) return;
238
+ Expression* first = (*list)[0];
239
+ bool first_invisible = first->is_invisible();
240
+ if (!first_invisible) first->perform(this);
241
+ for (size_t i = 1, L = list->length(); i < L; ++i) {
242
+ Expression* next = (*list)[i];
243
+ bool next_invisible = next->is_invisible();
244
+ if (i == 1 && !first_invisible && !next_invisible) append_singleline_part_to_buffer(sep);
245
+ else if (!next_invisible) append_singleline_part_to_buffer(sep);
246
+ next->perform(this);
247
+ }
248
+ }
249
+
250
+ // helper function for serializing colors
251
+ template <size_t range>
252
+ static double cap_channel(double c) {
253
+ if (c > range) return range;
254
+ else if (c < 0) return 0;
255
+ else return c;
256
+ }
257
+
258
+ void Output_Compressed::operator()(Color* c)
259
+ {
260
+ stringstream ss;
261
+ double r = round(cap_channel<0xff>(c->r()));
262
+ double g = round(cap_channel<0xff>(c->g()));
263
+ double b = round(cap_channel<0xff>(c->b()));
264
+ double a = cap_channel<1> (c->a());
265
+
266
+ // retain the originally specified color definition if unchanged
267
+ if (!c->disp().empty()) {
268
+ ss << c->disp();
269
+ }
270
+ else if (r == 0 && g == 0 && b == 0 && a == 0) {
271
+ ss << "transparent";
272
+ }
273
+ else if (a >= 1) {
274
+ // see if it's a named color
275
+ int numval = r * 0x10000;
276
+ numval += g * 0x100;
277
+ numval += b;
278
+ if (ctx && ctx->colors_to_names.count(numval)) {
279
+ ss << ctx->colors_to_names[numval];
280
+ }
281
+ else {
282
+ // otherwise output the hex triplet
283
+ ss << '#' << setw(2) << setfill('0');
284
+ ss << hex << setw(2) << static_cast<unsigned long>(r);
285
+ ss << hex << setw(2) << static_cast<unsigned long>(g);
286
+ ss << hex << setw(2) << static_cast<unsigned long>(b);
287
+ }
288
+ }
289
+ else {
290
+ ss << "rgba(";
291
+ ss << static_cast<unsigned long>(r) << ",";
292
+ ss << static_cast<unsigned long>(g) << ",";
293
+ ss << static_cast<unsigned long>(b) << ",";
294
+ ss << a << ')';
295
+ }
296
+ append_singleline_part_to_buffer(ss.str());
297
+ }
298
+
299
+ void Output_Compressed::operator()(Media_Query_Expression* mqe)
300
+ {
301
+ if (mqe->is_interpolated()) {
302
+ mqe->feature()->perform(this);
303
+ }
304
+ else {
305
+ append_singleline_part_to_buffer("(");
306
+ mqe->feature()->perform(this);
307
+ if (mqe->value()) {
308
+ append_singleline_part_to_buffer(":");
309
+ mqe->value()->perform(this);
310
+ }
311
+ append_singleline_part_to_buffer(")");
312
+ }
313
+ }
314
+
315
+ void Output_Compressed::operator()(Null* n)
316
+ {
317
+ // noop
318
+ }
319
+
320
+ void Output_Compressed::operator()(Argument* a)
321
+ {
322
+ if (!a->name().empty()) {
323
+ append_singleline_part_to_buffer(a->name());
324
+ append_singleline_part_to_buffer(":");
325
+ }
326
+ a->value()->perform(this);
327
+ if (a->is_rest_argument()) {
328
+ append_singleline_part_to_buffer("...");
329
+ }
330
+ }
331
+
332
+ void Output_Compressed::operator()(Arguments* a)
333
+ {
334
+ append_singleline_part_to_buffer("(");
335
+ if (!a->empty()) {
336
+ (*a)[0]->perform(this);
337
+ for (size_t i = 1, L = a->length(); i < L; ++i) {
338
+ append_singleline_part_to_buffer(",");
339
+ (*a)[i]->perform(this);
340
+ }
341
+ }
342
+ append_singleline_part_to_buffer(")");
343
+ }
344
+
345
+ void Output_Compressed::operator()(Complex_Selector* c)
346
+ {
347
+ Compound_Selector* head = c->head();
348
+ Complex_Selector* tail = c->tail();
349
+ Complex_Selector::Combinator comb = c->combinator();
350
+ if (head && head->is_empty_reference() && tail)
351
+ {
352
+ tail->perform(this);
353
+ return;
354
+ }
355
+ if (head && !head->is_empty_reference()) head->perform(this);
356
+ switch (comb) {
357
+ case Complex_Selector::ANCESTOR_OF:
358
+ if (tail) append_singleline_part_to_buffer(" ");
359
+ break;
360
+ case Complex_Selector::PARENT_OF:
361
+ append_singleline_part_to_buffer(">");
362
+ break;
363
+ case Complex_Selector::PRECEDES:
364
+ // Apparently need to preserve spaces around this combinator?
365
+ if (head && !head->is_empty_reference()) append_singleline_part_to_buffer(" ");
366
+ append_singleline_part_to_buffer("~");
367
+ if (tail) append_singleline_part_to_buffer(" ");
368
+ break;
369
+ case Complex_Selector::ADJACENT_TO:
370
+ append_singleline_part_to_buffer("+");
371
+ break;
372
+ }
373
+ if (tail) tail->perform(this);
374
+ }
375
+
376
+ void Output_Compressed::operator()(Selector_List* g)
377
+ {
378
+ if (g->empty()) return;
379
+ (*g)[0]->perform(this);
380
+ for (size_t i = 1, L = g->length(); i < L; ++i) {
381
+ append_singleline_part_to_buffer(",");
382
+ (*g)[i]->perform(this);
383
+ }
384
+ }
385
+
386
+ void Output_Compressed::append_singleline_part_to_buffer(const string& text)
387
+ {
388
+ buffer += text;
389
+ if (ctx && !ctx->_skip_source_map_update)
390
+ ctx->source_map.update_column(text);
391
+ for(const char& chr : text) {
392
+ // abort clause
393
+ if (seen_utf8) break;
394
+ // skip all normal ascii chars
395
+ if (Util::isAscii(chr)) continue;
396
+ // singleton
397
+ seen_utf8 = true;
398
+ }
399
+ }
400
+
401
+ }