srctree

Robin Linden parent b8423def d2b4d13c
css: Expand the flex-flow shorthand property

inlinesplit
css/parser.cpp added: 106, removed: 3, total 103
@@ -437,6 +437,8 @@ void Parser::add_declaration(
expand_border_radius_values(declarations, value);
} else if (name == "text-decoration") {
expand_text_decoration_values(declarations, value);
} else if (name == "flex-flow") {
expand_flex_flow(declarations, value);
} else if (is_in_array<kBorderShorthandProperties>(name)) {
expand_border(name, declarations, value);
} else {
@@ -638,6 +640,62 @@ void Parser::expand_text_decoration_values(std::map<PropertyId, std::string> &de
declarations.insert_or_assign(PropertyId::TextDecorationStyle, "solid");
}
 
// https://developer.mozilla.org/en-US/docs/Web/CSS/flex-flow
void Parser::expand_flex_flow(std::map<PropertyId, std::string> &declarations, std::string_view value) {
static constexpr std::array kGlobalValues{"inherit", "initial", "revert", "revert-layer", "unset"};
 
auto is_wrap = [](std::string_view str) {
return str == "wrap" || str == "nowrap" || str == "wrap-reverse";
};
auto is_direction = [](std::string_view str) {
return str == "row" || str == "row-reverse" || str == "column" || str == "column-reverse";
};
 
std::string direction{"row"};
std::string wrap{"nowrap"};
 
Tokenizer tokenizer{value, ' '};
if (tokenizer.size() != 1 && tokenizer.size() != 2) {
spdlog::warn("Unsupported flex-flow value: '{}'", value);
return;
}
 
auto first = tokenizer.get();
auto second = tokenizer.next().get();
// Global values are only allowed if there's a single value.
if (first && !second && is_in_array<kGlobalValues>(*first)) {
wrap = direction = *first;
declarations.insert_or_assign(PropertyId::FlexDirection, std::move(direction));
declarations.insert_or_assign(PropertyId::FlexWrap, std::move(wrap));
return;
}
 
// No duplicates of wrap or direction allowed.
if ((first && second)
&& ((is_wrap(*first) && !is_direction(*second)) || (is_direction(*first) && !is_wrap(*second)))) {
spdlog::warn("Unsupported flex-flow value: '{}'", value);
return;
}
 
for (auto const &v : std::array{first, second}) {
if (!v) {
continue;
}
 
if (is_wrap(*v)) {
wrap = *v;
} else if (is_direction(*v)) {
direction = *v;
} else {
spdlog::warn("Unsupported flex-flow value: '{}'", value);
return;
}
}
 
declarations.insert_or_assign(PropertyId::FlexDirection, std::move(direction));
declarations.insert_or_assign(PropertyId::FlexWrap, std::move(wrap));
}
 
void Parser::expand_edge_values(
std::map<PropertyId, std::string> &declarations, std::string property, std::string_view value) const {
std::string_view top = "", bottom = "", left = "", right = "";
 
css/parser.h added: 106, removed: 3, total 103
@@ -71,6 +71,9 @@ private:
 
static void expand_text_decoration_values(std::map<PropertyId, std::string> &declarations, std::string_view value);
 
// https://developer.mozilla.org/en-US/docs/Web/CSS/flex-flow
static void expand_flex_flow(std::map<PropertyId, std::string> &, std::string_view);
 
void expand_edge_values(
std::map<PropertyId, std::string> &declarations, std::string property, std::string_view value) const;
 
 
css/parser_test.cpp added: 106, removed: 3, total 103
@@ -1025,5 +1025,47 @@ int main() {
std::ignore = css::parse("p { font-size:");
});
 
etest::test("parser: flex-flow shorthand, global value", [] {
expect_eq(css::parse("p { flex-flow: revert; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "revert"s},
{css::PropertyId::FlexWrap, "revert"s},
});
expect_eq(css::parse("p { flex-flow: revert row; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, one value", [] {
expect_eq(css::parse("p { flex-flow: column; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "column"s},
{css::PropertyId::FlexWrap, "nowrap"s},
});
expect_eq(css::parse("p { flex-flow: wrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "row"s},
{css::PropertyId::FlexWrap, "wrap"s},
});
expect_eq(css::parse("p { flex-flow: aaaaaaaaaa; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, two values", [] {
expect_eq(css::parse("p { flex-flow: column wrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "column"s},
{css::PropertyId::FlexWrap, "wrap"s},
});
expect_eq(css::parse("p { flex-flow: wrap wrap; }").rules.at(0).declarations, //
std::map<css::PropertyId, std::string>{});
expect_eq(css::parse("p { flex-flow: wrap asdf; }").rules.at(0).declarations, //
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, too many values :(", [] {
expect_eq(css::parse("p { flex-flow: column wrap nowrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
return etest::run_all_tests();
}