mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Parse border-image
shorthand property
This commit is contained in:
parent
c0390f759c
commit
923deb0c01
Notes:
github-actions[bot]
2025-07-03 09:20:50 +00:00
Author: https://github.com/tcl3
Commit: 923deb0c01
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5253
Reviewed-by: https://github.com/AtkinsSJ ✅
10 changed files with 318 additions and 3 deletions
|
@ -412,6 +412,7 @@ private:
|
|||
RefPtr<CSSStyleValue const> parse_single_background_repeat_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_single_background_size_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_border_value(PropertyID, TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_border_image_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_border_image_slice_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_border_radius_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_border_radius_shorthand_value(TokenStream<ComponentValue>&);
|
||||
|
|
|
@ -530,6 +530,10 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
|
|||
if (auto parsed_value = parse_border_value(property_id, tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::BorderImage:
|
||||
if (auto parsed_value = parse_border_image_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::BorderImageSlice:
|
||||
if (auto parsed_value = parse_border_image_slice_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
|
@ -1658,6 +1662,133 @@ RefPtr<CSSStyleValue const> Parser::parse_border_value(PropertyID property_id, T
|
|||
{ border_width.release_nonnull(), border_style.release_nonnull(), border_color.release_nonnull() });
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds/#border-image
|
||||
RefPtr<CSSStyleValue const> Parser::parse_border_image_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// <'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>
|
||||
auto transaction = tokens.begin_transaction();
|
||||
|
||||
RefPtr<CSSStyleValue const> source_value;
|
||||
RefPtr<CSSStyleValue const> slice_value;
|
||||
RefPtr<CSSStyleValue const> width_value;
|
||||
RefPtr<CSSStyleValue const> outset_value;
|
||||
RefPtr<CSSStyleValue const> repeat_value;
|
||||
|
||||
auto make_border_image_shorthand = [&]() {
|
||||
transaction.commit();
|
||||
if (!source_value)
|
||||
source_value = property_initial_value(PropertyID::BorderImageSource);
|
||||
if (!slice_value)
|
||||
slice_value = property_initial_value(PropertyID::BorderImageSlice);
|
||||
if (!width_value)
|
||||
width_value = property_initial_value(PropertyID::BorderImageWidth);
|
||||
if (!outset_value)
|
||||
outset_value = property_initial_value(PropertyID::BorderImageOutset);
|
||||
if (!repeat_value)
|
||||
repeat_value = property_initial_value(PropertyID::BorderImageRepeat);
|
||||
|
||||
return ShorthandStyleValue::create(PropertyID::BorderImage,
|
||||
{ PropertyID::BorderImageSource, PropertyID::BorderImageSlice, PropertyID::BorderImageWidth, PropertyID::BorderImageOutset, PropertyID::BorderImageRepeat },
|
||||
{ source_value.release_nonnull(), slice_value.release_nonnull(), width_value.release_nonnull(), outset_value.release_nonnull(), repeat_value.release_nonnull() });
|
||||
};
|
||||
|
||||
auto parse_value_list = [&](PropertyID property_id, TokenStream<ComponentValue>& inner_tokens, Optional<char> delimiter = {}) -> RefPtr<CSSStyleValue const> {
|
||||
auto inner_transaction = inner_tokens.begin_transaction();
|
||||
|
||||
auto remaining_values = property_maximum_value_count(property_id);
|
||||
StyleValueVector values;
|
||||
while (inner_tokens.has_next_token() && remaining_values > 0) {
|
||||
if (delimiter.has_value() && inner_tokens.next_token().is_delim(*delimiter))
|
||||
break;
|
||||
auto value = parse_css_value_for_property(property_id, inner_tokens);
|
||||
if (!value)
|
||||
break;
|
||||
values.append(*value);
|
||||
--remaining_values;
|
||||
}
|
||||
if (values.is_empty())
|
||||
return nullptr;
|
||||
|
||||
inner_transaction.commit();
|
||||
if (values.size() == 1)
|
||||
return values[0];
|
||||
|
||||
return StyleValueList::create(move(values), StyleValueList::Separator::Space);
|
||||
};
|
||||
|
||||
auto parse_slice_portion = [&]() {
|
||||
// <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]?
|
||||
auto transaction = tokens.begin_transaction();
|
||||
tokens.discard_whitespace();
|
||||
if (auto value = parse_border_image_slice_value(tokens)) {
|
||||
slice_value = move(value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
tokens.discard_whitespace();
|
||||
if (tokens.next_token().is_delim('/')) {
|
||||
tokens.discard_a_token();
|
||||
tokens.discard_whitespace();
|
||||
if (auto width = parse_value_list(PropertyID::BorderImageWidth, tokens)) {
|
||||
width_value = move(width);
|
||||
tokens.discard_whitespace();
|
||||
if (!tokens.next_token().is_delim('/')) {
|
||||
transaction.commit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tokens.next_token().is_delim('/'))
|
||||
return false;
|
||||
|
||||
tokens.discard_a_token();
|
||||
tokens.discard_whitespace();
|
||||
if (auto outset = parse_value_list(PropertyID::BorderImageOutset, tokens)) {
|
||||
outset_value = move(outset);
|
||||
tokens.discard_whitespace();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
tokens.discard_whitespace();
|
||||
transaction.commit();
|
||||
return true;
|
||||
};
|
||||
|
||||
auto has_source = false;
|
||||
auto has_repeat = false;
|
||||
auto has_slice_portion = false;
|
||||
while (tokens.has_next_token()) {
|
||||
if (auto source = parse_css_value_for_property(PropertyID::BorderImageSource, tokens)) {
|
||||
if (has_source)
|
||||
return nullptr;
|
||||
|
||||
has_source = true;
|
||||
source_value = move(source);
|
||||
continue;
|
||||
}
|
||||
if (auto repeat = parse_value_list(PropertyID::BorderImageRepeat, tokens)) {
|
||||
if (has_repeat)
|
||||
return nullptr;
|
||||
|
||||
has_repeat = true;
|
||||
repeat_value = move(repeat);
|
||||
continue;
|
||||
}
|
||||
if (parse_slice_portion()) {
|
||||
if (has_slice_portion)
|
||||
return nullptr;
|
||||
|
||||
has_slice_portion = true;
|
||||
continue;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return make_border_image_shorthand();
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds/#border-image-slice
|
||||
RefPtr<CSSStyleValue const> Parser::parse_border_image_slice_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
|
|
|
@ -705,6 +705,17 @@
|
|||
],
|
||||
"max-values": 1
|
||||
},
|
||||
"border-image": {
|
||||
"inherited": false,
|
||||
"initial": "none 100% 1 0 stretch",
|
||||
"longhands": [
|
||||
"border-image-source",
|
||||
"border-image-slice",
|
||||
"border-image-width",
|
||||
"border-image-outset",
|
||||
"border-image-repeat"
|
||||
]
|
||||
},
|
||||
"border-image-outset": {
|
||||
"affects-layout": false,
|
||||
"animation-type": "by-computed-value",
|
||||
|
|
|
@ -205,6 +205,19 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
|
||||
return MUST(builder.to_string());
|
||||
}
|
||||
case PropertyID::BorderImage: {
|
||||
auto source = longhand(PropertyID::BorderImageSource);
|
||||
auto slice = longhand(PropertyID::BorderImageSlice);
|
||||
auto width = longhand(PropertyID::BorderImageWidth);
|
||||
auto outset = longhand(PropertyID::BorderImageOutset);
|
||||
auto repeat = longhand(PropertyID::BorderImageRepeat);
|
||||
return MUST(String::formatted("{} {} / {} / {} {}",
|
||||
source->to_string(mode),
|
||||
slice->to_string(mode),
|
||||
width->to_string(mode),
|
||||
outset->to_string(mode),
|
||||
repeat->to_string(mode)));
|
||||
}
|
||||
case PropertyID::BorderRadius: {
|
||||
auto top_left = longhand(PropertyID::BorderTopLeftRadius);
|
||||
auto top_right = longhand(PropertyID::BorderTopRightRadius);
|
||||
|
|
|
@ -243,6 +243,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
|||
'border-end-end-radius': '0px'
|
||||
'borderEndStartRadius': '0px'
|
||||
'border-end-start-radius': '0px'
|
||||
'borderImage': 'none 100% / 1 / 0 stretch'
|
||||
'border-image': 'none 100% / 1 / 0 stretch'
|
||||
'borderImageOutset': '0'
|
||||
'border-image-outset': '0'
|
||||
'borderImageRepeat': 'stretch'
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 17 tests
|
||||
|
||||
17 Pass
|
||||
Pass e.style['border-image'] = "auto" should not set the property value
|
||||
Pass e.style['border-image'] = "none, url(\"http://www.example.com/\")" should not set the property value
|
||||
Pass e.style['border-image'] = "stretch repeat round" should not set the property value
|
||||
Pass e.style['border-image'] = "fill" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2 3 4 5" should not set the property value
|
||||
Pass e.style['border-image'] = "1% fill 2%" should not set the property value
|
||||
Pass e.style['border-image'] = "1 / -2px" should not set the property value
|
||||
Pass e.style['border-image'] = "-1 / 2px" should not set the property value
|
||||
Pass e.style['border-image'] = "1 / 1 2 3 4 5" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2 3 4 5 / / 1px" should not set the property value
|
||||
Pass e.style['border-image'] = "1 / / auto" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / / 1%" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% fill / / 1 2 3 4 5" should not set the property value
|
||||
Pass e.style['border-image'] = "1 / none / 1px" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / 1 2 3 4 5 / 2" should not set the property value
|
||||
Pass e.style['border-image'] = "1 2 3 4 5 / 1px / 1px" should not set the property value
|
||||
Pass e.style['border-image'] = "1 / 1px / auto" should not set the property value
|
|
@ -0,0 +1,36 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 30 tests
|
||||
|
||||
29 Pass
|
||||
1 Fail
|
||||
Pass e.style['border-image'] = "none" should set the property value
|
||||
Pass e.style['border-image'] = "stretch" should set the property value
|
||||
Pass e.style['border-image'] = "none 100% / 1 / 0 stretch" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") 1 2 3 4 fill" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") 1 2 3 4 fill / 1 / 0 stretch" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\")" should set the property value
|
||||
Pass e.style['border-image'] = "repeat round" should set the property value
|
||||
Pass e.style['border-image'] = "none repeat round" should set the property value
|
||||
Pass e.style['border-image'] = "space" should set the property value
|
||||
Fail e.style['border-image'] = "none space space" should set the property value
|
||||
Pass e.style['border-image'] = "none 100% / 1 / 0 space" should set the property value
|
||||
Pass e.style['border-image'] = "1" should set the property value
|
||||
Pass e.style['border-image'] = "none 1 1 1 1" should set the property value
|
||||
Pass e.style['border-image'] = "none 1 / 1 / 0 stretch" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") 1 2% 3 4%" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") 1 2% 3 4% fill" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") fill 1 2% 3 4%" should set the property value
|
||||
Pass e.style['border-image'] = "1 / 1px" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / 2%" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% fill / 3" should set the property value
|
||||
Pass e.style['border-image'] = "fill 1 2% 3 4% / auto" should set the property value
|
||||
Pass e.style['border-image'] = "1 / 1px 2% 3 auto" should set the property value
|
||||
Pass e.style['border-image'] = "1 / / 1px" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / / 2" should set the property value
|
||||
Pass e.style['border-image'] = "url(\"http://www.example.com/\") 1 2% 3 4% fill / / 1px 2 3px 4" should set the property value
|
||||
Pass e.style['border-image'] = "1 / 1px / 1px" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / 2% / 2" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% fill / 3 / 1px 2 3px 4" should set the property value
|
||||
Pass e.style['border-image'] = "1 / auto / 1px" should set the property value
|
||||
Pass e.style['border-image'] = "1 2% 3 4% / 1px 2% 3 auto / 2" should set the property value
|
|
@ -2,13 +2,13 @@ Harness status: OK
|
|||
|
||||
Found 20 tests
|
||||
|
||||
15 Pass
|
||||
5 Fail
|
||||
14 Pass
|
||||
6 Fail
|
||||
Pass The serialization of border: 1px; border-top: 1px; should be canonical.
|
||||
Pass The serialization of border: 1px solid red; should be canonical.
|
||||
Pass The serialization of border: 1px red; should be canonical.
|
||||
Pass The serialization of border: red; should be canonical.
|
||||
Pass The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical.
|
||||
Fail The serialization of border: 1px; border-top: 2px; should be canonical.
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Backgrounds and Borders Module Level 3: parsing border-image with invalid values</title>
|
||||
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-image">
|
||||
<meta name="assert" content="border-image supports only the grammar ' <‘border-image-source’> || <‘border-image-slice’> [ / <‘border-image-width’> | / <‘border-image-width’>? / <‘border-image-outset’> ]? || <‘border-image-repeat’>'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_invalid_value("border-image", "auto");
|
||||
test_invalid_value("border-image", 'none, url("http://www.example.com/")');
|
||||
|
||||
test_invalid_value("border-image", "stretch repeat round");
|
||||
|
||||
test_invalid_value("border-image", "fill");
|
||||
test_invalid_value("border-image", "1 2 3 4 5");
|
||||
test_invalid_value("border-image", "1% fill 2%");
|
||||
|
||||
test_invalid_value("border-image", "1 / -2px");
|
||||
test_invalid_value("border-image", "-1 / 2px");
|
||||
|
||||
test_invalid_value("border-image", "1 / 1 2 3 4 5");
|
||||
|
||||
test_invalid_value("border-image", "1 2 3 4 5 / / 1px");
|
||||
test_invalid_value("border-image", "1 / / auto");
|
||||
test_invalid_value("border-image", "1 2% 3 4% / / 1%");
|
||||
test_invalid_value("border-image", "1 2% 3 4% fill / / 1 2 3 4 5");
|
||||
|
||||
test_invalid_value("border-image", "1 / none / 1px");
|
||||
test_invalid_value("border-image", "1 2% 3 4% / 1 2 3 4 5 / 2");
|
||||
test_invalid_value("border-image", "1 2 3 4 5 / 1px / 1px");
|
||||
test_invalid_value("border-image", "1 / 1px / auto");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Backgrounds and Borders Module Level 3: parsing border-image with valid values</title>
|
||||
<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-image">
|
||||
<meta name="assert" content="border-image supports the full grammar ' <‘border-image-source’> || <‘border-image-slice’> [ / <‘border-image-width’> | / <‘border-image-width’>? / <‘border-image-outset’> ]? || <‘border-image-repeat’>'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// WebKit fails all these tests by returning an empty string as the value of border-image.
|
||||
|
||||
// "none" in Edge, "none 100% / 1 / 0 stretch" in Firefox and Blink.
|
||||
test_valid_value("border-image", "none", ["none", "none 100% / 1 / 0 stretch"]);
|
||||
test_valid_value("border-image", "stretch", ["stretch", "none", "none 100% / 1 / 0 stretch"]);
|
||||
test_valid_value("border-image", "none 100% / 1 / 0 stretch", ["none", "none 100% / 1 / 0 stretch"]);
|
||||
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") 1 2 3 4 fill', ['url("http://www.example.com/") 1 2 3 4 fill', 'url("http://www.example.com/") 1 2 3 4 fill / 1 / 0 stretch']);
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") 1 2 3 4 fill / 1 / 0 stretch', ['url("http://www.example.com/") 1 2 3 4 fill', 'url("http://www.example.com/") 1 2 3 4 fill / 1 / 0 stretch']);
|
||||
|
||||
test_valid_value("border-image", 'url("http://www.example.com/")', ['url("http://www.example.com/")', 'url("http://www.example.com/") 100% / 1 / 0 stretch']);
|
||||
|
||||
test_valid_value("border-image", "repeat round", ["repeat round", "none repeat round", "none 100% / 1 / 0 repeat round"]);
|
||||
test_valid_value("border-image", "none repeat round", ["repeat round", "none repeat round", "none 100% / 1 / 0 repeat round"]);
|
||||
|
||||
test_valid_value("border-image", "space", ["space", "none space space", "none 100% / 1 / 0 space"]);
|
||||
test_valid_value("border-image", "none space space", ["space", "none space space", "none space", "none 100% / 1 / 0 space"]);
|
||||
test_valid_value("border-image", "none 100% / 1 / 0 space", ["space", "none space space", "none 100% / 1 / 0 space"]);
|
||||
|
||||
test_valid_value("border-image", "1", ["1", "none 1 1 1 1", "none 1 / 1 / 0 stretch"]);
|
||||
test_valid_value("border-image", "none 1 1 1 1", ["1", "none 1 1 1 1", "none 1", "none 1 / 1 / 0 stretch"]);
|
||||
test_valid_value("border-image", "none 1 / 1 / 0 stretch", ["1", "none 1 1 1 1", "none 1 / 1 / 0 stretch"]);
|
||||
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") 1 2% 3 4%', ['url("http://www.example.com/") 1 2% 3 4%', 'url("http://www.example.com/") 1 2% 3 4% / 1 / 0 stretch']);
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") 1 2% 3 4% fill', ['url("http://www.example.com/") 1 2% 3 4% fill', 'url("http://www.example.com/") 1 2% 3 4% fill / 1 / 0 stretch']);
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") fill 1 2% 3 4%', ['url("http://www.example.com/") 1 2% 3 4% fill', 'url("http://www.example.com/") 1 2% 3 4% fill / 1 / 0 stretch']);
|
||||
|
||||
test_valid_value("border-image", "1 / 1px", ["1 / 1px", "none 1 / 1px / 0 stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% / 2%", ["1 2% 3 4% / 2%", "none 1 2% 3 4% / 2% 2% 2% 2%", "none 1 2% 3 4% / 2% / 0 stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% fill / 3", ["1 2% 3 4% fill / 3", "none 1 2% 3 4% fill / 3 3 3 3", "none 1 2% 3 4% fill / 3 / 0 stretch"]);
|
||||
test_valid_value("border-image", "fill 1 2% 3 4% / auto", ["1 2% 3 4% fill / auto", "none 1 2% 3 4% fill / auto / 0 stretch"]);
|
||||
test_valid_value("border-image", "1 / 1px 2% 3 auto", ["1 / 1px 2% 3 auto", "none 1 / 1px 2% 3 auto / 0 stretch"]);
|
||||
|
||||
test_valid_value("border-image", "1 / / 1px", ["1 / / 1px", "none 1 / 1 / 1px stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% / / 2", ["1 2% 3 4% / / 2", "none 1 2% 3 4% / 1 / 2 stretch"]);
|
||||
test_valid_value("border-image", 'url("http://www.example.com/") 1 2% 3 4% fill / / 1px 2 3px 4', ['url("http://www.example.com/") 1 2% 3 4% fill / / 1px 2 3px 4', 'url("http://www.example.com/") 1 2% 3 4% fill / 1 / 1px 2 3px 4 stretch']);
|
||||
|
||||
test_valid_value("border-image", "1 / 1px / 1px", ["1 / 1px / 1px", "none 1 / 1px / 1px stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% / 2% / 2", ["1 2% 3 4% / 2% / 2", "none 1 2% 3 4% / 2% / 2 stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% fill / 3 / 1px 2 3px 4", ["1 2% 3 4% fill / 3 / 1px 2 3px 4", "none 1 2% 3 4% fill / 3 / 1px 2 3px 4 stretch"]);
|
||||
test_valid_value("border-image", "1 / auto / 1px", ["1 / auto / 1px", "none 1 / auto / 1px stretch"]);
|
||||
test_valid_value("border-image", "1 2% 3 4% / 1px 2% 3 auto / 2", ["1 2% 3 4% / 1px 2% 3 auto / 2", "none 1 2% 3 4% / 1px 2% 3 auto / 2 2 2 2", "none 1 2% 3 4% / 1px 2% 3 auto / 2 stretch"]);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue