sassc 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d99b651f166586b10487e114cbe57530cf41072
4
- data.tar.gz: e8d4530c45f6aac6d2f8f4b6a8b596e459c2a150
3
+ metadata.gz: cba905c4a611564a30f673941af311b360e64f79
4
+ data.tar.gz: 83bfb6df3c6ebb5e086badf0a950ebc839cbc6f7
5
5
  SHA512:
6
- metadata.gz: 488fc5c6270fbdc0e86f3a6639e3a64ace06c9497eb0f56f545d014c6bb26135ffae85cfcb5abdbc94bdf8dae067f51e826e66e381a871529c32b1dfb78ca1d2
7
- data.tar.gz: 68bb498e92248b581a9eeffc90d9fc661712ab504bb547cf562a52376d545f4bbbf0323cd1d5ee84c43e753aaeafc15697c26f325fe5958815f5d69096899dd3
6
+ metadata.gz: bd8dbb02e65de541608e51da7738824d1de7a8db2429d4b05396173a861ec2bbcd4d191ab39b426427b7ed5f31bcacf94a22782295827d736b1c0c1e8bd44212
7
+ data.tar.gz: e6c839d26054ff6bba74ab525e357f3161a25416748baacc0a2abd416ad21d0a9dafeb6d8d038e8a929d08eac12e28a53d109b0a2aaa4e4902b89abd715be1ac
data/README.md CHANGED
@@ -6,7 +6,7 @@ This gem combines the speed of `libsass`, the [Sass C implementation](https://gi
6
6
 
7
7
  ### libsass Version
8
8
 
9
- [3.2.0-beta.6](https://github.com/sass/libsass/releases/tag/3.2.0-beta.6)
9
+ [3.2.2](https://github.com/sass/libsass/releases/tag/3.2.2)
10
10
 
11
11
  ## Usage
12
12
 
@@ -7,7 +7,7 @@ by Aaron Leung ([@akhleung]) and Hampton Catlin ([@hcatlin])
7
7
  [![Windows CI](https://ci.appveyor.com/api/projects/status/github/sass/libsass?svg=true)](https://ci.appveyor.com/project/sass/libsass/branch/master)
8
8
  [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283068)](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE)
9
9
  [![Coverage Status](https://img.shields.io/coveralls/sass/libsass.svg)](https://coveralls.io/r/sass/libsass?branch=feature%2Ftest-travis-ci-3)
10
- [![Join us](https://still-ridge-9421.herokuapp.com/badge.svg)](https://still-ridge-9421.herokuapp.com/)
10
+ [![Join us](https://libsass-slack.herokuapp.com/badge.svg)](https://libsass-slack.herokuapp.com/)
11
11
 
12
12
  https://github.com/sass/libsass
13
13
 
@@ -589,6 +589,270 @@ namespace Sass {
589
589
  return result;
590
590
  }*/
591
591
 
592
+ Number::Number(ParserState pstate, double val, string u, bool zero)
593
+ : Expression(pstate),
594
+ value_(val),
595
+ zero_(zero),
596
+ numerator_units_(vector<string>()),
597
+ denominator_units_(vector<string>()),
598
+ hash_(0)
599
+ {
600
+ size_t l = 0, r = 0;
601
+ if (!u.empty()) {
602
+ bool nominator = true;
603
+ while (true) {
604
+ r = u.find_first_of("*/", l);
605
+ string unit(u.substr(l, r - l));
606
+ if (nominator) numerator_units_.push_back(unit);
607
+ else denominator_units_.push_back(unit);
608
+ if (u[r] == '/') nominator = false;
609
+ if (r == string::npos) break;
610
+ else l = r + 1;
611
+ }
612
+ }
613
+ concrete_type(NUMBER);
614
+ }
615
+
616
+ string Number::unit() const
617
+ {
618
+ stringstream u;
619
+ for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
620
+ if (i) u << '*';
621
+ u << numerator_units_[i];
622
+ }
623
+ if (!denominator_units_.empty()) u << '/';
624
+ for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
625
+ if (i) u << '*';
626
+ u << denominator_units_[i];
627
+ }
628
+ return u.str();
629
+ }
630
+
631
+ bool Number::is_unitless()
632
+ { return numerator_units_.empty() && denominator_units_.empty(); }
633
+
634
+ void Number::normalize(const string& prefered)
635
+ {
636
+
637
+ // first make sure same units cancel each other out
638
+ // it seems that a map table will fit nicely to do this
639
+ // we basically construct exponents for each unit
640
+ // has the advantage that they will be pre-sorted
641
+ map<string, int> exponents;
642
+
643
+ // initialize by summing up occurences in unit vectors
644
+ for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
645
+ for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
646
+
647
+ // the final conversion factor
648
+ double factor = 1;
649
+
650
+ // get the first entry of numerators
651
+ // forward it when entry is converted
652
+ vector<string>::iterator nom_it = numerator_units_.begin();
653
+ vector<string>::iterator nom_end = numerator_units_.end();
654
+ vector<string>::iterator denom_it = denominator_units_.begin();
655
+ vector<string>::iterator denom_end = denominator_units_.end();
656
+
657
+ // main normalization loop
658
+ // should be close to optimal
659
+ while (denom_it != denom_end)
660
+ {
661
+ // get and increment afterwards
662
+ const string denom = *(denom_it ++);
663
+ // skip already canceled out unit
664
+ if (exponents[denom] >= 0) continue;
665
+ // skip all units we don't know how to convert
666
+ if (string_to_unit(denom) == INCOMMENSURABLE) continue;
667
+ // now search for nominator
668
+ while (nom_it != nom_end)
669
+ {
670
+ // get and increment afterwards
671
+ const string nom = *(nom_it ++);
672
+ // skip already canceled out unit
673
+ if (exponents[nom] <= 0) continue;
674
+ // skip all units we don't know how to convert
675
+ if (string_to_unit(nom) == INCOMMENSURABLE) continue;
676
+ // we now have two convertable units
677
+ // add factor for current conversion
678
+ factor *= conversion_factor(nom, denom);
679
+ // update nominator/denominator exponent
680
+ -- exponents[nom]; ++ exponents[denom];
681
+ // inner loop done
682
+ break;
683
+ }
684
+ }
685
+
686
+ // now we can build up the new unit arrays
687
+ numerator_units_.clear();
688
+ denominator_units_.clear();
689
+
690
+ // build them by iterating over the exponents
691
+ for (auto exp : exponents)
692
+ {
693
+ // maybe there is more effecient way to push
694
+ // the same item multiple times to a vector?
695
+ for(size_t i = 0, S = abs(exp.second); i < S; ++i)
696
+ {
697
+ // opted to have these switches in the inner loop
698
+ // makes it more readable and should not cost much
699
+ if (exp.second < 0) denominator_units_.push_back(exp.first);
700
+ else if (exp.second > 0) numerator_units_.push_back(exp.first);
701
+ }
702
+ }
703
+
704
+ // apply factor to value_
705
+ // best precision this way
706
+ value_ *= factor;
707
+
708
+ // maybe convert to other unit
709
+ // easier implemented on its own
710
+ convert(prefered);
711
+
712
+ }
713
+
714
+ void Number::convert(const string& prefered)
715
+ {
716
+ // abort if unit is empty
717
+ if (prefered.empty()) return;
718
+
719
+ // first make sure same units cancel each other out
720
+ // it seems that a map table will fit nicely to do this
721
+ // we basically construct exponents for each unit
722
+ // has the advantage that they will be pre-sorted
723
+ map<string, int> exponents;
724
+
725
+ // initialize by summing up occurences in unit vectors
726
+ for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) ++ exponents[numerator_units_[i]];
727
+ for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) -- exponents[denominator_units_[i]];
728
+
729
+ // the final conversion factor
730
+ double factor = 1;
731
+
732
+ vector<string>::iterator denom_it = denominator_units_.begin();
733
+ vector<string>::iterator denom_end = denominator_units_.end();
734
+
735
+ // main normalization loop
736
+ // should be close to optimal
737
+ while (denom_it != denom_end)
738
+ {
739
+ // get and increment afterwards
740
+ const string denom = *(denom_it ++);
741
+ // check if conversion is needed
742
+ if (denom == prefered) continue;
743
+ // skip already canceled out unit
744
+ if (exponents[denom] >= 0) continue;
745
+ // skip all units we don't know how to convert
746
+ if (string_to_unit(denom) == INCOMMENSURABLE) continue;
747
+ // we now have two convertable units
748
+ // add factor for current conversion
749
+ factor *= conversion_factor(denom, prefered);
750
+ // update nominator/denominator exponent
751
+ ++ exponents[denom]; -- exponents[prefered];
752
+ }
753
+
754
+ vector<string>::iterator nom_it = numerator_units_.begin();
755
+ vector<string>::iterator nom_end = numerator_units_.end();
756
+
757
+ // now search for nominator
758
+ while (nom_it != nom_end)
759
+ {
760
+ // get and increment afterwards
761
+ const string nom = *(nom_it ++);
762
+ // check if conversion is needed
763
+ if (nom == prefered) continue;
764
+ // skip already canceled out unit
765
+ if (exponents[nom] <= 0) continue;
766
+ // skip all units we don't know how to convert
767
+ if (string_to_unit(nom) == INCOMMENSURABLE) continue;
768
+ // we now have two convertable units
769
+ // add factor for current conversion
770
+ factor *= conversion_factor(nom, prefered);
771
+ // update nominator/denominator exponent
772
+ -- exponents[nom]; ++ exponents[prefered];
773
+ }
774
+
775
+ // now we can build up the new unit arrays
776
+ numerator_units_.clear();
777
+ denominator_units_.clear();
778
+
779
+ // build them by iterating over the exponents
780
+ for (auto exp : exponents)
781
+ {
782
+ // maybe there is more effecient way to push
783
+ // the same item multiple times to a vector?
784
+ for(size_t i = 0, S = abs(exp.second); i < S; ++i)
785
+ {
786
+ // opted to have these switches in the inner loop
787
+ // makes it more readable and should not cost much
788
+ if (exp.second < 0) denominator_units_.push_back(exp.first);
789
+ else if (exp.second > 0) numerator_units_.push_back(exp.first);
790
+ }
791
+ }
792
+
793
+ // apply factor to value_
794
+ // best precision this way
795
+ value_ *= factor;
796
+
797
+ }
798
+
799
+ // useful for making one number compatible with another
800
+ string Number::find_convertible_unit() const
801
+ {
802
+ for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
803
+ string u(numerator_units_[i]);
804
+ if (string_to_unit(u) != INCOMMENSURABLE) return u;
805
+ }
806
+ for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
807
+ string u(denominator_units_[i]);
808
+ if (string_to_unit(u) != INCOMMENSURABLE) return u;
809
+ }
810
+ return string();
811
+ }
812
+
813
+
814
+ bool Number::operator== (Expression* rhs) const
815
+ {
816
+ try
817
+ {
818
+ Number l(pstate_, value_, unit());
819
+ Number& r = dynamic_cast<Number&>(*rhs);
820
+ l.normalize(find_convertible_unit());
821
+ r.normalize(find_convertible_unit());
822
+ return l.unit() == r.unit() &&
823
+ l.value() == r.value();
824
+ }
825
+ catch (std::bad_cast&) {}
826
+ catch (...) { throw; }
827
+ return false;
828
+ }
829
+
830
+ bool Number::operator== (Expression& rhs) const
831
+ {
832
+ return operator==(&rhs);
833
+ }
834
+
835
+ bool List::operator==(Expression* rhs) const
836
+ {
837
+ try
838
+ {
839
+ List* r = dynamic_cast<List*>(rhs);
840
+ if (!r || length() != r->length()) return false;
841
+ if (separator() != r->separator()) return false;
842
+ for (size_t i = 0, L = r->length(); i < L; ++i)
843
+ if (*elements()[i] != *(*r)[i]) return false;
844
+ return true;
845
+ }
846
+ catch (std::bad_cast&) {}
847
+ catch (...) { throw; }
848
+ return false;
849
+ }
850
+
851
+ bool List::operator== (Expression& rhs) const
852
+ {
853
+ return operator==(&rhs);
854
+ }
855
+
592
856
  Expression* Hashed::at(Expression* k) const
593
857
  {
594
858
  if (elements_.count(k))
@@ -113,6 +113,7 @@ namespace Sass {
113
113
  static string type_name() { return ""; }
114
114
  virtual bool is_false() { return false; }
115
115
  virtual bool operator==( Expression& rhs) const { return false; }
116
+ virtual void set_delayed(bool delayed) { is_delayed(delayed); }
116
117
  virtual size_t hash() { return 0; }
117
118
  };
118
119
  }
@@ -756,23 +757,8 @@ namespace Sass {
756
757
  bool is_invisible() { return !length(); }
757
758
  Expression* value_at_index(size_t i);
758
759
 
759
- virtual bool operator==(Expression& rhs) const
760
- {
761
- try
762
- {
763
- List& l = dynamic_cast<List&>(rhs);
764
- if (!(l && length() == l.length() && separator() == l.separator())) return false;
765
- for (size_t i = 0, L = l.length(); i < L; ++i)
766
- if (!(*(elements()[i]) == *(l[i]))) return false;
767
- return true;
768
- }
769
- catch (std::bad_cast&)
770
- {
771
- return false;
772
- }
773
- catch (...) { throw; }
774
-
775
- }
760
+ virtual bool operator==(Expression& rhs) const;
761
+ virtual bool operator==(Expression* rhs) const;
776
762
 
777
763
  virtual size_t hash()
778
764
  {
@@ -786,6 +772,13 @@ namespace Sass {
786
772
  return hash_;
787
773
  }
788
774
 
775
+ virtual void set_delayed(bool delayed)
776
+ {
777
+ for (size_t i = 0, L = length(); i < L; ++i)
778
+ (elements()[i])->set_delayed(delayed);
779
+ is_delayed(delayed);
780
+ }
781
+
789
782
  ATTACH_OPERATIONS();
790
783
  };
791
784
 
@@ -857,6 +850,31 @@ namespace Sass {
857
850
  Type t, Expression* lhs, Expression* rhs)
858
851
  : Expression(pstate), type_(t), left_(lhs), right_(rhs), hash_(0)
859
852
  { }
853
+ const string type_name() {
854
+ switch (type_) {
855
+ case AND: return "and"; break;
856
+ case OR: return "or"; break;
857
+ case EQ: return "eq"; break;
858
+ case NEQ: return "neq"; break;
859
+ case GT: return "gt"; break;
860
+ case GTE: return "gte"; break;
861
+ case LT: return "lt"; break;
862
+ case LTE: return "lte"; break;
863
+ case ADD: return "add"; break;
864
+ case SUB: return "sub"; break;
865
+ case MUL: return "mul"; break;
866
+ case DIV: return "div"; break;
867
+ case MOD: return "mod"; break;
868
+ case NUM_OPS: return "num_ops"; break;
869
+ default: return "invalid"; break;
870
+ }
871
+ }
872
+ virtual void set_delayed(bool delayed)
873
+ {
874
+ right()->set_delayed(delayed);
875
+ left()->set_delayed(delayed);
876
+ is_delayed(delayed);
877
+ }
860
878
  virtual bool operator==(Expression& rhs) const
861
879
  {
862
880
  try
@@ -896,6 +914,14 @@ namespace Sass {
896
914
  Unary_Expression(ParserState pstate, Type t, Expression* o)
897
915
  : Expression(pstate), type_(t), operand_(o), hash_(0)
898
916
  { }
917
+ const string type_name() {
918
+ switch (type_) {
919
+ case PLUS: return "plus"; break;
920
+ case MINUS: return "minus"; break;
921
+ case NOT: return "not"; break;
922
+ default: return "invalid"; break;
923
+ }
924
+ }
899
925
  virtual bool operator==(Expression& rhs) const
900
926
  {
901
927
  try
@@ -1161,129 +1187,22 @@ namespace Sass {
1161
1187
  vector<string> denominator_units_;
1162
1188
  size_t hash_;
1163
1189
  public:
1164
- Number(ParserState pstate, double val, string u = "", bool zero = true)
1165
- : Expression(pstate),
1166
- value_(val),
1167
- zero_(zero),
1168
- numerator_units_(vector<string>()),
1169
- denominator_units_(vector<string>()),
1170
- hash_(0)
1171
- {
1172
- if (!u.empty()) numerator_units_.push_back(u);
1173
- concrete_type(NUMBER);
1174
- }
1190
+ Number(ParserState pstate, double val, string u = "", bool zero = true);
1175
1191
  bool zero() { return zero_; }
1176
1192
  vector<string>& numerator_units() { return numerator_units_; }
1177
1193
  vector<string>& denominator_units() { return denominator_units_; }
1178
1194
  string type() { return "number"; }
1179
1195
  static string type_name() { return "number"; }
1180
- string unit() const
1181
- {
1182
- stringstream u;
1183
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
1184
- if (i) u << '*';
1185
- u << numerator_units_[i];
1186
- }
1187
- if (!denominator_units_.empty()) u << '/';
1188
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
1189
- if (i) u << '*';
1190
- u << denominator_units_[i];
1191
- }
1192
- return u.str();
1193
- }
1194
- bool is_unitless()
1195
- { return numerator_units_.empty() && denominator_units_.empty(); }
1196
- void normalize(string to = "")
1197
- {
1198
- // (multiple passes because I'm too tired to think up something clever)
1199
- // Find a unit to convert everything to, if one isn't provided.
1200
- if (to.empty()) {
1201
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
1202
- string u(numerator_units_[i]);
1203
- if (string_to_unit(u) == INCOMMENSURABLE) {
1204
- continue;
1205
- }
1206
- else {
1207
- to = u;
1208
- break;
1209
- }
1210
- }
1211
- }
1212
- if (to.empty()) {
1213
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
1214
- string u(denominator_units_[i]);
1215
- if (string_to_unit(u) == INCOMMENSURABLE) {
1216
- continue;
1217
- }
1218
- else {
1219
- to = u;
1220
- break;
1221
- }
1222
- }
1223
- }
1224
- // Now loop through again and do all the conversions.
1225
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
1226
- string from(numerator_units_[i]);
1227
- if (string_to_unit(from) == INCOMMENSURABLE) continue;
1228
- value_ *= conversion_factor(from, to);
1229
- numerator_units_[i] = to;
1230
- }
1231
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
1232
- string from(denominator_units_[i]);
1233
- if (string_to_unit(from) == INCOMMENSURABLE) continue;
1234
- value_ /= conversion_factor(from, to);
1235
- denominator_units_[i] = to;
1236
- }
1237
- // Now divide out identical units in the numerator and denominator.
1238
- vector<string> ncopy;
1239
- ncopy.reserve(numerator_units_.size());
1240
- for (vector<string>::iterator n = numerator_units_.begin();
1241
- n != numerator_units_.end();
1242
- ++n) {
1243
- vector<string>::iterator d = find(denominator_units_.begin(),
1244
- denominator_units_.end(),
1245
- *n);
1246
- if (d != denominator_units_.end()) {
1247
- denominator_units_.erase(d);
1248
- }
1249
- else {
1250
- ncopy.push_back(*n);
1251
- }
1252
- }
1253
- numerator_units_ = ncopy;
1254
- // Sort the units to make them pretty and, well, normal.
1255
- sort(numerator_units_.begin(), numerator_units_.end());
1256
- sort(denominator_units_.begin(), denominator_units_.end());
1257
- }
1196
+ string unit() const;
1197
+
1198
+ bool is_unitless();
1199
+ void convert(const string& unit = "");
1200
+ void normalize(const string& unit = "");
1258
1201
  // useful for making one number compatible with another
1259
- string find_convertible_unit() const
1260
- {
1261
- for (size_t i = 0, S = numerator_units_.size(); i < S; ++i) {
1262
- string u(numerator_units_[i]);
1263
- if (string_to_unit(u) != INCOMMENSURABLE) return u;
1264
- }
1265
- for (size_t i = 0, S = denominator_units_.size(); i < S; ++i) {
1266
- string u(denominator_units_[i]);
1267
- if (string_to_unit(u) != INCOMMENSURABLE) return u;
1268
- }
1269
- return string();
1270
- }
1202
+ string find_convertible_unit() const;
1271
1203
 
1272
- virtual bool operator==(Expression& rhs) const
1273
- {
1274
- try
1275
- {
1276
- Number& e(dynamic_cast<Number&>(rhs));
1277
- if (!e) return false;
1278
- e.normalize(find_convertible_unit());
1279
- return unit() == e.unit() && value() == e.value();
1280
- }
1281
- catch (std::bad_cast&)
1282
- {
1283
- return false;
1284
- }
1285
- catch (...) { throw; }
1286
- }
1204
+ virtual bool operator== (Expression& rhs) const;
1205
+ virtual bool operator== (Expression* rhs) const;
1287
1206
 
1288
1207
  virtual size_t hash()
1289
1208
  {