Browse Source

LibWeb: Correct serialization of steps() easing functions

Pavel Shliak 8 months ago
parent
commit
8cd514d83c

+ 6 - 2
Libraries/LibWeb/CSS/StyleValues/EasingStyleValue.cpp

@@ -315,6 +315,7 @@ double EasingStyleValue::CubicBezier::evaluate_at(double input_progress, bool) c
     return sample1.y + factor * (sample2.y - sample1.y);
 }
 
+// https://drafts.csswg.org/css-easing/#bezier-serialization
 String EasingStyleValue::CubicBezier::to_string() const
 {
     StringBuilder builder;
@@ -377,13 +378,16 @@ double EasingStyleValue::Steps::evaluate_at(double input_progress, bool before_f
     return current_step / jumps;
 }
 
+// https://drafts.csswg.org/css-easing/#steps-serialization
 String EasingStyleValue::Steps::to_string() const
 {
     StringBuilder builder;
+    // Unlike the other easing function keywords, step-start and step-end do not serialize as themselves.
+    // Instead, they serialize as "steps(1, start)" and "steps(1)", respectively.
     if (*this == Steps::step_start()) {
-        builder.append("step-start"sv);
+        builder.append("steps(1, start)"sv);
     } else if (*this == Steps::step_end()) {
-        builder.append("step-end"sv);
+        builder.append("steps(1)"sv);
     } else {
         auto position = [&] -> Optional<StringView> {
             switch (this->position) {

+ 10 - 0
Tests/LibWeb/Text/expected/WebAnimations/misc/steps-serialization.txt

@@ -0,0 +1,10 @@
+Input: steps(1, jump-none), Computed: steps(1, jump-none)
+Input: steps(1, start), Computed: steps(1, start)
+Input: steps(1), Computed: steps(1)
+Input: steps(4, jump-both), Computed: steps(4, jump-both)
+Input: steps(2, jump-start), Computed: steps(2, jump-start)
+Input: steps(3, end), Computed: steps(3)
+Input: steps(5, start), Computed: steps(5, start)
+Input: steps(6, jump-none), Computed: steps(6, jump-none)
+Input: steps(10, jump-both), Computed: steps(10, jump-both)
+Input: steps(1, jump-end), Computed: steps(1)

+ 35 - 0
Tests/LibWeb/Text/input/WebAnimations/misc/steps-serialization.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<script src="../../include.js"></script>
+<script>
+    test(() => {
+        const div = document.createElement('div');
+        div.style.width = '50px';
+        div.style.height = '50px';
+        div.style.backgroundColor = 'red';
+        div.style.animation = 'test-animation 2s infinite';
+
+        document.body.appendChild(div);
+
+        const testCases = [
+            { input: 'steps(1, jump-none)' },
+            { input: 'steps(1, start)' },
+            { input: 'steps(1)' }, // Equivalent to steps(1, end)
+            { input: 'steps(4, jump-both)' },
+            { input: 'steps(2, jump-start)' },
+            { input: 'steps(3, end)' }, // Implicitly steps(3)
+            { input: 'steps(5, start)' },
+            { input: 'steps(6, jump-none)' },
+            { input: 'steps(10, jump-both)' },
+            { input: 'steps(1, jump-end)' }, // Implicitly steps(1)
+        ];
+
+        testCases.forEach(({ input }) => {
+            div.style.animationTimingFunction = input;
+            const computed = getComputedStyle(div).animationTimingFunction;
+
+            println(`Input: ${input}, Computed: ${computed}`);
+        });
+
+        document.body.removeChild(div);
+    });
+</script>