2 #include "stylesheet.h"
7 void litehtml::css::parse_stylesheet(const char* str
, const char* baseurl
, const std::shared_ptr
<document
>& doc
, const media_query_list::ptr
& media
)
12 string::size_type c_start
= text
.find("/*");
13 while(c_start
!= string::npos
)
15 string::size_type c_end
= text
.find("*/", c_start
+ 2);
16 if(c_end
== string::npos
)
21 text
.erase(c_start
, c_end
- c_start
+ 2);
22 c_start
= text
.find("/*");
25 string::size_type pos
= text
.find_first_not_of(" \n\r\t");
26 while(pos
!= string::npos
)
28 while(pos
!= string::npos
&& text
[pos
] == '@')
30 string::size_type sPos
= pos
;
31 pos
= text
.find_first_of("{;", pos
);
32 if(pos
!= string::npos
&& text
[pos
] == '{')
34 pos
= find_close_bracket(text
, pos
, '{', '}');
36 if(pos
!= string::npos
)
38 parse_atrule(text
.substr(sPos
, pos
- sPos
+ 1), baseurl
, doc
, media
);
41 parse_atrule(text
.substr(sPos
), baseurl
, doc
, media
);
44 if(pos
!= string::npos
)
46 pos
= text
.find_first_not_of(" \n\r\t", pos
+ 1);
50 if(pos
== string::npos
)
55 string::size_type style_start
= text
.find('{', pos
);
56 string::size_type style_end
= text
.find('}', pos
);
57 if(style_start
!= string::npos
&& style_end
!= string::npos
)
59 auto str_style
= text
.substr(style_start
+ 1, style_end
- style_start
- 1);
60 style::ptr style
= std::make_shared
<litehtml::style
>();
61 style
->add(str_style
, baseurl
? baseurl
: "", doc
->container());
63 parse_selectors(text
.substr(pos
, style_start
- pos
), style
, media
);
67 doc
->add_media_list(media
);
76 if(pos
!= string::npos
)
78 pos
= text
.find_first_not_of(" \n\r\t", pos
);
83 void litehtml::css::parse_css_url( const string
& str
, string
& url
)
86 size_t pos1
= str
.find('(');
87 size_t pos2
= str
.find(')');
88 if(pos1
!= string::npos
&& pos2
!= string::npos
)
90 url
= str
.substr(pos1
+ 1, pos2
- pos1
- 1);
93 if(url
[0] == '\'' || url
[0] == '"')
100 if(url
[url
.length() - 1] == '\'' || url
[url
.length() - 1] == '"')
102 url
.erase(url
.length() - 1, 1);
108 bool litehtml::css::parse_selectors( const string
& txt
, const style::ptr
& styles
, const media_query_list::ptr
& media
)
110 string selector
= txt
;
112 string_vector tokens
;
113 split_string(selector
, tokens
, ",");
115 bool added_something
= false;
117 for(auto & token
: tokens
)
119 css_selector::ptr new_selector
= std::make_shared
<css_selector
>(media
);
120 new_selector
->m_style
= styles
;
122 if(new_selector
->parse(token
))
124 new_selector
->calc_specificity();
125 add_selector(new_selector
);
126 added_something
= true;
130 return added_something
;
133 void litehtml::css::sort_selectors()
135 std::sort(m_selectors
.begin(), m_selectors
.end(),
136 [](const css_selector::ptr
& v1
, const css_selector::ptr
& v2
)
138 return (*v1
) < (*v2
);
143 void litehtml::css::parse_atrule(const string
& text
, const char* baseurl
, const std::shared_ptr
<document
>& doc
, const media_query_list::ptr
& media
)
145 if(text
.substr(0, 7) == "@import")
149 iStr
= text
.substr(sPos
);
150 if(iStr
[iStr
.length() - 1] == ';')
152 iStr
.erase(iStr
.length() - 1);
155 string_vector tokens
;
156 split_string(iStr
, tokens
, " ", "", "(\"");
160 parse_css_url(tokens
.front(), url
);
163 url
= tokens
.front();
165 tokens
.erase(tokens
.begin());
168 document_container
* doc_cont
= doc
->container();
175 css_baseurl
= baseurl
;
177 doc_cont
->import_css(css_text
, url
, css_baseurl
);
178 if(!css_text
.empty())
180 media_query_list::ptr new_media
= media
;
184 for(auto iter
= tokens
.begin(); iter
!= tokens
.end(); iter
++)
186 if(iter
!= tokens
.begin())
190 media_str
+= (*iter
);
192 new_media
= media_query_list::create_from_string(media_str
, doc
);
198 parse_stylesheet(css_text
.c_str(), css_baseurl
.c_str(), doc
, new_media
);
203 } else if(text
.substr(0, 6) == "@media")
205 string::size_type b1
= text
.find_first_of('{');
206 string::size_type b2
= text
.find_last_of('}');
207 if(b1
!= string::npos
)
209 string media_type
= text
.substr(6, b1
- 6);
211 media_query_list::ptr new_media
= media_query_list::create_from_string(media_type
, doc
);
214 if(b2
!= string::npos
)
216 media_style
= text
.substr(b1
+ 1, b2
- b1
- 1);
219 media_style
= text
.substr(b1
+ 1);
222 parse_stylesheet(media_style
.c_str(), baseurl
, doc
, new_media
);