aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuri Kobets <yuri.kobets@gmail.com>2024-04-30 01:03:48 +0300
committerYuri Kobets <yuri.kobets@gmail.com>2024-05-26 00:39:37 +0300
commit66d1048db705eb53ed850f325679aed60dfbf3d5 (patch)
tree70c887d7603b260094a72ccc38a86683d65011f5
parentaf645b141090ed969a2c15e6b1786d1e8d641389 (diff)
Parse grid and gap CSS propertiesupstream/grid_layout
grid grid-auto-flow grid-auto-columns grid-auto-rows gap row-gap column-gap
-rw-r--r--include/litehtml/grid.h13
-rw-r--r--include/litehtml/html.h4
-rw-r--r--include/litehtml/string_id.h7
-rw-r--r--include/litehtml/style.h7
-rw-r--r--src/grid.cpp14
-rw-r--r--src/style.cpp158
6 files changed, 190 insertions, 13 deletions
diff --git a/include/litehtml/grid.h b/include/litehtml/grid.h
index f42273e6..d9ed789b 100644
--- a/include/litehtml/grid.h
+++ b/include/litehtml/grid.h
@@ -7,6 +7,13 @@
namespace litehtml
{
+ enum grid_auto_flow
+ {
+ grid_auto_flow_row = 0x1,
+ grid_auto_flow_column = 0x2,
+ grid_auto_flow_dense = 0x10
+ };
+
// <grid-line> =
// auto |
// <custom-ident> |
@@ -267,6 +274,12 @@ namespace litehtml
bool from_tokens(const css_token_vector& tokens);
};
+
+ struct css_grid_auto_row_columns
+ {
+ std::vector<css_grid_template::track_size> value;
+ bool from_tokens(const css_token_vector& tokens);
+ };
}
#endif //LITEHTML_GRID_H
diff --git a/include/litehtml/html.h b/include/litehtml/html.h
index 0b0b763a..7048c250 100644
--- a/include/litehtml/html.h
+++ b/include/litehtml/html.h
@@ -30,8 +30,8 @@ namespace litehtml
string index_value(int index, const string& strings, char delim = ';');
bool value_in_list(const string& val, const string& strings, char delim = ';');
string::size_type find_close_bracket(const string& s, string::size_type off, char open_b = '(', char close_b = ')');
- void split_string(const string& str, string_vector& tokens, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"");
- string_vector split_string(const string& str, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"");
+ void split_string(const string& str, string_vector& tokens, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"", const string& chars_to_trim = "");
+ string_vector split_string(const string& str, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"", const string& chars_to_trim = "");
void join_string(string& str, const string_vector& tokens, const string& delims);
double t_strtod(const char* string, char** endPtr = nullptr);
string get_escaped_string(const string& in_str);
diff --git a/include/litehtml/string_id.h b/include/litehtml/string_id.h
index 1ea0ec86..a0e3c8e8 100644
--- a/include/litehtml/string_id.h
+++ b/include/litehtml/string_id.h
@@ -353,6 +353,13 @@ STRING_ID(
_grid_template_rows_,
_grid_template_columns_,
_grid_template_,
+ _grid_,
+ _grid_auto_flow_,
+ _grid_auto_rows_,
+ _grid_auto_columns_,
+ _gap_,
+ _row_gap_,
+ _column_gap_
)
#undef STRING_ID
extern const string_id empty_id; // _id("")
diff --git a/include/litehtml/style.h b/include/litehtml/style.h
index 98c52512..dd7badee 100644
--- a/include/litehtml/style.h
+++ b/include/litehtml/style.h
@@ -26,7 +26,8 @@ namespace litehtml
css_token_vector,
css_grid_line,
css_grid_template_areas,
- css_grid_template
+ css_grid_template,
+ css_grid_auto_row_columns
>
{
bool m_important = false;
@@ -94,7 +95,9 @@ namespace litehtml
void parse_grid_row_col(string_id name, const css_token_vector& tokens, bool important);
void parse_grid_area(const css_token_vector& tokens, bool important);
- void parse_grid_template(const css_token_vector& tokens, bool important);
+ bool parse_grid_template(const css_token_vector& tokens, bool important);
+ void parse_grid(const css_token_vector& tokens, bool important);
+ void parse_grid_auto_flow(const css_token_vector& tokens, bool important);
void add_parsed_property(string_id name, const property_value& propval);
void add_length_property(string_id name, css_token val, string keywords, int options, bool important);
diff --git a/src/grid.cpp b/src/grid.cpp
index 4cb99cda..a8ccd8cc 100644
--- a/src/grid.cpp
+++ b/src/grid.cpp
@@ -522,3 +522,17 @@ bool litehtml::css_grid_template::fit_content::parse(const litehtml::css_token &
}
return false;
}
+
+bool litehtml::css_grid_auto_row_columns::from_tokens(const litehtml::css_token_vector &tokens)
+{
+ for(auto iter = tokens.cbegin(); iter != tokens.cend(); ++iter)
+ {
+ css_grid_template::track_size ts;
+ if(ts.parse(iter, tokens.cend()))
+ {
+ value.emplace_back(ts);
+ } else
+ return false;
+ }
+ return true;
+}
diff --git a/src/style.cpp b/src/style.cpp
index b7a6ce9f..ea4245ed 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -529,6 +529,56 @@ void style::add_property(string_id name, const css_token_vector& value, const st
parse_grid_template(value, important);
break;
+ case _grid_auto_flow_:
+ parse_grid_auto_flow(value, important);
+ break;
+
+ case _grid_:
+ parse_grid(value, important);
+ break;
+
+ case _grid_auto_columns_:
+ case _grid_auto_rows_:
+ {
+ css_grid_auto_row_columns auto_rc;
+ if(auto_rc.from_tokens(value))
+ {
+ add_parsed_property(name, property_value(auto_rc, important));
+ }
+ }
+ break;
+
+ case _row_gap_:
+ case _column_gap_:
+ add_length_property(name, val, "normal", f_number|f_length_percentage|f_positive, important);
+ break;
+
+ case _gap_:
+ {
+ if(value.size() == 1)
+ {
+ css_length length;
+ if (length.from_token(value[0], f_number|f_length_percentage|f_positive, "normal"))
+ {
+ add_parsed_property(_row_gap_, property_value(length, important));
+ add_parsed_property(_column_gap_, property_value(length, important));
+ }
+ } else if(value.size() == 2)
+ {
+ css_length row_gap;
+ css_length column_gap;
+ if (row_gap.from_token(value[0], f_number|f_length_percentage|f_positive, "normal"))
+ {
+ if (column_gap.from_token(value[1], f_number|f_length_percentage|f_positive, "normal"))
+ {
+ add_parsed_property(_row_gap_, property_value(row_gap, important));
+ add_parsed_property(_column_gap_, property_value(column_gap, important));
+ }
+ }
+ }
+ }
+ break;
+
// ============================= CUSTOM PROPERTY =============================
// https://drafts.csswg.org/css-variables-2/#defining-variables
@@ -1627,18 +1677,18 @@ void style::parse_grid_area(const css_token_vector &tokens, bool important)
// none |
// [ <'grid-template-rows'> / <'grid-template-columns'> ] |
// [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?
-void style::parse_grid_template(const css_token_vector &tokens, bool important)
+bool style::parse_grid_template(const css_token_vector &tokens, bool important)
{
if(tokens.size() == 1 && tokens[0].type == IDENT && tokens[0].name == "none")
{
add_parsed_property(_grid_template_columns_, property_value(css_grid_template(), important));
add_parsed_property(_grid_template_rows_, property_value(css_grid_template(), important));
add_parsed_property(_grid_template_areas_, property_value(css_grid_template_areas(), important));
- return;
+ return false;
}
auto parts = parse_slash_separated_list(tokens);
- if(parts.empty() || parts.size() > 2) return;
+ if(parts.empty() || parts.size() > 2) return false;
if(parts.size() == 2)
{
@@ -1651,7 +1701,7 @@ void style::parse_grid_template(const css_token_vector &tokens, bool important)
add_parsed_property(_grid_template_columns_, property_value(cols, important));
add_parsed_property(_grid_template_rows_, property_value(rows, important));
add_parsed_property(_grid_template_areas_, property_value(css_grid_template_areas(), important));
- return;
+ return false;
}
}
}
@@ -1686,10 +1736,10 @@ void style::parse_grid_template(const css_token_vector &tokens, bool important)
}
tl.value.emplace_back(ln);
} else
- return;
+ return false;
} else if((*p_iter).type == STRING)
{
- if(!areas.from_token((*p_iter))) return;
+ if(!areas.from_token((*p_iter))) return false;
} else
{
css_grid_template::track_size ts;
@@ -1697,22 +1747,112 @@ void style::parse_grid_template(const css_token_vector &tokens, bool important)
{
tl.value.emplace_back(ts);
} else
- return;
+ return false;
}
}
- if(areas.is_none()) return;
+ if(areas.is_none()) return false;
css_grid_template rows;
rows.value = tl;
css_grid_template cols;
if(parts.size() == 2)
{
- if(!cols.from_tokens(parts[1])) return;
+ if(!cols.from_tokens(parts[1])) return false;
}
add_parsed_property(_grid_template_columns_, property_value(cols, important));
add_parsed_property(_grid_template_rows_, property_value(rows, important));
add_parsed_property(_grid_template_areas_, property_value(areas, important));
+ return true;
+}
+
+// <'grid-template'> |
+// <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? |
+// [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
+void style::parse_grid(const css_token_vector &tokens, bool important)
+{
+ if(parse_grid_template(tokens, important)) return;
+
+ auto parts = parse_slash_separated_list(tokens);
+ if(parts.size() != 2) return;
+
+ // [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
+ if(parts[0][0].type == IDENT && is_one_of(parts[0][0].name, "auto-flow", "dense"))
+ {
+ css_grid_template cols;
+ if(!cols.from_tokens(parts[1])) return;
+ int auto_flow = 0;
+ if(parts[0][0].name == "auto-flow")
+ {
+ parts[0].erase(parts[0].begin());
+ auto_flow = grid_auto_flow_row;
+ }
+ if(parts[0][0].type == IDENT && parts[0][0].name == "dense")
+ {
+ parts[0].erase(parts[0].begin());
+ auto_flow = grid_auto_flow_dense;
+ }
+ if(!(auto_flow & grid_auto_flow_row)) return;
+
+ css_grid_auto_row_columns auto_rows;
+ if(!auto_rows.from_tokens(parts[0])) return;
+
+ add_parsed_property(_grid_auto_flow_, property_value(auto_flow, important));
+ add_parsed_property(_grid_auto_rows_, property_value(auto_rows, important));
+ add_parsed_property(_grid_template_columns_, property_value(cols, important));
+ }
+ // <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>?
+ else if(parts[1][0].type == IDENT && is_one_of(parts[1][0].name, "auto-flow", "dense"))
+ {
+ css_grid_template rows;
+ if(!rows.from_tokens(parts[0])) return;
+ int auto_flow = 0;
+ if(parts[1][0].name == "auto-flow")
+ {
+ parts[1].erase(parts[0].begin());
+ auto_flow = grid_auto_flow_column;
+ }
+ if(parts[1][0].type == IDENT && parts[1][0].name == "dense")
+ {
+ parts[1].erase(parts[1].begin());
+ auto_flow = grid_auto_flow_dense;
+ }
+ if(!(auto_flow & grid_auto_flow_column)) return;
+
+ css_grid_auto_row_columns auto_cols;
+ if(!auto_cols.from_tokens(parts[1])) return;
+
+ add_parsed_property(_grid_auto_flow_, property_value(auto_flow, important));
+ add_parsed_property(_grid_auto_columns_, property_value(auto_cols, important));
+ add_parsed_property(_grid_template_rows_, property_value(rows, important));
+ }
+}
+
+// [ row | column ] || dense
+void style::parse_grid_auto_flow(const css_token_vector &tokens, bool important)
+{
+ if(tokens.empty() || tokens.size() > 2) return;
+ int auto_flow = 0;
+ for(const auto& item : tokens)
+ {
+ if(item.type == IDENT)
+ {
+ if(item.name == "row")
+ {
+ if(auto_flow & (grid_auto_flow_row | grid_auto_flow_column)) return;
+ auto_flow |= grid_auto_flow_row;
+ } else if(item.name == "column")
+ {
+ if(auto_flow & (grid_auto_flow_row | grid_auto_flow_column)) return;
+ auto_flow |= grid_auto_flow_column;
+ } else if(item.name == "dense")
+ {
+ if(auto_flow & grid_auto_flow_dense) return;
+ auto_flow |= grid_auto_flow_dense;
+ }
+ }
+ }
+ add_parsed_property(_grid_auto_flow_, property_value(auto_flow, important));
}
} // namespace litehtml \ No newline at end of file