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