@@ -1742,7 +1742,9 @@ namespace Sass {
1742
1742
{ }
1743
1743
virtual ~Selector () = 0 ;
1744
1744
// virtual Selector_Placeholder* find_placeholder();
1745
- virtual int specificity () { return Constants::SPECIFICITY_BASE; }
1745
+ virtual unsigned long specificity () {
1746
+ return Constants::Specificity_Universal;
1747
+ };
1746
1748
};
1747
1749
inline Selector::~Selector () { }
1748
1750
@@ -1770,6 +1772,7 @@ namespace Sass {
1770
1772
virtual ~Simple_Selector () = 0 ;
1771
1773
virtual Compound_Selector* unify_with (Compound_Selector*, Context&);
1772
1774
virtual bool is_pseudo_element () { return false ; }
1775
+ virtual bool is_pseudo_class () { return false ; }
1773
1776
1774
1777
bool operator ==(const Simple_Selector& rhs) const ;
1775
1778
inline bool operator !=(const Simple_Selector& rhs) const { return !(*this == rhs); }
@@ -1787,10 +1790,10 @@ namespace Sass {
1787
1790
Selector_Reference (ParserState pstate, Selector* r = 0 )
1788
1791
: Simple_Selector(pstate), selector_(r)
1789
1792
{ has_reference (true ); }
1790
- virtual int specificity ()
1793
+ virtual unsigned long specificity ()
1791
1794
{
1792
- if (selector ()) return selector ()-> specificity () ;
1793
- else return 0 ;
1795
+ if (! selector ()) return 0 ;
1796
+ return selector ()-> specificity () ;
1794
1797
}
1795
1798
ATTACH_OPERATIONS ();
1796
1799
};
@@ -1817,10 +1820,11 @@ namespace Sass {
1817
1820
Type_Selector (ParserState pstate, string n)
1818
1821
: Simple_Selector(pstate), name_(n)
1819
1822
{ }
1820
- virtual int specificity ()
1823
+ virtual unsigned long specificity ()
1821
1824
{
1822
- if (name () == " *" ) return 0 ;
1823
- else return 1 ;
1825
+ // ToDo: What is the specificity of the star selector?
1826
+ if (name () == " *" ) return Constants::Specificity_Universal;
1827
+ else return Constants::Specificity_Type;
1824
1828
}
1825
1829
virtual Compound_Selector* unify_with (Compound_Selector*, Context&);
1826
1830
ATTACH_OPERATIONS ();
@@ -1835,10 +1839,11 @@ namespace Sass {
1835
1839
Selector_Qualifier (ParserState pstate, string n)
1836
1840
: Simple_Selector(pstate), name_(n)
1837
1841
{ }
1838
- virtual int specificity ()
1842
+ virtual unsigned long specificity ()
1839
1843
{
1840
- if (name ()[0 ] == ' #' ) return Constants::SPECIFICITY_BASE * Constants::SPECIFICITY_BASE;
1841
- else return Constants::SPECIFICITY_BASE;
1844
+ if (name ()[0 ] == ' #' ) return Constants::Specificity_ID;
1845
+ if (name ()[0 ] == ' .' ) return Constants::Specificity_Class;
1846
+ else return Constants::Specificity_Type;
1842
1847
}
1843
1848
virtual Compound_Selector* unify_with (Compound_Selector*, Context&);
1844
1849
ATTACH_OPERATIONS ();
@@ -1855,42 +1860,62 @@ namespace Sass {
1855
1860
Attribute_Selector (ParserState pstate, string n, string m, String* v)
1856
1861
: Simple_Selector(pstate), name_(n), matcher_(m), value_(v)
1857
1862
{ }
1863
+ virtual unsigned long specificity ()
1864
+ {
1865
+ return Constants::Specificity_Attr;
1866
+ }
1858
1867
ATTACH_OPERATIONS ();
1859
1868
};
1860
1869
1861
1870
// ////////////////////////////////////////////////////////////////
1862
1871
// Pseudo selectors -- e.g., :first-child, :nth-of-type(...), etc.
1863
1872
// ////////////////////////////////////////////////////////////////
1873
+ /* '::' starts a pseudo-element, ':' a pseudo-class */
1874
+ /* Except :first-line, :first-letter, :before and :after */
1875
+ /* Note that pseudo-elements are restricted to one per selector */
1876
+ /* and occur only in the last simple_selector_sequence. */
1877
+ inline bool is_pseudo_class_element (const string& name)
1878
+ {
1879
+ return name == " :before" ||
1880
+ name == " :after" ||
1881
+ name == " :first-line" ||
1882
+ name == " :first-letter" ;
1883
+ }
1884
+
1864
1885
class Pseudo_Selector : public Simple_Selector {
1865
1886
ADD_PROPERTY (string, name);
1866
1887
ADD_PROPERTY (String*, expression);
1867
1888
public:
1868
1889
Pseudo_Selector (ParserState pstate, string n, String* expr = 0 )
1869
1890
: Simple_Selector(pstate), name_(n), expression_(expr)
1870
1891
{ }
1871
- virtual int specificity ()
1892
+
1893
+ // A pseudo-class always consists of a "colon" (:) followed by the name
1894
+ // of the pseudo-class and optionally by a value between parentheses.
1895
+ virtual bool is_pseudo_class ()
1872
1896
{
1873
- // TODO: clean up the pseudo-element checking
1874
- if (name () == " :before" || name () == " ::before" ||
1875
- name () == " :after" || name () == " ::after" ||
1876
- name () == " :first-line" || name () == " ::first-line" ||
1877
- name () == " :first-letter" || name () == " ::first-letter" )
1878
- return 1 ;
1879
- else
1880
- return Constants::SPECIFICITY_BASE;
1897
+ return (name_[0 ] == ' :' && name_[1 ] != ' :' )
1898
+ && ! is_pseudo_class_element (name_);
1881
1899
}
1900
+
1901
+ // A pseudo-element is made of two colons (::) followed by the name.
1902
+ // The `::` notation is introduced by the current document in order to
1903
+ // establish a discrimination between pseudo-classes and pseudo-elements.
1904
+ // For compatibility with existing style sheets, user agents must also
1905
+ // accept the previous one-colon notation for pseudo-elements introduced
1906
+ // in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
1907
+ // :after). This compatibility is not allowed for the new pseudo-elements
1908
+ // introduced in this specification.
1882
1909
virtual bool is_pseudo_element ()
1883
1910
{
1884
- if (name () == " :before" || name () == " ::before" ||
1885
- name () == " :after" || name () == " ::after" ||
1886
- name () == " :first-line" || name () == " ::first-line" ||
1887
- name () == " :first-letter" || name () == " ::first-letter" ) {
1888
- return true ;
1889
- }
1890
- else {
1891
- // If it's not a known pseudo-element, check whether it looks like one. This is similar to the type method on the Pseudo class in ruby sass.
1892
- return name ().find (" ::" ) == 0 ;
1893
- }
1911
+ return (name_[0 ] == ' :' && name_[1 ] == ' :' )
1912
+ || is_pseudo_class_element (name_);
1913
+ }
1914
+ virtual unsigned long specificity ()
1915
+ {
1916
+ if (is_pseudo_element ())
1917
+ return Constants::Specificity_Type;
1918
+ return Constants::Specificity_Pseudo;
1894
1919
}
1895
1920
virtual Compound_Selector* unify_with (Compound_Selector*, Context&);
1896
1921
ATTACH_OPERATIONS ();
@@ -1906,6 +1931,12 @@ namespace Sass {
1906
1931
Wrapped_Selector (ParserState pstate, string n, Selector* sel)
1907
1932
: Simple_Selector(pstate), name_(n), selector_(sel)
1908
1933
{ }
1934
+ // Selectors inside the negation pseudo-class are counted like any
1935
+ // other, but the negation itself does not count as a pseudo-class.
1936
+ virtual unsigned long specificity ()
1937
+ {
1938
+ return selector_ ? selector_->specificity () : 0 ;
1939
+ }
1909
1940
ATTACH_OPERATIONS ();
1910
1941
};
1911
1942
@@ -1946,7 +1977,7 @@ namespace Sass {
1946
1977
return 0 ;
1947
1978
}
1948
1979
bool is_superselector_of (Compound_Selector* rhs);
1949
- virtual int specificity ()
1980
+ virtual unsigned long specificity ()
1950
1981
{
1951
1982
int sum = 0 ;
1952
1983
for (size_t i = 0 , L = length (); i < L; ++i)
@@ -2007,7 +2038,7 @@ namespace Sass {
2007
2038
// virtual Selector_Placeholder* find_placeholder();
2008
2039
Combinator clear_innermost ();
2009
2040
void set_innermost (Complex_Selector*, Combinator);
2010
- virtual int specificity () const
2041
+ virtual unsigned long specificity () const
2011
2042
{
2012
2043
int sum = 0 ;
2013
2044
if (head ()) sum += head ()->specificity ();
@@ -2088,9 +2119,9 @@ namespace Sass {
2088
2119
: Selector(pstate), Vectorized<Complex_Selector*>(s), wspace_(0 )
2089
2120
{ }
2090
2121
// virtual Selector_Placeholder* find_placeholder();
2091
- virtual int specificity ()
2122
+ virtual unsigned long specificity ()
2092
2123
{
2093
- int sum = 0 ;
2124
+ unsigned long sum = 0 ;
2094
2125
for (size_t i = 0 , L = length (); i < L; ++i)
2095
2126
{ sum += (*this )[i]->specificity (); }
2096
2127
return sum;
0 commit comments