sassc 1.11.4 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +4 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.github/CONTRIBUTING.md +7 -7
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +37 -18
- data/ext/libsass/GNUmakefile.am +23 -37
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Makefile.conf +3 -0
- data/ext/libsass/Readme.md +68 -63
- data/ext/libsass/appveyor.yml +7 -3
- data/ext/libsass/configure.ac +10 -14
- data/ext/libsass/docs/api-context-internal.md +29 -21
- data/ext/libsass/docs/api-context.md +26 -6
- data/ext/libsass/docs/api-doc.md +49 -16
- data/ext/libsass/docs/api-function-example.md +1 -1
- data/ext/libsass/docs/api-function.md +31 -7
- data/ext/libsass/docs/api-importer.md +19 -19
- data/ext/libsass/docs/api-value.md +4 -2
- data/ext/libsass/docs/build-on-windows.md +4 -4
- data/ext/libsass/docs/build-with-mingw.md +3 -3
- data/ext/libsass/docs/build.md +9 -9
- data/ext/libsass/docs/custom-functions-internal.md +10 -8
- data/ext/libsass/docs/implementations.md +20 -8
- data/ext/libsass/docs/unicode.md +16 -10
- data/ext/libsass/include/sass/base.h +0 -3
- data/ext/libsass/include/sass/context.h +20 -2
- data/ext/libsass/include/sass/functions.h +31 -0
- data/ext/libsass/include/sass/values.h +3 -1
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass/version.h.in +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/res/resource.rc +6 -6
- data/ext/libsass/script/ci-build-libsass +10 -5
- data/ext/libsass/script/ci-build-plugin +62 -0
- data/ext/libsass/script/ci-install-compiler +1 -1
- data/ext/libsass/script/ci-install-deps +4 -7
- data/ext/libsass/script/ci-report-coverage +13 -3
- data/ext/libsass/script/tap-driver +1 -1
- data/ext/libsass/script/tap-runner +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -1
- data/ext/libsass/src/ast.cpp +537 -762
- data/ext/libsass/src/ast.hpp +377 -419
- data/ext/libsass/src/ast_def_macros.hpp +26 -1
- data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
- data/ext/libsass/src/b64/encode.h +3 -1
- data/ext/libsass/src/backtrace.cpp +46 -0
- data/ext/libsass/src/backtrace.hpp +7 -54
- data/ext/libsass/src/bind.cpp +72 -50
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/cencode.c +6 -0
- data/ext/libsass/src/check_nesting.cpp +157 -135
- data/ext/libsass/src/check_nesting.hpp +11 -10
- data/ext/libsass/src/color_maps.cpp +10 -6
- data/ext/libsass/src/color_maps.hpp +6 -8
- data/ext/libsass/src/constants.cpp +4 -3
- data/ext/libsass/src/constants.hpp +4 -3
- data/ext/libsass/src/context.cpp +110 -47
- data/ext/libsass/src/context.hpp +11 -1
- data/ext/libsass/src/cssize.cpp +105 -94
- data/ext/libsass/src/cssize.hpp +4 -5
- data/ext/libsass/src/debugger.hpp +247 -244
- data/ext/libsass/src/emitter.cpp +30 -6
- data/ext/libsass/src/emitter.hpp +7 -0
- data/ext/libsass/src/environment.cpp +67 -16
- data/ext/libsass/src/environment.hpp +28 -7
- data/ext/libsass/src/error_handling.cpp +92 -64
- data/ext/libsass/src/error_handling.hpp +64 -43
- data/ext/libsass/src/eval.cpp +494 -544
- data/ext/libsass/src/eval.hpp +17 -23
- data/ext/libsass/src/expand.cpp +182 -154
- data/ext/libsass/src/expand.hpp +4 -5
- data/ext/libsass/src/extend.cpp +299 -291
- data/ext/libsass/src/extend.hpp +46 -11
- data/ext/libsass/src/file.cpp +103 -36
- data/ext/libsass/src/file.hpp +21 -4
- data/ext/libsass/src/functions.cpp +561 -312
- data/ext/libsass/src/functions.hpp +8 -5
- data/ext/libsass/src/inspect.cpp +108 -53
- data/ext/libsass/src/inspect.hpp +5 -2
- data/ext/libsass/src/lexer.cpp +15 -7
- data/ext/libsass/src/lexer.hpp +13 -4
- data/ext/libsass/src/listize.cpp +3 -2
- data/ext/libsass/src/listize.hpp +0 -1
- data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
- data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
- data/ext/libsass/src/node.cpp +34 -38
- data/ext/libsass/src/node.hpp +6 -8
- data/ext/libsass/src/operation.hpp +2 -2
- data/ext/libsass/src/operators.cpp +240 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/output.cpp +22 -20
- data/ext/libsass/src/parser.cpp +719 -358
- data/ext/libsass/src/parser.hpp +57 -22
- data/ext/libsass/src/plugins.cpp +28 -10
- data/ext/libsass/src/position.cpp +21 -3
- data/ext/libsass/src/position.hpp +2 -1
- data/ext/libsass/src/prelexer.cpp +104 -19
- data/ext/libsass/src/prelexer.hpp +10 -3
- data/ext/libsass/src/remove_placeholders.cpp +9 -10
- data/ext/libsass/src/remove_placeholders.hpp +1 -5
- data/ext/libsass/src/sass.cpp +62 -4
- data/ext/libsass/src/sass.hpp +5 -2
- data/ext/libsass/src/sass_context.cpp +96 -58
- data/ext/libsass/src/sass_context.hpp +7 -5
- data/ext/libsass/src/sass_functions.cpp +63 -1
- data/ext/libsass/src/sass_functions.hpp +19 -1
- data/ext/libsass/src/sass_util.cpp +3 -3
- data/ext/libsass/src/sass_util.hpp +4 -4
- data/ext/libsass/src/sass_values.cpp +42 -39
- data/ext/libsass/src/sass_values.hpp +2 -1
- data/ext/libsass/src/source_map.cpp +16 -18
- data/ext/libsass/src/subset_map.cpp +6 -8
- data/ext/libsass/src/subset_map.hpp +6 -6
- data/ext/libsass/src/to_c.cpp +2 -2
- data/ext/libsass/src/to_value.cpp +8 -3
- data/ext/libsass/src/to_value.hpp +1 -0
- data/ext/libsass/src/units.cpp +349 -45
- data/ext/libsass/src/units.hpp +39 -22
- data/ext/libsass/src/utf8/checked.h +7 -0
- data/ext/libsass/src/utf8/unchecked.h +7 -0
- data/ext/libsass/src/utf8_string.cpp +1 -1
- data/ext/libsass/src/util.cpp +139 -45
- data/ext/libsass/src/util.hpp +4 -7
- data/ext/libsass/src/values.cpp +15 -23
- data/ext/libsass/win/libsass.sln +13 -2
- data/ext/libsass/win/libsass.sln.DotSettings +9 -0
- data/ext/libsass/win/libsass.targets +3 -0
- data/ext/libsass/win/libsass.vcxproj.filters +9 -0
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -1
- data/test/native_test.rb +1 -1
- metadata +11 -4
@@ -18,9 +18,14 @@ if [ "x$TRAVIS_OS_NAME" == "x" ]; then export TRAVIS_OS_NAME=`uname -s | perl -n
|
|
18
18
|
|
19
19
|
if [ "x$COVERAGE" == "xyes" ]; then
|
20
20
|
COVERAGE_OPT="--enable-coverage"
|
21
|
-
export EXTRA_CFLAGS="
|
22
|
-
export EXTRA_CXXFLAGS="
|
23
|
-
|
21
|
+
export EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage"
|
22
|
+
export EXTRA_CXXFLAGS="-fprofile-arcs -ftest-coverage"
|
23
|
+
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
24
|
+
# osx doesn't seem to know gcov lib?
|
25
|
+
export EXTRA_LDFLAGS="--coverage"
|
26
|
+
else
|
27
|
+
export EXTRA_LDFLAGS="-lgcov --coverage"
|
28
|
+
fi
|
24
29
|
else
|
25
30
|
COVERAGE_OPT="--disable-coverage"
|
26
31
|
fi
|
@@ -37,7 +42,7 @@ fi
|
|
37
42
|
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
|
38
43
|
MAKE_OPTS="$MAKE_OPTS -j1 V=1"
|
39
44
|
else
|
40
|
-
MAKE_OPTS="$MAKE_OPTS -
|
45
|
+
MAKE_OPTS="$MAKE_OPTS -j5 V=1"
|
41
46
|
fi
|
42
47
|
|
43
48
|
if [ "x$PREFIX" == "x" ]; then
|
@@ -109,7 +114,7 @@ then
|
|
109
114
|
then
|
110
115
|
echo "Travis rate limit on github exceeded"
|
111
116
|
echo "Retrying via 'special purpose proxy'"
|
112
|
-
JSON=$(curl -L -sS
|
117
|
+
JSON=$(curl -L -sS https://github-api-reverse-proxy.herokuapp.com/repos/sass/libsass/pulls/$TRAVIS_PULL_REQUEST)
|
113
118
|
fi
|
114
119
|
|
115
120
|
RE_SPEC_PR="sass\/sass-spec(#|\/pull\/)([0-9]+)"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
PLUGIN=$1
|
4
|
+
RUBY_BIN=ruby
|
5
|
+
SASS_SPEC_PATH=sass-spec
|
6
|
+
SASSC_BIN=sassc/bin/sassc
|
7
|
+
SASS_SPEC_SPEC_DIR=plugins/libsass-${PLUGIN}/test
|
8
|
+
|
9
|
+
if [ -e ./tester ] ; then
|
10
|
+
SASSC_BIN=./tester
|
11
|
+
fi
|
12
|
+
|
13
|
+
if [ -d ./build/lib ] ; then
|
14
|
+
cp -a build/lib lib
|
15
|
+
fi
|
16
|
+
|
17
|
+
if [ "x$1" == "x" ] ; then
|
18
|
+
echo "No plugin name given"
|
19
|
+
exit 1
|
20
|
+
fi
|
21
|
+
|
22
|
+
if [ "x$COVERAGE" == "0" ] ; then
|
23
|
+
unset COVERAGE
|
24
|
+
fi
|
25
|
+
|
26
|
+
export EXTRA_CFLAGS=""
|
27
|
+
export EXTRA_CXXFLAGS=""
|
28
|
+
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
29
|
+
# osx doesn't seem to know gcov lib?
|
30
|
+
export EXTRA_LDFLAGS="--coverage"
|
31
|
+
else
|
32
|
+
export EXTRA_LDFLAGS="-lgcov --coverage"
|
33
|
+
fi
|
34
|
+
|
35
|
+
mkdir -p plugins
|
36
|
+
if [ ! -d plugins/libsass-${PLUGIN} ] ; then
|
37
|
+
git clone https://github.com/mgreter/libsass-${PLUGIN} plugins/libsass-${PLUGIN}
|
38
|
+
fi
|
39
|
+
if [ ! -d plugins/libsass-${PLUGIN}/build ] ; then
|
40
|
+
mkdir plugins/libsass-${PLUGIN}/build
|
41
|
+
fi
|
42
|
+
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
|
43
|
+
|
44
|
+
cd plugins/libsass-${PLUGIN}/build
|
45
|
+
cmake -G "Unix Makefiles" -D LIBSASS_DIR="../../.." ..
|
46
|
+
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
|
47
|
+
make VERBOSE=1 -j2
|
48
|
+
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
|
49
|
+
cd ../../..
|
50
|
+
|
51
|
+
# glob only works on paths relative to imports
|
52
|
+
if [ "x$PLUGIN" == "xglob" ]; then
|
53
|
+
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss > ${SASS_SPEC_SPEC_DIR}/basic/result.css
|
54
|
+
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss --sourcemap > /dev/null
|
55
|
+
else
|
56
|
+
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic > ${SASS_SPEC_SPEC_DIR}/basic/result.css
|
57
|
+
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic --sourcemap > /dev/null
|
58
|
+
fi
|
59
|
+
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
|
60
|
+
|
61
|
+
diff ${SASS_SPEC_SPEC_DIR}/basic/expected_output.css ${SASS_SPEC_SPEC_DIR}/basic/result.css
|
62
|
+
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
if [ "x$COVERAGE" == "xyes" ]; then
|
3
|
-
|
4
|
-
|
3
|
+
pip2 install --user gcovr
|
4
|
+
pip2 install --user cpp-coveralls
|
5
5
|
else
|
6
6
|
echo "no dependencies to install"
|
7
7
|
fi
|
@@ -15,9 +15,6 @@ if [ "x$AUTOTOOLS" == "xyes" ]; then
|
|
15
15
|
sudo apt-get -qq install automake
|
16
16
|
fi
|
17
17
|
|
18
|
-
# https://github.com/sass/libsass/pull/2183
|
19
|
-
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
20
|
-
brew uninstall libtool
|
21
|
-
brew install libtool
|
22
|
-
fi
|
23
18
|
fi
|
19
|
+
|
20
|
+
exit 0
|
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
if [ "x$COVERAGE" = "xyes" ]; then
|
4
4
|
|
5
|
+
# find / -name "gcovr"
|
6
|
+
# find / -name "coveralls"
|
7
|
+
# this is only needed for mac os x builds!
|
8
|
+
PATH=$PATH:/Users/travis/Library/Python/2.7/bin/
|
9
|
+
|
10
|
+
|
5
11
|
# exclude some directories from profiling (.libs is from autotools)
|
6
12
|
export EXCLUDE_COVERAGE="--exclude plugins
|
7
13
|
--exclude sassc/sassc.c
|
@@ -21,10 +27,14 @@ if [ "x$COVERAGE" = "xyes" ]; then
|
|
21
27
|
--exclude src/test
|
22
28
|
--exclude src/posix
|
23
29
|
--exclude src/debugger.hpp"
|
24
|
-
# debug
|
25
|
-
|
30
|
+
# debug used gcov version
|
31
|
+
# option not available on mac
|
32
|
+
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
|
33
|
+
gcov -v
|
34
|
+
fi
|
35
|
+
# create summarized report
|
26
36
|
gcovr -r .
|
27
|
-
#
|
37
|
+
# submit report to coveralls.io
|
28
38
|
coveralls $EXCLUDE_COVERAGE --gcov-options '\-lp'
|
29
39
|
|
30
40
|
else
|
@@ -1 +1 @@
|
|
1
|
-
$@ | tapout tap
|
1
|
+
$@ $TEST_FLAGS --tap --silent | tapout tap
|
@@ -34,7 +34,7 @@ include $(top_srcdir)/Makefile.conf
|
|
34
34
|
|
35
35
|
libsass_la_SOURCES = ${CSOURCES} ${SOURCES}
|
36
36
|
|
37
|
-
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:
|
37
|
+
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
|
38
38
|
|
39
39
|
if ENABLE_TESTS
|
40
40
|
if ENABLE_COVERAGE
|
data/ext/libsass/src/ast.cpp
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "ast.hpp"
|
3
3
|
#include "context.hpp"
|
4
4
|
#include "node.hpp"
|
5
|
+
#include "eval.hpp"
|
5
6
|
#include "extend.hpp"
|
6
7
|
#include "emitter.hpp"
|
7
8
|
#include "color_maps.hpp"
|
@@ -18,80 +19,73 @@ namespace Sass {
|
|
18
19
|
|
19
20
|
static Null sass_null(ParserState("null"));
|
20
21
|
|
21
|
-
bool
|
22
|
-
|
23
|
-
|
22
|
+
bool Wrapped_Selector::find ( bool (*f)(AST_Node_Obj) )
|
23
|
+
{
|
24
|
+
// check children first
|
25
|
+
if (selector_) {
|
26
|
+
if (selector_->find(f)) return true;
|
24
27
|
}
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const {
|
29
|
-
return SASS_MEMORY_CAST(Supports_Negation, cond) ||
|
30
|
-
SASS_MEMORY_CAST(Supports_Operator, cond);
|
28
|
+
// execute last
|
29
|
+
return f(this);
|
31
30
|
}
|
32
31
|
|
33
|
-
|
34
|
-
|
32
|
+
bool Selector_List::find ( bool (*f)(AST_Node_Obj) )
|
33
|
+
{
|
34
|
+
// check children first
|
35
|
+
for (Complex_Selector_Obj sel : elements()) {
|
36
|
+
if (sel->find(f)) return true;
|
37
|
+
}
|
38
|
+
// execute last
|
39
|
+
return f(this);
|
35
40
|
}
|
36
41
|
|
37
|
-
|
38
|
-
|
42
|
+
bool Compound_Selector::find ( bool (*f)(AST_Node_Obj) )
|
43
|
+
{
|
44
|
+
// check children first
|
45
|
+
for (Simple_Selector_Obj sel : elements()) {
|
46
|
+
if (sel->find(f)) return true;
|
47
|
+
}
|
48
|
+
// execute last
|
49
|
+
return f(this);
|
39
50
|
}
|
40
51
|
|
41
|
-
|
42
|
-
|
43
|
-
|
52
|
+
bool Complex_Selector::find ( bool (*f)(AST_Node_Obj) )
|
53
|
+
{
|
54
|
+
// check children first
|
55
|
+
if (head_ && head_->find(f)) return true;
|
56
|
+
if (tail_ && tail_->find(f)) return true;
|
57
|
+
// execute last
|
58
|
+
return f(this);
|
44
59
|
}
|
45
60
|
|
46
|
-
bool
|
47
|
-
|
61
|
+
bool Supports_Operator::needs_parens(Supports_Condition_Obj cond) const {
|
62
|
+
if (Supports_Operator_Obj op = Cast<Supports_Operator>(cond)) {
|
63
|
+
return op->operand() != operand();
|
64
|
+
}
|
65
|
+
return Cast<Supports_Negation>(cond) != NULL;
|
48
66
|
}
|
49
67
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
str.erase( str.begin() , it2);
|
54
|
-
return str;
|
68
|
+
bool Supports_Negation::needs_parens(Supports_Condition_Obj cond) const {
|
69
|
+
return Cast<Supports_Negation>(cond) ||
|
70
|
+
Cast<Supports_Operator>(cond);
|
55
71
|
}
|
56
72
|
|
57
|
-
std::string
|
73
|
+
void str_rtrim(std::string& str, const std::string& delimiters = " \f\n\r\t\v")
|
58
74
|
{
|
59
|
-
|
60
|
-
str.erase( it1.base() , str.end() );
|
61
|
-
return str;
|
75
|
+
str.erase( str.find_last_not_of( delimiters ) + 1 );
|
62
76
|
}
|
63
77
|
|
64
78
|
void String_Constant::rtrim()
|
65
79
|
{
|
66
|
-
|
67
|
-
}
|
68
|
-
void String_Constant::ltrim()
|
69
|
-
{
|
70
|
-
value_ = str_ltrim(value_);
|
71
|
-
}
|
72
|
-
void String_Constant::trim()
|
73
|
-
{
|
74
|
-
rtrim();
|
75
|
-
ltrim();
|
80
|
+
str_rtrim(value_);
|
76
81
|
}
|
77
82
|
|
78
83
|
void String_Schema::rtrim()
|
79
84
|
{
|
80
85
|
if (!empty()) {
|
81
|
-
if (String_Ptr str =
|
86
|
+
if (String_Ptr str = Cast<String>(last())) str->rtrim();
|
82
87
|
}
|
83
88
|
}
|
84
|
-
void String_Schema::ltrim()
|
85
|
-
{
|
86
|
-
if (!empty()) {
|
87
|
-
if (String_Ptr str = SASS_MEMORY_CAST(String, first())) str->ltrim();
|
88
|
-
}
|
89
|
-
}
|
90
|
-
void String_Schema::trim()
|
91
|
-
{
|
92
|
-
rtrim();
|
93
|
-
ltrim();
|
94
|
-
}
|
95
89
|
|
96
90
|
void Argument::set_delayed(bool delayed)
|
97
91
|
{
|
@@ -111,7 +105,7 @@ namespace Sass {
|
|
111
105
|
bool At_Root_Query::exclude(std::string str)
|
112
106
|
{
|
113
107
|
bool with = feature() && unquote(feature()->to_string()).compare("with") == 0;
|
114
|
-
List_Ptr l = static_cast<List_Ptr>(
|
108
|
+
List_Ptr l = static_cast<List_Ptr>(value().ptr());
|
115
109
|
std::string v;
|
116
110
|
|
117
111
|
if (with)
|
@@ -141,21 +135,20 @@ namespace Sass {
|
|
141
135
|
pstate_.offset += pstate - pstate_ + pstate.offset;
|
142
136
|
}
|
143
137
|
|
144
|
-
|
145
|
-
{
|
146
|
-
pstate_.offset = offset;
|
147
|
-
}
|
148
|
-
|
149
|
-
inline bool is_ns_eq(const std::string& l, const std::string& r)
|
138
|
+
bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
|
150
139
|
{
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
140
|
+
// https://github.com/sass/sass/issues/2229
|
141
|
+
if ((has_ns_ == r.has_ns_) ||
|
142
|
+
(has_ns_ && ns_.empty()) ||
|
143
|
+
(r.has_ns_ && r.ns_.empty())
|
144
|
+
) {
|
145
|
+
if (ns_.empty() && r.ns() == "*") return false;
|
146
|
+
else if (r.ns().empty() && ns() == "*") return false;
|
147
|
+
else return ns() == r.ns();
|
148
|
+
}
|
149
|
+
return false;
|
155
150
|
}
|
156
151
|
|
157
|
-
|
158
|
-
|
159
152
|
bool Compound_Selector::operator< (const Compound_Selector& rhs) const
|
160
153
|
{
|
161
154
|
size_t L = std::min(length(), rhs.length());
|
@@ -173,7 +166,7 @@ namespace Sass {
|
|
173
166
|
return length() < rhs.length();
|
174
167
|
}
|
175
168
|
|
176
|
-
bool Compound_Selector::has_parent_ref()
|
169
|
+
bool Compound_Selector::has_parent_ref() const
|
177
170
|
{
|
178
171
|
for (Simple_Selector_Obj s : *this) {
|
179
172
|
if (s && s->has_parent_ref()) return true;
|
@@ -181,7 +174,7 @@ namespace Sass {
|
|
181
174
|
return false;
|
182
175
|
}
|
183
176
|
|
184
|
-
bool Compound_Selector::has_real_parent_ref()
|
177
|
+
bool Compound_Selector::has_real_parent_ref() const
|
185
178
|
{
|
186
179
|
for (Simple_Selector_Obj s : *this) {
|
187
180
|
if (s && s->has_real_parent_ref()) return true;
|
@@ -189,13 +182,13 @@ namespace Sass {
|
|
189
182
|
return false;
|
190
183
|
}
|
191
184
|
|
192
|
-
bool Complex_Selector::has_parent_ref()
|
185
|
+
bool Complex_Selector::has_parent_ref() const
|
193
186
|
{
|
194
187
|
return (head() && head()->has_parent_ref()) ||
|
195
188
|
(tail() && tail()->has_parent_ref());
|
196
189
|
}
|
197
190
|
|
198
|
-
bool Complex_Selector::has_real_parent_ref()
|
191
|
+
bool Complex_Selector::has_real_parent_ref() const
|
199
192
|
{
|
200
193
|
return (head() && head()->has_real_parent_ref()) ||
|
201
194
|
(tail() && tail()->has_real_parent_ref());
|
@@ -206,25 +199,31 @@ namespace Sass {
|
|
206
199
|
// const iterators for tails
|
207
200
|
Complex_Selector_Ptr_Const l = this;
|
208
201
|
Complex_Selector_Ptr_Const r = &rhs;
|
209
|
-
Compound_Selector_Ptr l_h =
|
210
|
-
Compound_Selector_Ptr r_h =
|
202
|
+
Compound_Selector_Ptr l_h = NULL;
|
203
|
+
Compound_Selector_Ptr r_h = NULL;
|
204
|
+
if (l) l_h = l->head();
|
205
|
+
if (r) r_h = r->head();
|
211
206
|
// process all tails
|
212
207
|
while (true)
|
213
208
|
{
|
209
|
+
#ifdef DEBUG
|
214
210
|
// skip empty ancestor first
|
215
211
|
if (l && l->is_empty_ancestor())
|
216
212
|
{
|
217
|
-
|
218
|
-
|
213
|
+
l_h = NULL;
|
214
|
+
l = l->tail();
|
215
|
+
if(l) l_h = l->head();
|
219
216
|
continue;
|
220
217
|
}
|
221
218
|
// skip empty ancestor first
|
222
219
|
if (r && r->is_empty_ancestor())
|
223
220
|
{
|
224
|
-
|
225
|
-
|
221
|
+
r_h = NULL;
|
222
|
+
r = r->tail();
|
223
|
+
if (r) r_h = r->head();
|
226
224
|
continue;
|
227
225
|
}
|
226
|
+
#endif
|
228
227
|
// check for valid selectors
|
229
228
|
if (!l) return !!r;
|
230
229
|
if (!r) return false;
|
@@ -235,11 +234,12 @@ namespace Sass {
|
|
235
234
|
if (l->combinator() != r->combinator())
|
236
235
|
{ return l->combinator() < r->combinator(); }
|
237
236
|
// advance to next tails
|
238
|
-
l =
|
239
|
-
r =
|
237
|
+
l = l->tail();
|
238
|
+
r = r->tail();
|
240
239
|
// fetch the next headers
|
241
|
-
l_h =
|
242
|
-
|
240
|
+
l_h = NULL; r_h = NULL;
|
241
|
+
if (l) l_h = l->head();
|
242
|
+
if (r) r_h = r->head();
|
243
243
|
}
|
244
244
|
// one side is null
|
245
245
|
else if (!r_h) return true;
|
@@ -251,16 +251,16 @@ namespace Sass {
|
|
251
251
|
if (l->combinator() != r->combinator())
|
252
252
|
{ return l->combinator() < r->combinator(); }
|
253
253
|
// advance to next tails
|
254
|
-
l =
|
255
|
-
r =
|
254
|
+
l = l->tail();
|
255
|
+
r = r->tail();
|
256
256
|
// fetch the next headers
|
257
|
-
l_h =
|
258
|
-
|
257
|
+
l_h = NULL; r_h = NULL;
|
258
|
+
if (l) l_h = l->head();
|
259
|
+
if (r) r_h = r->head();
|
259
260
|
}
|
260
261
|
// heads are not equal
|
261
262
|
else return *l_h < *r_h;
|
262
263
|
}
|
263
|
-
return true;
|
264
264
|
}
|
265
265
|
|
266
266
|
bool Complex_Selector::operator== (const Complex_Selector& rhs) const
|
@@ -268,25 +268,31 @@ namespace Sass {
|
|
268
268
|
// const iterators for tails
|
269
269
|
Complex_Selector_Ptr_Const l = this;
|
270
270
|
Complex_Selector_Ptr_Const r = &rhs;
|
271
|
-
Compound_Selector_Ptr l_h =
|
272
|
-
Compound_Selector_Ptr r_h =
|
271
|
+
Compound_Selector_Ptr l_h = NULL;
|
272
|
+
Compound_Selector_Ptr r_h = NULL;
|
273
|
+
if (l) l_h = l->head();
|
274
|
+
if (r) r_h = r->head();
|
273
275
|
// process all tails
|
274
276
|
while (true)
|
275
277
|
{
|
278
|
+
#ifdef DEBUG
|
276
279
|
// skip empty ancestor first
|
277
280
|
if (l && l->is_empty_ancestor())
|
278
281
|
{
|
279
|
-
|
280
|
-
|
282
|
+
l_h = NULL;
|
283
|
+
l = l->tail();
|
284
|
+
if (l) l_h = l->head();
|
281
285
|
continue;
|
282
286
|
}
|
283
287
|
// skip empty ancestor first
|
284
288
|
if (r && r->is_empty_ancestor())
|
285
289
|
{
|
286
|
-
|
287
|
-
|
290
|
+
r_h = NULL;
|
291
|
+
r = r->tail();
|
292
|
+
if (r) r_h = r->head();
|
288
293
|
continue;
|
289
294
|
}
|
295
|
+
#endif
|
290
296
|
// check the pointers
|
291
297
|
if (!r) return !l;
|
292
298
|
if (!l) return !r;
|
@@ -297,27 +303,29 @@ namespace Sass {
|
|
297
303
|
if (l->combinator() != r->combinator())
|
298
304
|
{ return l->combinator() < r->combinator(); }
|
299
305
|
// advance to next tails
|
300
|
-
l =
|
301
|
-
r =
|
306
|
+
l = l->tail();
|
307
|
+
r = r->tail();
|
302
308
|
// fetch the next heads
|
303
|
-
l_h =
|
304
|
-
|
309
|
+
l_h = NULL; r_h = NULL;
|
310
|
+
if (l) l_h = l->head();
|
311
|
+
if (r) r_h = r->head();
|
305
312
|
}
|
306
313
|
// equals if other head is empty
|
307
314
|
else if ((!l_h && !r_h) ||
|
308
315
|
(!l_h && r_h->empty()) ||
|
309
316
|
(!r_h && l_h->empty()) ||
|
310
|
-
(*l_h == *r_h))
|
317
|
+
(l_h && r_h && *l_h == *r_h))
|
311
318
|
{
|
312
319
|
// check combinator after heads
|
313
320
|
if (l->combinator() != r->combinator())
|
314
321
|
{ return l->combinator() == r->combinator(); }
|
315
322
|
// advance to next tails
|
316
|
-
l =
|
317
|
-
r =
|
323
|
+
l = l->tail();
|
324
|
+
r = r->tail();
|
318
325
|
// fetch the next heads
|
319
|
-
l_h =
|
320
|
-
|
326
|
+
l_h = NULL; r_h = NULL;
|
327
|
+
if (l) l_h = l->head();
|
328
|
+
if (r) r_h = r->head();
|
321
329
|
}
|
322
330
|
// abort
|
323
331
|
else break;
|
@@ -326,78 +334,105 @@ namespace Sass {
|
|
326
334
|
return false;
|
327
335
|
}
|
328
336
|
|
329
|
-
Compound_Selector_Ptr Compound_Selector::unify_with(Compound_Selector_Ptr rhs
|
337
|
+
Compound_Selector_Ptr Compound_Selector::unify_with(Compound_Selector_Ptr rhs)
|
330
338
|
{
|
331
339
|
if (empty()) return rhs;
|
332
340
|
Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
|
333
341
|
for (size_t i = 0, L = length(); i < L; ++i)
|
334
342
|
{
|
335
343
|
if (unified.isNull()) break;
|
336
|
-
unified = at(i)->unify_with(
|
344
|
+
unified = at(i)->unify_with(unified);
|
337
345
|
}
|
338
346
|
return unified.detach();
|
339
347
|
}
|
340
348
|
|
341
|
-
bool
|
349
|
+
bool Complex_Selector::operator== (const Selector& rhs) const
|
342
350
|
{
|
343
|
-
if (
|
344
|
-
if (
|
351
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
|
352
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
|
353
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
|
354
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
|
345
355
|
throw std::runtime_error("invalid selector base classes to compare");
|
346
|
-
return false;
|
347
356
|
}
|
348
357
|
|
349
|
-
|
358
|
+
|
359
|
+
bool Complex_Selector::operator< (const Selector& rhs) const
|
350
360
|
{
|
351
|
-
if (
|
352
|
-
if (
|
361
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
|
362
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
|
363
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
|
364
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
|
365
|
+
throw std::runtime_error("invalid selector base classes to compare");
|
366
|
+
}
|
367
|
+
|
368
|
+
bool Compound_Selector::operator== (const Selector& rhs) const
|
369
|
+
{
|
370
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
|
371
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
|
372
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
|
373
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
|
374
|
+
throw std::runtime_error("invalid selector base classes to compare");
|
375
|
+
}
|
376
|
+
|
377
|
+
bool Compound_Selector::operator< (const Selector& rhs) const
|
378
|
+
{
|
379
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
|
380
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
|
381
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
|
382
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
|
383
|
+
throw std::runtime_error("invalid selector base classes to compare");
|
384
|
+
}
|
385
|
+
|
386
|
+
bool Selector_Schema::operator== (const Selector& rhs) const
|
387
|
+
{
|
388
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this == *sl;
|
389
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
|
390
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this == *cs;
|
391
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this == *ch;
|
392
|
+
throw std::runtime_error("invalid selector base classes to compare");
|
393
|
+
}
|
394
|
+
|
395
|
+
bool Selector_Schema::operator< (const Selector& rhs) const
|
396
|
+
{
|
397
|
+
if (const Selector_List* sl = Cast<Selector_List>(&rhs)) return *this < *sl;
|
398
|
+
if (const Simple_Selector* sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
|
399
|
+
if (const Complex_Selector* cs = Cast<Complex_Selector>(&rhs)) return *this < *cs;
|
400
|
+
if (const Compound_Selector* ch = Cast<Compound_Selector>(&rhs)) return *this < *ch;
|
353
401
|
throw std::runtime_error("invalid selector base classes to compare");
|
354
|
-
return false;
|
355
402
|
}
|
356
403
|
|
357
404
|
bool Simple_Selector::operator== (const Selector& rhs) const
|
358
405
|
{
|
359
|
-
if (Simple_Selector_Ptr_Const sp =
|
406
|
+
if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this == *sp;
|
360
407
|
return false;
|
361
408
|
}
|
362
409
|
|
363
410
|
bool Simple_Selector::operator< (const Selector& rhs) const
|
364
411
|
{
|
365
|
-
if (Simple_Selector_Ptr_Const sp =
|
412
|
+
if (Simple_Selector_Ptr_Const sp = Cast<Simple_Selector>(&rhs)) return *this < *sp;
|
366
413
|
return false;
|
367
414
|
}
|
368
415
|
|
369
416
|
bool Simple_Selector::operator== (const Simple_Selector& rhs) const
|
370
417
|
{
|
371
|
-
|
372
|
-
|
373
|
-
if (
|
374
|
-
|
375
|
-
}
|
376
|
-
else if (type == WRAPPED_SEL /* Wrapped_Selector_Ptr_Const lw = dynamic_cast<Wrapped_Selector_Ptr_Const>(this) */) {
|
377
|
-
return *static_cast<Wrapped_Selector_Ptr_Const>(this) == rhs;
|
378
|
-
}
|
379
|
-
else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */) {
|
380
|
-
return *static_cast<Attribute_Selector_Ptr_Const>(this) == rhs;
|
381
|
-
}
|
418
|
+
// solve the double dispatch problem by using RTTI information via dynamic cast
|
419
|
+
if (const Pseudo_Selector* lhs = Cast<Pseudo_Selector>(this)) {return *lhs == rhs; }
|
420
|
+
else if (const Wrapped_Selector* lhs = Cast<Wrapped_Selector>(this)) {return *lhs == rhs; }
|
421
|
+
else if (const Element_Selector* lhs = Cast<Element_Selector>(this)) {return *lhs == rhs; }
|
422
|
+
else if (const Attribute_Selector* lhs = Cast<Attribute_Selector>(this)) {return *lhs == rhs; }
|
382
423
|
else if (name_ == rhs.name_)
|
383
|
-
{ return is_ns_eq(
|
424
|
+
{ return is_ns_eq(rhs); }
|
384
425
|
else return false;
|
385
426
|
}
|
386
427
|
|
387
428
|
bool Simple_Selector::operator< (const Simple_Selector& rhs) const
|
388
429
|
{
|
389
|
-
|
390
|
-
|
391
|
-
if (
|
392
|
-
|
393
|
-
}
|
394
|
-
|
395
|
-
return *static_cast<Wrapped_Selector_Ptr_Const>(this) < rhs;
|
396
|
-
}
|
397
|
-
else if (type == ATTR_SEL /* Attribute_Selector_Ptr_Const la = dynamic_cast<Attribute_Selector_Ptr_Const>(this) */) {
|
398
|
-
return *static_cast<Attribute_Selector_Ptr_Const>(this) < rhs;
|
399
|
-
}
|
400
|
-
if (is_ns_eq(ns_, rhs.ns_))
|
430
|
+
// solve the double dispatch problem by using RTTI information via dynamic cast
|
431
|
+
if (const Pseudo_Selector* lhs = Cast<Pseudo_Selector>(this)) {return *lhs < rhs; }
|
432
|
+
else if (const Wrapped_Selector* lhs = Cast<Wrapped_Selector>(this)) {return *lhs < rhs; }
|
433
|
+
else if (const Element_Selector* lhs = Cast<Element_Selector>(this)) {return *lhs < rhs; }
|
434
|
+
else if (const Attribute_Selector* lhs = Cast<Attribute_Selector>(this)) {return *lhs < rhs; }
|
435
|
+
if (is_ns_eq(rhs))
|
401
436
|
{ return name_ < rhs.name_; }
|
402
437
|
return ns_ < rhs.ns_;
|
403
438
|
}
|
@@ -405,19 +440,19 @@ namespace Sass {
|
|
405
440
|
bool Selector_List::operator== (const Selector& rhs) const
|
406
441
|
{
|
407
442
|
// solve the double dispatch problem by using RTTI information via dynamic cast
|
408
|
-
if (Selector_List_Ptr_Const
|
409
|
-
else if (Complex_Selector_Ptr_Const
|
410
|
-
else if (Compound_Selector_Ptr_Const
|
443
|
+
if (Selector_List_Ptr_Const sl = Cast<Selector_List>(&rhs)) { return *this == *sl; }
|
444
|
+
else if (Complex_Selector_Ptr_Const cpx = Cast<Complex_Selector>(&rhs)) { return *this == *cpx; }
|
445
|
+
else if (Compound_Selector_Ptr_Const cpd = Cast<Compound_Selector>(&rhs)) { return *this == *cpd; }
|
411
446
|
// no compare method
|
412
447
|
return this == &rhs;
|
413
448
|
}
|
414
449
|
|
415
450
|
// Selector lists can be compared to comma lists
|
416
|
-
bool Selector_List::operator==(const Expression& rhs) const
|
451
|
+
bool Selector_List::operator== (const Expression& rhs) const
|
417
452
|
{
|
418
453
|
// solve the double dispatch problem by using RTTI information via dynamic cast
|
419
|
-
if (List_Ptr_Const ls =
|
420
|
-
if (Selector_Ptr_Const ls =
|
454
|
+
if (List_Ptr_Const ls = Cast<List>(&rhs)) { return *ls == *this; }
|
455
|
+
if (Selector_Ptr_Const ls = Cast<Selector>(&rhs)) { return *this == *ls; }
|
421
456
|
// compare invalid (maybe we should error?)
|
422
457
|
return false;
|
423
458
|
}
|
@@ -431,8 +466,8 @@ namespace Sass {
|
|
431
466
|
// create temporary vectors and sort them
|
432
467
|
std::vector<Complex_Selector_Obj> l_lst = this->elements();
|
433
468
|
std::vector<Complex_Selector_Obj> r_lst = rhs.elements();
|
434
|
-
std::sort(l_lst.begin(), l_lst.end(),
|
435
|
-
std::sort(r_lst.begin(), r_lst.end(),
|
469
|
+
std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
|
470
|
+
std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
|
436
471
|
// process loop
|
437
472
|
while (true)
|
438
473
|
{
|
@@ -451,38 +486,38 @@ namespace Sass {
|
|
451
486
|
// advance
|
452
487
|
++i; ++n;
|
453
488
|
}
|
454
|
-
// no
|
455
|
-
return true;
|
489
|
+
// there is no break?!
|
456
490
|
}
|
457
491
|
|
458
492
|
bool Selector_List::operator< (const Selector& rhs) const
|
459
493
|
{
|
460
|
-
if (Selector_List_Ptr_Const sp =
|
494
|
+
if (Selector_List_Ptr_Const sp = Cast<Selector_List>(&rhs)) return *this < *sp;
|
461
495
|
return false;
|
462
496
|
}
|
463
497
|
|
464
498
|
bool Selector_List::operator< (const Selector_List& rhs) const
|
465
499
|
{
|
466
|
-
|
467
|
-
|
468
|
-
|
500
|
+
size_t l = rhs.length();
|
501
|
+
if (length() < l) l = length();
|
502
|
+
for (size_t i = 0; i < l; i ++) {
|
503
|
+
if (*at(i) < *rhs.at(i)) return true;
|
469
504
|
}
|
470
|
-
return
|
505
|
+
return false;
|
471
506
|
}
|
472
507
|
|
473
|
-
Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs
|
508
|
+
Compound_Selector_Ptr Simple_Selector::unify_with(Compound_Selector_Ptr rhs)
|
474
509
|
{
|
475
510
|
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
476
|
-
{ if (to_string(
|
511
|
+
{ if (to_string() == rhs->at(i)->to_string()) return rhs; }
|
477
512
|
|
478
513
|
// check for pseudo elements because they are always last
|
479
514
|
size_t i, L;
|
480
515
|
bool found = false;
|
481
|
-
if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector))
|
516
|
+
if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector) || typeid(*this) == typeid(Attribute_Selector))
|
482
517
|
{
|
483
518
|
for (i = 0, L = rhs->length(); i < L; ++i)
|
484
519
|
{
|
485
|
-
if ((
|
520
|
+
if ((Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
|
486
521
|
{ found = true; break; }
|
487
522
|
}
|
488
523
|
}
|
@@ -490,20 +525,20 @@ namespace Sass {
|
|
490
525
|
{
|
491
526
|
for (i = 0, L = rhs->length(); i < L; ++i)
|
492
527
|
{
|
493
|
-
if (
|
528
|
+
if (Cast<Pseudo_Selector>((*rhs)[i]) || Cast<Wrapped_Selector>((*rhs)[i]) || Cast<Attribute_Selector>((*rhs)[i]))
|
494
529
|
{ found = true; break; }
|
495
530
|
}
|
496
531
|
}
|
497
532
|
if (!found)
|
498
533
|
{
|
499
534
|
rhs->append(this);
|
500
|
-
|
535
|
+
} else {
|
536
|
+
rhs->elements().insert(rhs->elements().begin() + i, this);
|
501
537
|
}
|
502
|
-
rhs->elements().insert(rhs->elements().begin() + i, this);
|
503
538
|
return rhs;
|
504
539
|
}
|
505
540
|
|
506
|
-
Simple_Selector_Ptr Element_Selector::unify_with(Simple_Selector_Ptr rhs
|
541
|
+
Simple_Selector_Ptr Element_Selector::unify_with(Simple_Selector_Ptr rhs)
|
507
542
|
{
|
508
543
|
// check if ns can be extended
|
509
544
|
// true for no ns or universal
|
@@ -534,7 +569,7 @@ namespace Sass {
|
|
534
569
|
return this;
|
535
570
|
}
|
536
571
|
|
537
|
-
Compound_Selector_Ptr Element_Selector::unify_with(Compound_Selector_Ptr rhs
|
572
|
+
Compound_Selector_Ptr Element_Selector::unify_with(Compound_Selector_Ptr rhs)
|
538
573
|
{
|
539
574
|
// TODO: handle namespaces
|
540
575
|
|
@@ -544,18 +579,18 @@ namespace Sass {
|
|
544
579
|
return rhs;
|
545
580
|
}
|
546
581
|
|
547
|
-
Simple_Selector_Ptr rhs_0 =
|
582
|
+
Simple_Selector_Ptr rhs_0 = rhs->at(0);
|
548
583
|
// otherwise, this is a tag name
|
549
584
|
if (name() == "*")
|
550
585
|
{
|
551
586
|
if (typeid(*rhs_0) == typeid(Element_Selector))
|
552
587
|
{
|
553
588
|
// if rhs is universal, just return this tagname + rhs's qualifiers
|
554
|
-
Element_Selector_Ptr ts =
|
555
|
-
rhs->at(0) = this->unify_with(ts
|
589
|
+
Element_Selector_Ptr ts = Cast<Element_Selector>(rhs_0);
|
590
|
+
rhs->at(0) = this->unify_with(ts);
|
556
591
|
return rhs;
|
557
592
|
}
|
558
|
-
else if (
|
593
|
+
else if (Cast<Class_Selector>(rhs_0) || Cast<Id_Selector>(rhs_0)) {
|
559
594
|
// qualifier is `.class`, so we can prefix with `ns|*.class`
|
560
595
|
if (has_ns() && !rhs_0->has_ns()) {
|
561
596
|
if (ns() != "*") rhs->elements().insert(rhs->begin(), this);
|
@@ -572,7 +607,7 @@ namespace Sass {
|
|
572
607
|
// if rhs is universal, just return this tagname + rhs's qualifiers
|
573
608
|
if (rhs_0->name() != "*" && rhs_0->ns() != "*" && rhs_0->name() != name()) return 0;
|
574
609
|
// otherwise create new compound and unify first simple selector
|
575
|
-
rhs->at(0) = this->unify_with(rhs_0
|
610
|
+
rhs->at(0) = this->unify_with(rhs_0);
|
576
611
|
return rhs;
|
577
612
|
|
578
613
|
}
|
@@ -581,64 +616,61 @@ namespace Sass {
|
|
581
616
|
return rhs;
|
582
617
|
}
|
583
618
|
|
584
|
-
Compound_Selector_Ptr Class_Selector::unify_with(Compound_Selector_Ptr rhs
|
619
|
+
Compound_Selector_Ptr Class_Selector::unify_with(Compound_Selector_Ptr rhs)
|
585
620
|
{
|
586
621
|
rhs->has_line_break(has_line_break());
|
587
|
-
return Simple_Selector::unify_with(rhs
|
622
|
+
return Simple_Selector::unify_with(rhs);
|
588
623
|
}
|
589
624
|
|
590
|
-
Compound_Selector_Ptr Id_Selector::unify_with(Compound_Selector_Ptr rhs
|
625
|
+
Compound_Selector_Ptr Id_Selector::unify_with(Compound_Selector_Ptr rhs)
|
591
626
|
{
|
592
627
|
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
593
628
|
{
|
594
|
-
if (Id_Selector_Ptr sel =
|
629
|
+
if (Id_Selector_Ptr sel = Cast<Id_Selector>(rhs->at(i))) {
|
595
630
|
if (sel->name() != name()) return 0;
|
596
631
|
}
|
597
632
|
}
|
598
633
|
rhs->has_line_break(has_line_break());
|
599
|
-
return Simple_Selector::unify_with(rhs
|
634
|
+
return Simple_Selector::unify_with(rhs);
|
600
635
|
}
|
601
636
|
|
602
|
-
Compound_Selector_Ptr Pseudo_Selector::unify_with(Compound_Selector_Ptr rhs
|
637
|
+
Compound_Selector_Ptr Pseudo_Selector::unify_with(Compound_Selector_Ptr rhs)
|
603
638
|
{
|
604
639
|
if (is_pseudo_element())
|
605
640
|
{
|
606
641
|
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
607
642
|
{
|
608
|
-
if (Pseudo_Selector_Ptr sel =
|
643
|
+
if (Pseudo_Selector_Ptr sel = Cast<Pseudo_Selector>(rhs->at(i))) {
|
609
644
|
if (sel->is_pseudo_element() && sel->name() != name()) return 0;
|
610
645
|
}
|
611
646
|
}
|
612
647
|
}
|
613
|
-
return Simple_Selector::unify_with(rhs
|
648
|
+
return Simple_Selector::unify_with(rhs);
|
614
649
|
}
|
615
650
|
|
616
651
|
bool Attribute_Selector::operator< (const Attribute_Selector& rhs) const
|
617
652
|
{
|
618
|
-
if (is_ns_eq(
|
653
|
+
if (is_ns_eq(rhs)) {
|
619
654
|
if (name() == rhs.name()) {
|
620
655
|
if (matcher() == rhs.matcher()) {
|
621
656
|
bool no_lhs_val = value().isNull();
|
622
657
|
bool no_rhs_val = rhs.value().isNull();
|
623
|
-
if (no_lhs_val && no_rhs_val)
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
return *value() < *rhs.value();
|
628
|
-
}
|
658
|
+
if (no_lhs_val && no_rhs_val) return false; // equal
|
659
|
+
else if (no_lhs_val) return true; // lhs is null
|
660
|
+
else if (no_rhs_val) return false; // rhs is null
|
661
|
+
return *value() < *rhs.value(); // both are given
|
629
662
|
} else { return matcher() < rhs.matcher(); }
|
630
663
|
} else { return name() < rhs.name(); }
|
631
|
-
}
|
632
|
-
return false;
|
664
|
+
} else { return ns() < rhs.ns(); }
|
633
665
|
}
|
634
666
|
|
635
667
|
bool Attribute_Selector::operator< (const Simple_Selector& rhs) const
|
636
668
|
{
|
637
|
-
if (Attribute_Selector_Ptr_Const w =
|
669
|
+
if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
|
638
670
|
{
|
639
671
|
return *this < *w;
|
640
672
|
}
|
641
|
-
if (is_ns_eq(
|
673
|
+
if (is_ns_eq(rhs))
|
642
674
|
{ return name() < rhs.name(); }
|
643
675
|
return ns() < rhs.ns();
|
644
676
|
}
|
@@ -652,13 +684,13 @@ namespace Sass {
|
|
652
684
|
if (no_lhs_val && no_rhs_val) {
|
653
685
|
return (name() == rhs.name())
|
654
686
|
&& (matcher() == rhs.matcher())
|
655
|
-
&& (is_ns_eq(
|
687
|
+
&& (is_ns_eq(rhs));
|
656
688
|
}
|
657
689
|
// both are defined, evaluate
|
658
690
|
if (no_lhs_val == no_rhs_val) {
|
659
691
|
return (name() == rhs.name())
|
660
692
|
&& (matcher() == rhs.matcher())
|
661
|
-
&& (is_ns_eq(
|
693
|
+
&& (is_ns_eq(rhs))
|
662
694
|
&& (*value() == *rhs.value());
|
663
695
|
}
|
664
696
|
// not equal
|
@@ -668,97 +700,130 @@ namespace Sass {
|
|
668
700
|
|
669
701
|
bool Attribute_Selector::operator== (const Simple_Selector& rhs) const
|
670
702
|
{
|
671
|
-
if (Attribute_Selector_Ptr_Const w =
|
703
|
+
if (Attribute_Selector_Ptr_Const w = Cast<Attribute_Selector>(&rhs))
|
672
704
|
{
|
673
|
-
return
|
705
|
+
return is_ns_eq(rhs) &&
|
706
|
+
name() == rhs.name() &&
|
707
|
+
*this == *w;
|
708
|
+
}
|
709
|
+
return false;
|
710
|
+
}
|
711
|
+
|
712
|
+
bool Element_Selector::operator< (const Element_Selector& rhs) const
|
713
|
+
{
|
714
|
+
if (is_ns_eq(rhs))
|
715
|
+
{ return name() < rhs.name(); }
|
716
|
+
return ns() < rhs.ns();
|
717
|
+
}
|
718
|
+
|
719
|
+
bool Element_Selector::operator< (const Simple_Selector& rhs) const
|
720
|
+
{
|
721
|
+
if (Element_Selector_Ptr_Const w = Cast<Element_Selector>(&rhs))
|
722
|
+
{
|
723
|
+
return *this < *w;
|
724
|
+
}
|
725
|
+
if (is_ns_eq(rhs))
|
726
|
+
{ return name() < rhs.name(); }
|
727
|
+
return ns() < rhs.ns();
|
728
|
+
}
|
729
|
+
|
730
|
+
bool Element_Selector::operator== (const Element_Selector& rhs) const
|
731
|
+
{
|
732
|
+
return is_ns_eq(rhs) &&
|
733
|
+
name() == rhs.name();
|
734
|
+
}
|
735
|
+
|
736
|
+
bool Element_Selector::operator== (const Simple_Selector& rhs) const
|
737
|
+
{
|
738
|
+
if (Element_Selector_Ptr_Const w = Cast<Element_Selector>(&rhs))
|
739
|
+
{
|
740
|
+
return is_ns_eq(rhs) &&
|
741
|
+
name() == rhs.name() &&
|
742
|
+
*this == *w;
|
674
743
|
}
|
675
|
-
|
676
|
-
{ return name() == rhs.name(); }
|
677
|
-
return ns() == rhs.ns();
|
744
|
+
return false;
|
678
745
|
}
|
679
746
|
|
680
747
|
bool Pseudo_Selector::operator== (const Pseudo_Selector& rhs) const
|
681
748
|
{
|
682
|
-
if (is_ns_eq(
|
749
|
+
if (is_ns_eq(rhs) && name() == rhs.name())
|
683
750
|
{
|
684
751
|
String_Obj lhs_ex = expression();
|
685
752
|
String_Obj rhs_ex = rhs.expression();
|
686
753
|
if (rhs_ex && lhs_ex) return *lhs_ex == *rhs_ex;
|
687
|
-
else return lhs_ex == rhs_ex;
|
754
|
+
else return lhs_ex.ptr() == rhs_ex.ptr();
|
688
755
|
}
|
689
756
|
else return false;
|
690
757
|
}
|
691
758
|
|
692
759
|
bool Pseudo_Selector::operator== (const Simple_Selector& rhs) const
|
693
760
|
{
|
694
|
-
if (Pseudo_Selector_Ptr_Const w =
|
761
|
+
if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
|
695
762
|
{
|
696
763
|
return *this == *w;
|
697
764
|
}
|
698
|
-
|
699
|
-
|
700
|
-
return ns() == rhs.ns();
|
765
|
+
return is_ns_eq(rhs) &&
|
766
|
+
name() == rhs.name();
|
701
767
|
}
|
702
768
|
|
703
769
|
bool Pseudo_Selector::operator< (const Pseudo_Selector& rhs) const
|
704
770
|
{
|
705
|
-
if (is_ns_eq(
|
771
|
+
if (is_ns_eq(rhs) && name() == rhs.name())
|
706
772
|
{
|
707
773
|
String_Obj lhs_ex = expression();
|
708
774
|
String_Obj rhs_ex = rhs.expression();
|
709
775
|
if (rhs_ex && lhs_ex) return *lhs_ex < *rhs_ex;
|
710
|
-
else return lhs_ex < rhs_ex;
|
776
|
+
else return lhs_ex.ptr() < rhs_ex.ptr();
|
711
777
|
}
|
712
|
-
if (is_ns_eq(
|
778
|
+
if (is_ns_eq(rhs))
|
713
779
|
{ return name() < rhs.name(); }
|
714
780
|
return ns() < rhs.ns();
|
715
781
|
}
|
716
782
|
|
717
783
|
bool Pseudo_Selector::operator< (const Simple_Selector& rhs) const
|
718
784
|
{
|
719
|
-
if (Pseudo_Selector_Ptr_Const w =
|
785
|
+
if (Pseudo_Selector_Ptr_Const w = Cast<Pseudo_Selector>(&rhs))
|
720
786
|
{
|
721
787
|
return *this < *w;
|
722
788
|
}
|
723
|
-
if (is_ns_eq(
|
789
|
+
if (is_ns_eq(rhs))
|
724
790
|
{ return name() < rhs.name(); }
|
725
791
|
return ns() < rhs.ns();
|
726
792
|
}
|
727
793
|
|
728
794
|
bool Wrapped_Selector::operator== (const Wrapped_Selector& rhs) const
|
729
795
|
{
|
730
|
-
if (is_ns_eq(
|
796
|
+
if (is_ns_eq(rhs) && name() == rhs.name())
|
731
797
|
{ return *(selector()) == *(rhs.selector()); }
|
732
798
|
else return false;
|
733
799
|
}
|
734
800
|
|
735
801
|
bool Wrapped_Selector::operator== (const Simple_Selector& rhs) const
|
736
802
|
{
|
737
|
-
if (Wrapped_Selector_Ptr_Const w =
|
803
|
+
if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
|
738
804
|
{
|
739
805
|
return *this == *w;
|
740
806
|
}
|
741
|
-
|
742
|
-
|
743
|
-
return ns() == rhs.ns();
|
807
|
+
return is_ns_eq(rhs) &&
|
808
|
+
name() == rhs.name();
|
744
809
|
}
|
745
810
|
|
746
811
|
bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const
|
747
812
|
{
|
748
|
-
if (is_ns_eq(
|
813
|
+
if (is_ns_eq(rhs) && name() == rhs.name())
|
749
814
|
{ return *(selector()) < *(rhs.selector()); }
|
750
|
-
if (is_ns_eq(
|
815
|
+
if (is_ns_eq(rhs))
|
751
816
|
{ return name() < rhs.name(); }
|
752
817
|
return ns() < rhs.ns();
|
753
818
|
}
|
754
819
|
|
755
820
|
bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const
|
756
821
|
{
|
757
|
-
if (Wrapped_Selector_Ptr_Const w =
|
822
|
+
if (Wrapped_Selector_Ptr_Const w = Cast<Wrapped_Selector>(&rhs))
|
758
823
|
{
|
759
824
|
return *this < *w;
|
760
825
|
}
|
761
|
-
if (is_ns_eq(
|
826
|
+
if (is_ns_eq(rhs))
|
762
827
|
{ return name() < rhs.name(); }
|
763
828
|
return ns() < rhs.ns();
|
764
829
|
}
|
@@ -767,28 +832,26 @@ namespace Sass {
|
|
767
832
|
{
|
768
833
|
if (this->name() != sub->name()) return false;
|
769
834
|
if (this->name() == ":current") return false;
|
770
|
-
if (Selector_List_Obj rhs_list =
|
771
|
-
if (Selector_List_Obj lhs_list =
|
835
|
+
if (Selector_List_Obj rhs_list = Cast<Selector_List>(sub->selector())) {
|
836
|
+
if (Selector_List_Obj lhs_list = Cast<Selector_List>(selector())) {
|
772
837
|
return lhs_list->is_superselector_of(rhs_list);
|
773
838
|
}
|
774
|
-
error("is_superselector expected a Selector_List", sub->pstate());
|
775
|
-
} else {
|
776
|
-
error("is_superselector expected a Selector_List", sub->pstate());
|
777
839
|
}
|
840
|
+
coreError("is_superselector expected a Selector_List", sub->pstate());
|
778
841
|
return false;
|
779
842
|
}
|
780
843
|
|
781
844
|
bool Compound_Selector::is_superselector_of(Selector_List_Obj rhs, std::string wrapped)
|
782
845
|
{
|
783
846
|
for (Complex_Selector_Obj item : rhs->elements()) {
|
784
|
-
if (is_superselector_of(
|
847
|
+
if (is_superselector_of(item, wrapped)) return true;
|
785
848
|
}
|
786
849
|
return false;
|
787
850
|
}
|
788
851
|
|
789
852
|
bool Compound_Selector::is_superselector_of(Complex_Selector_Obj rhs, std::string wrapped)
|
790
853
|
{
|
791
|
-
if (rhs->head()) return is_superselector_of(
|
854
|
+
if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
|
792
855
|
return false;
|
793
856
|
}
|
794
857
|
|
@@ -821,6 +884,9 @@ namespace Sass {
|
|
821
884
|
return false;
|
822
885
|
}
|
823
886
|
|
887
|
+
// would like to replace this without stringification
|
888
|
+
// https://github.com/sass/sass/issues/2229
|
889
|
+
// SimpleSelectorSet lset, rset;
|
824
890
|
std::set<std::string> lset, rset;
|
825
891
|
|
826
892
|
if (lbase && rbase)
|
@@ -837,20 +903,20 @@ namespace Sass {
|
|
837
903
|
|
838
904
|
for (size_t i = 0, iL = length(); i < iL; ++i)
|
839
905
|
{
|
840
|
-
Selector_Obj
|
906
|
+
Selector_Obj wlhs = (*this)[i];
|
841
907
|
// very special case for wrapped matches selector
|
842
|
-
if (Wrapped_Selector_Obj wrapped =
|
908
|
+
if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(wlhs)) {
|
843
909
|
if (wrapped->name() == ":not") {
|
844
|
-
if (Selector_List_Obj not_list =
|
910
|
+
if (Selector_List_Obj not_list = Cast<Selector_List>(wrapped->selector())) {
|
845
911
|
if (not_list->is_superselector_of(rhs, wrapped->name())) return false;
|
846
912
|
} else {
|
847
913
|
throw std::runtime_error("wrapped not selector is not a list");
|
848
914
|
}
|
849
915
|
}
|
850
916
|
if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
|
851
|
-
|
852
|
-
if (Selector_List_Obj list =
|
853
|
-
if (Compound_Selector_Obj comp =
|
917
|
+
wlhs = wrapped->selector();
|
918
|
+
if (Selector_List_Obj list = Cast<Selector_List>(wrapped->selector())) {
|
919
|
+
if (Compound_Selector_Obj comp = Cast<Compound_Selector>(rhs)) {
|
854
920
|
if (!wrapping.empty() && wrapping != wrapped->name()) return false;
|
855
921
|
if (wrapping.empty() || wrapping != wrapped->name()) {;
|
856
922
|
if (list->is_superselector_of(comp, wrapped->name())) return true;
|
@@ -858,26 +924,25 @@ namespace Sass {
|
|
858
924
|
}
|
859
925
|
}
|
860
926
|
}
|
861
|
-
Simple_Selector_Ptr rhs_sel =
|
862
|
-
if (
|
927
|
+
Simple_Selector_Ptr rhs_sel = NULL;
|
928
|
+
if (rhs->elements().size() > i) rhs_sel = (*rhs)[i];
|
929
|
+
if (Wrapped_Selector_Ptr wrapped_r = Cast<Wrapped_Selector>(rhs_sel)) {
|
863
930
|
if (wrapped->name() == wrapped_r->name()) {
|
864
931
|
if (wrapped->is_superselector_of(wrapped_r)) {
|
865
932
|
continue;
|
866
|
-
rset.insert(lhs->to_string());
|
867
|
-
|
868
933
|
}}
|
869
934
|
}
|
870
935
|
}
|
871
936
|
// match from here on as strings
|
872
|
-
lset.insert(
|
937
|
+
lset.insert(wlhs->to_string());
|
873
938
|
}
|
874
939
|
|
875
940
|
for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
|
876
941
|
{
|
877
|
-
Selector_Obj r =
|
878
|
-
if (Wrapped_Selector_Obj wrapped =
|
942
|
+
Selector_Obj r = (*rhs)[n];
|
943
|
+
if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(r)) {
|
879
944
|
if (wrapped->name() == ":not") {
|
880
|
-
if (Selector_List_Obj ls =
|
945
|
+
if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
|
881
946
|
ls->remove_parent_selectors();
|
882
947
|
if (is_superselector_of(ls, wrapped->name())) return false;
|
883
948
|
}
|
@@ -886,7 +951,7 @@ namespace Sass {
|
|
886
951
|
if (!wrapping.empty()) {
|
887
952
|
if (wrapping != wrapped->name()) return false;
|
888
953
|
}
|
889
|
-
if (Selector_List_Obj ls =
|
954
|
+
if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
|
890
955
|
ls->remove_parent_selectors();
|
891
956
|
return (is_superselector_of(ls, wrapped->name()));
|
892
957
|
}
|
@@ -915,7 +980,7 @@ namespace Sass {
|
|
915
980
|
0);
|
916
981
|
}
|
917
982
|
|
918
|
-
Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other
|
983
|
+
Selector_List_Ptr Complex_Selector::unify_with(Complex_Selector_Ptr other)
|
919
984
|
{
|
920
985
|
|
921
986
|
// get last tails (on the right side)
|
@@ -941,7 +1006,7 @@ namespace Sass {
|
|
941
1006
|
SASS_ASSERT(r_last_head, "rhs head is null");
|
942
1007
|
|
943
1008
|
// get the unification of the last compound selectors
|
944
|
-
Compound_Selector_Obj unified = r_last_head->unify_with(
|
1009
|
+
Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
|
945
1010
|
|
946
1011
|
// abort if we could not unify heads
|
947
1012
|
if (unified == 0) return 0;
|
@@ -958,28 +1023,28 @@ namespace Sass {
|
|
958
1023
|
}
|
959
1024
|
|
960
1025
|
// create nodes from both selectors
|
961
|
-
Node lhsNode = complexSelectorToNode(this
|
962
|
-
Node rhsNode = complexSelectorToNode(other
|
1026
|
+
Node lhsNode = complexSelectorToNode(this);
|
1027
|
+
Node rhsNode = complexSelectorToNode(other);
|
963
1028
|
|
964
1029
|
// overwrite universal base
|
965
1030
|
if (!is_universal)
|
966
1031
|
{
|
967
1032
|
// create some temporaries to convert to node
|
968
1033
|
Complex_Selector_Obj fake = unified->to_complex();
|
969
|
-
Node unified_node = complexSelectorToNode(
|
1034
|
+
Node unified_node = complexSelectorToNode(fake);
|
970
1035
|
// add to permutate the list?
|
971
1036
|
rhsNode.plus(unified_node);
|
972
1037
|
}
|
973
1038
|
|
974
1039
|
// do some magic we inherit from node and extend
|
975
|
-
Node node =
|
976
|
-
|
1040
|
+
Node node = subweave(lhsNode, rhsNode);
|
1041
|
+
Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate());
|
977
1042
|
NodeDequePtr col = node.collection(); // move from collection to list
|
978
1043
|
for (NodeDeque::iterator it = col->begin(), end = col->end(); it != end; it++)
|
979
|
-
{ result->append(nodeToComplexSelector(Node::naiveTrim(*it
|
1044
|
+
{ result->append(nodeToComplexSelector(Node::naiveTrim(*it))); }
|
980
1045
|
|
981
1046
|
// only return if list has some entries
|
982
|
-
return result->length() ? result : 0;
|
1047
|
+
return result->length() ? result.detach() : 0;
|
983
1048
|
|
984
1049
|
}
|
985
1050
|
|
@@ -992,8 +1057,8 @@ namespace Sass {
|
|
992
1057
|
// create temporary vectors and sort them
|
993
1058
|
std::vector<Simple_Selector_Obj> l_lst = this->elements();
|
994
1059
|
std::vector<Simple_Selector_Obj> r_lst = rhs.elements();
|
995
|
-
std::sort(l_lst.begin(), l_lst.end(),
|
996
|
-
std::sort(r_lst.begin(), r_lst.end(),
|
1060
|
+
std::sort(l_lst.begin(), l_lst.end(), OrderNodes());
|
1061
|
+
std::sort(r_lst.begin(), r_lst.end(), OrderNodes());
|
997
1062
|
// process loop
|
998
1063
|
while (true)
|
999
1064
|
{
|
@@ -1012,12 +1077,7 @@ namespace Sass {
|
|
1012
1077
|
// advance now
|
1013
1078
|
++i; ++n;
|
1014
1079
|
}
|
1015
|
-
// no
|
1016
|
-
return true;
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
bool Complex_Selector_Pointer_Compare::operator() (const Complex_Selector_Obj& pLeft, const Complex_Selector_Obj& pRight) const {
|
1020
|
-
return *pLeft < *pRight;
|
1080
|
+
// there is no break?!
|
1021
1081
|
}
|
1022
1082
|
|
1023
1083
|
bool Complex_Selector::is_superselector_of(Compound_Selector_Obj rhs, std::string wrapping)
|
@@ -1043,7 +1103,7 @@ namespace Sass {
|
|
1043
1103
|
{ return false; }
|
1044
1104
|
|
1045
1105
|
if (l_len == 1)
|
1046
|
-
{ return lhs->head()->is_superselector_of(
|
1106
|
+
{ return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); }
|
1047
1107
|
|
1048
1108
|
// we have to look one tail deeper, since we cary the
|
1049
1109
|
// combinator around for it (which is important here)
|
@@ -1054,7 +1114,7 @@ namespace Sass {
|
|
1054
1114
|
if (lhs_tail->head() && !rhs_tail->head()) return false;
|
1055
1115
|
if (!lhs_tail->head() && rhs_tail->head()) return false;
|
1056
1116
|
if (lhs_tail->head() && rhs_tail->head()) {
|
1057
|
-
if (!lhs_tail->head()->is_superselector_of(
|
1117
|
+
if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
|
1058
1118
|
}
|
1059
1119
|
}
|
1060
1120
|
|
@@ -1063,7 +1123,7 @@ namespace Sass {
|
|
1063
1123
|
for (size_t i = 0, L = rhs->length(); i < L; ++i) {
|
1064
1124
|
if (i == L-1)
|
1065
1125
|
{ return false; }
|
1066
|
-
if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(
|
1126
|
+
if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping))
|
1067
1127
|
{ found = true; break; }
|
1068
1128
|
marker = marker->tail();
|
1069
1129
|
}
|
@@ -1089,20 +1149,15 @@ namespace Sass {
|
|
1089
1149
|
{ return false; }
|
1090
1150
|
if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
|
1091
1151
|
{ return false; }
|
1092
|
-
return lhs->tail()->is_superselector_of(
|
1152
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
1093
1153
|
}
|
1094
1154
|
else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
|
1095
1155
|
{
|
1096
1156
|
if (marker->combinator() != Complex_Selector::PARENT_OF)
|
1097
1157
|
{ return false; }
|
1098
|
-
return lhs->tail()->is_superselector_of(
|
1158
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
1099
1159
|
}
|
1100
|
-
|
1101
|
-
{
|
1102
|
-
return lhs->tail()->is_superselector_of(&marker->tail());
|
1103
|
-
}
|
1104
|
-
// catch-all
|
1105
|
-
return false;
|
1160
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
1106
1161
|
}
|
1107
1162
|
|
1108
1163
|
size_t Complex_Selector::length() const
|
@@ -1112,20 +1167,11 @@ namespace Sass {
|
|
1112
1167
|
return 1 + tail()->length();
|
1113
1168
|
}
|
1114
1169
|
|
1115
|
-
Complex_Selector_Obj Complex_Selector::context(Context& ctx)
|
1116
|
-
{
|
1117
|
-
if (!tail()) return 0;
|
1118
|
-
if (!head()) return tail()->context(ctx);
|
1119
|
-
Complex_Selector_Obj cpy = SASS_MEMORY_NEW(Complex_Selector, pstate(), combinator(), head(), tail()->context(ctx));
|
1120
|
-
cpy->media_block(media_block());
|
1121
|
-
return cpy;
|
1122
|
-
}
|
1123
|
-
|
1124
1170
|
// append another complex selector at the end
|
1125
1171
|
// check if we need to append some headers
|
1126
1172
|
// then we need to check for the combinator
|
1127
1173
|
// only then we can safely set the new tail
|
1128
|
-
void Complex_Selector::append(
|
1174
|
+
void Complex_Selector::append(Complex_Selector_Obj ss, Backtraces& traces)
|
1129
1175
|
{
|
1130
1176
|
|
1131
1177
|
Complex_Selector_Obj t = ss->tail();
|
@@ -1139,47 +1185,49 @@ namespace Sass {
|
|
1139
1185
|
// append old headers
|
1140
1186
|
if (h && h->length()) {
|
1141
1187
|
if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
|
1142
|
-
|
1188
|
+
traces.push_back(Backtrace(pstate()));
|
1189
|
+
throw Exception::InvalidParent(this, traces, ss);
|
1143
1190
|
} else if (last()->head_ && last()->head_->length()) {
|
1144
1191
|
Compound_Selector_Obj rh = last()->head();
|
1145
|
-
size_t i
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1192
|
+
size_t i;
|
1193
|
+
size_t L = h->length();
|
1194
|
+
if (Cast<Element_Selector>(h->first())) {
|
1195
|
+
if (Class_Selector_Ptr cs = Cast<Class_Selector>(rh->last())) {
|
1196
|
+
Class_Selector_Ptr sqs = SASS_MEMORY_COPY(cs);
|
1149
1197
|
sqs->name(sqs->name() + (*h)[0]->name());
|
1150
1198
|
sqs->pstate((*h)[0]->pstate());
|
1151
1199
|
(*rh)[rh->length()-1] = sqs;
|
1152
1200
|
rh->pstate(h->pstate());
|
1153
|
-
for (i = 1; i < L; ++i) rh->append(
|
1154
|
-
} else if (Id_Selector_Ptr
|
1155
|
-
Id_Selector_Ptr sqs = SASS_MEMORY_COPY(
|
1201
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
1202
|
+
} else if (Id_Selector_Ptr is = Cast<Id_Selector>(rh->last())) {
|
1203
|
+
Id_Selector_Ptr sqs = SASS_MEMORY_COPY(is);
|
1156
1204
|
sqs->name(sqs->name() + (*h)[0]->name());
|
1157
1205
|
sqs->pstate((*h)[0]->pstate());
|
1158
1206
|
(*rh)[rh->length()-1] = sqs;
|
1159
1207
|
rh->pstate(h->pstate());
|
1160
|
-
for (i = 1; i < L; ++i) rh->append(
|
1161
|
-
} else if (Element_Selector_Ptr ts =
|
1208
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
1209
|
+
} else if (Element_Selector_Ptr ts = Cast<Element_Selector>(rh->last())) {
|
1162
1210
|
Element_Selector_Ptr tss = SASS_MEMORY_COPY(ts);
|
1163
1211
|
tss->name(tss->name() + (*h)[0]->name());
|
1164
1212
|
tss->pstate((*h)[0]->pstate());
|
1165
1213
|
(*rh)[rh->length()-1] = tss;
|
1166
1214
|
rh->pstate(h->pstate());
|
1167
|
-
for (i = 1; i < L; ++i) rh->append(
|
1168
|
-
} else if (Placeholder_Selector_Ptr ps =
|
1215
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
1216
|
+
} else if (Placeholder_Selector_Ptr ps = Cast<Placeholder_Selector>(rh->last())) {
|
1169
1217
|
Placeholder_Selector_Ptr pss = SASS_MEMORY_COPY(ps);
|
1170
1218
|
pss->name(pss->name() + (*h)[0]->name());
|
1171
1219
|
pss->pstate((*h)[0]->pstate());
|
1172
1220
|
(*rh)[rh->length()-1] = pss;
|
1173
1221
|
rh->pstate(h->pstate());
|
1174
|
-
for (i = 1; i < L; ++i) rh->append(
|
1222
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
1175
1223
|
} else {
|
1176
|
-
last()->head_->concat(
|
1224
|
+
last()->head_->concat(h);
|
1177
1225
|
}
|
1178
1226
|
} else {
|
1179
|
-
last()->head_->concat(
|
1227
|
+
last()->head_->concat(h);
|
1180
1228
|
}
|
1181
|
-
} else {
|
1182
|
-
last()->head_->concat(
|
1229
|
+
} else if (last()->head_) {
|
1230
|
+
last()->head_->concat(h);
|
1183
1231
|
}
|
1184
1232
|
} else {
|
1185
1233
|
// std::cerr << "has no or empty head\n";
|
@@ -1201,28 +1249,35 @@ namespace Sass {
|
|
1201
1249
|
}
|
1202
1250
|
}
|
1203
1251
|
|
1252
|
+
}
|
1204
1253
|
|
1254
|
+
Selector_List_Obj Selector_List::eval(Eval& eval)
|
1255
|
+
{
|
1256
|
+
Selector_List_Obj list = schema() ?
|
1257
|
+
eval(schema()) : eval(this);
|
1258
|
+
list->schema(schema());
|
1259
|
+
return list;
|
1205
1260
|
}
|
1206
1261
|
|
1207
|
-
Selector_List_Ptr Selector_List::resolve_parent_refs(
|
1262
|
+
Selector_List_Ptr Selector_List::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
|
1208
1263
|
{
|
1209
1264
|
if (!this->has_parent_ref()) return this;
|
1210
1265
|
Selector_List_Ptr ss = SASS_MEMORY_NEW(Selector_List, pstate());
|
1211
|
-
Selector_List_Ptr ps =
|
1266
|
+
Selector_List_Ptr ps = pstack.back();
|
1212
1267
|
for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) {
|
1213
1268
|
for (size_t si = 0, sL = this->length(); si < sL; ++si) {
|
1214
|
-
Selector_List_Obj rv = at(si)->resolve_parent_refs(
|
1215
|
-
ss->concat(
|
1269
|
+
Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, traces, implicit_parent);
|
1270
|
+
ss->concat(rv);
|
1216
1271
|
}
|
1217
1272
|
}
|
1218
1273
|
return ss;
|
1219
1274
|
}
|
1220
1275
|
|
1221
|
-
Selector_List_Ptr Complex_Selector::resolve_parent_refs(
|
1276
|
+
Selector_List_Ptr Complex_Selector::resolve_parent_refs(std::vector<Selector_List_Obj>& pstack, Backtraces& traces, bool implicit_parent)
|
1222
1277
|
{
|
1223
1278
|
Complex_Selector_Obj tail = this->tail();
|
1224
1279
|
Compound_Selector_Obj head = this->head();
|
1225
|
-
Selector_List_Ptr parents =
|
1280
|
+
Selector_List_Ptr parents = pstack.back();
|
1226
1281
|
|
1227
1282
|
if (!this->has_real_parent_ref() && !implicit_parent) {
|
1228
1283
|
Selector_List_Ptr retval = SASS_MEMORY_NEW(Selector_List, pstate());
|
@@ -1231,14 +1286,14 @@ namespace Sass {
|
|
1231
1286
|
}
|
1232
1287
|
|
1233
1288
|
// first resolve_parent_refs the tail (which may return an expanded list)
|
1234
|
-
Selector_List_Obj tails = tail ? tail->resolve_parent_refs(
|
1289
|
+
Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, traces, implicit_parent) : 0;
|
1235
1290
|
|
1236
1291
|
if (head && head->length() > 0) {
|
1237
1292
|
|
1238
1293
|
Selector_List_Obj retval;
|
1239
1294
|
// we have a parent selector in a simple compound list
|
1240
1295
|
// mix parent complex selector into the compound list
|
1241
|
-
if (
|
1296
|
+
if (Cast<Parent_Selector>((*head)[0])) {
|
1242
1297
|
retval = SASS_MEMORY_NEW(Selector_List, pstate());
|
1243
1298
|
|
1244
1299
|
// it turns out that real parent references reach
|
@@ -1246,7 +1301,7 @@ namespace Sass {
|
|
1246
1301
|
if (parents == NULL && head->has_real_parent_ref()) {
|
1247
1302
|
int i = pstack.size() - 1;
|
1248
1303
|
while (!parents && i > -1) {
|
1249
|
-
parents =
|
1304
|
+
parents = pstack.at(i--);
|
1250
1305
|
}
|
1251
1306
|
}
|
1252
1307
|
|
@@ -1258,22 +1313,26 @@ namespace Sass {
|
|
1258
1313
|
Complex_Selector_Obj parent = (*parents)[i];
|
1259
1314
|
Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
|
1260
1315
|
Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
|
1261
|
-
ss->tail(t ? SASS_MEMORY_CLONE(t) :
|
1316
|
+
ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL);
|
1262
1317
|
Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
|
1263
1318
|
// remove parent selector from sequence
|
1264
|
-
if (h->length()) h->erase(h->begin());
|
1265
|
-
ss->head(h->length() ? &h : 0);
|
1266
|
-
// adjust for parent selector (1 char)
|
1267
1319
|
if (h->length()) {
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1320
|
+
h->erase(h->begin());
|
1321
|
+
ss->head(h);
|
1322
|
+
} else {
|
1323
|
+
ss->head(NULL);
|
1272
1324
|
}
|
1325
|
+
// adjust for parent selector (1 char)
|
1326
|
+
// if (h->length()) {
|
1327
|
+
// ParserState state(h->at(0)->pstate());
|
1328
|
+
// state.offset.column += 1;
|
1329
|
+
// state.column -= 1;
|
1330
|
+
// (*h)[0]->pstate(state);
|
1331
|
+
// }
|
1273
1332
|
// keep old parser state
|
1274
1333
|
s->pstate(pstate());
|
1275
1334
|
// append new tail
|
1276
|
-
s->append(
|
1335
|
+
s->append(ss, traces);
|
1277
1336
|
retval->append(s);
|
1278
1337
|
}
|
1279
1338
|
}
|
@@ -1288,26 +1347,31 @@ namespace Sass {
|
|
1288
1347
|
// this is only if valid if the parent has no trailing op
|
1289
1348
|
// otherwise we cannot append more simple selectors to head
|
1290
1349
|
if (parent->last()->combinator() != ANCESTOR_OF) {
|
1291
|
-
|
1350
|
+
traces.push_back(Backtrace(pstate()));
|
1351
|
+
throw Exception::InvalidParent(parent, traces, ss);
|
1292
1352
|
}
|
1293
|
-
ss->tail(tail ? SASS_MEMORY_CLONE(tail) :
|
1353
|
+
ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL);
|
1294
1354
|
Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
|
1295
1355
|
// remove parent selector from sequence
|
1296
|
-
if (h->length())
|
1297
|
-
|
1356
|
+
if (h->length()) {
|
1357
|
+
h->erase(h->begin());
|
1358
|
+
ss->head(h);
|
1359
|
+
} else {
|
1360
|
+
ss->head(NULL);
|
1361
|
+
}
|
1298
1362
|
// \/ IMO ruby sass bug \/
|
1299
1363
|
ss->has_line_feed(false);
|
1300
1364
|
// adjust for parent selector (1 char)
|
1301
|
-
if (h->length()) {
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
}
|
1365
|
+
// if (h->length()) {
|
1366
|
+
// ParserState state(h->at(0)->pstate());
|
1367
|
+
// state.offset.column += 1;
|
1368
|
+
// state.column -= 1;
|
1369
|
+
// (*h)[0]->pstate(state);
|
1370
|
+
// }
|
1307
1371
|
// keep old parser state
|
1308
1372
|
s->pstate(pstate());
|
1309
1373
|
// append new tail
|
1310
|
-
s->append(
|
1374
|
+
s->append(ss, traces);
|
1311
1375
|
retval->append(s);
|
1312
1376
|
}
|
1313
1377
|
}
|
@@ -1320,7 +1384,7 @@ namespace Sass {
|
|
1320
1384
|
cpy->tail(SASS_MEMORY_CLONE(tails->at(n)));
|
1321
1385
|
cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
|
1322
1386
|
for (size_t i = 1, L = this->head()->length(); i < L; ++i)
|
1323
|
-
cpy->head()->append(
|
1387
|
+
cpy->head()->append((*this->head())[i]);
|
1324
1388
|
if (!cpy->head()->length()) cpy->head(0);
|
1325
1389
|
retval->append(cpy->skip_empty_reference());
|
1326
1390
|
}
|
@@ -1330,7 +1394,7 @@ namespace Sass {
|
|
1330
1394
|
Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
|
1331
1395
|
cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
|
1332
1396
|
for (size_t i = 1, L = this->head()->length(); i < L; ++i)
|
1333
|
-
cpy->head()->append(
|
1397
|
+
cpy->head()->append((*this->head())[i]);
|
1334
1398
|
if (!cpy->head()->length()) cpy->head(0);
|
1335
1399
|
retval->append(cpy->skip_empty_reference());
|
1336
1400
|
}
|
@@ -1338,13 +1402,13 @@ namespace Sass {
|
|
1338
1402
|
}
|
1339
1403
|
// no parent selector in head
|
1340
1404
|
else {
|
1341
|
-
retval = this->tails(
|
1405
|
+
retval = this->tails(tails);
|
1342
1406
|
}
|
1343
1407
|
|
1344
1408
|
for (Simple_Selector_Obj ss : head->elements()) {
|
1345
|
-
if (Wrapped_Selector_Ptr ws =
|
1346
|
-
if (Selector_List_Ptr sl =
|
1347
|
-
if (parents) ws->selector(sl->resolve_parent_refs(
|
1409
|
+
if (Wrapped_Selector_Ptr ws = Cast<Wrapped_Selector>(ss)) {
|
1410
|
+
if (Selector_List_Ptr sl = Cast<Selector_List>(ws->selector())) {
|
1411
|
+
if (parents) ws->selector(sl->resolve_parent_refs(pstack, traces, implicit_parent));
|
1348
1412
|
}
|
1349
1413
|
}
|
1350
1414
|
}
|
@@ -1353,15 +1417,10 @@ namespace Sass {
|
|
1353
1417
|
|
1354
1418
|
}
|
1355
1419
|
// has no head
|
1356
|
-
|
1357
|
-
return this->tails(ctx, &tails);
|
1358
|
-
}
|
1359
|
-
|
1360
|
-
// unreachable
|
1361
|
-
return 0;
|
1420
|
+
return this->tails(tails);
|
1362
1421
|
}
|
1363
1422
|
|
1364
|
-
Selector_List_Ptr Complex_Selector::tails(
|
1423
|
+
Selector_List_Ptr Complex_Selector::tails(Selector_List_Ptr tails)
|
1365
1424
|
{
|
1366
1425
|
Selector_List_Ptr rv = SASS_MEMORY_NEW(Selector_List, pstate_);
|
1367
1426
|
if (tails && tails->length()) {
|
@@ -1389,21 +1448,27 @@ namespace Sass {
|
|
1389
1448
|
// get the head
|
1390
1449
|
head = cur->head_;
|
1391
1450
|
// abort (and return) if it is not a parent selector
|
1392
|
-
if (!head || head->length() != 1 || !
|
1451
|
+
if (!head || head->length() != 1 || !Cast<Parent_Selector>((*head)[0])) {
|
1393
1452
|
break;
|
1394
1453
|
}
|
1395
1454
|
// advance to next
|
1396
1455
|
cur = cur->tail_;
|
1397
1456
|
}
|
1398
1457
|
// result
|
1399
|
-
return
|
1458
|
+
return cur;
|
1400
1459
|
}
|
1401
1460
|
|
1402
1461
|
// return the last tail that is defined
|
1403
1462
|
Complex_Selector_Obj Complex_Selector::last()
|
1404
1463
|
{
|
1405
|
-
|
1406
|
-
|
1464
|
+
Complex_Selector_Ptr cur = this;
|
1465
|
+
Complex_Selector_Ptr nxt = cur;
|
1466
|
+
// loop until last
|
1467
|
+
while (nxt) {
|
1468
|
+
cur = nxt;
|
1469
|
+
nxt = cur->tail();
|
1470
|
+
}
|
1471
|
+
return cur;
|
1407
1472
|
}
|
1408
1473
|
|
1409
1474
|
Complex_Selector::Combinator Complex_Selector::clear_innermost()
|
@@ -1474,7 +1539,31 @@ namespace Sass {
|
|
1474
1539
|
}
|
1475
1540
|
}
|
1476
1541
|
|
1477
|
-
|
1542
|
+
size_t Wrapped_Selector::hash()
|
1543
|
+
{
|
1544
|
+
if (hash_ == 0) {
|
1545
|
+
hash_combine(hash_, Simple_Selector::hash());
|
1546
|
+
if (selector_) hash_combine(hash_, selector_->hash());
|
1547
|
+
}
|
1548
|
+
return hash_;
|
1549
|
+
}
|
1550
|
+
bool Wrapped_Selector::has_parent_ref() const {
|
1551
|
+
// if (has_reference()) return true;
|
1552
|
+
if (!selector()) return false;
|
1553
|
+
return selector()->has_parent_ref();
|
1554
|
+
}
|
1555
|
+
bool Wrapped_Selector::has_real_parent_ref() const {
|
1556
|
+
// if (has_reference()) return true;
|
1557
|
+
if (!selector()) return false;
|
1558
|
+
return selector()->has_real_parent_ref();
|
1559
|
+
}
|
1560
|
+
unsigned long Wrapped_Selector::specificity() const
|
1561
|
+
{
|
1562
|
+
return selector_ ? selector_->specificity() : 0;
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
|
1566
|
+
bool Selector_List::has_parent_ref() const
|
1478
1567
|
{
|
1479
1568
|
for (Complex_Selector_Obj s : elements()) {
|
1480
1569
|
if (s && s->has_parent_ref()) return true;
|
@@ -1482,7 +1571,7 @@ namespace Sass {
|
|
1482
1571
|
return false;
|
1483
1572
|
}
|
1484
1573
|
|
1485
|
-
bool Selector_List::has_real_parent_ref()
|
1574
|
+
bool Selector_List::has_real_parent_ref() const
|
1486
1575
|
{
|
1487
1576
|
for (Complex_Selector_Obj s : elements()) {
|
1488
1577
|
if (s && s->has_real_parent_ref()) return true;
|
@@ -1490,18 +1579,18 @@ namespace Sass {
|
|
1490
1579
|
return false;
|
1491
1580
|
}
|
1492
1581
|
|
1493
|
-
bool Selector_Schema::has_parent_ref()
|
1582
|
+
bool Selector_Schema::has_parent_ref() const
|
1494
1583
|
{
|
1495
|
-
if (String_Schema_Obj schema =
|
1496
|
-
return schema->length() > 0 &&
|
1584
|
+
if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
|
1585
|
+
return schema->length() > 0 && Cast<Parent_Selector>(schema->at(0)) != NULL;
|
1497
1586
|
}
|
1498
1587
|
return false;
|
1499
1588
|
}
|
1500
1589
|
|
1501
|
-
bool Selector_Schema::has_real_parent_ref()
|
1590
|
+
bool Selector_Schema::has_real_parent_ref() const
|
1502
1591
|
{
|
1503
|
-
if (String_Schema_Obj schema =
|
1504
|
-
Parent_Selector_Obj p =
|
1592
|
+
if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
|
1593
|
+
Parent_Selector_Obj p = Cast<Parent_Selector>(schema->at(0));
|
1505
1594
|
return schema->length() > 0 && p && p->is_real_parent_ref();
|
1506
1595
|
}
|
1507
1596
|
return false;
|
@@ -1518,7 +1607,7 @@ namespace Sass {
|
|
1518
1607
|
{
|
1519
1608
|
// Check every rhs selector against left hand list
|
1520
1609
|
for(size_t i = 0, L = sub->length(); i < L; ++i) {
|
1521
|
-
if (!is_superselector_of(
|
1610
|
+
if (!is_superselector_of((*sub)[i], wrapping)) return false;
|
1522
1611
|
}
|
1523
1612
|
return true;
|
1524
1613
|
}
|
@@ -1529,7 +1618,7 @@ namespace Sass {
|
|
1529
1618
|
{
|
1530
1619
|
// Check every rhs selector against left hand list
|
1531
1620
|
for(size_t i = 0, L = sub->length(); i < L; ++i) {
|
1532
|
-
if (!is_superselector_of(
|
1621
|
+
if (!is_superselector_of((*sub)[i], wrapping)) return false;
|
1533
1622
|
}
|
1534
1623
|
return true;
|
1535
1624
|
}
|
@@ -1556,18 +1645,18 @@ namespace Sass {
|
|
1556
1645
|
return false;
|
1557
1646
|
}
|
1558
1647
|
|
1559
|
-
Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs
|
1648
|
+
Selector_List_Ptr Selector_List::unify_with(Selector_List_Ptr rhs) {
|
1560
1649
|
std::vector<Complex_Selector_Obj> unified_complex_selectors;
|
1561
1650
|
// Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
|
1562
1651
|
for (size_t lhs_i = 0, lhs_L = length(); lhs_i < lhs_L; ++lhs_i) {
|
1563
1652
|
Complex_Selector_Obj seq1 = (*this)[lhs_i];
|
1564
1653
|
for(size_t rhs_i = 0, rhs_L = rhs->length(); rhs_i < rhs_L; ++rhs_i) {
|
1565
|
-
Complex_Selector_Ptr seq2 =
|
1654
|
+
Complex_Selector_Ptr seq2 = rhs->at(rhs_i);
|
1566
1655
|
|
1567
|
-
Selector_List_Obj result = seq1->unify_with(seq2
|
1656
|
+
Selector_List_Obj result = seq1->unify_with(seq2);
|
1568
1657
|
if( result ) {
|
1569
1658
|
for(size_t i = 0, L = result->length(); i < L; ++i) {
|
1570
|
-
unified_complex_selectors.push_back(
|
1659
|
+
unified_complex_selectors.push_back( (*result)[i] );
|
1571
1660
|
}
|
1572
1661
|
}
|
1573
1662
|
}
|
@@ -1581,7 +1670,7 @@ namespace Sass {
|
|
1581
1670
|
return final_result;
|
1582
1671
|
}
|
1583
1672
|
|
1584
|
-
void Selector_List::populate_extends(Selector_List_Obj extendee,
|
1673
|
+
void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
|
1585
1674
|
{
|
1586
1675
|
|
1587
1676
|
Selector_List_Ptr extender = this;
|
@@ -1594,7 +1683,7 @@ namespace Sass {
|
|
1594
1683
|
Complex_Selector_Obj pIter = complex_sel;
|
1595
1684
|
while (pIter) {
|
1596
1685
|
Compound_Selector_Obj pHead = pIter->head();
|
1597
|
-
if (pHead &&
|
1686
|
+
if (pHead && Cast<Parent_Selector>(pHead->elements()[0]) == NULL) {
|
1598
1687
|
compound_sel = pHead;
|
1599
1688
|
break;
|
1600
1689
|
}
|
@@ -1603,32 +1692,24 @@ namespace Sass {
|
|
1603
1692
|
}
|
1604
1693
|
|
1605
1694
|
if (!pIter->head() || pIter->tail()) {
|
1606
|
-
|
1695
|
+
coreError("nested selectors may not be extended", c->pstate());
|
1607
1696
|
}
|
1608
1697
|
|
1609
1698
|
compound_sel->is_optional(extendee->is_optional());
|
1610
1699
|
|
1611
1700
|
for (size_t i = 0, L = extender->length(); i < L; ++i) {
|
1612
|
-
extends.put(compound_sel, std::make_pair(
|
1701
|
+
extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
|
1613
1702
|
}
|
1614
1703
|
}
|
1615
1704
|
};
|
1616
1705
|
|
1617
|
-
std::vector<std::string> Compound_Selector::to_str_vec()
|
1618
|
-
{
|
1619
|
-
std::vector<std::string> result(length());
|
1620
|
-
for (size_t i = 0, L = length(); i < L; ++i)
|
1621
|
-
{ result.push_back((*this)[i]->to_string()); }
|
1622
|
-
return result;
|
1623
|
-
}
|
1624
|
-
|
1625
1706
|
void Compound_Selector::append(Simple_Selector_Ptr element)
|
1626
1707
|
{
|
1627
1708
|
Vectorized<Simple_Selector_Obj>::append(element);
|
1628
1709
|
pstate_.offset += element->pstate().offset;
|
1629
1710
|
}
|
1630
1711
|
|
1631
|
-
Compound_Selector_Ptr Compound_Selector::minus(Compound_Selector_Ptr rhs
|
1712
|
+
Compound_Selector_Ptr Compound_Selector::minus(Compound_Selector_Ptr rhs)
|
1632
1713
|
{
|
1633
1714
|
Compound_Selector_Ptr result = SASS_MEMORY_NEW(Compound_Selector, pstate());
|
1634
1715
|
// result->has_parent_reference(has_parent_reference());
|
@@ -1637,24 +1718,24 @@ namespace Sass {
|
|
1637
1718
|
for (size_t i = 0, L = length(); i < L; ++i)
|
1638
1719
|
{
|
1639
1720
|
bool found = false;
|
1640
|
-
std::string thisSelector((*this)[i]->to_string(
|
1721
|
+
std::string thisSelector((*this)[i]->to_string());
|
1641
1722
|
for (size_t j = 0, M = rhs->length(); j < M; ++j)
|
1642
1723
|
{
|
1643
|
-
if (thisSelector == (*rhs)[j]->to_string(
|
1724
|
+
if (thisSelector == (*rhs)[j]->to_string())
|
1644
1725
|
{
|
1645
1726
|
found = true;
|
1646
1727
|
break;
|
1647
1728
|
}
|
1648
1729
|
}
|
1649
|
-
if (!found) result->append(
|
1730
|
+
if (!found) result->append((*this)[i]);
|
1650
1731
|
}
|
1651
1732
|
|
1652
1733
|
return result;
|
1653
1734
|
}
|
1654
1735
|
|
1655
|
-
void Compound_Selector::mergeSources(
|
1736
|
+
void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
|
1656
1737
|
{
|
1657
|
-
for (
|
1738
|
+
for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
|
1658
1739
|
this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
|
1659
1740
|
}
|
1660
1741
|
}
|
@@ -1686,38 +1767,38 @@ namespace Sass {
|
|
1686
1767
|
void Arguments::adjust_after_pushing(Argument_Obj a)
|
1687
1768
|
{
|
1688
1769
|
if (!a->name().empty()) {
|
1689
|
-
if (
|
1690
|
-
|
1770
|
+
if (has_keyword_argument()) {
|
1771
|
+
coreError("named arguments must precede variable-length argument", a->pstate());
|
1691
1772
|
}
|
1692
|
-
|
1773
|
+
has_named_arguments(true);
|
1693
1774
|
}
|
1694
1775
|
else if (a->is_rest_argument()) {
|
1695
|
-
if (
|
1696
|
-
|
1776
|
+
if (has_rest_argument()) {
|
1777
|
+
coreError("functions and mixins may only be called with one variable-length argument", a->pstate());
|
1697
1778
|
}
|
1698
1779
|
if (has_keyword_argument_) {
|
1699
|
-
|
1780
|
+
coreError("only keyword arguments may follow variable arguments", a->pstate());
|
1700
1781
|
}
|
1701
|
-
|
1782
|
+
has_rest_argument(true);
|
1702
1783
|
}
|
1703
1784
|
else if (a->is_keyword_argument()) {
|
1704
|
-
if (
|
1705
|
-
|
1785
|
+
if (has_keyword_argument()) {
|
1786
|
+
coreError("functions and mixins may only be called with one keyword argument", a->pstate());
|
1706
1787
|
}
|
1707
|
-
|
1788
|
+
has_keyword_argument(true);
|
1708
1789
|
}
|
1709
1790
|
else {
|
1710
|
-
if (
|
1711
|
-
|
1791
|
+
if (has_rest_argument()) {
|
1792
|
+
coreError("ordinal arguments must precede variable-length arguments", a->pstate());
|
1712
1793
|
}
|
1713
|
-
if (
|
1714
|
-
|
1794
|
+
if (has_named_arguments()) {
|
1795
|
+
coreError("ordinal arguments must precede named arguments", a->pstate());
|
1715
1796
|
}
|
1716
1797
|
}
|
1717
1798
|
}
|
1718
1799
|
|
1719
1800
|
bool Ruleset::is_invisible() const {
|
1720
|
-
if (Selector_List_Ptr sl =
|
1801
|
+
if (Selector_List_Ptr sl = Cast<Selector_List>(selector())) {
|
1721
1802
|
for (size_t i = 0, L = sl->length(); i < L; ++i)
|
1722
1803
|
if (!(*sl)[i]->has_placeholder()) return false;
|
1723
1804
|
}
|
@@ -1734,367 +1815,52 @@ namespace Sass {
|
|
1734
1815
|
|
1735
1816
|
Number::Number(ParserState pstate, double val, std::string u, bool zero)
|
1736
1817
|
: Value(pstate),
|
1818
|
+
Units(),
|
1737
1819
|
value_(val),
|
1738
1820
|
zero_(zero),
|
1739
|
-
numerator_units_(std::vector<std::string>()),
|
1740
|
-
denominator_units_(std::vector<std::string>()),
|
1741
1821
|
hash_(0)
|
1742
1822
|
{
|
1743
|
-
size_t l = 0
|
1823
|
+
size_t l = 0;
|
1824
|
+
size_t r;
|
1744
1825
|
if (!u.empty()) {
|
1745
1826
|
bool nominator = true;
|
1746
1827
|
while (true) {
|
1747
1828
|
r = u.find_first_of("*/", l);
|
1748
1829
|
std::string unit(u.substr(l, r == std::string::npos ? r : r - l));
|
1749
1830
|
if (!unit.empty()) {
|
1750
|
-
if (nominator)
|
1751
|
-
else
|
1831
|
+
if (nominator) numerators.push_back(unit);
|
1832
|
+
else denominators.push_back(unit);
|
1752
1833
|
}
|
1753
1834
|
if (r == std::string::npos) break;
|
1754
1835
|
// ToDo: should error for multiple slashes
|
1755
1836
|
// if (!nominator && u[r] == '/') error(...)
|
1756
1837
|
if (u[r] == '/')
|
1757
1838
|
nominator = false;
|
1839
|
+
// strange math parsing?
|
1840
|
+
// else if (u[r] == '*')
|
1841
|
+
// nominator = true;
|
1758
1842
|
l = r + 1;
|
1759
1843
|
}
|
1760
1844
|
}
|
1761
1845
|
concrete_type(NUMBER);
|
1762
1846
|
}
|
1763
1847
|
|
1764
|
-
|
1765
|
-
|
1766
|
-
std::string u;
|
1767
|
-
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
|
1768
|
-
if (i) u += '*';
|
1769
|
-
u += numerator_units_[i];
|
1770
|
-
}
|
1771
|
-
if (!denominator_units_.empty()) u += '/';
|
1772
|
-
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
|
1773
|
-
if (i) u += '*';
|
1774
|
-
u += denominator_units_[i];
|
1775
|
-
}
|
1776
|
-
return u;
|
1777
|
-
}
|
1778
|
-
|
1779
|
-
bool Number::is_valid_css_unit() const
|
1848
|
+
// cancel out unnecessary units
|
1849
|
+
void Number::reduce()
|
1780
1850
|
{
|
1781
|
-
|
1782
|
-
|
1851
|
+
// apply conversion factor
|
1852
|
+
value_ *= this->Units::reduce();
|
1783
1853
|
}
|
1784
1854
|
|
1785
|
-
|
1786
|
-
{ return numerator_units_.empty() && denominator_units_.empty(); }
|
1787
|
-
|
1788
|
-
void Number::normalize(const std::string& prefered, bool strict)
|
1855
|
+
void Number::normalize()
|
1789
1856
|
{
|
1790
|
-
|
1791
|
-
|
1792
|
-
// it seems that a map table will fit nicely to do this
|
1793
|
-
// we basically construct exponents for each unit
|
1794
|
-
// has the advantage that they will be pre-sorted
|
1795
|
-
std::map<std::string, int> exponents;
|
1796
|
-
|
1797
|
-
// initialize by summing up occurences in unit vectors
|
1798
|
-
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
|
1799
|
-
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
|
1800
|
-
|
1801
|
-
// the final conversion factor
|
1802
|
-
double factor = 1;
|
1803
|
-
|
1804
|
-
// get the first entry of numerators
|
1805
|
-
// forward it when entry is converted
|
1806
|
-
std::vector<std::string>::iterator nom_it = numerator_units_.begin();
|
1807
|
-
std::vector<std::string>::iterator nom_end = numerator_units_.end();
|
1808
|
-
std::vector<std::string>::iterator denom_it = denominator_units_.begin();
|
1809
|
-
std::vector<std::string>::iterator denom_end = denominator_units_.end();
|
1810
|
-
|
1811
|
-
// main normalization loop
|
1812
|
-
// should be close to optimal
|
1813
|
-
while (denom_it != denom_end)
|
1814
|
-
{
|
1815
|
-
// get and increment afterwards
|
1816
|
-
const std::string denom = *(denom_it ++);
|
1817
|
-
// skip already canceled out unit
|
1818
|
-
if (exponents[denom] >= 0) continue;
|
1819
|
-
// skip all units we don't know how to convert
|
1820
|
-
if (string_to_unit(denom) == UNKNOWN) continue;
|
1821
|
-
// now search for nominator
|
1822
|
-
while (nom_it != nom_end)
|
1823
|
-
{
|
1824
|
-
// get and increment afterwards
|
1825
|
-
const std::string nom = *(nom_it ++);
|
1826
|
-
// skip already canceled out unit
|
1827
|
-
if (exponents[nom] <= 0) continue;
|
1828
|
-
// skip all units we don't know how to convert
|
1829
|
-
if (string_to_unit(nom) == UNKNOWN) continue;
|
1830
|
-
// we now have two convertable units
|
1831
|
-
// add factor for current conversion
|
1832
|
-
factor *= conversion_factor(nom, denom, strict);
|
1833
|
-
// update nominator/denominator exponent
|
1834
|
-
-- exponents[nom]; ++ exponents[denom];
|
1835
|
-
// inner loop done
|
1836
|
-
break;
|
1837
|
-
}
|
1838
|
-
}
|
1839
|
-
|
1840
|
-
// now we can build up the new unit arrays
|
1841
|
-
numerator_units_.clear();
|
1842
|
-
denominator_units_.clear();
|
1843
|
-
|
1844
|
-
// build them by iterating over the exponents
|
1845
|
-
for (auto exp : exponents)
|
1846
|
-
{
|
1847
|
-
// maybe there is more effecient way to push
|
1848
|
-
// the same item multiple times to a vector?
|
1849
|
-
for(size_t i = 0, S = abs(exp.second); i < S; ++i)
|
1850
|
-
{
|
1851
|
-
// opted to have these switches in the inner loop
|
1852
|
-
// makes it more readable and should not cost much
|
1853
|
-
if (!exp.first.empty()) {
|
1854
|
-
if (exp.second < 0) denominator_units_.push_back(exp.first);
|
1855
|
-
else if (exp.second > 0) numerator_units_.push_back(exp.first);
|
1856
|
-
}
|
1857
|
-
}
|
1858
|
-
}
|
1859
|
-
|
1860
|
-
// apply factor to value_
|
1861
|
-
// best precision this way
|
1862
|
-
value_ *= factor;
|
1863
|
-
|
1864
|
-
// maybe convert to other unit
|
1865
|
-
// easier implemented on its own
|
1866
|
-
try { convert(prefered, strict); }
|
1867
|
-
catch (incompatibleUnits& err)
|
1868
|
-
{ error(err.what(), pstate()); }
|
1869
|
-
catch (...) { throw; }
|
1870
|
-
|
1871
|
-
}
|
1872
|
-
|
1873
|
-
// this does not cover all cases (multiple prefered units)
|
1874
|
-
double Number::convert_factor(const Number& n) const
|
1875
|
-
{
|
1876
|
-
|
1877
|
-
// first make sure same units cancel each other out
|
1878
|
-
// it seems that a map table will fit nicely to do this
|
1879
|
-
// we basically construct exponents for each unit class
|
1880
|
-
// std::map<std::string, int> exponents;
|
1881
|
-
// initialize by summing up occurences in unit vectors
|
1882
|
-
// for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[unit_to_class(numerator_units_[i])];
|
1883
|
-
// for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[unit_to_class(denominator_units_[i])];
|
1884
|
-
|
1885
|
-
std::vector<std::string> l_miss_nums(0);
|
1886
|
-
std::vector<std::string> l_miss_dens(0);
|
1887
|
-
// create copy since we need these for state keeping
|
1888
|
-
std::vector<std::string> r_nums(n.numerator_units_);
|
1889
|
-
std::vector<std::string> r_dens(n.denominator_units_);
|
1890
|
-
|
1891
|
-
std::vector<std::string>::const_iterator l_num_it = numerator_units_.begin();
|
1892
|
-
std::vector<std::string>::const_iterator l_num_end = numerator_units_.end();
|
1893
|
-
|
1894
|
-
bool l_unitless = is_unitless();
|
1895
|
-
bool r_unitless = n.is_unitless();
|
1896
|
-
|
1897
|
-
// overall conversion
|
1898
|
-
double factor = 1;
|
1899
|
-
|
1900
|
-
// process all left numerators
|
1901
|
-
while (l_num_it != l_num_end)
|
1902
|
-
{
|
1903
|
-
// get and increment afterwards
|
1904
|
-
const std::string l_num = *(l_num_it ++);
|
1905
|
-
|
1906
|
-
std::vector<std::string>::iterator r_num_it = r_nums.begin();
|
1907
|
-
std::vector<std::string>::iterator r_num_end = r_nums.end();
|
1908
|
-
|
1909
|
-
bool found = false;
|
1910
|
-
// search for compatible numerator
|
1911
|
-
while (r_num_it != r_num_end)
|
1912
|
-
{
|
1913
|
-
// get and increment afterwards
|
1914
|
-
const std::string r_num = *(r_num_it);
|
1915
|
-
// get possible converstion factor for units
|
1916
|
-
double conversion = conversion_factor(l_num, r_num, false);
|
1917
|
-
// skip incompatible numerator
|
1918
|
-
if (conversion == 0) {
|
1919
|
-
++ r_num_it;
|
1920
|
-
continue;
|
1921
|
-
}
|
1922
|
-
// apply to global factor
|
1923
|
-
factor *= conversion;
|
1924
|
-
// remove item from vector
|
1925
|
-
r_nums.erase(r_num_it);
|
1926
|
-
// found numerator
|
1927
|
-
found = true;
|
1928
|
-
break;
|
1929
|
-
}
|
1930
|
-
// maybe we did not find any
|
1931
|
-
// left numerator is leftover
|
1932
|
-
if (!found) l_miss_nums.push_back(l_num);
|
1933
|
-
}
|
1934
|
-
|
1935
|
-
std::vector<std::string>::const_iterator l_den_it = denominator_units_.begin();
|
1936
|
-
std::vector<std::string>::const_iterator l_den_end = denominator_units_.end();
|
1937
|
-
|
1938
|
-
// process all left denominators
|
1939
|
-
while (l_den_it != l_den_end)
|
1940
|
-
{
|
1941
|
-
// get and increment afterwards
|
1942
|
-
const std::string l_den = *(l_den_it ++);
|
1943
|
-
|
1944
|
-
std::vector<std::string>::iterator r_den_it = r_dens.begin();
|
1945
|
-
std::vector<std::string>::iterator r_den_end = r_dens.end();
|
1946
|
-
|
1947
|
-
bool found = false;
|
1948
|
-
// search for compatible denominator
|
1949
|
-
while (r_den_it != r_den_end)
|
1950
|
-
{
|
1951
|
-
// get and increment afterwards
|
1952
|
-
const std::string r_den = *(r_den_it);
|
1953
|
-
// get possible converstion factor for units
|
1954
|
-
double conversion = conversion_factor(l_den, r_den, false);
|
1955
|
-
// skip incompatible denominator
|
1956
|
-
if (conversion == 0) {
|
1957
|
-
++ r_den_it;
|
1958
|
-
continue;
|
1959
|
-
}
|
1960
|
-
// apply to global factor
|
1961
|
-
factor *= conversion;
|
1962
|
-
// remove item from vector
|
1963
|
-
r_dens.erase(r_den_it);
|
1964
|
-
// found denominator
|
1965
|
-
found = true;
|
1966
|
-
break;
|
1967
|
-
}
|
1968
|
-
// maybe we did not find any
|
1969
|
-
// left denominator is leftover
|
1970
|
-
if (!found) l_miss_dens.push_back(l_den);
|
1971
|
-
}
|
1972
|
-
|
1973
|
-
// check left-overs (ToDo: might cancel out)
|
1974
|
-
if (l_miss_nums.size() > 0 && !r_unitless) {
|
1975
|
-
throw Exception::IncompatibleUnits(n, *this);
|
1976
|
-
}
|
1977
|
-
if (l_miss_dens.size() > 0 && !r_unitless) {
|
1978
|
-
throw Exception::IncompatibleUnits(n, *this);
|
1979
|
-
}
|
1980
|
-
if (r_nums.size() > 0 && !l_unitless) {
|
1981
|
-
throw Exception::IncompatibleUnits(n, *this);
|
1982
|
-
}
|
1983
|
-
if (r_dens.size() > 0 && !l_unitless) {
|
1984
|
-
throw Exception::IncompatibleUnits(n, *this);
|
1985
|
-
}
|
1986
|
-
|
1987
|
-
return factor;
|
1988
|
-
}
|
1989
|
-
|
1990
|
-
// this does not cover all cases (multiple prefered units)
|
1991
|
-
bool Number::convert(const std::string& prefered, bool strict)
|
1992
|
-
{
|
1993
|
-
// no conversion if unit is empty
|
1994
|
-
if (prefered.empty()) return true;
|
1995
|
-
|
1996
|
-
// first make sure same units cancel each other out
|
1997
|
-
// it seems that a map table will fit nicely to do this
|
1998
|
-
// we basically construct exponents for each unit
|
1999
|
-
// has the advantage that they will be pre-sorted
|
2000
|
-
std::map<std::string, int> exponents;
|
2001
|
-
|
2002
|
-
// initialize by summing up occurences in unit vectors
|
2003
|
-
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
|
2004
|
-
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
|
2005
|
-
|
2006
|
-
// the final conversion factor
|
2007
|
-
double factor = 1;
|
2008
|
-
|
2009
|
-
std::vector<std::string>::iterator denom_it = denominator_units_.begin();
|
2010
|
-
std::vector<std::string>::iterator denom_end = denominator_units_.end();
|
2011
|
-
|
2012
|
-
// main normalization loop
|
2013
|
-
// should be close to optimal
|
2014
|
-
while (denom_it != denom_end)
|
2015
|
-
{
|
2016
|
-
// get and increment afterwards
|
2017
|
-
const std::string denom = *(denom_it ++);
|
2018
|
-
// check if conversion is needed
|
2019
|
-
if (denom == prefered) continue;
|
2020
|
-
// skip already canceled out unit
|
2021
|
-
if (exponents[denom] >= 0) continue;
|
2022
|
-
// skip all units we don't know how to convert
|
2023
|
-
if (string_to_unit(denom) == UNKNOWN) continue;
|
2024
|
-
// we now have two convertable units
|
2025
|
-
// add factor for current conversion
|
2026
|
-
factor *= conversion_factor(denom, prefered, strict);
|
2027
|
-
// update nominator/denominator exponent
|
2028
|
-
++ exponents[denom]; -- exponents[prefered];
|
2029
|
-
}
|
2030
|
-
|
2031
|
-
std::vector<std::string>::iterator nom_it = numerator_units_.begin();
|
2032
|
-
std::vector<std::string>::iterator nom_end = numerator_units_.end();
|
2033
|
-
|
2034
|
-
// now search for nominator
|
2035
|
-
while (nom_it != nom_end)
|
2036
|
-
{
|
2037
|
-
// get and increment afterwards
|
2038
|
-
const std::string nom = *(nom_it ++);
|
2039
|
-
// check if conversion is needed
|
2040
|
-
if (nom == prefered) continue;
|
2041
|
-
// skip already canceled out unit
|
2042
|
-
if (exponents[nom] <= 0) continue;
|
2043
|
-
// skip all units we don't know how to convert
|
2044
|
-
if (string_to_unit(nom) == UNKNOWN) continue;
|
2045
|
-
// we now have two convertable units
|
2046
|
-
// add factor for current conversion
|
2047
|
-
factor *= conversion_factor(nom, prefered, strict);
|
2048
|
-
// update nominator/denominator exponent
|
2049
|
-
-- exponents[nom]; ++ exponents[prefered];
|
2050
|
-
}
|
2051
|
-
|
2052
|
-
// now we can build up the new unit arrays
|
2053
|
-
numerator_units_.clear();
|
2054
|
-
denominator_units_.clear();
|
2055
|
-
|
2056
|
-
// build them by iterating over the exponents
|
2057
|
-
for (auto exp : exponents)
|
2058
|
-
{
|
2059
|
-
// maybe there is more effecient way to push
|
2060
|
-
// the same item multiple times to a vector?
|
2061
|
-
for(size_t i = 0, S = abs(exp.second); i < S; ++i)
|
2062
|
-
{
|
2063
|
-
// opted to have these switches in the inner loop
|
2064
|
-
// makes it more readable and should not cost much
|
2065
|
-
if (!exp.first.empty()) {
|
2066
|
-
if (exp.second < 0) denominator_units_.push_back(exp.first);
|
2067
|
-
else if (exp.second > 0) numerator_units_.push_back(exp.first);
|
2068
|
-
}
|
2069
|
-
}
|
2070
|
-
}
|
2071
|
-
|
2072
|
-
// apply factor to value_
|
2073
|
-
// best precision this way
|
2074
|
-
value_ *= factor;
|
2075
|
-
|
2076
|
-
// success?
|
2077
|
-
return true;
|
2078
|
-
|
2079
|
-
}
|
2080
|
-
|
2081
|
-
// useful for making one number compatible with another
|
2082
|
-
std::string Number::find_convertible_unit() const
|
2083
|
-
{
|
2084
|
-
for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
|
2085
|
-
std::string u(numerator_units_[i]);
|
2086
|
-
if (string_to_unit(u) != UNKNOWN) return u;
|
2087
|
-
}
|
2088
|
-
for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
|
2089
|
-
std::string u(denominator_units_[i]);
|
2090
|
-
if (string_to_unit(u) != UNKNOWN) return u;
|
2091
|
-
}
|
2092
|
-
return std::string();
|
1857
|
+
// apply conversion factor
|
1858
|
+
value_ *= this->Units::normalize();
|
2093
1859
|
}
|
2094
1860
|
|
2095
1861
|
bool Custom_Warning::operator== (const Expression& rhs) const
|
2096
1862
|
{
|
2097
|
-
if (Custom_Warning_Ptr_Const r =
|
1863
|
+
if (Custom_Warning_Ptr_Const r = Cast<Custom_Warning>(&rhs)) {
|
2098
1864
|
return message() == r->message();
|
2099
1865
|
}
|
2100
1866
|
return false;
|
@@ -2102,67 +1868,59 @@ namespace Sass {
|
|
2102
1868
|
|
2103
1869
|
bool Custom_Error::operator== (const Expression& rhs) const
|
2104
1870
|
{
|
2105
|
-
if (Custom_Error_Ptr_Const r =
|
1871
|
+
if (Custom_Error_Ptr_Const r = Cast<Custom_Error>(&rhs)) {
|
2106
1872
|
return message() == r->message();
|
2107
1873
|
}
|
2108
1874
|
return false;
|
2109
1875
|
}
|
2110
1876
|
|
2111
|
-
bool Number::
|
1877
|
+
bool Number::operator== (const Expression& rhs) const
|
2112
1878
|
{
|
2113
|
-
if (
|
2114
|
-
|
2115
|
-
size_t rhs_units = r->numerator_units_.size() + r->denominator_units_.size();
|
2116
|
-
if (!lhs_units && !rhs_units) {
|
2117
|
-
return std::fabs(value() - r->value()) < NUMBER_EPSILON;
|
2118
|
-
}
|
2119
|
-
return (numerator_units_ == r->numerator_units_) &&
|
2120
|
-
(denominator_units_ == r->denominator_units_) &&
|
2121
|
-
std::fabs(value() - r->value()) < NUMBER_EPSILON;
|
1879
|
+
if (auto rhsnr = Cast<Number>(&rhs)) {
|
1880
|
+
return *this == *rhsnr;
|
2122
1881
|
}
|
2123
1882
|
return false;
|
2124
1883
|
}
|
2125
1884
|
|
2126
|
-
bool Number::operator== (const
|
1885
|
+
bool Number::operator== (const Number& rhs) const
|
2127
1886
|
{
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
}
|
2135
|
-
return (numerator_units_ == r->numerator_units_) &&
|
2136
|
-
(denominator_units_ == r->denominator_units_) &&
|
2137
|
-
std::fabs(value() - r->value()) < NUMBER_EPSILON;
|
1887
|
+
Number l(*this), r(rhs); l.reduce(); r.reduce();
|
1888
|
+
size_t lhs_units = l.numerators.size() + l.denominators.size();
|
1889
|
+
size_t rhs_units = r.numerators.size() + r.denominators.size();
|
1890
|
+
// unitless and only having one unit seems equivalent (will change in future)
|
1891
|
+
if (!lhs_units || !rhs_units) {
|
1892
|
+
return NEAR_EQUAL(l.value(), r.value());
|
2138
1893
|
}
|
2139
|
-
|
1894
|
+
l.normalize(); r.normalize();
|
1895
|
+
Units &lhs_unit = l, &rhs_unit = r;
|
1896
|
+
return lhs_unit == rhs_unit &&
|
1897
|
+
NEAR_EQUAL(l.value(), r.value());
|
2140
1898
|
}
|
2141
1899
|
|
2142
1900
|
bool Number::operator< (const Number& rhs) const
|
2143
1901
|
{
|
2144
|
-
|
2145
|
-
size_t
|
1902
|
+
Number l(*this), r(rhs); l.reduce(); r.reduce();
|
1903
|
+
size_t lhs_units = l.numerators.size() + l.denominators.size();
|
1904
|
+
size_t rhs_units = r.numerators.size() + r.denominators.size();
|
2146
1905
|
// unitless and only having one unit seems equivalent (will change in future)
|
2147
1906
|
if (!lhs_units || !rhs_units) {
|
2148
|
-
return value() <
|
1907
|
+
return l.value() < r.value();
|
2149
1908
|
}
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
if (unit() != tmp_r.unit()) {
|
2156
|
-
error("cannot compare numbers with incompatible units", pstate());
|
1909
|
+
l.normalize(); r.normalize();
|
1910
|
+
Units &lhs_unit = l, &rhs_unit = r;
|
1911
|
+
if (!(lhs_unit == rhs_unit)) {
|
1912
|
+
/* ToDo: do we always get usefull backtraces? */
|
1913
|
+
throw Exception::IncompatibleUnits(rhs, *this);
|
2157
1914
|
}
|
2158
|
-
return
|
1915
|
+
return lhs_unit < rhs_unit ||
|
1916
|
+
l.value() < r.value();
|
2159
1917
|
}
|
2160
1918
|
|
2161
1919
|
bool String_Quoted::operator== (const Expression& rhs) const
|
2162
1920
|
{
|
2163
|
-
if (String_Quoted_Ptr_Const qstr =
|
1921
|
+
if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
|
2164
1922
|
return (value() == qstr->value());
|
2165
|
-
} else if (String_Constant_Ptr_Const cstr =
|
1923
|
+
} else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
|
2166
1924
|
return (value() == cstr->value());
|
2167
1925
|
}
|
2168
1926
|
return false;
|
@@ -2174,9 +1932,9 @@ namespace Sass {
|
|
2174
1932
|
|
2175
1933
|
bool String_Constant::operator== (const Expression& rhs) const
|
2176
1934
|
{
|
2177
|
-
if (String_Quoted_Ptr_Const qstr =
|
1935
|
+
if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(&rhs)) {
|
2178
1936
|
return (value() == qstr->value());
|
2179
|
-
} else if (String_Constant_Ptr_Const cstr =
|
1937
|
+
} else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(&rhs)) {
|
2180
1938
|
return (value() == cstr->value());
|
2181
1939
|
}
|
2182
1940
|
return false;
|
@@ -2193,7 +1951,7 @@ namespace Sass {
|
|
2193
1951
|
|
2194
1952
|
bool String_Schema::operator== (const Expression& rhs) const
|
2195
1953
|
{
|
2196
|
-
if (String_Schema_Ptr_Const r =
|
1954
|
+
if (String_Schema_Ptr_Const r = Cast<String_Schema>(&rhs)) {
|
2197
1955
|
if (length() != r->length()) return false;
|
2198
1956
|
for (size_t i = 0, L = length(); i < L; ++i) {
|
2199
1957
|
Expression_Obj rv = (*r)[i];
|
@@ -2208,7 +1966,7 @@ namespace Sass {
|
|
2208
1966
|
|
2209
1967
|
bool Boolean::operator== (const Expression& rhs) const
|
2210
1968
|
{
|
2211
|
-
if (Boolean_Ptr_Const r =
|
1969
|
+
if (Boolean_Ptr_Const r = Cast<Boolean>(&rhs)) {
|
2212
1970
|
return (value() == r->value());
|
2213
1971
|
}
|
2214
1972
|
return false;
|
@@ -2216,7 +1974,7 @@ namespace Sass {
|
|
2216
1974
|
|
2217
1975
|
bool Color::operator== (const Expression& rhs) const
|
2218
1976
|
{
|
2219
|
-
if (Color_Ptr_Const r =
|
1977
|
+
if (Color_Ptr_Const r = Cast<Color>(&rhs)) {
|
2220
1978
|
return r_ == r->r() &&
|
2221
1979
|
g_ == r->g() &&
|
2222
1980
|
b_ == r->b() &&
|
@@ -2227,9 +1985,10 @@ namespace Sass {
|
|
2227
1985
|
|
2228
1986
|
bool List::operator== (const Expression& rhs) const
|
2229
1987
|
{
|
2230
|
-
if (List_Ptr_Const r =
|
1988
|
+
if (List_Ptr_Const r = Cast<List>(&rhs)) {
|
2231
1989
|
if (length() != r->length()) return false;
|
2232
1990
|
if (separator() != r->separator()) return false;
|
1991
|
+
if (is_bracketed() != r->is_bracketed()) return false;
|
2233
1992
|
for (size_t i = 0, L = length(); i < L; ++i) {
|
2234
1993
|
Expression_Obj rv = r->at(i);
|
2235
1994
|
Expression_Obj lv = this->at(i);
|
@@ -2243,7 +2002,7 @@ namespace Sass {
|
|
2243
2002
|
|
2244
2003
|
bool Map::operator== (const Expression& rhs) const
|
2245
2004
|
{
|
2246
|
-
if (Map_Ptr_Const r =
|
2005
|
+
if (Map_Ptr_Const r = Cast<Map>(&rhs)) {
|
2247
2006
|
if (length() != r->length()) return false;
|
2248
2007
|
for (auto key : keys()) {
|
2249
2008
|
Expression_Obj lv = at(key);
|
@@ -2261,13 +2020,23 @@ namespace Sass {
|
|
2261
2020
|
return rhs.concrete_type() == NULL_VAL;
|
2262
2021
|
}
|
2263
2022
|
|
2023
|
+
bool Function::operator== (const Expression& rhs) const
|
2024
|
+
{
|
2025
|
+
if (Function_Ptr_Const r = Cast<Function>(&rhs)) {
|
2026
|
+
Definition_Ptr_Const d1 = Cast<Definition>(definition());
|
2027
|
+
Definition_Ptr_Const d2 = Cast<Definition>(r->definition());
|
2028
|
+
return d1 && d2 && d1 == d2 && is_css() == r->is_css();
|
2029
|
+
}
|
2030
|
+
return false;
|
2031
|
+
}
|
2032
|
+
|
2264
2033
|
size_t List::size() const {
|
2265
2034
|
if (!is_arglist_) return length();
|
2266
2035
|
// arglist expects a list of arguments
|
2267
2036
|
// so we need to break before keywords
|
2268
2037
|
for (size_t i = 0, L = length(); i < L; ++i) {
|
2269
2038
|
Expression_Obj obj = this->at(i);
|
2270
|
-
if (
|
2039
|
+
if (Argument_Ptr arg = Cast<Argument>(obj)) {
|
2271
2040
|
if (!arg->name().empty()) return i;
|
2272
2041
|
}
|
2273
2042
|
}
|
@@ -2290,7 +2059,7 @@ namespace Sass {
|
|
2290
2059
|
return is_interpolant() || (right() && right()->is_right_interpolant());
|
2291
2060
|
}
|
2292
2061
|
|
2293
|
-
std::string AST_Node::to_string(Sass_Inspect_Options opt) const
|
2062
|
+
const std::string AST_Node::to_string(Sass_Inspect_Options opt) const
|
2294
2063
|
{
|
2295
2064
|
Sass_Output_Options out(opt);
|
2296
2065
|
Emitter emitter(out);
|
@@ -2301,7 +2070,7 @@ namespace Sass {
|
|
2301
2070
|
return i.get_buffer();
|
2302
2071
|
}
|
2303
2072
|
|
2304
|
-
std::string AST_Node::to_string() const
|
2073
|
+
const std::string AST_Node::to_string() const
|
2305
2074
|
{
|
2306
2075
|
return to_string({ NESTED, 5 });
|
2307
2076
|
}
|
@@ -2316,33 +2085,40 @@ namespace Sass {
|
|
2316
2085
|
return quote(value_, '*');
|
2317
2086
|
}
|
2318
2087
|
|
2088
|
+
bool Declaration::is_invisible() const
|
2089
|
+
{
|
2090
|
+
if (is_custom_property()) return false;
|
2091
|
+
|
2092
|
+
return !(value_ && value_->concrete_type() != Expression::NULL_VAL);
|
2093
|
+
}
|
2094
|
+
|
2319
2095
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2320
2096
|
// Additional method on Lists to retrieve values directly or from an encompassed Argument.
|
2321
2097
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2322
2098
|
Expression_Obj List::value_at_index(size_t i) {
|
2323
2099
|
Expression_Obj obj = this->at(i);
|
2324
2100
|
if (is_arglist_) {
|
2325
|
-
if (
|
2101
|
+
if (Argument_Ptr arg = Cast<Argument>(obj)) {
|
2326
2102
|
return arg->value();
|
2327
2103
|
} else {
|
2328
|
-
return
|
2104
|
+
return obj;
|
2329
2105
|
}
|
2330
2106
|
} else {
|
2331
|
-
return
|
2107
|
+
return obj;
|
2332
2108
|
}
|
2333
2109
|
}
|
2334
2110
|
|
2335
2111
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2336
2112
|
// Convert map to (key, value) list.
|
2337
2113
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2338
|
-
List_Obj Map::to_list(
|
2114
|
+
List_Obj Map::to_list(ParserState& pstate) {
|
2339
2115
|
List_Obj ret = SASS_MEMORY_NEW(List, pstate, length(), SASS_COMMA);
|
2340
2116
|
|
2341
2117
|
for (auto key : keys()) {
|
2342
2118
|
List_Obj l = SASS_MEMORY_NEW(List, pstate, 2);
|
2343
|
-
l->append(
|
2119
|
+
l->append(key);
|
2344
2120
|
l->append(at(key));
|
2345
|
-
ret->append(
|
2121
|
+
ret->append(l);
|
2346
2122
|
}
|
2347
2123
|
|
2348
2124
|
return ret;
|
@@ -2396,6 +2172,7 @@ namespace Sass {
|
|
2396
2172
|
IMPLEMENT_AST_OPERATORS(Custom_Error);
|
2397
2173
|
IMPLEMENT_AST_OPERATORS(List);
|
2398
2174
|
IMPLEMENT_AST_OPERATORS(Map);
|
2175
|
+
IMPLEMENT_AST_OPERATORS(Function);
|
2399
2176
|
IMPLEMENT_AST_OPERATORS(Number);
|
2400
2177
|
IMPLEMENT_AST_OPERATORS(Binary_Expression);
|
2401
2178
|
IMPLEMENT_AST_OPERATORS(String_Schema);
|
@@ -2439,7 +2216,6 @@ namespace Sass {
|
|
2439
2216
|
IMPLEMENT_AST_OPERATORS(Function_Call_Schema);
|
2440
2217
|
IMPLEMENT_AST_OPERATORS(Block);
|
2441
2218
|
IMPLEMENT_AST_OPERATORS(Content);
|
2442
|
-
IMPLEMENT_AST_OPERATORS(Textual);
|
2443
2219
|
IMPLEMENT_AST_OPERATORS(Trace);
|
2444
2220
|
IMPLEMENT_AST_OPERATORS(Keyframe_Rule);
|
2445
2221
|
IMPLEMENT_AST_OPERATORS(Bubble);
|
@@ -2447,5 +2223,4 @@ namespace Sass {
|
|
2447
2223
|
IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
|
2448
2224
|
IMPLEMENT_AST_OPERATORS(Definition);
|
2449
2225
|
IMPLEMENT_AST_OPERATORS(Declaration);
|
2450
|
-
|
2451
2226
|
}
|