sassc 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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
  {