sassc 1.8.3 → 1.8.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
//////////////////////////////////////////////////////////////////////////////////////////
|