sassc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.gitmodules +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +21 -0
- data/ext/libsass/.editorconfig +15 -0
- data/ext/libsass/.gitattributes +2 -0
- data/ext/libsass/.gitignore +61 -0
- data/ext/libsass/.travis.yml +38 -0
- data/ext/libsass/COPYING +25 -0
- data/ext/libsass/INSTALL +1 -0
- data/ext/libsass/LICENSE +25 -0
- data/ext/libsass/Makefile +223 -0
- data/ext/libsass/Makefile.am +145 -0
- data/ext/libsass/Readme.md +93 -0
- data/ext/libsass/appveyor.yml +76 -0
- data/ext/libsass/ast.cpp +581 -0
- data/ext/libsass/ast.hpp +1949 -0
- data/ext/libsass/ast_def_macros.hpp +16 -0
- data/ext/libsass/ast_factory.hpp +87 -0
- data/ext/libsass/ast_fwd_decl.hpp +72 -0
- data/ext/libsass/b64/cencode.h +32 -0
- data/ext/libsass/b64/encode.h +77 -0
- data/ext/libsass/backtrace.hpp +81 -0
- data/ext/libsass/base64vlq.cpp +43 -0
- data/ext/libsass/base64vlq.hpp +28 -0
- data/ext/libsass/bind.cpp +187 -0
- data/ext/libsass/bind.hpp +18 -0
- data/ext/libsass/cencode.c +102 -0
- data/ext/libsass/color_names.hpp +324 -0
- data/ext/libsass/configure.ac +130 -0
- data/ext/libsass/constants.cpp +144 -0
- data/ext/libsass/constants.hpp +145 -0
- data/ext/libsass/context.cpp +507 -0
- data/ext/libsass/context.hpp +150 -0
- data/ext/libsass/contextualize.cpp +157 -0
- data/ext/libsass/contextualize.hpp +65 -0
- data/ext/libsass/copy_c_str.cpp +13 -0
- data/ext/libsass/copy_c_str.hpp +5 -0
- data/ext/libsass/debug.hpp +39 -0
- data/ext/libsass/environment.hpp +75 -0
- data/ext/libsass/error_handling.cpp +28 -0
- data/ext/libsass/error_handling.hpp +28 -0
- data/ext/libsass/eval.cpp +1149 -0
- data/ext/libsass/eval.hpp +80 -0
- data/ext/libsass/expand.cpp +430 -0
- data/ext/libsass/expand.hpp +77 -0
- data/ext/libsass/extconf.rb +6 -0
- data/ext/libsass/extend.cpp +1962 -0
- data/ext/libsass/extend.hpp +50 -0
- data/ext/libsass/file.cpp +291 -0
- data/ext/libsass/file.hpp +18 -0
- data/ext/libsass/functions.cpp +1565 -0
- data/ext/libsass/functions.hpp +187 -0
- data/ext/libsass/inspect.cpp +727 -0
- data/ext/libsass/inspect.hpp +108 -0
- data/ext/libsass/json.cpp +1411 -0
- data/ext/libsass/json.hpp +117 -0
- data/ext/libsass/kwd_arg_macros.hpp +23 -0
- data/ext/libsass/m4/.gitkeep +0 -0
- data/ext/libsass/mapping.hpp +17 -0
- data/ext/libsass/memory_manager.hpp +54 -0
- data/ext/libsass/node.cpp +251 -0
- data/ext/libsass/node.hpp +122 -0
- data/ext/libsass/operation.hpp +153 -0
- data/ext/libsass/output_compressed.cpp +401 -0
- data/ext/libsass/output_compressed.hpp +95 -0
- data/ext/libsass/output_nested.cpp +364 -0
- data/ext/libsass/output_nested.hpp +108 -0
- data/ext/libsass/parser.cpp +2016 -0
- data/ext/libsass/parser.hpp +264 -0
- data/ext/libsass/paths.hpp +69 -0
- data/ext/libsass/position.hpp +22 -0
- data/ext/libsass/posix/getopt.c +562 -0
- data/ext/libsass/posix/getopt.h +95 -0
- data/ext/libsass/prelexer.cpp +688 -0
- data/ext/libsass/prelexer.hpp +513 -0
- data/ext/libsass/remove_placeholders.cpp +59 -0
- data/ext/libsass/remove_placeholders.hpp +43 -0
- data/ext/libsass/res/resource.rc +35 -0
- data/ext/libsass/sass.cpp +33 -0
- data/ext/libsass/sass.h +60 -0
- data/ext/libsass/sass2scss.cpp +834 -0
- data/ext/libsass/sass2scss.h +110 -0
- data/ext/libsass/sass_context.cpp +709 -0
- data/ext/libsass/sass_context.h +120 -0
- data/ext/libsass/sass_functions.cpp +137 -0
- data/ext/libsass/sass_functions.h +90 -0
- data/ext/libsass/sass_interface.cpp +277 -0
- data/ext/libsass/sass_interface.h +97 -0
- data/ext/libsass/sass_util.cpp +136 -0
- data/ext/libsass/sass_util.hpp +259 -0
- data/ext/libsass/sass_values.cpp +337 -0
- data/ext/libsass/sass_values.h +124 -0
- data/ext/libsass/script/bootstrap +10 -0
- data/ext/libsass/script/branding +10 -0
- data/ext/libsass/script/ci-build-libsass +72 -0
- data/ext/libsass/script/ci-install-compiler +4 -0
- data/ext/libsass/script/ci-install-deps +19 -0
- data/ext/libsass/script/ci-report-coverage +25 -0
- data/ext/libsass/script/coveralls-debug +32 -0
- data/ext/libsass/script/spec +5 -0
- data/ext/libsass/script/tap-driver +652 -0
- data/ext/libsass/script/tap-runner +1 -0
- data/ext/libsass/source_map.cpp +133 -0
- data/ext/libsass/source_map.hpp +46 -0
- data/ext/libsass/subset_map.hpp +145 -0
- data/ext/libsass/support/libsass.pc.in +11 -0
- data/ext/libsass/test-driver +127 -0
- data/ext/libsass/test/test_node.cpp +98 -0
- data/ext/libsass/test/test_paths.cpp +29 -0
- data/ext/libsass/test/test_selector_difference.cpp +28 -0
- data/ext/libsass/test/test_specificity.cpp +28 -0
- data/ext/libsass/test/test_subset_map.cpp +472 -0
- data/ext/libsass/test/test_superselector.cpp +71 -0
- data/ext/libsass/test/test_unification.cpp +33 -0
- data/ext/libsass/to_c.cpp +61 -0
- data/ext/libsass/to_c.hpp +44 -0
- data/ext/libsass/to_string.cpp +29 -0
- data/ext/libsass/to_string.hpp +32 -0
- data/ext/libsass/token.hpp +32 -0
- data/ext/libsass/units.cpp +54 -0
- data/ext/libsass/units.hpp +10 -0
- data/ext/libsass/utf8.h +34 -0
- data/ext/libsass/utf8/checked.h +327 -0
- data/ext/libsass/utf8/core.h +329 -0
- data/ext/libsass/utf8/unchecked.h +228 -0
- data/ext/libsass/utf8_string.cpp +102 -0
- data/ext/libsass/utf8_string.hpp +36 -0
- data/ext/libsass/util.cpp +189 -0
- data/ext/libsass/util.hpp +26 -0
- data/ext/libsass/win/libsass.filters +291 -0
- data/ext/libsass/win/libsass.sln +28 -0
- data/ext/libsass/win/libsass.vcxproj +255 -0
- data/lib/sassc.rb +6 -0
- data/lib/sassc/engine.rb +13 -0
- data/lib/sassc/native.rb +44 -0
- data/lib/sassc/native/native_context_api.rb +140 -0
- data/lib/sassc/native/native_functions_api.rb +41 -0
- data/lib/sassc/native/sass_input_style.rb +11 -0
- data/lib/sassc/native/sass_output_style.rb +10 -0
- data/lib/sassc/native/sass_value.rb +95 -0
- data/lib/sassc/native/string_list.rb +8 -0
- data/lib/sassc/version.rb +3 -0
- data/sassc.gemspec +43 -0
- data/test/smoke_test.rb +171 -0
- data/test/test_helper.rb +4 -0
- metadata +281 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
|
3
|
+
All rights reserved.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
*/
|
23
|
+
|
24
|
+
#ifndef CCAN_JSON_H
|
25
|
+
#define CCAN_JSON_H
|
26
|
+
|
27
|
+
#include <stdbool.h>
|
28
|
+
#include <stddef.h>
|
29
|
+
|
30
|
+
typedef enum {
|
31
|
+
JSON_NULL,
|
32
|
+
JSON_BOOL,
|
33
|
+
JSON_STRING,
|
34
|
+
JSON_NUMBER,
|
35
|
+
JSON_ARRAY,
|
36
|
+
JSON_OBJECT,
|
37
|
+
} JsonTag;
|
38
|
+
|
39
|
+
typedef struct JsonNode JsonNode;
|
40
|
+
|
41
|
+
struct JsonNode
|
42
|
+
{
|
43
|
+
/* only if parent is an object or array (NULL otherwise) */
|
44
|
+
JsonNode *parent;
|
45
|
+
JsonNode *prev, *next;
|
46
|
+
|
47
|
+
/* only if parent is an object (NULL otherwise) */
|
48
|
+
char *key; /* Must be valid UTF-8. */
|
49
|
+
|
50
|
+
JsonTag tag;
|
51
|
+
union {
|
52
|
+
/* JSON_BOOL */
|
53
|
+
bool bool_;
|
54
|
+
|
55
|
+
/* JSON_STRING */
|
56
|
+
char *string_; /* Must be valid UTF-8. */
|
57
|
+
|
58
|
+
/* JSON_NUMBER */
|
59
|
+
double number_;
|
60
|
+
|
61
|
+
/* JSON_ARRAY */
|
62
|
+
/* JSON_OBJECT */
|
63
|
+
struct {
|
64
|
+
JsonNode *head, *tail;
|
65
|
+
} children;
|
66
|
+
};
|
67
|
+
};
|
68
|
+
|
69
|
+
/*** Encoding, decoding, and validation ***/
|
70
|
+
|
71
|
+
JsonNode *json_decode (const char *json);
|
72
|
+
char *json_encode (const JsonNode *node);
|
73
|
+
char *json_encode_string (const char *str);
|
74
|
+
char *json_stringify (const JsonNode *node, const char *space);
|
75
|
+
void json_delete (JsonNode *node);
|
76
|
+
|
77
|
+
bool json_validate (const char *json);
|
78
|
+
|
79
|
+
/*** Lookup and traversal ***/
|
80
|
+
|
81
|
+
JsonNode *json_find_element (JsonNode *array, int index);
|
82
|
+
JsonNode *json_find_member (JsonNode *object, const char *key);
|
83
|
+
|
84
|
+
JsonNode *json_first_child (const JsonNode *node);
|
85
|
+
|
86
|
+
#define json_foreach(i, object_or_array) \
|
87
|
+
for ((i) = json_first_child(object_or_array); \
|
88
|
+
(i) != NULL; \
|
89
|
+
(i) = (i)->next)
|
90
|
+
|
91
|
+
/*** Construction and manipulation ***/
|
92
|
+
|
93
|
+
JsonNode *json_mknull(void);
|
94
|
+
JsonNode *json_mkbool(bool b);
|
95
|
+
JsonNode *json_mkstring(const char *s);
|
96
|
+
JsonNode *json_mknumber(double n);
|
97
|
+
JsonNode *json_mkarray(void);
|
98
|
+
JsonNode *json_mkobject(void);
|
99
|
+
|
100
|
+
void json_append_element(JsonNode *array, JsonNode *element);
|
101
|
+
void json_prepend_element(JsonNode *array, JsonNode *element);
|
102
|
+
void json_append_member(JsonNode *object, const char *key, JsonNode *value);
|
103
|
+
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
|
104
|
+
|
105
|
+
void json_remove_from_parent(JsonNode *node);
|
106
|
+
|
107
|
+
/*** Debugging ***/
|
108
|
+
|
109
|
+
/*
|
110
|
+
* Look for structure and encoding problems in a JsonNode or its descendents.
|
111
|
+
*
|
112
|
+
* If a problem is detected, return false, writing a description of the problem
|
113
|
+
* to errmsg (unless errmsg is NULL).
|
114
|
+
*/
|
115
|
+
bool json_check(const JsonNode *node, char errmsg[256]);
|
116
|
+
|
117
|
+
#endif
|
@@ -0,0 +1,23 @@
|
|
1
|
+
// Example usage:
|
2
|
+
// KWD_ARG_SET(Args) {
|
3
|
+
// KWD_ARG(Args, string, foo);
|
4
|
+
// KWD_ARG(Args, int, bar);
|
5
|
+
// ...
|
6
|
+
// };
|
7
|
+
//
|
8
|
+
// ... and later ...
|
9
|
+
//
|
10
|
+
// something(Args().foo("hey").bar(3));
|
11
|
+
|
12
|
+
#define KWD_ARG_SET(set_name) class set_name
|
13
|
+
|
14
|
+
#define KWD_ARG(set_name, type, name) \
|
15
|
+
private: \
|
16
|
+
type name##_; \
|
17
|
+
public: \
|
18
|
+
set_name& name(type name##__) { \
|
19
|
+
name##_ = name##__; \
|
20
|
+
return *this; \
|
21
|
+
} \
|
22
|
+
type name() { return name##_; } \
|
23
|
+
private:
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#define SASS_MAPPING
|
2
|
+
|
3
|
+
#ifndef SASS_POSITION
|
4
|
+
#include "position.hpp"
|
5
|
+
#endif
|
6
|
+
|
7
|
+
namespace Sass {
|
8
|
+
|
9
|
+
struct Mapping {
|
10
|
+
Position original_position;
|
11
|
+
Position generated_position;
|
12
|
+
|
13
|
+
Mapping(const Position& original_position, const Position& generated_position)
|
14
|
+
: original_position(original_position), generated_position(generated_position) { }
|
15
|
+
};
|
16
|
+
|
17
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#define SASS_MEMORY_MANAGER
|
2
|
+
|
3
|
+
#include <vector>
|
4
|
+
#include <iostream>
|
5
|
+
using namespace std;
|
6
|
+
|
7
|
+
namespace Sass {
|
8
|
+
/////////////////////////////////////////////////////////////////////////////
|
9
|
+
// A class for tracking allocations of AST_Node objects. The intended usage
|
10
|
+
// is something like: Some_Node* n = new (mem_mgr) Some_Node(...);
|
11
|
+
// Then, at the end of the program, the memory manager will delete all of the
|
12
|
+
// allocated nodes that have been passed to it.
|
13
|
+
// In the future, this class may implement a custom allocator.
|
14
|
+
/////////////////////////////////////////////////////////////////////////////
|
15
|
+
template <typename T>
|
16
|
+
class Memory_Manager {
|
17
|
+
vector<T*> nodes;
|
18
|
+
|
19
|
+
public:
|
20
|
+
Memory_Manager(size_t size = 0) : nodes(vector<T*>())
|
21
|
+
{ nodes.reserve(size); }
|
22
|
+
|
23
|
+
~Memory_Manager()
|
24
|
+
{
|
25
|
+
for (size_t i = 0, S = nodes.size(); i < S; ++i) {
|
26
|
+
// cout << "deleting " << typeid(*nodes[i]).name() << endl;
|
27
|
+
delete nodes[i];
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
T* operator()(T* np)
|
32
|
+
{
|
33
|
+
nodes.push_back(np);
|
34
|
+
// cout << "registering " << typeid(*np).name() << endl;
|
35
|
+
return np;
|
36
|
+
}
|
37
|
+
|
38
|
+
void remove(T* np)
|
39
|
+
{
|
40
|
+
nodes.erase(find(nodes.begin(), nodes.end(), np));
|
41
|
+
}
|
42
|
+
};
|
43
|
+
}
|
44
|
+
|
45
|
+
template <typename T>
|
46
|
+
inline void* operator new(size_t size, Sass::Memory_Manager<T>& mem_mgr)
|
47
|
+
{ return mem_mgr(static_cast<T*>(operator new(size))); }
|
48
|
+
|
49
|
+
template <typename T>
|
50
|
+
inline void operator delete(void *np, Sass::Memory_Manager<T>& mem_mgr)
|
51
|
+
{
|
52
|
+
mem_mgr.remove(reinterpret_cast<T*>(np));
|
53
|
+
operator delete(np);
|
54
|
+
}
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#include "node.hpp"
|
2
|
+
#include "to_string.hpp"
|
3
|
+
#include "context.hpp"
|
4
|
+
#include "parser.hpp"
|
5
|
+
|
6
|
+
namespace Sass {
|
7
|
+
|
8
|
+
|
9
|
+
Node Node::createCombinator(const Complex_Selector::Combinator& combinator) {
|
10
|
+
NodeDequePtr null;
|
11
|
+
return Node(COMBINATOR, combinator, NULL /*pSelector*/, null /*pCollection*/);
|
12
|
+
}
|
13
|
+
|
14
|
+
|
15
|
+
Node Node::createSelector(Complex_Selector* pSelector, Context& ctx) {
|
16
|
+
NodeDequePtr null;
|
17
|
+
|
18
|
+
Complex_Selector* pStripped = pSelector->clone(ctx);
|
19
|
+
pStripped->tail(NULL);
|
20
|
+
pStripped->combinator(Complex_Selector::ANCESTOR_OF);
|
21
|
+
|
22
|
+
return Node(SELECTOR, Complex_Selector::ANCESTOR_OF, pStripped, null /*pCollection*/);
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
Node Node::createCollection() {
|
27
|
+
NodeDequePtr pEmptyCollection = make_shared<NodeDeque>();
|
28
|
+
return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pEmptyCollection);
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
Node Node::createCollection(const NodeDeque& values) {
|
33
|
+
NodeDequePtr pShallowCopiedCollection = make_shared<NodeDeque>(values);
|
34
|
+
return Node(COLLECTION, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, pShallowCopiedCollection);
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
Node Node::createNil() {
|
39
|
+
NodeDequePtr null;
|
40
|
+
return Node(NIL, Complex_Selector::ANCESTOR_OF, NULL /*pSelector*/, null /*pCollection*/);
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
Node::Node(const TYPE& type, Complex_Selector::Combinator combinator, Complex_Selector* pSelector, NodeDequePtr& pCollection) :
|
45
|
+
mType(type),
|
46
|
+
mCombinator(combinator),
|
47
|
+
mpSelector(pSelector),
|
48
|
+
mpCollection(pCollection) {}
|
49
|
+
|
50
|
+
|
51
|
+
Node Node::clone(Context& ctx) const {
|
52
|
+
NodeDequePtr pNewCollection = make_shared<NodeDeque>();
|
53
|
+
if (mpCollection) {
|
54
|
+
for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
|
55
|
+
Node& toClone = *iter;
|
56
|
+
pNewCollection->push_back(toClone.clone(ctx));
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
return Node(mType, mCombinator, mpSelector ? mpSelector->clone(ctx) : NULL, pNewCollection);
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
bool Node::contains(const Node& potentialChild, bool simpleSelectorOrderDependent) const {
|
65
|
+
bool found = false;
|
66
|
+
|
67
|
+
for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
|
68
|
+
Node& toTest = *iter;
|
69
|
+
|
70
|
+
if (nodesEqual(toTest, potentialChild, simpleSelectorOrderDependent)) {
|
71
|
+
found = true;
|
72
|
+
break;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
return found;
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
bool Node::operator==(const Node& rhs) const {
|
81
|
+
return nodesEqual(*this, rhs, true /*simpleSelectorOrderDependent*/);
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
bool nodesEqual(const Node& lhs, const Node& rhs, bool simpleSelectorOrderDependent) {
|
86
|
+
if (lhs.type() != rhs.type()) {
|
87
|
+
return false;
|
88
|
+
}
|
89
|
+
|
90
|
+
if (lhs.isCombinator()) {
|
91
|
+
|
92
|
+
return lhs.combinator() == rhs.combinator();
|
93
|
+
|
94
|
+
} else if (lhs.isNil()) {
|
95
|
+
|
96
|
+
return true; // no state to check
|
97
|
+
|
98
|
+
} else if (lhs.isSelector()){
|
99
|
+
|
100
|
+
return selectors_equal(*lhs.selector(), *rhs.selector(), simpleSelectorOrderDependent);
|
101
|
+
|
102
|
+
} else if (lhs.isCollection()) {
|
103
|
+
|
104
|
+
if (lhs.collection()->size() != rhs.collection()->size()) {
|
105
|
+
return false;
|
106
|
+
}
|
107
|
+
|
108
|
+
for (NodeDeque::iterator lhsIter = lhs.collection()->begin(), lhsIterEnd = lhs.collection()->end(),
|
109
|
+
rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) {
|
110
|
+
|
111
|
+
if (!nodesEqual(*lhsIter, *rhsIter, simpleSelectorOrderDependent)) {
|
112
|
+
return false;
|
113
|
+
}
|
114
|
+
|
115
|
+
}
|
116
|
+
|
117
|
+
return true;
|
118
|
+
|
119
|
+
}
|
120
|
+
|
121
|
+
// We shouldn't get here.
|
122
|
+
throw "Comparing unknown node types. A new type was probably added and this method wasn't implemented for it.";
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
void Node::plus(Node& rhs) {
|
127
|
+
if (!this->isCollection() || !rhs.isCollection()) {
|
128
|
+
throw "Both the current node and rhs must be collections.";
|
129
|
+
}
|
130
|
+
this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end());
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
ostream& operator<<(ostream& os, const Node& node) {
|
135
|
+
|
136
|
+
if (node.isCombinator()) {
|
137
|
+
|
138
|
+
switch (node.combinator()) {
|
139
|
+
case Complex_Selector::ANCESTOR_OF: os << "\" \""; break;
|
140
|
+
case Complex_Selector::PARENT_OF: os << "\">\""; break;
|
141
|
+
case Complex_Selector::PRECEDES: os << "\"~\""; break;
|
142
|
+
case Complex_Selector::ADJACENT_TO: os << "\"+\""; break;
|
143
|
+
}
|
144
|
+
|
145
|
+
} else if (node.isNil()) {
|
146
|
+
|
147
|
+
os << "nil";
|
148
|
+
|
149
|
+
} else if (node.isSelector()){
|
150
|
+
|
151
|
+
To_String to_string;
|
152
|
+
os << node.selector()->head()->perform(&to_string);
|
153
|
+
|
154
|
+
} else if (node.isCollection()) {
|
155
|
+
|
156
|
+
os << "[";
|
157
|
+
|
158
|
+
for (NodeDeque::iterator iter = node.collection()->begin(), iterBegin = node.collection()->begin(), iterEnd = node.collection()->end(); iter != iterEnd; iter++) {
|
159
|
+
if (iter != iterBegin) {
|
160
|
+
os << ", ";
|
161
|
+
}
|
162
|
+
|
163
|
+
os << (*iter);
|
164
|
+
}
|
165
|
+
|
166
|
+
os << "]";
|
167
|
+
|
168
|
+
}
|
169
|
+
|
170
|
+
return os;
|
171
|
+
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
Node complexSelectorToNode(Complex_Selector* pToConvert, Context& ctx) {
|
176
|
+
if (pToConvert == NULL) {
|
177
|
+
return Node::createNil();
|
178
|
+
}
|
179
|
+
|
180
|
+
Node node = Node::createCollection();
|
181
|
+
|
182
|
+
while (pToConvert) {
|
183
|
+
|
184
|
+
// the first Complex_Selector may contain a dummy head pointer, skip it.
|
185
|
+
if (pToConvert->head() != NULL && !pToConvert->head()->is_empty_reference()) {
|
186
|
+
node.collection()->push_back(Node::createSelector(pToConvert, ctx));
|
187
|
+
}
|
188
|
+
|
189
|
+
if (pToConvert->combinator() != Complex_Selector::ANCESTOR_OF) {
|
190
|
+
node.collection()->push_back(Node::createCombinator(pToConvert->combinator()));
|
191
|
+
}
|
192
|
+
|
193
|
+
pToConvert = pToConvert->tail();
|
194
|
+
}
|
195
|
+
|
196
|
+
return node;
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
Complex_Selector* nodeToComplexSelector(const Node& toConvert, Context& ctx) {
|
201
|
+
if (toConvert.isNil()) {
|
202
|
+
return NULL;
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
if (!toConvert.isCollection()) {
|
207
|
+
throw "The node to convert to a Complex_Selector* must be a collection type or nil.";
|
208
|
+
}
|
209
|
+
|
210
|
+
|
211
|
+
NodeDeque& childNodes = *toConvert.collection();
|
212
|
+
|
213
|
+
string noPath("");
|
214
|
+
Position noPosition;
|
215
|
+
Complex_Selector* pFirst = new (ctx.mem) Complex_Selector(noPath, noPosition, Complex_Selector::ANCESTOR_OF, NULL, NULL);
|
216
|
+
Complex_Selector* pCurrent = pFirst;
|
217
|
+
|
218
|
+
for (NodeDeque::iterator childIter = childNodes.begin(), childIterEnd = childNodes.end(); childIter != childIterEnd; childIter++) {
|
219
|
+
|
220
|
+
Node& child = *childIter;
|
221
|
+
|
222
|
+
if (child.isSelector()) {
|
223
|
+
pCurrent->tail(child.selector()->clone(ctx)); // JMA - need to clone the selector, because they can end up getting shared across Node collections, and can result in an infinite loop during the call to parentSuperselector()
|
224
|
+
pCurrent = pCurrent->tail();
|
225
|
+
} else if (child.isCombinator()) {
|
226
|
+
pCurrent->combinator(child.combinator());
|
227
|
+
|
228
|
+
// if the next node is also a combinator, create another Complex_Selector to hold it so it doesn't replace the current combinator
|
229
|
+
if (childIter+1 != childIterEnd) {
|
230
|
+
Node& nextNode = *(childIter+1);
|
231
|
+
if (nextNode.isCombinator()) {
|
232
|
+
pCurrent->tail(new (ctx.mem) Complex_Selector(noPath, noPosition, Complex_Selector::ANCESTOR_OF, NULL, NULL));
|
233
|
+
pCurrent = pCurrent->tail();
|
234
|
+
}
|
235
|
+
}
|
236
|
+
} else {
|
237
|
+
throw "The node to convert's children must be only combinators or selectors.";
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
// Put the dummy Compound_Selector in the first position, for consistency with the rest of libsass
|
242
|
+
Compound_Selector* fakeHead = new (ctx.mem) Compound_Selector(noPath, noPosition, 1);
|
243
|
+
Selector_Reference* selectorRef = new (ctx.mem) Selector_Reference(noPath, noPosition, NULL);
|
244
|
+
fakeHead->elements().push_back(selectorRef);
|
245
|
+
pFirst->head(fakeHead);
|
246
|
+
|
247
|
+
return pFirst;
|
248
|
+
}
|
249
|
+
|
250
|
+
|
251
|
+
}
|