2#include "css_selector.h"
5void litehtml::css_element_selector::parse(
const tstring& txt )
7 tstring::size_type el_end = txt.find_first_of(_t(
".#[:"));
8 m_tag = txt.substr(0, el_end);
9 litehtml::lcase(m_tag);
11 while(el_end != tstring::npos)
13 if(txt[el_end] == _t(
'.'))
15 css_attribute_selector attribute;
17 tstring::size_type pos = txt.find_first_of(_t(
".#[:"), el_end + 1);
18 attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
19 split_string( attribute.val, attribute.class_val, _t(
" ") );
20 attribute.condition = select_equal;
21 attribute.attribute = _t(
"class");
22 m_attrs.push_back(attribute);
24 }
else if(txt[el_end] == _t(
':'))
26 css_attribute_selector attribute;
28 if(txt[el_end + 1] == _t(
':'))
30 tstring::size_type pos = txt.find_first_of(_t(
".#[:"), el_end + 2);
31 attribute.val = txt.substr(el_end + 2, pos - el_end - 2);
32 attribute.condition = select_pseudo_element;
33 litehtml::lcase(attribute.val);
34 attribute.attribute = _t(
"pseudo-el");
35 m_attrs.push_back(attribute);
39 tstring::size_type pos = txt.find_first_of(_t(
".#[:("), el_end + 1);
40 if(pos != tstring::npos && txt.at(pos) == _t(
'('))
42 pos = find_close_bracket(txt, pos);
43 if(pos != tstring::npos)
52 if(pos != tstring::npos)
54 attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
57 attribute.val = txt.substr(el_end + 1);
59 litehtml::lcase(attribute.val);
60 if(attribute.val == _t(
"after") || attribute.val == _t(
"before"))
62 attribute.condition = select_pseudo_element;
65 attribute.condition = select_pseudo_class;
67 attribute.attribute = _t(
"pseudo");
68 m_attrs.push_back(attribute);
71 }
else if(txt[el_end] == _t(
'#'))
73 css_attribute_selector attribute;
75 tstring::size_type pos = txt.find_first_of(_t(
".#[:"), el_end + 1);
76 attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
77 attribute.condition = select_equal;
78 attribute.attribute = _t(
"id");
79 m_attrs.push_back(attribute);
81 }
else if(txt[el_end] == _t(
'['))
83 css_attribute_selector attribute;
85 tstring::size_type pos = txt.find_first_of(_t(
"]~=|$*^"), el_end + 1);
86 tstring attr = txt.substr(el_end + 1, pos - el_end - 1);
88 litehtml::lcase(attr);
89 if(pos != tstring::npos)
91 if(txt[pos] == _t(
']'))
93 attribute.condition = select_exists;
94 }
else if(txt[pos] == _t(
'='))
96 attribute.condition = select_equal;
98 }
else if(txt.substr(pos, 2) == _t(
"~="))
100 attribute.condition = select_contain_str;
102 }
else if(txt.substr(pos, 2) == _t(
"|="))
104 attribute.condition = select_start_str;
106 }
else if(txt.substr(pos, 2) == _t(
"^="))
108 attribute.condition = select_start_str;
110 }
else if(txt.substr(pos, 2) == _t(
"$="))
112 attribute.condition = select_end_str;
114 }
else if(txt.substr(pos, 2) == _t(
"*="))
116 attribute.condition = select_contain_str;
120 attribute.condition = select_exists;
123 pos = txt.find_first_not_of(_t(
" \t"), pos);
124 if(pos != tstring::npos)
126 if(txt[pos] == _t(
'"'))
128 tstring::size_type pos2 = txt.find_first_of(_t(
"\""), pos + 1);
129 attribute.val = txt.substr(pos + 1, pos2 == tstring::npos ? pos2 : (pos2 - pos - 1));
130 pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
131 }
else if(txt[pos] == _t(
']'))
136 tstring::size_type pos2 = txt.find_first_of(_t(
"]"), pos + 1);
137 attribute.val = txt.substr(pos, pos2 == tstring::npos ? pos2 : (pos2 - pos));
139 pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
144 attribute.condition = select_exists;
146 attribute.attribute = attr;
147 m_attrs.push_back(attribute);
153 el_end = txt.find_first_of(_t(
".#[:"), el_end);
158bool litehtml::css_selector::parse(
const tstring& text )
164 string_vector tokens;
165 split_string(text, tokens, _t(
""), _t(
" \t>+~"), _t(
"(["));
173 tstring right = tokens.back();
174 tchar_t combinator = 0;
177 while(!tokens.empty() && (tokens.back() == _t(
" ") || tokens.back() == _t(
"\t") || tokens.back() == _t(
"+") || tokens.back() == _t(
"~") || tokens.back() == _t(
">")))
179 if(combinator == _t(
' ') || combinator == 0)
181 combinator = tokens.back()[0];
186 for(string_vector::const_iterator i = tokens.begin(); i != tokens.end(); i++)
199 m_right.parse(right);
204 m_combinator = combinator_child;
207 m_combinator = combinator_adjacent_sibling;
210 m_combinator = combinator_general_sibling;
213 m_combinator = combinator_descendant;
221 m_left = std::make_shared<css_selector>(media_query_list::ptr(0));
222 if(!m_left->parse(left))
231void litehtml::css_selector::calc_specificity()
233 if(!m_right.m_tag.empty() && m_right.m_tag != _t(
"*"))
237 for(css_attribute_selector::vector::iterator i = m_right.m_attrs.begin(); i != m_right.m_attrs.end(); i++)
239 if(i->attribute == _t(
"id"))
244 if(i->attribute == _t(
"class"))
246 m_specificity.c += (int) i->class_val.size();
255 m_left->calc_specificity();
256 m_specificity += m_left->m_specificity;
260void litehtml::css_selector::add_media_to_doc( document* doc )
const
262 if(m_media_query && doc)
264 doc->add_media_list(m_media_query);