sassc 1.8.3 → 1.8.4
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 +4 -4
- data/README.md +3 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.gitignore +1 -0
- data/ext/libsass/LICENSE +1 -1
- data/ext/libsass/Makefile +20 -14
- data/ext/libsass/Makefile.conf +0 -1
- data/ext/libsass/Readme.md +3 -1
- data/ext/libsass/appveyor.yml +19 -11
- data/ext/libsass/docs/api-importer-example.md +2 -1235
- data/ext/libsass/docs/build-with-autotools.md +10 -0
- data/ext/libsass/docs/build-with-makefiles.md +18 -0
- data/ext/libsass/include/sass/base.h +4 -1
- data/ext/libsass/include/sass/values.h +2 -1
- data/ext/libsass/src/ast.cpp +279 -346
- data/ext/libsass/src/ast.hpp +234 -60
- data/ext/libsass/src/base64vlq.cpp +1 -0
- data/ext/libsass/src/bind.cpp +35 -45
- data/ext/libsass/src/bind.hpp +1 -0
- data/ext/libsass/src/color_maps.cpp +1 -0
- data/ext/libsass/src/constants.cpp +4 -1
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +41 -31
- data/ext/libsass/src/context.hpp +10 -10
- data/ext/libsass/src/cssize.cpp +7 -4
- data/ext/libsass/src/cssize.hpp +1 -3
- data/ext/libsass/src/debugger.hpp +73 -14
- data/ext/libsass/src/emitter.cpp +37 -25
- data/ext/libsass/src/emitter.hpp +10 -9
- data/ext/libsass/src/environment.cpp +16 -5
- data/ext/libsass/src/environment.hpp +5 -3
- data/ext/libsass/src/error_handling.cpp +91 -14
- data/ext/libsass/src/error_handling.hpp +105 -4
- data/ext/libsass/src/eval.cpp +519 -330
- data/ext/libsass/src/eval.hpp +12 -13
- data/ext/libsass/src/expand.cpp +92 -56
- data/ext/libsass/src/expand.hpp +5 -3
- data/ext/libsass/src/extend.cpp +60 -51
- data/ext/libsass/src/extend.hpp +1 -3
- data/ext/libsass/src/file.cpp +37 -27
- data/ext/libsass/src/functions.cpp +78 -62
- data/ext/libsass/src/functions.hpp +1 -0
- data/ext/libsass/src/inspect.cpp +293 -64
- data/ext/libsass/src/inspect.hpp +2 -0
- data/ext/libsass/src/lexer.cpp +1 -0
- data/ext/libsass/src/listize.cpp +14 -15
- data/ext/libsass/src/listize.hpp +3 -5
- data/ext/libsass/src/memory_manager.cpp +1 -0
- data/ext/libsass/src/node.cpp +2 -3
- data/ext/libsass/src/operation.hpp +70 -71
- data/ext/libsass/src/output.cpp +28 -32
- data/ext/libsass/src/output.hpp +1 -2
- data/ext/libsass/src/parser.cpp +402 -183
- data/ext/libsass/src/parser.hpp +19 -9
- data/ext/libsass/src/plugins.cpp +1 -0
- data/ext/libsass/src/position.cpp +1 -0
- data/ext/libsass/src/prelexer.cpp +134 -56
- data/ext/libsass/src/prelexer.hpp +51 -3
- data/ext/libsass/src/remove_placeholders.cpp +35 -9
- data/ext/libsass/src/remove_placeholders.hpp +4 -3
- data/ext/libsass/src/sass.cpp +1 -0
- data/ext/libsass/src/sass.hpp +129 -0
- data/ext/libsass/src/sass_context.cpp +31 -14
- data/ext/libsass/src/sass_context.hpp +2 -31
- data/ext/libsass/src/sass_functions.cpp +1 -0
- data/ext/libsass/src/sass_interface.cpp +5 -6
- data/ext/libsass/src/sass_util.cpp +1 -2
- data/ext/libsass/src/sass_util.hpp +5 -5
- data/ext/libsass/src/sass_values.cpp +13 -10
- data/ext/libsass/src/source_map.cpp +4 -3
- data/ext/libsass/src/source_map.hpp +2 -2
- data/ext/libsass/src/subset_map.hpp +0 -1
- data/ext/libsass/src/to_c.cpp +1 -0
- data/ext/libsass/src/to_c.hpp +1 -3
- data/ext/libsass/src/to_value.cpp +3 -5
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.cpp +96 -59
- data/ext/libsass/src/units.hpp +10 -8
- data/ext/libsass/src/utf8_string.cpp +5 -0
- data/ext/libsass/src/util.cpp +23 -156
- data/ext/libsass/src/util.hpp +10 -14
- data/ext/libsass/src/values.cpp +1 -0
- data/ext/libsass/test/test_node.cpp +2 -6
- data/ext/libsass/test/test_selector_difference.cpp +1 -3
- data/ext/libsass/test/test_specificity.cpp +0 -2
- data/ext/libsass/test/test_superselector.cpp +0 -2
- data/ext/libsass/test/test_unification.cpp +1 -3
- data/ext/libsass/win/libsass.targets +18 -5
- data/ext/libsass/win/libsass.vcxproj +9 -7
- data/ext/libsass/win/libsass.vcxproj.filters +148 -106
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +12 -0
- data/test/native_test.rb +1 -1
- metadata +3 -4
- data/ext/libsass/src/to_string.cpp +0 -48
- data/ext/libsass/src/to_string.hpp +0 -38
|
@@ -7,6 +7,16 @@ git clone https://github.com/sass/sassc.git libsass/sassc
|
|
|
7
7
|
git clone https://github.com/sass/sass-spec.git libsass/sass-spec
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
+
### Prerequisites
|
|
11
|
+
|
|
12
|
+
In order to run autotools you need a few tools installed on your system.
|
|
13
|
+
```bash
|
|
14
|
+
yum install automake libtool # RedHat Linux
|
|
15
|
+
emerge -a automake libtool # Gentoo Linux
|
|
16
|
+
pkgin install automake libtool # SmartOS
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
|
|
10
20
|
### Create configure script
|
|
11
21
|
```bash
|
|
12
22
|
cd libsass
|
|
@@ -32,6 +32,24 @@ $ ls libsass/lib
|
|
|
32
32
|
libsass.a libsass.so
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
### Install onto the system
|
|
36
|
+
|
|
37
|
+
We recommend to use [autotools to install](build-with-autotools.md) libsass onto the
|
|
38
|
+
system, since that brings all the benefits of using libtools as the main install method.
|
|
39
|
+
If you still want to install libsass via the makefile, you need to make sure that gnu
|
|
40
|
+
`install` utility (or compatible) is installed on your system.
|
|
41
|
+
```bash
|
|
42
|
+
yum install coreutils # RedHat Linux
|
|
43
|
+
emerge -a coreutils # Gentoo Linux
|
|
44
|
+
pkgin install coreutils # SmartOS
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You can set the install location by setting `PREFIX`
|
|
48
|
+
```bash
|
|
49
|
+
PREFIX="/opt/local" make install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
|
|
35
53
|
### Compling sassc
|
|
36
54
|
|
|
37
55
|
```bash
|
|
@@ -56,7 +56,10 @@ enum Sass_Output_Style {
|
|
|
56
56
|
SASS_STYLE_NESTED,
|
|
57
57
|
SASS_STYLE_EXPANDED,
|
|
58
58
|
SASS_STYLE_COMPACT,
|
|
59
|
-
SASS_STYLE_COMPRESSED
|
|
59
|
+
SASS_STYLE_COMPRESSED,
|
|
60
|
+
// only used internaly
|
|
61
|
+
SASS_STYLE_INSPECT,
|
|
62
|
+
SASS_STYLE_TO_SASS
|
|
60
63
|
};
|
|
61
64
|
|
|
62
65
|
// Some convenient string helper function
|
data/ext/libsass/src/ast.cpp
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
#include "sass.hpp"
|
|
1
2
|
#include "ast.hpp"
|
|
2
3
|
#include "context.hpp"
|
|
3
4
|
#include "node.hpp"
|
|
4
5
|
#include "extend.hpp"
|
|
5
|
-
#include "
|
|
6
|
+
#include "emitter.hpp"
|
|
6
7
|
#include "color_maps.hpp"
|
|
7
8
|
#include <set>
|
|
8
9
|
#include <iomanip>
|
|
@@ -58,7 +59,10 @@ namespace Sass {
|
|
|
58
59
|
|
|
59
60
|
bool Compound_Selector::has_parent_ref()
|
|
60
61
|
{
|
|
61
|
-
|
|
62
|
+
for (Simple_Selector* s : *this) {
|
|
63
|
+
if (s->has_parent_ref()) return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
bool Complex_Selector::has_parent_ref()
|
|
@@ -205,10 +209,8 @@ namespace Sass {
|
|
|
205
209
|
|
|
206
210
|
bool Simple_Selector::operator== (const Simple_Selector& rhs) const
|
|
207
211
|
{
|
|
208
|
-
const
|
|
209
|
-
const Attribute_Selector*
|
|
210
|
-
if (ll && rr) return *ll == *rr;
|
|
211
|
-
|
|
212
|
+
if (const Wrapped_Selector* lw = dynamic_cast<const Wrapped_Selector*>(this)) return *lw == rhs;
|
|
213
|
+
if (const Attribute_Selector* la = dynamic_cast<const Attribute_Selector*>(this)) return *la == rhs;
|
|
212
214
|
if (is_ns_eq(ns(), rhs.ns()))
|
|
213
215
|
{ return name() == rhs.name(); }
|
|
214
216
|
return ns() == rhs.ns();
|
|
@@ -216,10 +218,8 @@ namespace Sass {
|
|
|
216
218
|
|
|
217
219
|
bool Simple_Selector::operator< (const Simple_Selector& rhs) const
|
|
218
220
|
{
|
|
219
|
-
const
|
|
220
|
-
const Attribute_Selector*
|
|
221
|
-
if (ll && rr) return *ll < *rr;
|
|
222
|
-
|
|
221
|
+
if (const Wrapped_Selector* lw = dynamic_cast<const Wrapped_Selector*>(this)) return *lw < rhs;
|
|
222
|
+
if (const Attribute_Selector* la = dynamic_cast<const Attribute_Selector*>(this)) return *la < rhs;
|
|
223
223
|
if (is_ns_eq(ns(), rhs.ns()))
|
|
224
224
|
{ return name() < rhs.name(); }
|
|
225
225
|
return ns() < rhs.ns();
|
|
@@ -280,9 +280,8 @@ namespace Sass {
|
|
|
280
280
|
|
|
281
281
|
Compound_Selector* Simple_Selector::unify_with(Compound_Selector* rhs, Context& ctx)
|
|
282
282
|
{
|
|
283
|
-
To_String to_string(&ctx);
|
|
284
283
|
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
285
|
-
{ if (
|
|
284
|
+
{ if (to_string(ctx.c_options) == (*rhs)[i]->to_string(ctx.c_options)) return rhs; }
|
|
286
285
|
|
|
287
286
|
// check for pseudo elements because they are always last
|
|
288
287
|
size_t i, L;
|
|
@@ -291,7 +290,7 @@ namespace Sass {
|
|
|
291
290
|
{
|
|
292
291
|
for (i = 0, L = rhs->length(); i < L; ++i)
|
|
293
292
|
{
|
|
294
|
-
if ((
|
|
293
|
+
if ((dynamic_cast<Pseudo_Selector*>((*rhs)[i]) || dynamic_cast<Wrapped_Selector*>((*rhs)[i])) && (*rhs)[L-1]->is_pseudo_element())
|
|
295
294
|
{ found = true; break; }
|
|
296
295
|
}
|
|
297
296
|
}
|
|
@@ -299,7 +298,7 @@ namespace Sass {
|
|
|
299
298
|
{
|
|
300
299
|
for (i = 0, L = rhs->length(); i < L; ++i)
|
|
301
300
|
{
|
|
302
|
-
if (
|
|
301
|
+
if (dynamic_cast<Pseudo_Selector*>((*rhs)[i]) || dynamic_cast<Wrapped_Selector*>((*rhs)[i]))
|
|
303
302
|
{ found = true; break; }
|
|
304
303
|
}
|
|
305
304
|
}
|
|
@@ -500,6 +499,26 @@ namespace Sass {
|
|
|
500
499
|
return ns() == rhs.ns();
|
|
501
500
|
}
|
|
502
501
|
|
|
502
|
+
bool Wrapped_Selector::operator< (const Wrapped_Selector& rhs) const
|
|
503
|
+
{
|
|
504
|
+
if (is_ns_eq(ns(), rhs.ns()) && name() == rhs.name())
|
|
505
|
+
{ return *(selector()) < *(rhs.selector()); }
|
|
506
|
+
if (is_ns_eq(ns(), rhs.ns()))
|
|
507
|
+
{ return name() < rhs.name(); }
|
|
508
|
+
return ns() < rhs.ns();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
bool Wrapped_Selector::operator< (const Simple_Selector& rhs) const
|
|
512
|
+
{
|
|
513
|
+
if (const Wrapped_Selector* w = dynamic_cast<const Wrapped_Selector*>(&rhs))
|
|
514
|
+
{
|
|
515
|
+
return *this < *w;
|
|
516
|
+
}
|
|
517
|
+
if (is_ns_eq(ns(), rhs.ns()))
|
|
518
|
+
{ return name() < rhs.name(); }
|
|
519
|
+
return ns() < rhs.ns();
|
|
520
|
+
}
|
|
521
|
+
|
|
503
522
|
bool Wrapped_Selector::is_superselector_of(Wrapped_Selector* sub)
|
|
504
523
|
{
|
|
505
524
|
if (this->name() != sub->name()) return false;
|
|
@@ -531,8 +550,6 @@ namespace Sass {
|
|
|
531
550
|
|
|
532
551
|
bool Compound_Selector::is_superselector_of(Compound_Selector* rhs, std::string wrapping)
|
|
533
552
|
{
|
|
534
|
-
To_String to_string;
|
|
535
|
-
|
|
536
553
|
Compound_Selector* lhs = this;
|
|
537
554
|
Simple_Selector* lbase = lhs->base();
|
|
538
555
|
Simple_Selector* rbase = rhs->base();
|
|
@@ -543,7 +560,7 @@ namespace Sass {
|
|
|
543
560
|
for (size_t i = 0, L = length(); i < L; ++i)
|
|
544
561
|
{
|
|
545
562
|
if ((*this)[i]->is_pseudo_element()) {
|
|
546
|
-
std::string pseudo((*this)[i]->
|
|
563
|
+
std::string pseudo((*this)[i]->to_string());
|
|
547
564
|
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
548
565
|
lpsuedoset.insert(pseudo);
|
|
549
566
|
}
|
|
@@ -551,7 +568,7 @@ namespace Sass {
|
|
|
551
568
|
for (size_t i = 0, L = rhs->length(); i < L; ++i)
|
|
552
569
|
{
|
|
553
570
|
if ((*rhs)[i]->is_pseudo_element()) {
|
|
554
|
-
std::string pseudo((*rhs)[i]->
|
|
571
|
+
std::string pseudo((*rhs)[i]->to_string());
|
|
555
572
|
pseudo = pseudo.substr(pseudo.find_first_not_of(":")); // strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
|
556
573
|
rpsuedoset.insert(pseudo);
|
|
557
574
|
}
|
|
@@ -564,11 +581,11 @@ namespace Sass {
|
|
|
564
581
|
|
|
565
582
|
if (lbase && rbase)
|
|
566
583
|
{
|
|
567
|
-
if (lbase->
|
|
584
|
+
if (lbase->to_string() == rbase->to_string()) {
|
|
568
585
|
for (size_t i = 1, L = length(); i < L; ++i)
|
|
569
|
-
{ lset.insert((*this)[i]->
|
|
586
|
+
{ lset.insert((*this)[i]->to_string()); }
|
|
570
587
|
for (size_t i = 1, L = rhs->length(); i < L; ++i)
|
|
571
|
-
{ rset.insert((*rhs)[i]->
|
|
588
|
+
{ rset.insert((*rhs)[i]->to_string()); }
|
|
572
589
|
return includes(rset.begin(), rset.end(), lset.begin(), lset.end());
|
|
573
590
|
}
|
|
574
591
|
return false;
|
|
@@ -602,13 +619,13 @@ namespace Sass {
|
|
|
602
619
|
if (wrapped->name() == wrapped_r->name()) {
|
|
603
620
|
if (wrapped->is_superselector_of(wrapped_r)) {
|
|
604
621
|
continue;
|
|
605
|
-
rset.insert(lhs->
|
|
622
|
+
rset.insert(lhs->to_string());
|
|
606
623
|
|
|
607
624
|
}}
|
|
608
625
|
}
|
|
609
626
|
}
|
|
610
627
|
// match from here on as strings
|
|
611
|
-
lset.insert(lhs->
|
|
628
|
+
lset.insert(lhs->to_string());
|
|
612
629
|
}
|
|
613
630
|
|
|
614
631
|
for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
|
|
@@ -631,7 +648,7 @@ namespace Sass {
|
|
|
631
648
|
}
|
|
632
649
|
}
|
|
633
650
|
}
|
|
634
|
-
rset.insert(r->
|
|
651
|
+
rset.insert(r->to_string());
|
|
635
652
|
}
|
|
636
653
|
|
|
637
654
|
//for (auto l : lset) { cerr << "l: " << l << endl; }
|
|
@@ -767,7 +784,6 @@ namespace Sass {
|
|
|
767
784
|
bool Complex_Selector::is_superselector_of(Complex_Selector* rhs, std::string wrapping)
|
|
768
785
|
{
|
|
769
786
|
Complex_Selector* lhs = this;
|
|
770
|
-
To_String to_string;
|
|
771
787
|
// check for selectors with leading or trailing combinators
|
|
772
788
|
if (!lhs->head() || !rhs->head())
|
|
773
789
|
{ return false; }
|
|
@@ -793,7 +809,7 @@ namespace Sass {
|
|
|
793
809
|
if (lhs_tail->combinator() != rhs_tail->combinator()) return false;
|
|
794
810
|
if (lhs_tail->head() && !rhs_tail->head()) return false;
|
|
795
811
|
if (!lhs_tail->head() && rhs_tail->head()) return false;
|
|
796
|
-
if (lhs_tail->head() &&
|
|
812
|
+
if (lhs_tail->head() && rhs_tail->head()) {
|
|
797
813
|
if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
|
|
798
814
|
}
|
|
799
815
|
}
|
|
@@ -955,11 +971,12 @@ namespace Sass {
|
|
|
955
971
|
|
|
956
972
|
if (head && head->length() > 0) {
|
|
957
973
|
|
|
974
|
+
Selector_List* retval = 0;
|
|
958
975
|
// we have a parent selector in a simple compound list
|
|
959
976
|
// mix parent complex selector into the compound list
|
|
960
977
|
if (dynamic_cast<Parent_Selector*>((*head)[0])) {
|
|
978
|
+
retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
|
961
979
|
if (parents && parents->length()) {
|
|
962
|
-
Selector_List* retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
|
963
980
|
if (tails && tails->length() > 0) {
|
|
964
981
|
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
|
|
965
982
|
for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
|
|
@@ -998,11 +1015,9 @@ namespace Sass {
|
|
|
998
1015
|
*retval << s;
|
|
999
1016
|
}
|
|
1000
1017
|
}
|
|
1001
|
-
return retval;
|
|
1002
1018
|
}
|
|
1003
1019
|
// have no parent but some tails
|
|
1004
1020
|
else {
|
|
1005
|
-
Selector_List* retval = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
|
1006
1021
|
if (tails && tails->length() > 0) {
|
|
1007
1022
|
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
|
|
1008
1023
|
Complex_Selector* cpy = this->clone(ctx);
|
|
@@ -1023,14 +1038,23 @@ namespace Sass {
|
|
|
1023
1038
|
if (!cpy->head()->length()) cpy->head(0);
|
|
1024
1039
|
*retval << cpy->skip_empty_reference();
|
|
1025
1040
|
}
|
|
1026
|
-
return retval;
|
|
1027
1041
|
}
|
|
1028
1042
|
}
|
|
1029
1043
|
// no parent selector in head
|
|
1030
1044
|
else {
|
|
1031
|
-
|
|
1045
|
+
retval = this->tails(ctx, tails);
|
|
1032
1046
|
}
|
|
1033
1047
|
|
|
1048
|
+
for (Simple_Selector* ss : *head) {
|
|
1049
|
+
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
|
|
1050
|
+
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
|
|
1051
|
+
if (parents) ws->selector(sl->parentize(parents, ctx));
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
return retval;
|
|
1057
|
+
|
|
1034
1058
|
}
|
|
1035
1059
|
// has no head
|
|
1036
1060
|
else {
|
|
@@ -1141,6 +1165,7 @@ namespace Sass {
|
|
|
1141
1165
|
Complex_Selector* Complex_Selector::clone(Context& ctx) const
|
|
1142
1166
|
{
|
|
1143
1167
|
Complex_Selector* cpy = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, *this);
|
|
1168
|
+
cpy->is_optional(this->is_optional());
|
|
1144
1169
|
cpy->media_block(this->media_block());
|
|
1145
1170
|
if (tail()) cpy->tail(tail()->clone(ctx));
|
|
1146
1171
|
return cpy;
|
|
@@ -1149,7 +1174,8 @@ namespace Sass {
|
|
|
1149
1174
|
Complex_Selector* Complex_Selector::cloneFully(Context& ctx) const
|
|
1150
1175
|
{
|
|
1151
1176
|
Complex_Selector* cpy = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, *this);
|
|
1152
|
-
|
|
1177
|
+
cpy->is_optional(this->is_optional());
|
|
1178
|
+
cpy->media_block(this->media_block());
|
|
1153
1179
|
if (head()) {
|
|
1154
1180
|
cpy->head(head()->clone(ctx));
|
|
1155
1181
|
}
|
|
@@ -1164,13 +1190,16 @@ namespace Sass {
|
|
|
1164
1190
|
Compound_Selector* Compound_Selector::clone(Context& ctx) const
|
|
1165
1191
|
{
|
|
1166
1192
|
Compound_Selector* cpy = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, *this);
|
|
1193
|
+
cpy->is_optional(this->is_optional());
|
|
1167
1194
|
cpy->media_block(this->media_block());
|
|
1195
|
+
cpy->extended(this->extended());
|
|
1168
1196
|
return cpy;
|
|
1169
1197
|
}
|
|
1170
1198
|
|
|
1171
1199
|
Selector_List* Selector_List::clone(Context& ctx) const
|
|
1172
1200
|
{
|
|
1173
1201
|
Selector_List* cpy = SASS_MEMORY_NEW(ctx.mem, Selector_List, *this);
|
|
1202
|
+
cpy->is_optional(this->is_optional());
|
|
1174
1203
|
cpy->media_block(this->media_block());
|
|
1175
1204
|
return cpy;
|
|
1176
1205
|
}
|
|
@@ -1178,6 +1207,8 @@ namespace Sass {
|
|
|
1178
1207
|
Selector_List* Selector_List::cloneFully(Context& ctx) const
|
|
1179
1208
|
{
|
|
1180
1209
|
Selector_List* cpy = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
|
1210
|
+
cpy->is_optional(this->is_optional());
|
|
1211
|
+
cpy->media_block(this->media_block());
|
|
1181
1212
|
for (size_t i = 0, L = length(); i < L; ++i) {
|
|
1182
1213
|
*cpy << (*this)[i]->cloneFully(ctx);
|
|
1183
1214
|
}
|
|
@@ -1213,9 +1244,17 @@ namespace Sass {
|
|
|
1213
1244
|
}
|
|
1214
1245
|
}
|
|
1215
1246
|
|
|
1247
|
+
bool Selector_List::has_parent_ref()
|
|
1248
|
+
{
|
|
1249
|
+
for (Complex_Selector* s : *this) {
|
|
1250
|
+
if (s->has_parent_ref()) return true;
|
|
1251
|
+
}
|
|
1252
|
+
return false;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1216
1255
|
void Selector_List::adjust_after_pushing(Complex_Selector* c)
|
|
1217
1256
|
{
|
|
1218
|
-
if (c->has_reference()) has_reference(true);
|
|
1257
|
+
// if (c->has_reference()) has_reference(true);
|
|
1219
1258
|
}
|
|
1220
1259
|
|
|
1221
1260
|
// it's a superselector if every selector of the right side
|
|
@@ -1287,8 +1326,8 @@ namespace Sass {
|
|
|
1287
1326
|
return final_result;
|
|
1288
1327
|
}
|
|
1289
1328
|
|
|
1290
|
-
void Selector_List::populate_extends(Selector_List* extendee, Context& ctx, ExtensionSubsetMap& extends)
|
|
1291
|
-
|
|
1329
|
+
void Selector_List::populate_extends(Selector_List* extendee, Context& ctx, ExtensionSubsetMap& extends)
|
|
1330
|
+
{
|
|
1292
1331
|
|
|
1293
1332
|
Selector_List* extender = this;
|
|
1294
1333
|
for (auto complex_sel : extendee->elements()) {
|
|
@@ -1322,17 +1361,15 @@ namespace Sass {
|
|
|
1322
1361
|
|
|
1323
1362
|
std::vector<std::string> Compound_Selector::to_str_vec()
|
|
1324
1363
|
{
|
|
1325
|
-
To_String to_string;
|
|
1326
1364
|
std::vector<std::string> result;
|
|
1327
1365
|
result.reserve(length());
|
|
1328
1366
|
for (size_t i = 0, L = length(); i < L; ++i)
|
|
1329
|
-
{ result.push_back((*this)[i]->
|
|
1367
|
+
{ result.push_back((*this)[i]->to_string()); }
|
|
1330
1368
|
return result;
|
|
1331
1369
|
}
|
|
1332
1370
|
|
|
1333
1371
|
Compound_Selector* Compound_Selector::minus(Compound_Selector* rhs, Context& ctx)
|
|
1334
1372
|
{
|
|
1335
|
-
To_String to_string(&ctx);
|
|
1336
1373
|
Compound_Selector* result = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pstate());
|
|
1337
1374
|
// result->has_parent_reference(has_parent_reference());
|
|
1338
1375
|
|
|
@@ -1340,10 +1377,10 @@ namespace Sass {
|
|
|
1340
1377
|
for (size_t i = 0, L = length(); i < L; ++i)
|
|
1341
1378
|
{
|
|
1342
1379
|
bool found = false;
|
|
1343
|
-
std::string thisSelector((*this)[i]->
|
|
1380
|
+
std::string thisSelector((*this)[i]->to_string(ctx.c_options));
|
|
1344
1381
|
for (size_t j = 0, M = rhs->length(); j < M; ++j)
|
|
1345
1382
|
{
|
|
1346
|
-
if (thisSelector == (*rhs)[j]->
|
|
1383
|
+
if (thisSelector == (*rhs)[j]->to_string(ctx.c_options))
|
|
1347
1384
|
{
|
|
1348
1385
|
found = true;
|
|
1349
1386
|
break;
|
|
@@ -1362,6 +1399,36 @@ namespace Sass {
|
|
|
1362
1399
|
}
|
|
1363
1400
|
}
|
|
1364
1401
|
|
|
1402
|
+
Argument* Arguments::get_rest_argument()
|
|
1403
|
+
{
|
|
1404
|
+
Argument* arg = 0;
|
|
1405
|
+
if (this->has_rest_argument()) {
|
|
1406
|
+
for (auto a : this->elements()) {
|
|
1407
|
+
if (a->is_rest_argument()) {
|
|
1408
|
+
arg = a;
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
return arg;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
Argument* Arguments::get_keyword_argument()
|
|
1418
|
+
{
|
|
1419
|
+
Argument* arg = 0;
|
|
1420
|
+
if (this->has_keyword_argument()) {
|
|
1421
|
+
for (auto a : this->elements()) {
|
|
1422
|
+
if (a->is_keyword_argument()) {
|
|
1423
|
+
arg = a;
|
|
1424
|
+
break;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
return arg;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1365
1432
|
void Arguments::adjust_after_pushing(Argument* a)
|
|
1366
1433
|
{
|
|
1367
1434
|
if (!a->name().empty()) {
|
|
@@ -1453,7 +1520,13 @@ namespace Sass {
|
|
|
1453
1520
|
return u;
|
|
1454
1521
|
}
|
|
1455
1522
|
|
|
1456
|
-
bool Number::
|
|
1523
|
+
bool Number::is_valid_css_unit() const
|
|
1524
|
+
{
|
|
1525
|
+
return numerator_units().size() <= 1 &&
|
|
1526
|
+
denominator_units().size() == 0;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
bool Number::is_unitless() const
|
|
1457
1530
|
{ return numerator_units_.empty() && denominator_units_.empty(); }
|
|
1458
1531
|
|
|
1459
1532
|
void Number::normalize(const std::string& prefered, bool strict)
|
|
@@ -1541,10 +1614,128 @@ namespace Sass {
|
|
|
1541
1614
|
|
|
1542
1615
|
}
|
|
1543
1616
|
|
|
1544
|
-
|
|
1617
|
+
// this does not cover all cases (multiple prefered units)
|
|
1618
|
+
double Number::convert_factor(const Number& n) const
|
|
1619
|
+
{
|
|
1620
|
+
|
|
1621
|
+
// first make sure same units cancel each other out
|
|
1622
|
+
// it seems that a map table will fit nicely to do this
|
|
1623
|
+
// we basically construct exponents for each unit class
|
|
1624
|
+
// std::map<std::string, int> exponents;
|
|
1625
|
+
// initialize by summing up occurences in unit vectors
|
|
1626
|
+
// for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[unit_to_class(numerator_units_[i])];
|
|
1627
|
+
// for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[unit_to_class(denominator_units_[i])];
|
|
1628
|
+
|
|
1629
|
+
std::vector<std::string> l_miss_nums(0);
|
|
1630
|
+
std::vector<std::string> l_miss_dens(0);
|
|
1631
|
+
// create copy since we need these for state keeping
|
|
1632
|
+
std::vector<std::string> r_nums(n.numerator_units_);
|
|
1633
|
+
std::vector<std::string> r_dens(n.denominator_units_);
|
|
1634
|
+
|
|
1635
|
+
std::vector<std::string>::const_iterator l_num_it = numerator_units_.begin();
|
|
1636
|
+
std::vector<std::string>::const_iterator l_num_end = numerator_units_.end();
|
|
1637
|
+
|
|
1638
|
+
bool l_unitless = is_unitless();
|
|
1639
|
+
bool r_unitless = n.is_unitless();
|
|
1640
|
+
|
|
1641
|
+
// overall conversion
|
|
1642
|
+
double factor = 1;
|
|
1643
|
+
|
|
1644
|
+
// process all left numerators
|
|
1645
|
+
while (l_num_it != l_num_end)
|
|
1646
|
+
{
|
|
1647
|
+
// get and increment afterwards
|
|
1648
|
+
const std::string l_num = *(l_num_it ++);
|
|
1649
|
+
|
|
1650
|
+
std::vector<std::string>::iterator r_num_it = r_nums.begin();
|
|
1651
|
+
std::vector<std::string>::iterator r_num_end = r_nums.end();
|
|
1652
|
+
|
|
1653
|
+
bool found = false;
|
|
1654
|
+
// search for compatible numerator
|
|
1655
|
+
while (r_num_it != r_num_end)
|
|
1656
|
+
{
|
|
1657
|
+
// get and increment afterwards
|
|
1658
|
+
const std::string r_num = *(r_num_it);
|
|
1659
|
+
// get possible converstion factor for units
|
|
1660
|
+
double conversion = conversion_factor(l_num, r_num, false);
|
|
1661
|
+
// skip incompatible numerator
|
|
1662
|
+
if (conversion == 0) {
|
|
1663
|
+
++ r_num_it;
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
// apply to global factor
|
|
1667
|
+
factor *= conversion;
|
|
1668
|
+
// remove item from vector
|
|
1669
|
+
r_nums.erase(r_num_it);
|
|
1670
|
+
// found numerator
|
|
1671
|
+
found = true;
|
|
1672
|
+
break;
|
|
1673
|
+
}
|
|
1674
|
+
// maybe we did not find any
|
|
1675
|
+
// left numerator is leftover
|
|
1676
|
+
if (!found) l_miss_nums.push_back(l_num);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
std::vector<std::string>::const_iterator l_den_it = denominator_units_.begin();
|
|
1680
|
+
std::vector<std::string>::const_iterator l_den_end = denominator_units_.end();
|
|
1681
|
+
|
|
1682
|
+
// process all left denominators
|
|
1683
|
+
while (l_den_it != l_den_end)
|
|
1684
|
+
{
|
|
1685
|
+
// get and increment afterwards
|
|
1686
|
+
const std::string l_den = *(l_den_it ++);
|
|
1687
|
+
|
|
1688
|
+
std::vector<std::string>::iterator r_den_it = r_dens.begin();
|
|
1689
|
+
std::vector<std::string>::iterator r_den_end = r_dens.end();
|
|
1690
|
+
|
|
1691
|
+
bool found = false;
|
|
1692
|
+
// search for compatible denominator
|
|
1693
|
+
while (r_den_it != r_den_end)
|
|
1694
|
+
{
|
|
1695
|
+
// get and increment afterwards
|
|
1696
|
+
const std::string r_den = *(r_den_it);
|
|
1697
|
+
// get possible converstion factor for units
|
|
1698
|
+
double conversion = conversion_factor(l_den, r_den, false);
|
|
1699
|
+
// skip incompatible denominator
|
|
1700
|
+
if (conversion == 0) {
|
|
1701
|
+
++ r_den_it;
|
|
1702
|
+
continue;
|
|
1703
|
+
}
|
|
1704
|
+
// apply to global factor
|
|
1705
|
+
factor *= conversion;
|
|
1706
|
+
// remove item from vector
|
|
1707
|
+
r_dens.erase(r_den_it);
|
|
1708
|
+
// found denominator
|
|
1709
|
+
found = true;
|
|
1710
|
+
break;
|
|
1711
|
+
}
|
|
1712
|
+
// maybe we did not find any
|
|
1713
|
+
// left denominator is leftover
|
|
1714
|
+
if (!found) l_miss_dens.push_back(l_den);
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// check left-overs (ToDo: might cancel out)
|
|
1718
|
+
if (l_miss_nums.size() > 0 && !r_unitless) {
|
|
1719
|
+
throw Exception::IncompatibleUnits(n, *this);
|
|
1720
|
+
}
|
|
1721
|
+
if (l_miss_dens.size() > 0 && !r_unitless) {
|
|
1722
|
+
throw Exception::IncompatibleUnits(n, *this);
|
|
1723
|
+
}
|
|
1724
|
+
if (r_nums.size() > 0 && !l_unitless) {
|
|
1725
|
+
throw Exception::IncompatibleUnits(n, *this);
|
|
1726
|
+
}
|
|
1727
|
+
if (r_dens.size() > 0 && !l_unitless) {
|
|
1728
|
+
throw Exception::IncompatibleUnits(n, *this);
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
return factor;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
// this does not cover all cases (multiple prefered units)
|
|
1735
|
+
bool Number::convert(const std::string& prefered, bool strict)
|
|
1545
1736
|
{
|
|
1546
|
-
//
|
|
1547
|
-
if (prefered.empty()) return;
|
|
1737
|
+
// no conversion if unit is empty
|
|
1738
|
+
if (prefered.empty()) return true;
|
|
1548
1739
|
|
|
1549
1740
|
// first make sure same units cancel each other out
|
|
1550
1741
|
// it seems that a map table will fit nicely to do this
|
|
@@ -1626,6 +1817,9 @@ namespace Sass {
|
|
|
1626
1817
|
// best precision this way
|
|
1627
1818
|
value_ *= factor;
|
|
1628
1819
|
|
|
1820
|
+
// success?
|
|
1821
|
+
return true;
|
|
1822
|
+
|
|
1629
1823
|
}
|
|
1630
1824
|
|
|
1631
1825
|
// useful for making one number compatible with another
|
|
@@ -1661,6 +1855,12 @@ namespace Sass {
|
|
|
1661
1855
|
bool Number::operator== (const Expression& rhs) const
|
|
1662
1856
|
{
|
|
1663
1857
|
if (const Number* r = dynamic_cast<const Number*>(&rhs)) {
|
|
1858
|
+
size_t lhs_units = numerator_units_.size() + denominator_units_.size();
|
|
1859
|
+
size_t rhs_units = r->numerator_units_.size() + r->denominator_units_.size();
|
|
1860
|
+
// unitless and only having one unit seems equivalent (will change in future)
|
|
1861
|
+
if (!lhs_units || !rhs_units) {
|
|
1862
|
+
return std::fabs(value() - r->value()) < NUMBER_EPSILON;
|
|
1863
|
+
}
|
|
1664
1864
|
return (numerator_units_ == r->numerator_units_) &&
|
|
1665
1865
|
(denominator_units_ == r->denominator_units_) &&
|
|
1666
1866
|
std::fabs(value() - r->value()) < NUMBER_EPSILON;
|
|
@@ -1670,11 +1870,18 @@ namespace Sass {
|
|
|
1670
1870
|
|
|
1671
1871
|
bool Number::operator< (const Number& rhs) const
|
|
1672
1872
|
{
|
|
1873
|
+
size_t lhs_units = numerator_units_.size() + denominator_units_.size();
|
|
1874
|
+
size_t rhs_units = rhs.numerator_units_.size() + rhs.denominator_units_.size();
|
|
1875
|
+
// unitless and only having one unit seems equivalent (will change in future)
|
|
1876
|
+
if (!lhs_units || !rhs_units) {
|
|
1877
|
+
return value() < rhs.value();
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1673
1880
|
Number tmp_r(rhs);
|
|
1674
1881
|
tmp_r.normalize(find_convertible_unit());
|
|
1675
1882
|
std::string l_unit(unit());
|
|
1676
1883
|
std::string r_unit(tmp_r.unit());
|
|
1677
|
-
if (
|
|
1884
|
+
if (unit() != tmp_r.unit()) {
|
|
1678
1885
|
error("cannot compare numbers with incompatible units", pstate());
|
|
1679
1886
|
}
|
|
1680
1887
|
return value() < tmp_r.value();
|
|
@@ -1700,6 +1907,15 @@ namespace Sass {
|
|
|
1700
1907
|
return false;
|
|
1701
1908
|
}
|
|
1702
1909
|
|
|
1910
|
+
bool String_Schema::is_left_interpolant(void) const
|
|
1911
|
+
{
|
|
1912
|
+
return length() && first()->is_left_interpolant();
|
|
1913
|
+
}
|
|
1914
|
+
bool String_Schema::is_right_interpolant(void) const
|
|
1915
|
+
{
|
|
1916
|
+
return length() && last()->is_right_interpolant();
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1703
1919
|
bool String_Schema::operator== (const Expression& rhs) const
|
|
1704
1920
|
{
|
|
1705
1921
|
if (const String_Schema* r = dynamic_cast<const String_Schema*>(&rhs)) {
|
|
@@ -1789,65 +2005,29 @@ namespace Sass {
|
|
|
1789
2005
|
else { return &sass_null; }
|
|
1790
2006
|
}
|
|
1791
2007
|
|
|
1792
|
-
|
|
2008
|
+
bool Binary_Expression::is_left_interpolant(void) const
|
|
1793
2009
|
{
|
|
1794
|
-
|
|
1795
|
-
if (empty()) return res;
|
|
1796
|
-
if (is_invisible()) return res;
|
|
1797
|
-
bool items_output = false;
|
|
1798
|
-
for (auto key : keys()) {
|
|
1799
|
-
if (key->is_invisible()) continue;
|
|
1800
|
-
if (at(key)->is_invisible()) continue;
|
|
1801
|
-
if (items_output) res += compressed ? "," : ", ";
|
|
1802
|
-
Value* v_key = dynamic_cast<Value*>(key);
|
|
1803
|
-
Value* v_val = dynamic_cast<Value*>(at(key));
|
|
1804
|
-
if (v_key) res += v_key->to_string(compressed, precision);
|
|
1805
|
-
res += compressed ? ":" : ": ";
|
|
1806
|
-
if (v_val) res += v_val->to_string(compressed, precision);
|
|
1807
|
-
items_output = true;
|
|
1808
|
-
}
|
|
1809
|
-
return res;
|
|
2010
|
+
return is_interpolant() || (left() && left()->is_left_interpolant());
|
|
1810
2011
|
}
|
|
1811
|
-
|
|
1812
|
-
std::string List::to_string(bool compressed, int precision) const
|
|
2012
|
+
bool Binary_Expression::is_right_interpolant(void) const
|
|
1813
2013
|
{
|
|
1814
|
-
|
|
1815
|
-
if (empty()) return res;
|
|
1816
|
-
if (is_invisible()) return res;
|
|
1817
|
-
bool items_output = false;
|
|
1818
|
-
std::string sep = separator() == SASS_COMMA ? "," : " ";
|
|
1819
|
-
if (!compressed && sep == ",") sep += " ";
|
|
1820
|
-
for (size_t i = 0, L = size(); i < L; ++i) {
|
|
1821
|
-
Expression* item = (*this)[i];
|
|
1822
|
-
if (item->is_invisible()) continue;
|
|
1823
|
-
if (items_output) res += sep;
|
|
1824
|
-
if (Value* v_val = dynamic_cast<Value*>(item))
|
|
1825
|
-
{ res += v_val->to_string(compressed, precision); }
|
|
1826
|
-
items_output = true;
|
|
1827
|
-
}
|
|
1828
|
-
return res;
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
std::string String_Schema::to_string(bool compressed, int precision) const
|
|
1832
|
-
{
|
|
1833
|
-
std::string res("");
|
|
1834
|
-
for (size_t i = 0, L = length(); i < L; ++i) {
|
|
1835
|
-
if ((*this)[i]->is_interpolant()) res += "#{";
|
|
1836
|
-
if (Value* val = dynamic_cast<Value*>((*this)[i]))
|
|
1837
|
-
{ res += val->to_string(compressed, precision); }
|
|
1838
|
-
if ((*this)[i]->is_interpolant()) res += "}";
|
|
1839
|
-
}
|
|
1840
|
-
return res;
|
|
2014
|
+
return is_interpolant() || (right() && right()->is_right_interpolant());
|
|
1841
2015
|
}
|
|
1842
2016
|
|
|
1843
|
-
std::string
|
|
2017
|
+
std::string AST_Node::to_string(Sass_Inspect_Options opt) const
|
|
1844
2018
|
{
|
|
1845
|
-
|
|
2019
|
+
Sass_Output_Options out(opt);
|
|
2020
|
+
Emitter emitter(out);
|
|
2021
|
+
Inspect i(emitter);
|
|
2022
|
+
i.in_declaration = true;
|
|
2023
|
+
// ToDo: inspect should be const
|
|
2024
|
+
const_cast<AST_Node*>(this)->perform(&i);
|
|
2025
|
+
return i.get_buffer();
|
|
1846
2026
|
}
|
|
1847
2027
|
|
|
1848
|
-
std::string
|
|
2028
|
+
std::string AST_Node::to_string() const
|
|
1849
2029
|
{
|
|
1850
|
-
return
|
|
2030
|
+
return to_string({ NESTED, 5 });
|
|
1851
2031
|
}
|
|
1852
2032
|
|
|
1853
2033
|
// helper function for serializing colors
|
|
@@ -1858,261 +2038,14 @@ namespace Sass {
|
|
|
1858
2038
|
else return c;
|
|
1859
2039
|
}
|
|
1860
2040
|
|
|
1861
|
-
std::string
|
|
1862
|
-
{
|
|
1863
|
-
std::stringstream ss;
|
|
1864
|
-
|
|
1865
|
-
// original color name
|
|
1866
|
-
// maybe an unknown token
|
|
1867
|
-
std::string name = disp();
|
|
1868
|
-
|
|
1869
|
-
// resolved color
|
|
1870
|
-
std::string res_name = name;
|
|
1871
|
-
|
|
1872
|
-
double r = Sass::round(cap_channel<0xff>(r_));
|
|
1873
|
-
double g = Sass::round(cap_channel<0xff>(g_));
|
|
1874
|
-
double b = Sass::round(cap_channel<0xff>(b_));
|
|
1875
|
-
double a = cap_channel<1> (a_);
|
|
1876
|
-
|
|
1877
|
-
// get color from given name (if one was given at all)
|
|
1878
|
-
if (name != "" && name_to_color(name)) {
|
|
1879
|
-
const Color* n = name_to_color(name);
|
|
1880
|
-
r = Sass::round(cap_channel<0xff>(n->r()));
|
|
1881
|
-
g = Sass::round(cap_channel<0xff>(n->g()));
|
|
1882
|
-
b = Sass::round(cap_channel<0xff>(n->b()));
|
|
1883
|
-
a = cap_channel<1> (n->a());
|
|
1884
|
-
}
|
|
1885
|
-
// otherwise get the possible resolved color name
|
|
1886
|
-
else {
|
|
1887
|
-
double numval = r * 0x10000 + g * 0x100 + b;
|
|
1888
|
-
if (color_to_name(numval))
|
|
1889
|
-
res_name = color_to_name(numval);
|
|
1890
|
-
}
|
|
1891
|
-
|
|
1892
|
-
std::stringstream hexlet;
|
|
1893
|
-
hexlet << '#' << std::setw(1) << std::setfill('0');
|
|
1894
|
-
// create a short color hexlet if there is any need for it
|
|
1895
|
-
if (compressed && is_color_doublet(r, g, b) && a == 1) {
|
|
1896
|
-
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(r) >> 4);
|
|
1897
|
-
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(g) >> 4);
|
|
1898
|
-
hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(b) >> 4);
|
|
1899
|
-
} else {
|
|
1900
|
-
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(r);
|
|
1901
|
-
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(g);
|
|
1902
|
-
hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(b);
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
if (compressed && !this->is_delayed()) name = "";
|
|
1906
|
-
|
|
1907
|
-
// retain the originally specified color definition if unchanged
|
|
1908
|
-
if (name != "") {
|
|
1909
|
-
ss << name;
|
|
1910
|
-
}
|
|
1911
|
-
else if (r == 0 && g == 0 && b == 0 && a == 0) {
|
|
1912
|
-
ss << "transparent";
|
|
1913
|
-
}
|
|
1914
|
-
else if (a >= 1) {
|
|
1915
|
-
if (res_name != "") {
|
|
1916
|
-
if (compressed && hexlet.str().size() < res_name.size()) {
|
|
1917
|
-
ss << hexlet.str();
|
|
1918
|
-
} else {
|
|
1919
|
-
ss << res_name;
|
|
1920
|
-
}
|
|
1921
|
-
}
|
|
1922
|
-
else {
|
|
1923
|
-
ss << hexlet.str();
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
else {
|
|
1927
|
-
ss << "rgba(";
|
|
1928
|
-
ss << static_cast<unsigned long>(r) << ",";
|
|
1929
|
-
if (!compressed) ss << " ";
|
|
1930
|
-
ss << static_cast<unsigned long>(g) << ",";
|
|
1931
|
-
if (!compressed) ss << " ";
|
|
1932
|
-
ss << static_cast<unsigned long>(b) << ",";
|
|
1933
|
-
if (!compressed) ss << " ";
|
|
1934
|
-
ss << a << ')';
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
return ss.str();
|
|
1938
|
-
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
std::string Number::to_string(bool compressed, int precision) const
|
|
1942
|
-
{
|
|
1943
|
-
|
|
1944
|
-
std::string res;
|
|
1945
|
-
|
|
1946
|
-
// check if the fractional part of the value equals to zero
|
|
1947
|
-
// neat trick from http://stackoverflow.com/a/1521682/1550314
|
|
1948
|
-
// double int_part; bool is_int = modf(value, &int_part) == 0.0;
|
|
1949
|
-
|
|
1950
|
-
// this all cannot be done with one run only, since fixed
|
|
1951
|
-
// output differs from normal output and regular output
|
|
1952
|
-
// can contain scientific notation which we do not want!
|
|
1953
|
-
|
|
1954
|
-
// first sample
|
|
1955
|
-
std::stringstream ss;
|
|
1956
|
-
ss.precision(12);
|
|
1957
|
-
ss << value_;
|
|
1958
|
-
|
|
1959
|
-
// check if we got scientific notation in result
|
|
1960
|
-
if (ss.str().find_first_of("e") != std::string::npos) {
|
|
1961
|
-
ss.clear(); ss.str(std::string());
|
|
1962
|
-
ss.precision(std::max(12, precision));
|
|
1963
|
-
ss << std::fixed << value_;
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
std::string tmp = ss.str();
|
|
1967
|
-
size_t pos_point = tmp.find_first_of(".,");
|
|
1968
|
-
size_t pos_fract = tmp.find_last_not_of("0");
|
|
1969
|
-
bool is_int = pos_point == pos_fract ||
|
|
1970
|
-
pos_point == std::string::npos;
|
|
1971
|
-
|
|
1972
|
-
// reset stream for another run
|
|
1973
|
-
ss.clear(); ss.str(std::string());
|
|
1974
|
-
|
|
1975
|
-
// take a shortcut for integers
|
|
1976
|
-
if (is_int)
|
|
1977
|
-
{
|
|
1978
|
-
ss.precision(0);
|
|
1979
|
-
ss << std::fixed << value_;
|
|
1980
|
-
res = std::string(ss.str());
|
|
1981
|
-
}
|
|
1982
|
-
// process floats
|
|
1983
|
-
else
|
|
1984
|
-
{
|
|
1985
|
-
// do we have have too much precision?
|
|
1986
|
-
if (pos_fract < precision + pos_point)
|
|
1987
|
-
{ precision = (int)(pos_fract - pos_point); }
|
|
1988
|
-
// round value again
|
|
1989
|
-
ss.precision(precision);
|
|
1990
|
-
ss << std::fixed << value_;
|
|
1991
|
-
res = std::string(ss.str());
|
|
1992
|
-
// maybe we truncated up to decimal point
|
|
1993
|
-
size_t pos = res.find_last_not_of("0");
|
|
1994
|
-
bool at_dec_point = res[pos] == '.' ||
|
|
1995
|
-
res[pos] == ',';
|
|
1996
|
-
// don't leave a blank point
|
|
1997
|
-
if (at_dec_point) ++ pos;
|
|
1998
|
-
res.resize (pos + 1);
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
// some final cosmetics
|
|
2002
|
-
if (res == "-0.0") res.erase(0, 1);
|
|
2003
|
-
else if (res == "-0") res.erase(0, 1);
|
|
2004
|
-
else if (res == "") res = "0";
|
|
2005
|
-
|
|
2006
|
-
// add unit now
|
|
2007
|
-
res += unit();
|
|
2008
|
-
|
|
2009
|
-
// and return
|
|
2010
|
-
return res;
|
|
2011
|
-
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
std::string String_Quoted::to_string(bool compressed, int precision) const
|
|
2015
|
-
{
|
|
2016
|
-
return quote_mark_ ? quote(value_, quote_mark_, true) : value_;
|
|
2017
|
-
}
|
|
2018
|
-
|
|
2019
|
-
std::string String_Constant::to_string(bool compressed, int precision) const
|
|
2020
|
-
{
|
|
2021
|
-
return quote_mark_ ? quote(value_, quote_mark_, true) : value_;
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
|
-
std::string Custom_Error::to_string(bool compressed, int precision) const
|
|
2025
|
-
{
|
|
2026
|
-
return message();
|
|
2027
|
-
}
|
|
2028
|
-
std::string Custom_Warning::to_string(bool compressed, int precision) const
|
|
2029
|
-
{
|
|
2030
|
-
return message();
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
std::string Selector_List::to_string(bool compressed, int precision) const
|
|
2034
|
-
{
|
|
2035
|
-
std::string str("");
|
|
2036
|
-
auto end = this->end();
|
|
2037
|
-
auto start = this->begin();
|
|
2038
|
-
while (start < end && *start) {
|
|
2039
|
-
Complex_Selector* sel = *start;
|
|
2040
|
-
if (!str.empty()) str += ", ";
|
|
2041
|
-
str += sel->to_string(compressed, precision);
|
|
2042
|
-
++ start;
|
|
2043
|
-
}
|
|
2044
|
-
return str;
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
std::string Compound_Selector::to_string(bool compressed, int precision) const
|
|
2048
|
-
{
|
|
2049
|
-
std::string str("");
|
|
2050
|
-
auto end = this->end();
|
|
2051
|
-
auto start = this->begin();
|
|
2052
|
-
while (start < end && *start) {
|
|
2053
|
-
Simple_Selector* sel = *start;
|
|
2054
|
-
str += sel->to_string(compressed, precision);
|
|
2055
|
-
++ start;
|
|
2056
|
-
}
|
|
2057
|
-
return str;
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
std::string Complex_Selector::to_string(bool compressed, int precision) const
|
|
2061
|
-
{
|
|
2062
|
-
// first render head and tail if they are available
|
|
2063
|
-
std::string str_head(head() ? head()->to_string(compressed, precision) : "");
|
|
2064
|
-
std::string str_tail(tail() ? tail()->to_string(compressed, precision) : "");
|
|
2065
|
-
std::string str_ref(reference() ? reference()->to_string(compressed, precision) : "");
|
|
2066
|
-
// combinator in between
|
|
2067
|
-
std::string str_op("");
|
|
2068
|
-
// use a switch statement
|
|
2069
|
-
switch (combinator()) {
|
|
2070
|
-
case ANCESTOR_OF: str_op = " "; break;
|
|
2071
|
-
case PARENT_OF: str_op = ">"; break;
|
|
2072
|
-
case PRECEDES: str_op = "~"; break;
|
|
2073
|
-
case ADJACENT_TO: str_op = "+"; break;
|
|
2074
|
-
case REFERENCE: str_op = "/" + str_ref + "/"; break;
|
|
2075
|
-
}
|
|
2076
|
-
// prettify for non ancestors
|
|
2077
|
-
if (combinator() != ANCESTOR_OF) {
|
|
2078
|
-
// no spaces needed for compressed
|
|
2079
|
-
if (compressed == false) {
|
|
2080
|
-
// make sure we add some spaces where needed
|
|
2081
|
-
if (str_tail != "") str_op += " ";
|
|
2082
|
-
if (str_head != "") str_head += " ";
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
// is ancestor with no tail
|
|
2086
|
-
else if (str_tail == "") {
|
|
2087
|
-
str_op = ""; // superflous
|
|
2088
|
-
}
|
|
2089
|
-
// now build the final result
|
|
2090
|
-
return str_head + str_op + str_tail;
|
|
2091
|
-
}
|
|
2092
|
-
|
|
2093
|
-
std::string Selector_Schema::to_string(bool compressed, int precision) const
|
|
2094
|
-
{
|
|
2095
|
-
return contents()->to_string(compressed, precision);
|
|
2096
|
-
}
|
|
2097
|
-
|
|
2098
|
-
std::string Parent_Selector::to_string(bool compressed, int precision) const
|
|
2099
|
-
{
|
|
2100
|
-
return "&";
|
|
2101
|
-
}
|
|
2102
|
-
|
|
2103
|
-
std::string Attribute_Selector::to_string(bool compressed, int precision) const
|
|
2041
|
+
std::string String_Quoted::inspect() const
|
|
2104
2042
|
{
|
|
2105
|
-
|
|
2106
|
-
return "[" + this->ns_name() + this->matcher() + val + "]";
|
|
2043
|
+
return quote(value_, '*');
|
|
2107
2044
|
}
|
|
2108
2045
|
|
|
2109
|
-
std::string
|
|
2046
|
+
std::string String_Constant::inspect() const
|
|
2110
2047
|
{
|
|
2111
|
-
|
|
2112
|
-
std::string main(this->Simple_Selector::to_string(compressed, precision));
|
|
2113
|
-
std::string wrapped(selector() ? selector()->to_string(compressed, precision) : "");
|
|
2114
|
-
// now build the final result
|
|
2115
|
-
return main + "(" + wrapped + ")";
|
|
2048
|
+
return quote(value_, '*');
|
|
2116
2049
|
}
|
|
2117
2050
|
|
|
2118
2051
|
//////////////////////////////////////////////////////////////////////////////////////////
|