1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 22:45:07 +00:00

LibHTML: Improve CSS parser's handling of values somewhat

Now we just skip over url() and rgb() instead of crashing on them.
This commit is contained in:
Andreas Kling 2019-11-25 19:56:00 +01:00
parent 847b232680
commit 94bc46ee70

View file

@ -374,6 +374,72 @@ public:
return ch && ch != '!' && ch != ';' && ch != '}'; return ch && ch != '!' && ch != ';' && ch != '}';
} }
struct ValueAndImportant {
String value;
bool important { false };
};
ValueAndImportant consume_css_value()
{
buffer.clear();
int paren_nesting_level = 0;
bool important = false;
for (;;) {
char ch = peek();
if (ch == '(') {
++paren_nesting_level;
buffer.append(consume_one());
continue;
}
if (ch == ')') {
PARSE_ASSERT(paren_nesting_level > 0);
--paren_nesting_level;
buffer.append(consume_one());
continue;
}
if (paren_nesting_level > 0) {
buffer.append(consume_one());
continue;
}
if (next_is("!important")) {
consume_specific('!');
consume_specific('i');
consume_specific('m');
consume_specific('p');
consume_specific('o');
consume_specific('r');
consume_specific('t');
consume_specific('a');
consume_specific('n');
consume_specific('t');
important = true;
continue;
}
if (next_is("/*")) {
consume_whitespace_or_comments();
continue;
}
if (!ch)
break;
if (ch == '}')
break;
if (ch == ';')
break;
buffer.append(consume_one());
}
// Remove trailing whitespace.
while (!buffer.is_empty() && isspace(buffer.last()))
buffer.take_last();
auto string = String::copy(buffer);
buffer.clear();
return { string, important };
}
Optional<StyleProperty> parse_property() Optional<StyleProperty> parse_property()
{ {
consume_whitespace_or_comments(); consume_whitespace_or_comments();
@ -391,36 +457,16 @@ public:
consume_whitespace_or_comments(); consume_whitespace_or_comments();
consume_specific(':'); consume_specific(':');
consume_whitespace_or_comments(); consume_whitespace_or_comments();
while (is_valid_property_value_char(peek()))
buffer.append(consume_one());
// Remove trailing whitespace. auto [property_value, important] = consume_css_value();
while (!buffer.is_empty() && isspace(buffer.last()))
buffer.take_last();
auto property_value = String::copy(buffer);
buffer.clear();
consume_whitespace_or_comments(); consume_whitespace_or_comments();
bool is_important = false;
if (peek() == '!') {
consume_specific('!');
consume_specific('i');
consume_specific('m');
consume_specific('p');
consume_specific('o');
consume_specific('r');
consume_specific('t');
consume_specific('a');
consume_specific('n');
consume_specific('t');
consume_whitespace_or_comments();
is_important = true;
}
if (peek() && peek() != '}') if (peek() && peek() != '}')
consume_specific(';'); consume_specific(';');
auto property_id = CSS::property_id_from_string(property_name); auto property_id = CSS::property_id_from_string(property_name);
return StyleProperty { property_id, parse_css_value(property_value), is_important }; return StyleProperty { property_id, parse_css_value(property_value), important };
} }
void parse_declaration() void parse_declaration()