srctree

Robin Linden parent 7348e5e1 84039f1b
css: Fix crash on minified CSS

inlinesplit
css/parser.h added: 26, removed: 6, total 20
@@ -28,12 +28,16 @@ public:
}
 
private:
constexpr void skip_if_neq(char c) {
if (peek() != c) { advance(1); }
}
 
css::Rule parse_rule() {
Rule rule{};
while (peek() != '{') {
auto selector = consume_while([](char c) { return c != ' ' && c != ','; });
auto selector = consume_while([](char c) { return c != ' ' && c != ',' && c != '{'; });
rule.selectors.push_back(std::string{selector});
consume_char(); // ' ' or ','
skip_if_neq('{'); // ' ' or ','
skip_whitespace();
}
 
@@ -54,8 +58,8 @@ private:
auto name = consume_while([](char c) { return c != ':'; });
consume_char(); // :
skip_whitespace();
auto value = consume_while([](char c) { return c != ';'; });
consume_char(); // ;
auto value = consume_while([](char c) { return c != ';' && c != '}'; });
skip_if_neq('}'); // ;
return {std::string{name}, std::string{value}};
}
};
 
css/parser_test.cpp added: 26, removed: 6, total 20
@@ -17,6 +17,22 @@ int main() {
expect(body.declarations.at("width"s) == "50px"s);
});
 
etest::test("parser: minified", [] {
auto rules = css::parse("body{width:50px;font:inherit}head,p{display:none}"sv);
require(rules.size() == 2);
 
auto first = rules[0];
expect(first.selectors == std::vector{"body"s});
expect(first.declarations.size() == 2);
expect(first.declarations.at("width"s) == "50px"s);
expect(first.declarations.at("font"s) == "inherit"s);
 
auto second = rules[1];
expect(second.selectors == std::vector{"head"s, "p"s});
expect(second.declarations.size() == 1);
expect(second.declarations.at("display"s) == "none"s);
});
 
etest::test("parser: multiple rules", [] {
auto rules = css::parse("body { width: 50px; }\np { font-size: 8em; }"sv);
require(rules.size() == 2);