sassc 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.gitmodules +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +21 -0
- data/ext/libsass/.editorconfig +15 -0
- data/ext/libsass/.gitattributes +2 -0
- data/ext/libsass/.gitignore +61 -0
- data/ext/libsass/.travis.yml +38 -0
- data/ext/libsass/COPYING +25 -0
- data/ext/libsass/INSTALL +1 -0
- data/ext/libsass/LICENSE +25 -0
- data/ext/libsass/Makefile +223 -0
- data/ext/libsass/Makefile.am +145 -0
- data/ext/libsass/Readme.md +93 -0
- data/ext/libsass/appveyor.yml +76 -0
- data/ext/libsass/ast.cpp +581 -0
- data/ext/libsass/ast.hpp +1949 -0
- data/ext/libsass/ast_def_macros.hpp +16 -0
- data/ext/libsass/ast_factory.hpp +87 -0
- data/ext/libsass/ast_fwd_decl.hpp +72 -0
- data/ext/libsass/b64/cencode.h +32 -0
- data/ext/libsass/b64/encode.h +77 -0
- data/ext/libsass/backtrace.hpp +81 -0
- data/ext/libsass/base64vlq.cpp +43 -0
- data/ext/libsass/base64vlq.hpp +28 -0
- data/ext/libsass/bind.cpp +187 -0
- data/ext/libsass/bind.hpp +18 -0
- data/ext/libsass/cencode.c +102 -0
- data/ext/libsass/color_names.hpp +324 -0
- data/ext/libsass/configure.ac +130 -0
- data/ext/libsass/constants.cpp +144 -0
- data/ext/libsass/constants.hpp +145 -0
- data/ext/libsass/context.cpp +507 -0
- data/ext/libsass/context.hpp +150 -0
- data/ext/libsass/contextualize.cpp +157 -0
- data/ext/libsass/contextualize.hpp +65 -0
- data/ext/libsass/copy_c_str.cpp +13 -0
- data/ext/libsass/copy_c_str.hpp +5 -0
- data/ext/libsass/debug.hpp +39 -0
- data/ext/libsass/environment.hpp +75 -0
- data/ext/libsass/error_handling.cpp +28 -0
- data/ext/libsass/error_handling.hpp +28 -0
- data/ext/libsass/eval.cpp +1149 -0
- data/ext/libsass/eval.hpp +80 -0
- data/ext/libsass/expand.cpp +430 -0
- data/ext/libsass/expand.hpp +77 -0
- data/ext/libsass/extconf.rb +6 -0
- data/ext/libsass/extend.cpp +1962 -0
- data/ext/libsass/extend.hpp +50 -0
- data/ext/libsass/file.cpp +291 -0
- data/ext/libsass/file.hpp +18 -0
- data/ext/libsass/functions.cpp +1565 -0
- data/ext/libsass/functions.hpp +187 -0
- data/ext/libsass/inspect.cpp +727 -0
- data/ext/libsass/inspect.hpp +108 -0
- data/ext/libsass/json.cpp +1411 -0
- data/ext/libsass/json.hpp +117 -0
- data/ext/libsass/kwd_arg_macros.hpp +23 -0
- data/ext/libsass/m4/.gitkeep +0 -0
- data/ext/libsass/mapping.hpp +17 -0
- data/ext/libsass/memory_manager.hpp +54 -0
- data/ext/libsass/node.cpp +251 -0
- data/ext/libsass/node.hpp +122 -0
- data/ext/libsass/operation.hpp +153 -0
- data/ext/libsass/output_compressed.cpp +401 -0
- data/ext/libsass/output_compressed.hpp +95 -0
- data/ext/libsass/output_nested.cpp +364 -0
- data/ext/libsass/output_nested.hpp +108 -0
- data/ext/libsass/parser.cpp +2016 -0
- data/ext/libsass/parser.hpp +264 -0
- data/ext/libsass/paths.hpp +69 -0
- data/ext/libsass/position.hpp +22 -0
- data/ext/libsass/posix/getopt.c +562 -0
- data/ext/libsass/posix/getopt.h +95 -0
- data/ext/libsass/prelexer.cpp +688 -0
- data/ext/libsass/prelexer.hpp +513 -0
- data/ext/libsass/remove_placeholders.cpp +59 -0
- data/ext/libsass/remove_placeholders.hpp +43 -0
- data/ext/libsass/res/resource.rc +35 -0
- data/ext/libsass/sass.cpp +33 -0
- data/ext/libsass/sass.h +60 -0
- data/ext/libsass/sass2scss.cpp +834 -0
- data/ext/libsass/sass2scss.h +110 -0
- data/ext/libsass/sass_context.cpp +709 -0
- data/ext/libsass/sass_context.h +120 -0
- data/ext/libsass/sass_functions.cpp +137 -0
- data/ext/libsass/sass_functions.h +90 -0
- data/ext/libsass/sass_interface.cpp +277 -0
- data/ext/libsass/sass_interface.h +97 -0
- data/ext/libsass/sass_util.cpp +136 -0
- data/ext/libsass/sass_util.hpp +259 -0
- data/ext/libsass/sass_values.cpp +337 -0
- data/ext/libsass/sass_values.h +124 -0
- data/ext/libsass/script/bootstrap +10 -0
- data/ext/libsass/script/branding +10 -0
- data/ext/libsass/script/ci-build-libsass +72 -0
- data/ext/libsass/script/ci-install-compiler +4 -0
- data/ext/libsass/script/ci-install-deps +19 -0
- data/ext/libsass/script/ci-report-coverage +25 -0
- data/ext/libsass/script/coveralls-debug +32 -0
- data/ext/libsass/script/spec +5 -0
- data/ext/libsass/script/tap-driver +652 -0
- data/ext/libsass/script/tap-runner +1 -0
- data/ext/libsass/source_map.cpp +133 -0
- data/ext/libsass/source_map.hpp +46 -0
- data/ext/libsass/subset_map.hpp +145 -0
- data/ext/libsass/support/libsass.pc.in +11 -0
- data/ext/libsass/test-driver +127 -0
- data/ext/libsass/test/test_node.cpp +98 -0
- data/ext/libsass/test/test_paths.cpp +29 -0
- data/ext/libsass/test/test_selector_difference.cpp +28 -0
- data/ext/libsass/test/test_specificity.cpp +28 -0
- data/ext/libsass/test/test_subset_map.cpp +472 -0
- data/ext/libsass/test/test_superselector.cpp +71 -0
- data/ext/libsass/test/test_unification.cpp +33 -0
- data/ext/libsass/to_c.cpp +61 -0
- data/ext/libsass/to_c.hpp +44 -0
- data/ext/libsass/to_string.cpp +29 -0
- data/ext/libsass/to_string.hpp +32 -0
- data/ext/libsass/token.hpp +32 -0
- data/ext/libsass/units.cpp +54 -0
- data/ext/libsass/units.hpp +10 -0
- data/ext/libsass/utf8.h +34 -0
- data/ext/libsass/utf8/checked.h +327 -0
- data/ext/libsass/utf8/core.h +329 -0
- data/ext/libsass/utf8/unchecked.h +228 -0
- data/ext/libsass/utf8_string.cpp +102 -0
- data/ext/libsass/utf8_string.hpp +36 -0
- data/ext/libsass/util.cpp +189 -0
- data/ext/libsass/util.hpp +26 -0
- data/ext/libsass/win/libsass.filters +291 -0
- data/ext/libsass/win/libsass.sln +28 -0
- data/ext/libsass/win/libsass.vcxproj +255 -0
- data/lib/sassc.rb +6 -0
- data/lib/sassc/engine.rb +13 -0
- data/lib/sassc/native.rb +44 -0
- data/lib/sassc/native/native_context_api.rb +140 -0
- data/lib/sassc/native/native_functions_api.rb +41 -0
- data/lib/sassc/native/sass_input_style.rb +11 -0
- data/lib/sassc/native/sass_output_style.rb +10 -0
- data/lib/sassc/native/sass_value.rb +95 -0
- data/lib/sassc/native/string_list.rb +8 -0
- data/lib/sassc/version.rb +3 -0
- data/sassc.gemspec +43 -0
- data/test/smoke_test.rb +171 -0
- data/test/test_helper.rb +4 -0
- metadata +281 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
ACLOCAL_AMFLAGS = -I m4
|
|
2
|
+
|
|
3
|
+
AM_LDFLAGS = -lstdc++ -lm
|
|
4
|
+
AM_CFLAGS = -Wall -fPIC
|
|
5
|
+
AM_CXXFLAGS = -Wall -fPIC
|
|
6
|
+
AM_CFLAGS += -DLIBSASS_VERSION="\"$(LIBSASS_VERSION)\""
|
|
7
|
+
AM_CXXFLAGS += -DLIBSASS_VERSION="\"$(LIBSASS_VERSION)\""
|
|
8
|
+
|
|
9
|
+
AM_CXXFLAGS += -std=c++0x
|
|
10
|
+
|
|
11
|
+
if ENABLE_COVERAGE
|
|
12
|
+
AM_CFLAGS += -O0 --coverage
|
|
13
|
+
AM_CXXFLAGS += -O0 --coverage
|
|
14
|
+
AM_LDFLAGS += -O0 --coverage -lgcov
|
|
15
|
+
else
|
|
16
|
+
AM_CFLAGS += -O2
|
|
17
|
+
AM_CXXFLAGS += -O2
|
|
18
|
+
AM_LDFLAGS += -O2
|
|
19
|
+
endif
|
|
20
|
+
|
|
21
|
+
VERSION = $(LIBSASS_VERSION)
|
|
22
|
+
|
|
23
|
+
EXTRA_DIST = \
|
|
24
|
+
COPYING \
|
|
25
|
+
INSTALL \
|
|
26
|
+
LICENSE \
|
|
27
|
+
Readme.md
|
|
28
|
+
|
|
29
|
+
pkgconfigdir = $(libdir)/pkgconfig
|
|
30
|
+
pkgconfig_DATA = support/libsass.pc
|
|
31
|
+
|
|
32
|
+
lib_LTLIBRARIES = libsass.la
|
|
33
|
+
|
|
34
|
+
libsass_la_SOURCES = \
|
|
35
|
+
ast_fwd_decl.hpp ast_def_macros.hpp \
|
|
36
|
+
kwd_arg_macros.hpp memory_manager.hpp \
|
|
37
|
+
position.hpp operation.hpp \
|
|
38
|
+
subset_map.hpp mapping.hpp \
|
|
39
|
+
color_names.hpp backtrace.hpp \
|
|
40
|
+
cencode.c b64/cencode.h b64/encode.h \
|
|
41
|
+
token.hpp environment.hpp \
|
|
42
|
+
paths.hpp debug.hpp \
|
|
43
|
+
utf8.h utf8/core.h \
|
|
44
|
+
utf8/checked.h utf8/unchecked.h \
|
|
45
|
+
ast.cpp ast.hpp \
|
|
46
|
+
base64vlq.cpp base64vlq.hpp \
|
|
47
|
+
bind.cpp bind.hpp \
|
|
48
|
+
constants.cpp constants.hpp \
|
|
49
|
+
context.cpp context.hpp \
|
|
50
|
+
contextualize.cpp contextualize.hpp \
|
|
51
|
+
copy_c_str.cpp copy_c_str.hpp \
|
|
52
|
+
error_handling.cpp error_handling.hpp \
|
|
53
|
+
eval.cpp eval.hpp \
|
|
54
|
+
expand.cpp expand.hpp \
|
|
55
|
+
extend.cpp extend.hpp \
|
|
56
|
+
file.cpp file.hpp \
|
|
57
|
+
functions.cpp functions.hpp \
|
|
58
|
+
inspect.cpp inspect.hpp \
|
|
59
|
+
node.cpp node.hpp \
|
|
60
|
+
json.cpp json.hpp \
|
|
61
|
+
output_compressed.cpp output_compressed.hpp \
|
|
62
|
+
output_nested.cpp output_nested.hpp \
|
|
63
|
+
parser.cpp parser.hpp \
|
|
64
|
+
prelexer.cpp prelexer.hpp \
|
|
65
|
+
remove_placeholders.cpp remove_placeholders.hpp \
|
|
66
|
+
sass.cpp sass.h \
|
|
67
|
+
sass_util.cpp sass_util.hpp \
|
|
68
|
+
sass_values.cpp sass_values.h \
|
|
69
|
+
sass_context.cpp sass_context.h \
|
|
70
|
+
sass_functions.cpp sass_functions.h \
|
|
71
|
+
sass_interface.cpp sass_interface.h \
|
|
72
|
+
sass2scss.cpp sass2scss.h \
|
|
73
|
+
source_map.cpp source_map.hpp \
|
|
74
|
+
to_c.cpp to_c.hpp \
|
|
75
|
+
to_string.cpp to_string.hpp \
|
|
76
|
+
units.cpp units.hpp \
|
|
77
|
+
utf8_string.cpp utf8_string.hpp \
|
|
78
|
+
util.cpp util.hpp
|
|
79
|
+
|
|
80
|
+
libsass_la_CFLAGS = $(AM_CFLAGS)
|
|
81
|
+
libsass_la_CXXFLAGS = $(AM_CXXFLAGS)
|
|
82
|
+
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:9:0
|
|
83
|
+
|
|
84
|
+
include_HEADERS = sass2scss.h sass_context.h sass_functions.h sass_values.h sass.h
|
|
85
|
+
|
|
86
|
+
if ENABLE_TESTS
|
|
87
|
+
|
|
88
|
+
noinst_PROGRAMS = sassc_bin
|
|
89
|
+
|
|
90
|
+
sassc_bin_SOURCES = $(SASS_SASSC_PATH)/sassc.c
|
|
91
|
+
sassc_bin_LDADD = libsass.la
|
|
92
|
+
sassc_bin_CFLAGS = $(AM_CFLAGS)
|
|
93
|
+
sassc_bin_CXXFLAGS = $(AM_CXXFLAGS)
|
|
94
|
+
sassc_bin_LDFLAGS = $(AM_LDFLAGS) -no-install
|
|
95
|
+
|
|
96
|
+
if ENABLE_COVERAGE
|
|
97
|
+
nodist_EXTRA_sassc_bin_SOURCES = non-existent-file-to-force-CXX-linking.cxx
|
|
98
|
+
nodist_EXTRA_libsass_la_SOURCES = non-existent-file-to-force-CXX-linking.cxx
|
|
99
|
+
endif
|
|
100
|
+
|
|
101
|
+
SASS_SASSC_PATH ?= sassc
|
|
102
|
+
SASS_SPEC_PATH ?= sass-spec
|
|
103
|
+
SASSC_BIN = $(SASS_SASSC_PATH)/bin/sassc
|
|
104
|
+
|
|
105
|
+
TESTS = \
|
|
106
|
+
$(SASS_SPEC_PATH)/spec/basic \
|
|
107
|
+
$(SASS_SPEC_PATH)/spec/css \
|
|
108
|
+
$(SASS_SPEC_PATH)/spec/extend-tests \
|
|
109
|
+
$(SASS_SPEC_PATH)/spec/extends \
|
|
110
|
+
$(SASS_SPEC_PATH)/spec/libsass \
|
|
111
|
+
$(SASS_SPEC_PATH)/spec/libsass-closed-issues \
|
|
112
|
+
$(SASS_SPEC_PATH)/spec/maps \
|
|
113
|
+
$(SASS_SPEC_PATH)/spec/misc \
|
|
114
|
+
$(SASS_SPEC_PATH)/spec/regressions \
|
|
115
|
+
$(SASS_SPEC_PATH)/spec/scss \
|
|
116
|
+
$(SASS_SPEC_PATH)/spec/scss-tests \
|
|
117
|
+
$(SASS_SPEC_PATH)/spec/types
|
|
118
|
+
|
|
119
|
+
SASS_TEST_FLAGS =
|
|
120
|
+
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) ./script/tap-driver
|
|
121
|
+
AM_LOG_FLAGS = -c ./sassc_bin --ignore-todo $(LOG_FLAGS)
|
|
122
|
+
if USE_TAP
|
|
123
|
+
AM_LOG_FLAGS += -t
|
|
124
|
+
SASS_TEST_FLAGS += -t | tapout
|
|
125
|
+
LOG_COMPILER = ./script/tap-runner $(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb
|
|
126
|
+
else
|
|
127
|
+
LOG_COMPILER = $(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb
|
|
128
|
+
endif
|
|
129
|
+
|
|
130
|
+
$(SASSC_BIN): libsass.la
|
|
131
|
+
cd $(SASS_SASSC_PATH) && $(MAKE)
|
|
132
|
+
|
|
133
|
+
test: $(SASSC_BIN)
|
|
134
|
+
$(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --ignore-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
|
|
135
|
+
|
|
136
|
+
test_build: $(SASSC_BIN)
|
|
137
|
+
$(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --ignore-todo $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
|
|
138
|
+
|
|
139
|
+
test_full: $(SASSC_BIN)
|
|
140
|
+
$(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) $(LOG_FLAGS) $(SASS_SPEC_PATH) $(SASS_TEST_FLAGS)
|
|
141
|
+
|
|
142
|
+
test_issues: $(SASSC_BIN)
|
|
143
|
+
$(RUBY) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) $(LOG_FLAGS) $(SASS_SPEC_PATH)/spec/issues $(SASS_TEST_FLAGS)
|
|
144
|
+
|
|
145
|
+
endif
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Libsass
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
by Aaron Leung ([@akhleung]) and Hampton Catlin ([@hcatlin])
|
|
5
|
+
|
|
6
|
+
[](https://travis-ci.org/sass/libsass)
|
|
7
|
+
[](https://ci.appveyor.com/project/sass/libsass/branch/master)
|
|
8
|
+
[](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
|
9
|
+
[](https://coveralls.io/r/sass/libsass?branch=feature%2Ftest-travis-ci-3)
|
|
10
|
+
|
|
11
|
+
https://github.com/sass/libsass
|
|
12
|
+
|
|
13
|
+
Libsass is just a library, but if you want to RUN libsass,
|
|
14
|
+
then go to https://github.com/sass/sassc or
|
|
15
|
+
https://github.com/sass/ruby-libsass or
|
|
16
|
+
[find your local implementer](https://github.com/sass/libsass/wiki/Implementations).
|
|
17
|
+
|
|
18
|
+
LibSass requires GCC 4.5+ or Clang/LLVM. If your OS is older, this version may not compile.
|
|
19
|
+
|
|
20
|
+
About
|
|
21
|
+
-----
|
|
22
|
+
|
|
23
|
+
Libsass is a C/C++ port of the Sass CSS precompiler. The original version was written in Ruby, but this version is meant for efficiency and portability.
|
|
24
|
+
|
|
25
|
+
This library strives to be light, simple, and easy to build and integrate with a variety of platforms and languages.
|
|
26
|
+
|
|
27
|
+
Developing
|
|
28
|
+
----------
|
|
29
|
+
|
|
30
|
+
As you may have noticed, the libsass repo itself has
|
|
31
|
+
no executables and no tests. Oh noes! How can you develop???
|
|
32
|
+
|
|
33
|
+
Well, luckily, SassC is the official binary wrapper for
|
|
34
|
+
libsass and is *always* kept in sync. SassC uses a git submodule
|
|
35
|
+
to include libsass. When developing libsass, its best to actually
|
|
36
|
+
check out SassC and develop in that directory with the SassC spec
|
|
37
|
+
and tests there.
|
|
38
|
+
|
|
39
|
+
We even run Travis tests for SassC!
|
|
40
|
+
|
|
41
|
+
Tests
|
|
42
|
+
-------
|
|
43
|
+
|
|
44
|
+
Since libsass is a pure library, tests are run through the [SassSpec](https://github.com/sass/sass-spec) project using the [SassC](http://github.com/sass/sassc) driver.
|
|
45
|
+
|
|
46
|
+
To run tests against libsass while developing, you can run `./script/spec`. This will clone SassC and Sass-Spec under the project folder and then run the Sass-Spec test suite. You may want to update the clones to ensure you have the latest version.
|
|
47
|
+
|
|
48
|
+
Library Usage
|
|
49
|
+
-------------
|
|
50
|
+
|
|
51
|
+
While libsass is a library primarily written in C++, it provides a simple
|
|
52
|
+
C interface which should be used by most implementers. Libsass does not do
|
|
53
|
+
much on its own without an implementer. This can be a command line tool, like
|
|
54
|
+
[sassc](https://github.com/sass/sassc) or a [binding](https://github.com/sass/libsass/wiki/Implementations)
|
|
55
|
+
to your favorite programing language.
|
|
56
|
+
|
|
57
|
+
If you want to build or interface with libsass, we recommend to check out the
|
|
58
|
+
wiki pages about [building libsass](https://github.com/sass/libsass/wiki/Building-Libsass) and
|
|
59
|
+
the [C-API documentation](https://github.com/sass/libsass/wiki/API-Documentation).
|
|
60
|
+
|
|
61
|
+
About Sass
|
|
62
|
+
----------
|
|
63
|
+
|
|
64
|
+
Sass is a CSS pre-processor language to add on exciting, new,
|
|
65
|
+
awesome features to CSS. Sass was the first language of its kind
|
|
66
|
+
and by far the most mature and up to date codebase.
|
|
67
|
+
|
|
68
|
+
Sass was originally created by the co-creator of this library,
|
|
69
|
+
Hampton Catlin ([@hcatlin]). The extension and continuing evolution
|
|
70
|
+
of the language has all been the result of years of work by Natalie
|
|
71
|
+
Weizenbaum ([@nex3]) and Chris Eppstein ([@chriseppstein]).
|
|
72
|
+
|
|
73
|
+
For more information about Sass itself, please visit http://sass-lang.com
|
|
74
|
+
|
|
75
|
+
Contribution Agreement
|
|
76
|
+
----------------------
|
|
77
|
+
|
|
78
|
+
Any contribution to the project are seen as copyright assigned to Hampton Catlin, a
|
|
79
|
+
human on the planet earth. Your contribution warrants that you have the right to
|
|
80
|
+
assign copyright on your work. The intention here is to ensure that the project
|
|
81
|
+
remains totally free (liberal, like).
|
|
82
|
+
|
|
83
|
+
Our MIT license is designed to be as simple, and liberal as possible.
|
|
84
|
+
|
|
85
|
+
[@hcatlin]: https://github.com/hcatlin
|
|
86
|
+
[@akhleung]: https://github.com/akhleung
|
|
87
|
+
[@chriseppstein]: https://github.com/chriseppstein
|
|
88
|
+
[@nex3]: https://github.com/nex3
|
|
89
|
+
|
|
90
|
+
sass2scss was originally written by Marcel Greter [@mgreter]
|
|
91
|
+
and he happily agreed to have it merged into the project.
|
|
92
|
+
|
|
93
|
+
[sass_interface.h]: sass_interface.h
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
environment:
|
|
2
|
+
CTEST_OUTPUT_ON_FAILURE: 1
|
|
3
|
+
matrix:
|
|
4
|
+
- Compiler: mingw
|
|
5
|
+
Build: static
|
|
6
|
+
ruby_version: "21-x64"
|
|
7
|
+
- Compiler: mingw
|
|
8
|
+
Build: shared
|
|
9
|
+
ruby_version: "21-x64"
|
|
10
|
+
- Compiler: msvc
|
|
11
|
+
Config: Release
|
|
12
|
+
ruby_version: "21-x64"
|
|
13
|
+
- Compiler: msvc
|
|
14
|
+
Config: Debug
|
|
15
|
+
ruby_version: "21-x64"
|
|
16
|
+
|
|
17
|
+
cache:
|
|
18
|
+
- x86_64-4.9.2-release-win32-seh-rt_v3-rev0.7z
|
|
19
|
+
- C:\Ruby21-x64\lib\ruby\gems\2.1.0
|
|
20
|
+
- C:\Ruby21-x64\bin
|
|
21
|
+
|
|
22
|
+
install:
|
|
23
|
+
- git clone https://github.com/sass/sassc.git
|
|
24
|
+
- git clone https://github.com/sass/sass-spec.git
|
|
25
|
+
- set PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
|
26
|
+
- set SASS_LIBSASS_PATH=..
|
|
27
|
+
- gem install minitest
|
|
28
|
+
- ps: |
|
|
29
|
+
if ($env:Compiler -eq "mingw") {
|
|
30
|
+
if (-Not (Test-Path "x86_64-4.9.2-release-win32-seh-rt_v3-rev0.7z")) {
|
|
31
|
+
# Install MinGW.
|
|
32
|
+
$url = "http://sourceforge.net/projects/mingw-w64/files/"
|
|
33
|
+
$url += "Toolchains%20targetting%20Win64/Personal%20Builds/"
|
|
34
|
+
$url += "mingw-builds/4.9.2/threads-win32/seh/"
|
|
35
|
+
$url += "x86_64-4.9.2-release-win32-seh-rt_v3-rev0.7z/download"
|
|
36
|
+
Invoke-WebRequest -UserAgent wget -Uri $url -OutFile x86_64-4.9.2-release-win32-seh-rt_v3-rev0.7z
|
|
37
|
+
}
|
|
38
|
+
&7z x -oC:\ x86_64-4.9.2-release-win32-seh-rt_v3-rev0.7z > $null
|
|
39
|
+
}
|
|
40
|
+
- set PATH=C:\mingw64\bin;%PATH%
|
|
41
|
+
- set CC=gcc
|
|
42
|
+
|
|
43
|
+
build_script:
|
|
44
|
+
- ps: |
|
|
45
|
+
if ($env:Compiler -eq "mingw") {
|
|
46
|
+
mingw32-make -j4 sassc
|
|
47
|
+
} else {
|
|
48
|
+
msbuild /m:4 /p:Configuration=$env:Config win\libsass.sln
|
|
49
|
+
}
|
|
50
|
+
- ps: |
|
|
51
|
+
if ($env:Compiler -eq "mingw") {
|
|
52
|
+
sassc\bin\sassc.exe -v
|
|
53
|
+
ruby -v
|
|
54
|
+
} else {
|
|
55
|
+
if ($env:Config -eq "Debug") {
|
|
56
|
+
win\bin\Debug\sassc.exe -v
|
|
57
|
+
ruby -v
|
|
58
|
+
} else {
|
|
59
|
+
win\bin\sassc.exe -v
|
|
60
|
+
ruby -v
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
test_script:
|
|
65
|
+
- ps: |
|
|
66
|
+
if ($env:Compiler -eq "mingw") {
|
|
67
|
+
ruby sass-spec\sass-spec.rb -c sassc\bin\sassc.exe -s --ignore-todo sass-spec/spec
|
|
68
|
+
} else {
|
|
69
|
+
if ($env:Config -eq "Debug") {
|
|
70
|
+
echo test runner in debug mode build via msvc will throw debug assertions
|
|
71
|
+
echo ruby sass-spec\sass-spec.rb -c win\bin\Debug\sassc.exe -s --ignore-todo sass-spec/spec
|
|
72
|
+
} else {
|
|
73
|
+
ruby sass-spec\sass-spec.rb -c win\bin\sassc.exe -s --ignore-todo sass-spec/spec
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
data/ext/libsass/ast.cpp
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
#include "ast.hpp"
|
|
2
|
+
#include "context.hpp"
|
|
3
|
+
#include "to_string.hpp"
|
|
4
|
+
#include <set>
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
#include <iostream>
|
|
7
|
+
|
|
8
|
+
namespace Sass {
|
|
9
|
+
using namespace std;
|
|
10
|
+
|
|
11
|
+
bool Compound_Selector::operator<(const Compound_Selector& rhs) const
|
|
12
|
+
{
|
|
13
|
+
To_String to_string;
|
|
14
|
+
// ugly
|
|
15
|
+
return const_cast<Compound_Selector*>(this)->perform(&to_string) <
|
|
16
|
+
const_cast<Compound_Selector&>(rhs).perform(&to_string);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
bool Complex_Selector::operator<(const Complex_Selector& rhs) const
|
|
20
|
+
{
|
|
21
|
+
To_String to_string;
|
|
22
|
+
return const_cast<Complex_Selector*>(this)->perform(&to_string) <
|
|
23
|
+
const_cast<Complex_Selector&>(rhs).perform(&to_string);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
bool Complex_Selector::operator==(const Complex_Selector& rhs) const {
|
|
27
|
+
// TODO: We have to access the tail directly using tail_ since ADD_PROPERTY doesn't provide a const version.
|
|
28
|
+
|
|
29
|
+
const Complex_Selector* pOne = this;
|
|
30
|
+
const Complex_Selector* pTwo = &rhs;
|
|
31
|
+
|
|
32
|
+
// Consume any empty references at the beginning of the Complex_Selector
|
|
33
|
+
if (pOne->combinator() == Complex_Selector::ANCESTOR_OF && pOne->head()->is_empty_reference()) {
|
|
34
|
+
pOne = pOne->tail_;
|
|
35
|
+
}
|
|
36
|
+
if (pTwo->combinator() == Complex_Selector::ANCESTOR_OF && pTwo->head()->is_empty_reference()) {
|
|
37
|
+
pTwo = pTwo->tail_;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
while (pOne && pTwo) {
|
|
41
|
+
if (pOne->combinator() != pTwo->combinator()) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (*(pOne->head()) != *(pTwo->head())) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pOne = pOne->tail_;
|
|
50
|
+
pTwo = pTwo->tail_;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return pOne == NULL && pTwo == NULL;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Compound_Selector* Compound_Selector::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
57
|
+
{
|
|
58
|
+
Compound_Selector* unified = rhs;
|
|
59
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
60
|
+
{
|
|
61
|
+
if (!unified) break;
|
|
62
|
+
else unified = (*this)[i]->unify_with(unified, ctx);
|
|
63
|
+
}
|
|
64
|
+
return unified;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
bool Simple_Selector::operator==(const Simple_Selector& rhs) const
|
|
68
|
+
{
|
|
69
|
+
// Compare the string representations for equality.
|
|
70
|
+
|
|
71
|
+
// Cast away const here. To_String should take a const object, but it doesn't.
|
|
72
|
+
Simple_Selector* pLHS = const_cast<Simple_Selector*>(this);
|
|
73
|
+
Simple_Selector* pRHS = const_cast<Simple_Selector*>(&rhs);
|
|
74
|
+
|
|
75
|
+
To_String to_string;
|
|
76
|
+
return pLHS->perform(&to_string) == pRHS->perform(&to_string);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
bool Simple_Selector::operator<(const Simple_Selector& rhs) const {
|
|
80
|
+
// Use the string representation for ordering.
|
|
81
|
+
|
|
82
|
+
// Cast away const here. To_String should take a const object, but it doesn't.
|
|
83
|
+
Simple_Selector* pLHS = const_cast<Simple_Selector*>(this);
|
|
84
|
+
Simple_Selector* pRHS = const_cast<Simple_Selector*>(&rhs);
|
|
85
|
+
|
|
86
|
+
To_String to_string;
|
|
87
|
+
return pLHS->perform(&to_string) < pRHS->perform(&to_string);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Compound_Selector* Simple_Selector::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
91
|
+
{
|
|
92
|
+
To_String to_string;
|
|
93
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
94
|
+
{ if (perform(&to_string) == (*rhs)[i]->perform(&to_string)) return rhs; }
|
|
95
|
+
|
|
96
|
+
// check for pseudo elements because they need to come last
|
|
97
|
+
size_t i, L;
|
|
98
|
+
bool found = false;
|
|
99
|
+
if (typeid(*this) == typeid(Pseudo_Selector) || typeid(*this) == typeid(Wrapped_Selector))
|
|
100
|
+
{
|
|
101
|
+
for (i = 0, L = rhs->length(); i < L; ++i)
|
|
102
|
+
{
|
|
103
|
+
if ((typeid(*(*rhs)[i]) == typeid(Pseudo_Selector) || typeid(*(*rhs)[i]) == typeid(Wrapped_Selector)) && (*rhs)[L-1]->is_pseudo_element())
|
|
104
|
+
{ found = true; break; }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else
|
|
108
|
+
{
|
|
109
|
+
for (i = 0, L = rhs->length(); i < L; ++i)
|
|
110
|
+
{
|
|
111
|
+
if (typeid(*(*rhs)[i]) == typeid(Pseudo_Selector) || typeid(*(*rhs)[i]) == typeid(Wrapped_Selector))
|
|
112
|
+
{ found = true; break; }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!found)
|
|
116
|
+
{
|
|
117
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(*rhs);
|
|
118
|
+
(*cpy) << this;
|
|
119
|
+
return cpy;
|
|
120
|
+
}
|
|
121
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(rhs->path(), rhs->position());
|
|
122
|
+
for (size_t j = 0; j < i; ++j)
|
|
123
|
+
{ (*cpy) << (*rhs)[j]; }
|
|
124
|
+
(*cpy) << this;
|
|
125
|
+
for (size_t j = i; j < L; ++j)
|
|
126
|
+
{ (*cpy) << (*rhs)[j]; }
|
|
127
|
+
return cpy;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Compound_Selector* Type_Selector::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
131
|
+
{
|
|
132
|
+
// TODO: handle namespaces
|
|
133
|
+
|
|
134
|
+
// if the rhs is empty, just return a copy of this
|
|
135
|
+
if (rhs->length() == 0) {
|
|
136
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(rhs->path(), rhs->position());
|
|
137
|
+
(*cpy) << this;
|
|
138
|
+
return cpy;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// if this is a universal selector and rhs is not empty, just return the rhs
|
|
142
|
+
if (name() == "*")
|
|
143
|
+
{ return new (ctx.mem) Compound_Selector(*rhs); }
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
Simple_Selector* rhs_0 = (*rhs)[0];
|
|
147
|
+
// otherwise, this is a tag name
|
|
148
|
+
if (typeid(*rhs_0) == typeid(Type_Selector))
|
|
149
|
+
{
|
|
150
|
+
// if rhs is universal, just return this tagname + rhs's qualifiers
|
|
151
|
+
if (static_cast<Type_Selector*>(rhs_0)->name() == "*")
|
|
152
|
+
{
|
|
153
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(rhs->path(), rhs->position());
|
|
154
|
+
(*cpy) << this;
|
|
155
|
+
for (size_t i = 1, L = rhs->length(); i < L; ++i)
|
|
156
|
+
{ (*cpy) << (*rhs)[i]; }
|
|
157
|
+
return cpy;
|
|
158
|
+
}
|
|
159
|
+
// if rhs is another tag name and it matches this, return rhs
|
|
160
|
+
else if (static_cast<Type_Selector*>(rhs_0)->name() == name())
|
|
161
|
+
{ return new (ctx.mem) Compound_Selector(*rhs); }
|
|
162
|
+
// else the tag names don't match; return nil
|
|
163
|
+
else
|
|
164
|
+
{ return 0; }
|
|
165
|
+
}
|
|
166
|
+
// else it's a tag name and a bunch of qualifiers -- just append them
|
|
167
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(rhs->path(), rhs->position());
|
|
168
|
+
(*cpy) << this;
|
|
169
|
+
(*cpy) += rhs;
|
|
170
|
+
return cpy;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
Compound_Selector* Selector_Qualifier::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
174
|
+
{
|
|
175
|
+
if (name()[0] == '#')
|
|
176
|
+
{
|
|
177
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
178
|
+
{
|
|
179
|
+
Simple_Selector* rhs_i = (*rhs)[i];
|
|
180
|
+
if (typeid(*rhs_i) == typeid(Selector_Qualifier) &&
|
|
181
|
+
static_cast<Selector_Qualifier*>(rhs_i)->name()[0] == '#' &&
|
|
182
|
+
static_cast<Selector_Qualifier*>(rhs_i)->name() != name())
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return Simple_Selector::unify_with(rhs, ctx);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
Compound_Selector* Pseudo_Selector::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
190
|
+
{
|
|
191
|
+
if (is_pseudo_element())
|
|
192
|
+
{
|
|
193
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
194
|
+
{
|
|
195
|
+
Simple_Selector* rhs_i = (*rhs)[i];
|
|
196
|
+
if (typeid(*rhs_i) == typeid(Pseudo_Selector) &&
|
|
197
|
+
static_cast<Pseudo_Selector*>(rhs_i)->is_pseudo_element() &&
|
|
198
|
+
static_cast<Pseudo_Selector*>(rhs_i)->name() != name())
|
|
199
|
+
{ return 0; }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return Simple_Selector::unify_with(rhs, ctx);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
bool Compound_Selector::is_superselector_of(Compound_Selector* rhs)
|
|
206
|
+
{
|
|
207
|
+
To_String to_string;
|
|
208
|
+
|
|
209
|
+
Simple_Selector* lbase = base();
|
|
210
|
+
Simple_Selector* rbase = rhs->base();
|
|
211
|
+
|
|
212
|
+
// Check if pseudo-elements are the same between the selectors
|
|
213
|
+
|
|
214
|
+
set<string> lpsuedoset, rpsuedoset;
|
|
215
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
216
|
+
{
|
|
217
|
+
if ((*this)[i]->is_pseudo_element()) {
|
|
218
|
+
string pseudo((*this)[i]->perform(&to_string));
|
|
219
|
+
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
220
|
+
lpsuedoset.insert(pseudo);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
224
|
+
{
|
|
225
|
+
if ((*rhs)[i]->is_pseudo_element()) {
|
|
226
|
+
string pseudo((*rhs)[i]->perform(&to_string));
|
|
227
|
+
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
228
|
+
rpsuedoset.insert(pseudo);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (lpsuedoset != rpsuedoset) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Check the Simple_Selectors
|
|
236
|
+
|
|
237
|
+
set<string> lset, rset;
|
|
238
|
+
|
|
239
|
+
if (!lbase) // no lbase; just see if the left-hand qualifiers are a subset of the right-hand selector
|
|
240
|
+
{
|
|
241
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
242
|
+
{ lset.insert((*this)[i]->perform(&to_string)); }
|
|
243
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
244
|
+
{ rset.insert((*rhs)[i]->perform(&to_string)); }
|
|
245
|
+
return includes(rset.begin(), rset.end(), lset.begin(), lset.end());
|
|
246
|
+
}
|
|
247
|
+
else { // there's an lbase
|
|
248
|
+
for (size_t i = 1, L = length(); i < L; ++i)
|
|
249
|
+
{ lset.insert((*this)[i]->perform(&to_string)); }
|
|
250
|
+
if (rbase)
|
|
251
|
+
{
|
|
252
|
+
if (lbase->perform(&to_string) != rbase->perform(&to_string)) // if there's an rbase, make sure they match
|
|
253
|
+
{ return false; }
|
|
254
|
+
else // the bases do match, so compare qualifiers
|
|
255
|
+
{
|
|
256
|
+
for (size_t i = 1, L = rhs->length(); i < L; ++i)
|
|
257
|
+
{ rset.insert((*rhs)[i]->perform(&to_string)); }
|
|
258
|
+
return includes(rset.begin(), rset.end(), lset.begin(), lset.end());
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// catch-all
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
bool Compound_Selector::operator==(const Compound_Selector& rhs) const {
|
|
267
|
+
To_String to_string;
|
|
268
|
+
|
|
269
|
+
// Check if pseudo-elements are the same between the selectors
|
|
270
|
+
|
|
271
|
+
set<string> lpsuedoset, rpsuedoset;
|
|
272
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
273
|
+
{
|
|
274
|
+
if ((*this)[i]->is_pseudo_element()) {
|
|
275
|
+
string pseudo((*this)[i]->perform(&to_string));
|
|
276
|
+
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
277
|
+
lpsuedoset.insert(pseudo);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
for (size_t i = 0, L = rhs.length(); i < L; ++i)
|
|
281
|
+
{
|
|
282
|
+
if (rhs[i]->is_pseudo_element()) {
|
|
283
|
+
string pseudo(rhs[i]->perform(&to_string));
|
|
284
|
+
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
285
|
+
rpsuedoset.insert(pseudo);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (lpsuedoset != rpsuedoset) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Check the base
|
|
293
|
+
|
|
294
|
+
const Simple_Selector* const lbase = base();
|
|
295
|
+
const Simple_Selector* const rbase = rhs.base();
|
|
296
|
+
|
|
297
|
+
if ((lbase && !rbase) ||
|
|
298
|
+
(!lbase && rbase) ||
|
|
299
|
+
((lbase && rbase) && (*lbase != *rbase))) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
// Check the rest of the SimpleSelectors
|
|
305
|
+
// Use string representations. We can't create a set of Simple_Selector pointers because std::set == std::set is going to call ==
|
|
306
|
+
// on the pointers to determine equality. I don't know of a way to pass in a comparison object. The one you can specify as part of
|
|
307
|
+
// the template type is used for ordering, but not equality. We also can't just put in non-pointer Simple_Selectors because the
|
|
308
|
+
// class is intended to be subclassed, and we'd get splicing.
|
|
309
|
+
|
|
310
|
+
set<string> lset, rset;
|
|
311
|
+
|
|
312
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
313
|
+
{ lset.insert((*this)[i]->perform(&to_string)); }
|
|
314
|
+
for (size_t i = 0, L = rhs.length(); i < L; ++i)
|
|
315
|
+
{ rset.insert(rhs[i]->perform(&to_string)); }
|
|
316
|
+
|
|
317
|
+
return lset == rset;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
bool Complex_Selector_Pointer_Compare::operator() (const Complex_Selector* const pLeft, const Complex_Selector* const pRight) const {
|
|
321
|
+
return *pLeft < *pRight;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
bool Complex_Selector::is_superselector_of(Compound_Selector* rhs)
|
|
325
|
+
{
|
|
326
|
+
if (length() != 1)
|
|
327
|
+
{ return false; }
|
|
328
|
+
return base()->is_superselector_of(rhs);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
bool Complex_Selector::is_superselector_of(Complex_Selector* rhs)
|
|
332
|
+
{
|
|
333
|
+
Complex_Selector* lhs = this;
|
|
334
|
+
To_String to_string;
|
|
335
|
+
// check for selectors with leading or trailing combinators
|
|
336
|
+
if (!lhs->head() || !rhs->head())
|
|
337
|
+
{ return false; }
|
|
338
|
+
Complex_Selector* l_innermost = lhs->innermost();
|
|
339
|
+
if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF && !l_innermost->tail())
|
|
340
|
+
{ return false; }
|
|
341
|
+
Complex_Selector* r_innermost = rhs->innermost();
|
|
342
|
+
if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF && !r_innermost->tail())
|
|
343
|
+
{ return false; }
|
|
344
|
+
// more complex (i.e., longer) selectors are always more specific
|
|
345
|
+
size_t l_len = lhs->length(), r_len = rhs->length();
|
|
346
|
+
if (l_len > r_len)
|
|
347
|
+
{ return false; }
|
|
348
|
+
|
|
349
|
+
if (l_len == 1)
|
|
350
|
+
{ return lhs->head()->is_superselector_of(rhs->base()); }
|
|
351
|
+
|
|
352
|
+
bool found = false;
|
|
353
|
+
Complex_Selector* marker = rhs;
|
|
354
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i) {
|
|
355
|
+
if (i == L-1)
|
|
356
|
+
{ return false; }
|
|
357
|
+
if (lhs->head()->is_superselector_of(marker->head()))
|
|
358
|
+
{ found = true; break; }
|
|
359
|
+
marker = marker->tail();
|
|
360
|
+
}
|
|
361
|
+
if (!found)
|
|
362
|
+
{ return false; }
|
|
363
|
+
|
|
364
|
+
/*
|
|
365
|
+
Hmm, I hope I have the logic right:
|
|
366
|
+
|
|
367
|
+
if lhs has a combinator:
|
|
368
|
+
if !(marker has a combinator) return false
|
|
369
|
+
if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false
|
|
370
|
+
return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost)
|
|
371
|
+
else if marker has a combinator:
|
|
372
|
+
if !(marker.combinator == ">") return false
|
|
373
|
+
return lhs.tail.is_superselector_of(marker.tail)
|
|
374
|
+
else
|
|
375
|
+
return lhs.tail.is_superselector_of(marker.tail)
|
|
376
|
+
*/
|
|
377
|
+
if (lhs->combinator() != Complex_Selector::ANCESTOR_OF)
|
|
378
|
+
{
|
|
379
|
+
if (marker->combinator() == Complex_Selector::ANCESTOR_OF)
|
|
380
|
+
{ return false; }
|
|
381
|
+
if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
|
|
382
|
+
{ return false; }
|
|
383
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
|
384
|
+
}
|
|
385
|
+
else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
|
|
386
|
+
{
|
|
387
|
+
if (marker->combinator() != Complex_Selector::PARENT_OF)
|
|
388
|
+
{ return false; }
|
|
389
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
|
390
|
+
}
|
|
391
|
+
else
|
|
392
|
+
{
|
|
393
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
|
394
|
+
}
|
|
395
|
+
// catch-all
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
size_t Complex_Selector::length()
|
|
400
|
+
{
|
|
401
|
+
// TODO: make this iterative
|
|
402
|
+
if (!tail()) return 1;
|
|
403
|
+
return 1 + tail()->length();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
Compound_Selector* Complex_Selector::base()
|
|
407
|
+
{
|
|
408
|
+
if (!tail()) return head();
|
|
409
|
+
else return tail()->base();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
Complex_Selector* Complex_Selector::context(Context& ctx)
|
|
413
|
+
{
|
|
414
|
+
if (!tail()) return 0;
|
|
415
|
+
if (!head()) return tail()->context(ctx);
|
|
416
|
+
return new (ctx.mem) Complex_Selector(path(), position(), combinator(), head(), tail()->context(ctx));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
Complex_Selector* Complex_Selector::innermost()
|
|
420
|
+
{
|
|
421
|
+
if (!tail()) return this;
|
|
422
|
+
else return tail()->innermost();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
Complex_Selector::Combinator Complex_Selector::clear_innermost()
|
|
426
|
+
{
|
|
427
|
+
Combinator c;
|
|
428
|
+
if (!tail() || tail()->length() == 1)
|
|
429
|
+
{ c = combinator(); combinator(ANCESTOR_OF); tail(0); }
|
|
430
|
+
else
|
|
431
|
+
{ c = tail()->clear_innermost(); }
|
|
432
|
+
return c;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
void Complex_Selector::set_innermost(Complex_Selector* val, Combinator c)
|
|
436
|
+
{
|
|
437
|
+
if (!tail())
|
|
438
|
+
{ tail(val); combinator(c); }
|
|
439
|
+
else
|
|
440
|
+
{ tail()->set_innermost(val, c); }
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
Complex_Selector* Complex_Selector::clone(Context& ctx) const
|
|
444
|
+
{
|
|
445
|
+
Complex_Selector* cpy = new (ctx.mem) Complex_Selector(*this);
|
|
446
|
+
if (tail()) cpy->tail(tail()->clone(ctx));
|
|
447
|
+
return cpy;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
Complex_Selector* Complex_Selector::cloneFully(Context& ctx) const
|
|
451
|
+
{
|
|
452
|
+
Complex_Selector* cpy = new (ctx.mem) Complex_Selector(*this);
|
|
453
|
+
|
|
454
|
+
if (head()) {
|
|
455
|
+
cpy->head(head()->clone(ctx));
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (tail()) {
|
|
459
|
+
cpy->tail(tail()->cloneFully(ctx));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return cpy;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
Compound_Selector* Compound_Selector::clone(Context& ctx) const
|
|
466
|
+
{
|
|
467
|
+
Compound_Selector* cpy = new (ctx.mem) Compound_Selector(*this);
|
|
468
|
+
return cpy;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
Selector_Placeholder* Selector::find_placeholder()
|
|
474
|
+
{
|
|
475
|
+
return 0;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
void Selector_List::adjust_after_pushing(Complex_Selector* c)
|
|
479
|
+
{
|
|
480
|
+
if (c->has_reference()) has_reference(true);
|
|
481
|
+
if (c->has_placeholder()) has_placeholder(true);
|
|
482
|
+
|
|
483
|
+
#ifdef DEBUG
|
|
484
|
+
To_String to_string;
|
|
485
|
+
this->mCachedSelector(this->perform(&to_string));
|
|
486
|
+
#endif
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
Selector_Placeholder* Selector_List::find_placeholder()
|
|
490
|
+
{
|
|
491
|
+
if (has_placeholder()) {
|
|
492
|
+
for (size_t i = 0, L = length(); i < L; ++i) {
|
|
493
|
+
if ((*this)[i]->has_placeholder()) return (*this)[i]->find_placeholder();
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return 0;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
Selector_Placeholder* Complex_Selector::find_placeholder()
|
|
500
|
+
{
|
|
501
|
+
if (has_placeholder()) {
|
|
502
|
+
if (head() && head()->has_placeholder()) return head()->find_placeholder();
|
|
503
|
+
else if (tail() && tail()->has_placeholder()) return tail()->find_placeholder();
|
|
504
|
+
}
|
|
505
|
+
return 0;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
Selector_Placeholder* Compound_Selector::find_placeholder()
|
|
509
|
+
{
|
|
510
|
+
if (has_placeholder()) {
|
|
511
|
+
for (size_t i = 0, L = length(); i < L; ++i) {
|
|
512
|
+
if ((*this)[i]->has_placeholder()) return (*this)[i]->find_placeholder();
|
|
513
|
+
}
|
|
514
|
+
// return this;
|
|
515
|
+
}
|
|
516
|
+
return 0;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
Selector_Placeholder* Selector_Placeholder::find_placeholder()
|
|
520
|
+
{
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
vector<string> Compound_Selector::to_str_vec()
|
|
525
|
+
{
|
|
526
|
+
To_String to_string;
|
|
527
|
+
vector<string> result;
|
|
528
|
+
result.reserve(length());
|
|
529
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
530
|
+
{ result.push_back((*this)[i]->perform(&to_string)); }
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
Compound_Selector* Compound_Selector::minus(Compound_Selector* rhs, Context& ctx)
|
|
535
|
+
{
|
|
536
|
+
To_String to_string;
|
|
537
|
+
Compound_Selector* result = new (ctx.mem) Compound_Selector(path(), position());
|
|
538
|
+
|
|
539
|
+
// not very efficient because it needs to preserve order
|
|
540
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
|
541
|
+
{
|
|
542
|
+
bool found = false;
|
|
543
|
+
string thisSelector((*this)[i]->perform(&to_string));
|
|
544
|
+
for (size_t j = 0, M = rhs->length(); j < M; ++j)
|
|
545
|
+
{
|
|
546
|
+
if (thisSelector == (*rhs)[j]->perform(&to_string))
|
|
547
|
+
{
|
|
548
|
+
found = true;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (!found) (*result) << (*this)[i];
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return result;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
void Compound_Selector::mergeSources(SourcesSet& sources, Context& ctx)
|
|
559
|
+
{
|
|
560
|
+
for (SourcesSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
|
|
561
|
+
this->sources_.insert((*iterator)->clone(ctx));
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
vector<Compound_Selector*> Complex_Selector::to_vector()
|
|
566
|
+
{
|
|
567
|
+
vector<Compound_Selector*> result;
|
|
568
|
+
Compound_Selector* h = head();
|
|
569
|
+
Complex_Selector* t = tail();
|
|
570
|
+
if (h) result.push_back(h);
|
|
571
|
+
while (t)
|
|
572
|
+
{
|
|
573
|
+
h = t->head();
|
|
574
|
+
t = t->tail();
|
|
575
|
+
if (h) result.push_back(h);
|
|
576
|
+
}
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
}
|
|
581
|
+
|