瀏覽代碼

LibWeb: Support shorthands when setting style attribute

Better support for CSS shorthands when setting the style attribute. This
improves some tests in WPT /css/css-align/default-alignment/*shorthand.
When setting the style attribute in JS via element.style = '..' or the
setAttribute method, shorthand properties were not expanded to longhand
properties.
Sergei Azarkin 9 月之前
父節點
當前提交
2199fde5a9

+ 12 - 0
Tests/LibWeb/Text/expected/HTML/background-shorthand.txt

@@ -0,0 +1,12 @@
+style.cssText = background-color: rgb(255, 255, 0); background-image: none; background-position-x: left 0%; background-position-y: top 0%; background-size: auto auto; background-repeat: repeat repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;
+style.length = 9
+style[] =
+1. background-color
+2. background-image
+3. background-position-x
+4. background-position-y
+5. background-size
+6. background-repeat
+7. background-attachment
+8. background-origin
+9. background-clip

+ 48 - 0
Tests/LibWeb/Text/expected/HTML/place-items-shorthand.txt

@@ -0,0 +1,48 @@
+=== place-items: normal
+place-items: normal normal
+align-items: normal
+justify-items: normal
+=== place-items: stretch
+place-items: stretch stretch
+align-items: stretch
+justify-items: stretch
+=== place-items: start
+place-items: start start
+align-items: start
+justify-items: start
+=== place-items: end
+place-items: end end
+align-items: end
+justify-items: end
+=== place-items: self-start
+place-items: self-start self-start
+align-items: self-start
+justify-items: self-start
+=== place-items: self-end
+place-items: self-end self-end
+align-items: self-end
+justify-items: self-end
+=== place-items: center
+place-items: center center
+align-items: center
+justify-items: center
+=== place-items: flex-start
+place-items: flex-start flex-start
+align-items: flex-start
+justify-items: flex-start
+=== place-items: flex-end
+place-items: flex-end flex-end
+align-items: flex-end
+justify-items: flex-end
+=== place-items: baseline
+place-items: baseline baseline
+align-items: baseline
+justify-items: baseline
+=== place-items: normal start
+place-items: normal start
+align-items: normal
+justify-items: start
+=== place-items: normal center
+place-items: normal center
+align-items: normal
+justify-items: center

+ 15 - 0
Tests/LibWeb/Text/input/HTML/background-shorthand.html

@@ -0,0 +1,15 @@
+<!doctype html>
+<div id="target" style="background: yellow">Hello</div>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        let target = document.getElementById("target");
+        let style = target.style;
+        println(`style.cssText = ${style.cssText}`);
+        println(`style.length = ${style.length}`);
+        println(`style[] =`);
+        for (let i = 0; i < style.length; ++i) {
+            println(`${i+1}. ${style[i]}`);
+        }
+    });
+</script>

+ 34 - 0
Tests/LibWeb/Text/input/HTML/place-items-shorthand.html

@@ -0,0 +1,34 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        for (const alignValue of [
+            "normal",
+            "stretch",
+            "start",
+            "end",
+            "self-start",
+            "self-end",
+            "center",
+            "flex-start",
+            "flex-end",
+            "baseline",
+            // "first baseline",
+            // "last baseline",
+            // "safe flex-end",
+            // "unsafe end",
+            // "safe end",
+            // "unsafe flex-start",
+            // "safe center",
+            "normal start",
+            "normal center",
+        ]) {
+            println("=== place-items: " + alignValue);
+            var div = document.createElement("div");
+            div.setAttribute("style", "place-items: " + alignValue + ";");
+            document.body.appendChild(div);
+            for (const prop of ["place-items", "align-items", "justify-items"]) {
+                println(prop + ": " + div.style[prop]);
+            }
+        }
+    });
+</script>

+ 21 - 1
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -39,6 +39,7 @@
 #include <LibWeb/CSS/PropertyName.h>
 #include <LibWeb/CSS/Selector.h>
 #include <LibWeb/CSS/Sizing.h>
+#include <LibWeb/CSS/StyleComputer.h>
 #include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
 #include <LibWeb/CSS/StyleValues/BackgroundRepeatStyleValue.h>
 #include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
@@ -1187,9 +1188,28 @@ template Vector<Vector<ComponentValue>> Parser::parse_a_comma_separated_list_of_
 
 ElementInlineCSSStyleDeclaration* Parser::parse_as_style_attribute(DOM::Element& element)
 {
+    auto expand_shorthands = [&](Vector<StyleProperty>& properties) -> Vector<StyleProperty> {
+        Vector<StyleProperty> expanded_properties;
+        for (auto& property : properties) {
+            if (property_is_shorthand(property.property_id)) {
+                StyleComputer::for_each_property_expanding_shorthands(property.property_id, *property.value, StyleComputer::AllowUnresolved::Yes, [&](PropertyID longhand_property_id, CSSStyleValue const& longhand_value) {
+                    expanded_properties.append(CSS::StyleProperty {
+                        .important = property.important,
+                        .property_id = longhand_property_id,
+                        .value = longhand_value,
+                    });
+                });
+            } else {
+                expanded_properties.append(property);
+            }
+        }
+        return expanded_properties;
+    };
+
     auto declarations_and_at_rules = parse_a_blocks_contents(m_token_stream);
     auto [properties, custom_properties] = extract_properties(declarations_and_at_rules);
-    return ElementInlineCSSStyleDeclaration::create(element, move(properties), move(custom_properties));
+    auto expanded_properties = expand_shorthands(properties);
+    return ElementInlineCSSStyleDeclaration::create(element, move(expanded_properties), move(custom_properties));
 }
 
 Optional<URL::URL> Parser::parse_url_function(TokenStream<ComponentValue>& tokens)