diff options
| author | Yuri Kobets <yuri.kobets@gmail.com> | 2024-04-30 01:03:48 +0300 |
|---|---|---|
| committer | Yuri Kobets <yuri.kobets@gmail.com> | 2024-05-26 00:39:37 +0300 |
| commit | 66d1048db705eb53ed850f325679aed60dfbf3d5 (patch) | |
| tree | 70c887d7603b260094a72ccc38a86683d65011f5 | |
| parent | af645b141090ed969a2c15e6b1786d1e8d641389 (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.h | 13 | ||||
| -rw-r--r-- | include/litehtml/html.h | 4 | ||||
| -rw-r--r-- | include/litehtml/string_id.h | 7 | ||||
| -rw-r--r-- | include/litehtml/style.h | 7 | ||||
| -rw-r--r-- | src/grid.cpp | 14 | ||||
| -rw-r--r-- | src/style.cpp | 158 |
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 |
