diff options
author | Andreas Kling <kling@serenityos.org> | 2022-03-26 14:29:52 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-26 17:31:01 +0100 |
commit | fda25f95059d9c3d5e9a5fe433ace37c0af84591 (patch) | |
tree | 55242dd7bcd4de7a26c02d1d4d50982b80150e49 /Userland/Libraries/LibWeb/HTML/Parser | |
parent | 434970f0229262bc9f17669b7d36bf6897e803b1 (diff) | |
download | serenity-fda25f95059d9c3d5e9a5fe433ace37c0af84591.zip |
LibWeb: Move HTML dimension value parsing from CSS to HTML namespace
These are part of HTML, not CSS, so let's not confuse things.
Diffstat (limited to 'Userland/Libraries/LibWeb/HTML/Parser')
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp | 111 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h | 3 |
2 files changed, 114 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index c0da3e8b60..7422037db2 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -3642,4 +3642,115 @@ String HTMLParser::serialize_html_fragment(DOM::Node const& node) return builder.to_string(); } +// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#current-dimension-value +static RefPtr<CSS::StyleValue> parse_current_dimension_value(float value, Utf8View input, Utf8View::Iterator position) +{ + // 1. If position is past the end of input, then return value as a length. + if (position == input.end()) + return CSS::LengthStyleValue::create(CSS::Length::make_px(value)); + + // 2. If the code point at position within input is U+0025 (%), then return value as a percentage. + if (*position == '%') + return CSS::PercentageStyleValue::create(CSS::Percentage(value)); + + // 3. Return value as a length. + return CSS::LengthStyleValue::create(CSS::Length::make_px(value)); +} + +// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-dimension-values +RefPtr<CSS::StyleValue> parse_dimension_value(StringView string) +{ + // 1. Let input be the string being parsed. + auto input = Utf8View(string); + if (!input.validate()) + return nullptr; + + // 2. Let position be a position variable for input, initially pointing at the start of input. + auto position = input.begin(); + + // 3. Skip ASCII whitespace within input given position. + while (position != input.end() && is_ascii_space(*position)) + ++position; + + // 4. If position is past the end of input or the code point at position within input is not an ASCII digit, + // then return failure. + if (position == input.end() || !is_ascii_digit(*position)) + return nullptr; + + // 5. Collect a sequence of code points that are ASCII digits from input given position, + // and interpret the resulting sequence as a base-ten integer. Let value be that number. + StringBuilder number_string; + while (position != input.end() && is_ascii_digit(*position)) { + number_string.append(*position); + ++position; + } + auto integer_value = number_string.string_view().to_int(); + + // 6. If position is past the end of input, then return value as a length. + if (position == input.end()) + return CSS::LengthStyleValue::create(CSS::Length::make_px(*integer_value)); + + float value = *integer_value; + + // 7. If the code point at position within input is U+002E (.), then: + if (*position == '.') { + // 1. Advance position by 1. + ++position; + + // 2. If position is past the end of input or the code point at position within input is not an ASCII digit, + // then return the current dimension value with value, input, and position. + if (position == input.end() || !is_ascii_digit(*position)) + return parse_current_dimension_value(value, input, position); + + // 3. Let divisor have the value 1. + float divisor = 1; + + // 4. While true: + while (true) { + // 1. Multiply divisor by ten. + divisor *= 10; + + // 2. Add the value of the code point at position within input, + // interpreted as a base-ten digit (0..9) and divided by divisor, to value. + value += (*position - '0') / divisor; + + // 3. Advance position by 1. + ++position; + + // 4. If position is past the end of input, then return value as a length. + if (position == input.end()) + return CSS::LengthStyleValue::create(CSS::Length::make_px(value)); + + // 5. If the code point at position within input is not an ASCII digit, then break. + if (!is_ascii_digit(*position)) + break; + } + } + + // 8. Return the current dimension value with value, input, and position. + return parse_current_dimension_value(value, input, position); +} + +// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-non-zero-dimension-values +RefPtr<CSS::StyleValue> parse_nonzero_dimension_value(StringView string) +{ + // 1. Let input be the string being parsed. + // 2. Let value be the result of parsing input using the rules for parsing dimension values. + auto value = parse_dimension_value(string); + + // 3. If value is an error, return an error. + if (!value) + return nullptr; + + // 4. If value is zero, return an error. + if (value->is_length() && value->as_length().length().raw_value() == 0) + return nullptr; + if (value->is_percentage() && value->as_percentage().percentage().value() == 0) + return nullptr; + + // 5. If value is a percentage, return value as a percentage. + // 6. Return value as a length. + return value; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h index 78137adf24..7fbfb363d6 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.h @@ -186,4 +186,7 @@ private: StringBuilder m_character_insertion_builder; }; +RefPtr<CSS::StyleValue> parse_dimension_value(StringView); +RefPtr<CSS::StyleValue> parse_nonzero_dimension_value(StringView); + } |