LibWeb: Collapse & trim whitespace when serializing UnresolvedStyleValue

This commit is contained in:
Callum Law 2025-09-26 14:18:19 +12:00 committed by Sam Atkins
commit 9ee9be720c
Notes: github-actions[bot] 2025-09-26 06:31:11 +00:00
6 changed files with 202 additions and 9 deletions

View file

@ -8,6 +8,7 @@
#include <AK/Utf8View.h>
#include <LibWeb/CSS/Parser/ComponentValue.h>
#include <LibWeb/CSS/Serialize.h>
#include <LibWeb/Infra/Strings.h>
namespace Web::CSS {
@ -269,7 +270,7 @@ String serialize_a_series_of_component_values(ReadonlySpan<Parser::ComponentValu
{
// FIXME: There are special rules here where we should insert a comment between certain tokens. Do that!
if (insert_whitespace == InsertWhitespace::Yes)
return MUST(String::join(' ', component_values));
return MUST(Infra::strip_and_collapse_whitespace(MUST(String::join(' ', component_values))));
return MUST(String::join(""sv, component_values));
}

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 139 tests
128 Pass
11 Fail
130 Pass
9 Fail
Pass CSS Values and Units Test: attr
Fail CSS Values and Units Test: attr 1
Pass CSS Values and Units Test: attr 2
@ -34,7 +34,7 @@ Pass CSS Values and Units Test: attr 26
Fail CSS Values and Units Test: attr 27
Pass CSS Values and Units Test: attr 28
Pass CSS Values and Units Test: attr 29
Fail CSS Values and Units Test: attr 30
Pass CSS Values and Units Test: attr 30
Pass CSS Values and Units Test: attr 31
Pass CSS Values and Units Test: attr 32
Pass CSS Values and Units Test: attr 33
@ -55,7 +55,7 @@ Pass CSS Values and Units Test: attr 47
Pass CSS Values and Units Test: attr 48
Pass CSS Values and Units Test: attr 49
Fail CSS Values and Units Test: attr 50
Fail CSS Values and Units Test: attr 51
Pass CSS Values and Units Test: attr 51
Pass CSS Values and Units Test: attr 52
Pass CSS Values and Units Test: attr 53
Pass CSS Values and Units Test: attr 54

View file

@ -2,10 +2,10 @@ Harness status: OK
Found 5 tests
2 Pass
3 Fail
3 Pass
2 Fail
Pass Sanity check
Pass Attribute in null-namespace is substituted
Fail Fallback is taken when attribute does not exist in null-namespace
Pass Fallback is taken when attribute does not exist in null-namespace
Fail Attribute in null-namespace is substituted (JS)
Fail Fallback is taken when attribute does not does exist in null-namespace (JS)

View file

@ -0,0 +1,37 @@
Harness status: OK
Found 31 tests
30 Pass
1 Fail
Pass target1 --var2
Pass target1 margin-top
Pass target1 margin-right
Pass target1 margin-bottom
Pass target1 margin-left
Pass target2parent --var1
Pass target2parent --var2
Pass target2 --var1
Pass target2 --var2
Pass target3 --var1
Pass target3 --var2
Pass target4 --varA
Pass target4 --varB
Pass target4 --varC
Pass target5 --varA
Pass target5 --varB
Pass target5 --varC
Pass target6 --varA
Pass target6 --varB
Fail target6 --varC
Pass target7 --varA
Pass target7 --varB
Pass target7 --varC
Pass target8 --varA
Pass target8 --varB
Pass target9 --varA
Pass target9 --varB
Pass target9 --varC
Pass target10 --varA
Pass target10 --varB
Pass target10 --varC

View file

@ -0,0 +1,155 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing substituting variable references inside of variable declerations</title>
<meta rel="author" title="Kevin Babbitt">
<meta rel="author" title="Greg Whitworth">
<link rel="author" title="Microsoft Corporation" href="http://microsoft.com" />
<link rel="help" href="http://www.w3.org/TR/css-variables-1/#using-variables">
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<style>
#target1 {
margin: var(--var2);
--var2: var(--var1) 10px;
--var1: var(--var0) 13px 17px;
--var0: 23px;
}
#target2parent {
--var2: var(--var1, fallback);
--var1: var(--var2, fallback);
}
#target2 {
--var1: good;
}
#target3 {
--var2: var(--var1, 3px);
--var1: var(--var0, 5px);
}
#target4 {
--varA: var(--varB);
--varB: var(--varA);
--varC: var(--varB,13px);
}
#target5 {
--varA: var(--varB);
--varB: var(--varA) var(--varC);
--varC: var(--varB,13px);
}
#target6 {
--varA: var(--varB);
--varB: var(--varA) var(--varDoesNotExist,var(--varC));
--varC: var(--varB,13px);
}
#target7 {
--varDoesExist: 5px;
--varA: var(--varB);
--varB: var(--varA) var(--varDoesExist,var(--varC));
--varC: var(--varB,13px);
}
#target8 {
--varA: var(--varA, 9px);
--varB: var(--varA, 7px);
}
#target9 {
--varA: good;
--varB: very var(--varA, var(--varC));
--varC: var(--varB);
}
#target10parent {
--varA: good;
--varB: Also good;
--varC: another good one;
}
#target10 {
--varA: var(--varB);
--varB: var(--varA);
--varC: var(--varB);
}
</style>
</head>
<body>
<div id="target1"></div>
<div id="target2parent">
<div id="target2"></div>
</div>
<div id="target3"></div>
<div id="target4"></div>
<div id="target5"></div>
<div id="target6"></div>
<div id="target7"></div>
<div id="target8"></div>
<div id="target9"></div>
<div id="target10parent">
<div id="target10"></div>
</div>
<script type="text/javascript">
"use strict";
var testcases = [
{ element: "target1", propertyName: "--var2", expectedPropertyValue: "23px 13px 17px 10px" },
{ element: "target1", propertyName: "margin-top", expectedPropertyValue: "23px" },
{ element: "target1", propertyName: "margin-right", expectedPropertyValue: "13px" },
{ element: "target1", propertyName: "margin-bottom", expectedPropertyValue: "17px" },
{ element: "target1", propertyName: "margin-left", expectedPropertyValue: "10px" },
{ element: "target2parent", propertyName: "--var1", expectedPropertyValue: "" },
{ element: "target2parent", propertyName: "--var2", expectedPropertyValue: "" },
{ element: "target2", propertyName: "--var1", expectedPropertyValue: "good" },
{ element: "target2", propertyName: "--var2", expectedPropertyValue: "" },
{ element: "target3", propertyName: "--var1", expectedPropertyValue: "5px" },
{ element: "target3", propertyName: "--var2", expectedPropertyValue: "5px" },
{ element: "target4", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target4", propertyName: "--varB", expectedPropertyValue: "" },
{ element: "target4", propertyName: "--varC", expectedPropertyValue: "13px" },
{ element: "target5", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target5", propertyName: "--varB", expectedPropertyValue: "" },
{ element: "target5", propertyName: "--varC", expectedPropertyValue: "" },
{ element: "target6", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target6", propertyName: "--varB", expectedPropertyValue: "" },
{ element: "target6", propertyName: "--varC", expectedPropertyValue: "13px" },
{ element: "target7", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target7", propertyName: "--varB", expectedPropertyValue: "" },
{ element: "target7", propertyName: "--varC", expectedPropertyValue: "13px" },
{ element: "target8", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target8", propertyName: "--varB", expectedPropertyValue: "7px" },
{ element: "target9", propertyName: "--varA", expectedPropertyValue: "good" },
{ element: "target9", propertyName: "--varB", expectedPropertyValue: "very good" },
{ element: "target9", propertyName: "--varC", expectedPropertyValue: "very good" },
{ element: "target10", propertyName: "--varA", expectedPropertyValue: "" },
{ element: "target10", propertyName: "--varB", expectedPropertyValue: "" },
{ element: "target10", propertyName: "--varC", expectedPropertyValue: "" },
];
testcases.forEach(function (testcase) {
test( function () {
var div = document.getElementById(testcase.element);
var actualPropertyValue = window.getComputedStyle(div).getPropertyValue(testcase.propertyName);
assert_equals(actualPropertyValue, testcase.expectedPropertyValue);
}, testcase.element + " " + testcase.propertyName);
});
</script>
</body>
</html>