1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 09:14:58 +00:00

LibWeb: Add basic parse floating point number function

This commit is contained in:
Bastiaan van der Plaat 2023-11-15 19:54:01 +01:00 committed by Sam Atkins
parent 3175557cb8
commit 761d824b72
5 changed files with 42 additions and 32 deletions

View file

@ -953,10 +953,8 @@ String HTMLInputElement::value_sanitization_algorithm(String const& value) const
}
} else if (type_state() == HTMLInputElement::TypeAttributeState::Number) {
// If the value of the element is not a valid floating-point number, then set it to the empty string instead.
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
// 6. Skip ASCII whitespace within input given position.
auto maybe_double = value.bytes_as_string_view().to_double(TrimWhitespace::Yes);
if (!maybe_double.has_value() || !isfinite(maybe_double.value()))
auto maybe_value = parse_floating_point_number(value);
if (!maybe_value.has_value() || !isfinite(maybe_value.value()))
return String {};
} else if (type_state() == HTMLInputElement::TypeAttributeState::Date) {
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):value-sanitization-algorithm
@ -981,9 +979,16 @@ String HTMLInputElement::value_sanitization_algorithm(String const& value) const
return String {};
} else if (type_state() == HTMLInputElement::TypeAttributeState::Range) {
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):value-sanitization-algorithm
auto maybe_double = value.bytes_as_string_view().to_double(TrimWhitespace::Yes);
if (!maybe_double.has_value() || !isfinite(maybe_double.value()))
return JS::number_to_string(maybe_double.value_or(0));
// If the value of the element is not a valid floating-point number, then set it to the best representation, as a floating-point number, of the default value.
auto maybe_value = parse_floating_point_number(value);
if (!maybe_value.has_value() || !isfinite(maybe_value.value())) {
// The default value is the minimum plus half the difference between the minimum and the maximum, unless the maximum is less than the minimum, in which case the default value is the minimum.
auto min = parse_floating_point_number(get_attribute(HTML::AttributeNames::min).value_or("0"_string)).value_or(0);
auto max = parse_floating_point_number(get_attribute(HTML::AttributeNames::max).value_or("1"_string)).value_or(1);
if (max > min)
return JS::number_to_string(min);
return JS::number_to_string(min + (max - min) / 2);
}
} else if (type_state() == HTMLInputElement::TypeAttributeState::Color) {
// https://html.spec.whatwg.org/multipage/input.html#color-state-(type=color):value-sanitization-algorithm
// If the value of the element is a valid simple color, then set it to the value of the element converted to ASCII lowercase;

View file

@ -8,6 +8,7 @@
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/HTML/HTMLProgressElement.h>
#include <LibWeb/HTML/Numbers.h>
#include <LibWeb/Layout/BlockContainer.h>
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Layout/Progress.h>
@ -51,26 +52,21 @@ void HTMLProgressElement::progress_position_updated()
document().invalidate_layout();
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-progress-value
double HTMLProgressElement::value() const
{
auto const& value_characters = deprecated_attribute(HTML::AttributeNames::value);
if (value_characters == nullptr)
auto maybe_value_string = get_attribute(HTML::AttributeNames::value);
if (!maybe_value_string.has_value())
return 0;
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
// 6. Skip ASCII whitespace within input given position.
auto maybe_double = value_characters.to_double(AK::TrimWhitespace::Yes);
if (!maybe_double.has_value())
auto maybe_value = parse_floating_point_number(maybe_value_string.value());
if (!maybe_value.has_value())
return 0;
if (!isfinite(maybe_double.value()) || maybe_double.value() < 0)
return 0;
return min(maybe_double.value(), max());
return clamp(maybe_value.value(), 0, max());
}
WebIDL::ExceptionOr<void> HTMLProgressElement::set_value(double value)
{
if (value < 0)
if (value < 0 || value > max())
return {};
TRY(set_attribute(HTML::AttributeNames::value, MUST(String::number(value))));
@ -78,21 +74,16 @@ WebIDL::ExceptionOr<void> HTMLProgressElement::set_value(double value)
return {};
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-progress-max
double HTMLProgressElement::max() const
{
auto const& max_characters = deprecated_attribute(HTML::AttributeNames::max);
if (max_characters == nullptr)
auto maybe_max_string = get_attribute(HTML::AttributeNames::max);
if (!maybe_max_string.has_value())
return 1;
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
// 6. Skip ASCII whitespace within input given position.
auto double_or_none = max_characters.to_double(AK::TrimWhitespace::Yes);
if (!double_or_none.has_value())
auto maybe_max = parse_floating_point_number(maybe_max_string.value());
if (!maybe_max.has_value())
return 1;
if (!isfinite(double_or_none.value()) || double_or_none.value() <= 0)
return 1;
return double_or_none.value();
return AK::max(maybe_max.value(), 0);
}
WebIDL::ExceptionOr<void> HTMLProgressElement::set_max(double value)

View file

@ -7,6 +7,7 @@
#include <AK/GenericLexer.h>
#include <LibWeb/HTML/Numbers.h>
#include <LibWeb/Infra/CharacterTypes.h>
#include <math.h>
namespace Web::HTML {
@ -79,4 +80,16 @@ Optional<u32> parse_non_negative_integer(StringView string)
return static_cast<u32>(optional_value.value());
}
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
Optional<double> parse_floating_point_number(StringView string)
{
// FIXME: Implement spec compliant floating point number parsing
auto maybe_double = MUST(String::from_utf8(string)).to_number<double>(TrimWhitespace::Yes);
if (!maybe_double.has_value())
return {};
if (!isfinite(maybe_double.value()))
return {};
return maybe_double.value();
}
}

View file

@ -15,4 +15,6 @@ Optional<i32> parse_integer(StringView string);
Optional<u32> parse_non_negative_integer(StringView string);
Optional<double> parse_floating_point_number(StringView string);
}

View file

@ -402,8 +402,7 @@ ErrorOr<void> TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::
bar_style->set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::FlowRoot)));
auto value_style = TRY(style_computer.compute_style(progress, CSS::Selector::PseudoElement::ProgressValue));
value_style->set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Block)));
auto position = progress.position();
value_style->set_property(CSS::PropertyID::Width, CSS::PercentageStyleValue::create(CSS::Percentage(position >= 0 ? round_to<int>(100 * position) : 0)));
value_style->set_property(CSS::PropertyID::Width, CSS::PercentageStyleValue::create(CSS::Percentage(progress.position() * 100)));
auto bar_display = bar_style->display();
auto value_display = value_style->display();
auto progress_bar = DOM::Element::create_layout_node_for_display_type(document, bar_display, bar_style, nullptr);