1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 05:17:34 +00:00

LibHTML: Handle comments in the CSS parser

Turn consume_whitespace() into consume_whitespace_or_comments() and
have it swallow /* comments */ as well.
This commit is contained in:
Andreas Kling 2019-10-13 00:28:15 +02:00
parent b083a233d8
commit 08209cc665
2 changed files with 42 additions and 27 deletions

View file

@ -4,10 +4,15 @@
<title>Welcome!</title> <title>Welcome!</title>
<!-- this is a comment --> <!-- this is a comment -->
<style type="text/css"> <style type="text/css">
/* css comment */
body { body {
background-color: #fff; background-color: #fff;
color: #000; color: #000; /* another css comment */
} }
/* lol
a
css
comment */
h1 { h1 {
color: #800; color: #800;
} }

View file

@ -104,10 +104,10 @@ public:
{ {
} }
char peek() const char peek(int offset = 0) const
{ {
if (index < css.length()) if ((index + offset) < css.length())
return css[index]; return css[index + offset];
return 0; return 0;
} }
@ -125,10 +125,27 @@ public:
return css[index++]; return css[index++];
}; };
void consume_whitespace() void consume_whitespace_or_comments()
{ {
while (isspace(peek())) bool in_comment = false;
++index; for (; index < css.length(); ++index) {
char ch = peek();
if (isspace(ch))
continue;
if (!in_comment && ch == '/' && peek(1) == '*') {
in_comment = true;
++index;
continue;
}
if (in_comment && ch == '*' && peek(1) == '/') {
in_comment = false;
++index;
continue;
}
if (in_comment)
continue;
break;
}
} }
bool is_valid_selector_char(char ch) const bool is_valid_selector_char(char ch) const
@ -143,7 +160,7 @@ public:
Optional<Selector::Component> parse_selector_component() Optional<Selector::Component> parse_selector_component()
{ {
consume_whitespace(); consume_whitespace_or_comments();
Selector::Component::Type type; Selector::Component::Type type;
Selector::Component::Relation relation = Selector::Component::Relation::Descendant; Selector::Component::Relation relation = Selector::Component::Relation::Descendant;
@ -163,7 +180,7 @@ public:
break; break;
} }
consume_one(); consume_one();
consume_whitespace(); consume_whitespace_or_comments();
} }
if (peek() == '.') { if (peek() == '.') {
@ -211,7 +228,7 @@ public:
auto component = parse_selector_component(); auto component = parse_selector_component();
if (component.has_value()) if (component.has_value())
components.append(component.value()); components.append(component.value());
consume_whitespace(); consume_whitespace_or_comments();
if (peek() == ',' || peek() == '{') if (peek() == ',' || peek() == '{')
break; break;
} }
@ -227,7 +244,7 @@ public:
{ {
for (;;) { for (;;) {
parse_selector(); parse_selector();
consume_whitespace(); consume_whitespace_or_comments();
if (peek() == ',') { if (peek() == ',') {
consume_one(); consume_one();
continue; continue;
@ -249,7 +266,7 @@ public:
Optional<StyleProperty> parse_property() Optional<StyleProperty> parse_property()
{ {
consume_whitespace(); consume_whitespace_or_comments();
if (peek() == ';') { if (peek() == ';') {
consume_one(); consume_one();
return {}; return {};
@ -259,14 +276,14 @@ public:
buffer.append(consume_one()); buffer.append(consume_one());
auto property_name = String::copy(buffer); auto property_name = String::copy(buffer);
buffer.clear(); buffer.clear();
consume_whitespace(); consume_whitespace_or_comments();
consume_specific(':'); consume_specific(':');
consume_whitespace(); consume_whitespace_or_comments();
while (is_valid_property_value_char(peek())) while (is_valid_property_value_char(peek()))
buffer.append(consume_one()); buffer.append(consume_one());
auto property_value = String::copy(buffer); auto property_value = String::copy(buffer);
buffer.clear(); buffer.clear();
consume_whitespace(); consume_whitespace_or_comments();
bool is_important = false; bool is_important = false;
if (peek() == '!') { if (peek() == '!') {
consume_specific('!'); consume_specific('!');
@ -279,7 +296,7 @@ public:
consume_specific('a'); consume_specific('a');
consume_specific('n'); consume_specific('n');
consume_specific('t'); consume_specific('t');
consume_whitespace(); consume_whitespace_or_comments();
is_important = true; is_important = true;
} }
if (peek() && peek() != '}') if (peek() && peek() != '}')
@ -294,7 +311,7 @@ public:
auto property = parse_property(); auto property = parse_property();
if (property.has_value()) if (property.has_value())
current_rule.properties.append(property.value()); current_rule.properties.append(property.value());
consume_whitespace(); consume_whitespace_or_comments();
if (peek() == '}') if (peek() == '}')
break; break;
} }
@ -307,7 +324,7 @@ public:
parse_declaration(); parse_declaration();
consume_specific('}'); consume_specific('}');
rules.append(StyleRule::create(move(current_rule.selectors), StyleDeclaration::create(move(current_rule.properties)))); rules.append(StyleRule::create(move(current_rule.selectors), StyleDeclaration::create(move(current_rule.properties))));
consume_whitespace(); consume_whitespace_or_comments();
} }
NonnullRefPtr<StyleSheet> parse_sheet() NonnullRefPtr<StyleSheet> parse_sheet()
@ -321,12 +338,12 @@ public:
NonnullRefPtr<StyleDeclaration> parse_standalone_declaration() NonnullRefPtr<StyleDeclaration> parse_standalone_declaration()
{ {
consume_whitespace(); consume_whitespace_or_comments();
for (;;) { for (;;) {
auto property = parse_property(); auto property = parse_property();
if (property.has_value()) if (property.has_value())
current_rule.properties.append(property.value()); current_rule.properties.append(property.value());
consume_whitespace(); consume_whitespace_or_comments();
if (!peek()) if (!peek())
break; break;
} }
@ -336,13 +353,6 @@ public:
private: private:
NonnullRefPtrVector<StyleRule> rules; NonnullRefPtrVector<StyleRule> rules;
enum class State {
Free,
InSelectorComponent,
InPropertyName,
InPropertyValue,
};
struct CurrentRule { struct CurrentRule {
Vector<Selector> selectors; Vector<Selector> selectors;
Vector<StyleProperty> properties; Vector<StyleProperty> properties;