mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:27:45 +00:00
LibWeb: Support quotes in content
values
This adds initial support for `open-quote`, `close-quote`, `no-open-quote` and `no-close-quote`. We don't yet track the "nesting level" so we always use the first pair of quotes from the `quotes` property.
This commit is contained in:
parent
dc7a52957e
commit
f0a4baabc7
5 changed files with 75 additions and 4 deletions
19
Tests/LibWeb/Ref/css-quotes.html
Normal file
19
Tests/LibWeb/Ref/css-quotes.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!doctype html>
|
||||||
|
<link rel="match" href="reference/css-quotes-ref.html" />
|
||||||
|
<style>
|
||||||
|
div::before {
|
||||||
|
content: open-quote "Well, hello friends!" close-quote;
|
||||||
|
}
|
||||||
|
.a {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
quotes: auto;
|
||||||
|
}
|
||||||
|
.c {
|
||||||
|
quotes: "/* " " */";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="a"></div>
|
||||||
|
<div class="b"></div>
|
||||||
|
<div class="c"></div>
|
4
Tests/LibWeb/Ref/reference/css-quotes-ref.html
Normal file
4
Tests/LibWeb/Ref/reference/css-quotes-ref.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<!doctype html>
|
||||||
|
<div class="a">Well, hello friends!</div>
|
||||||
|
<div class="b">“Well, hello friends!”</div>
|
||||||
|
<div class="c">/* Well, hello friends! */</div>
|
|
@ -101,6 +101,7 @@
|
||||||
"center",
|
"center",
|
||||||
"circle",
|
"circle",
|
||||||
"clip",
|
"clip",
|
||||||
|
"close-quote",
|
||||||
"coarse",
|
"coarse",
|
||||||
"col-resize",
|
"col-resize",
|
||||||
"collapse",
|
"collapse",
|
||||||
|
@ -240,7 +241,9 @@
|
||||||
"ne-resize",
|
"ne-resize",
|
||||||
"nearest",
|
"nearest",
|
||||||
"nesw-resize",
|
"nesw-resize",
|
||||||
|
"no-close-quote",
|
||||||
"no-drop",
|
"no-drop",
|
||||||
|
"no-open-quote",
|
||||||
"no-preference",
|
"no-preference",
|
||||||
"no-repeat",
|
"no-repeat",
|
||||||
"none",
|
"none",
|
||||||
|
@ -253,6 +256,7 @@
|
||||||
"nwse-resize",
|
"nwse-resize",
|
||||||
"oblique",
|
"oblique",
|
||||||
"opaque",
|
"opaque",
|
||||||
|
"open-quote",
|
||||||
"optimizequality",
|
"optimizequality",
|
||||||
"optimizespeed",
|
"optimizespeed",
|
||||||
"outset",
|
"outset",
|
||||||
|
|
|
@ -699,7 +699,11 @@
|
||||||
],
|
],
|
||||||
"valid-identifiers": [
|
"valid-identifiers": [
|
||||||
"normal",
|
"normal",
|
||||||
"none"
|
"none",
|
||||||
|
"open-quote",
|
||||||
|
"close-quote",
|
||||||
|
"no-open-quote",
|
||||||
|
"no-close-quote"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cursor": {
|
"cursor": {
|
||||||
|
|
|
@ -649,6 +649,25 @@ Optional<CSS::Clear> StyleProperties::clear() const
|
||||||
CSS::ContentData StyleProperties::content() const
|
CSS::ContentData StyleProperties::content() const
|
||||||
{
|
{
|
||||||
auto value = property(CSS::PropertyID::Content);
|
auto value = property(CSS::PropertyID::Content);
|
||||||
|
auto quotes_data = quotes();
|
||||||
|
|
||||||
|
auto get_quote_string = [&](bool open, auto depth) {
|
||||||
|
switch (quotes_data.type) {
|
||||||
|
case QuotesData::Type::None:
|
||||||
|
return String {};
|
||||||
|
case QuotesData::Type::Auto:
|
||||||
|
// FIXME: "A typographically appropriate used value for quotes is automatically chosen by the UA
|
||||||
|
// based on the content language of the element and/or its parent."
|
||||||
|
if (open)
|
||||||
|
return depth % 2 ? "“"_string : "‘"_string;
|
||||||
|
return depth % 2 ? "”"_string : "’"_string;
|
||||||
|
case QuotesData::Type::Specified:
|
||||||
|
auto& level = quotes_data.strings[depth % quotes_data.strings.size()];
|
||||||
|
return open ? level[0] : level[1];
|
||||||
|
}
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
};
|
||||||
|
|
||||||
if (value->is_content()) {
|
if (value->is_content()) {
|
||||||
auto& content_style_value = value->as_content();
|
auto& content_style_value = value->as_content();
|
||||||
|
|
||||||
|
@ -661,12 +680,33 @@ CSS::ContentData StyleProperties::content() const
|
||||||
for (auto const& item : content_style_value.content().values()) {
|
for (auto const& item : content_style_value.content().values()) {
|
||||||
if (item->is_string()) {
|
if (item->is_string()) {
|
||||||
builder.append(item->as_string().string_value());
|
builder.append(item->as_string().string_value());
|
||||||
|
} else if (item->is_identifier()) {
|
||||||
|
switch (item->to_identifier()) {
|
||||||
|
case ValueID::OpenQuote:
|
||||||
|
// FIXME: Track nesting level and increment it here.
|
||||||
|
builder.append(get_quote_string(true, 1));
|
||||||
|
break;
|
||||||
|
case ValueID::CloseQuote:
|
||||||
|
// FIXME: Track nesting level and decrement it here.
|
||||||
|
builder.append(get_quote_string(false, 1));
|
||||||
|
break;
|
||||||
|
case ValueID::NoOpenQuote:
|
||||||
|
// FIXME: Track nesting level and increment it here.
|
||||||
|
break;
|
||||||
|
case ValueID::NoCloseQuote:
|
||||||
|
// FIXME: Track nesting level and decrement it here.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: Implement quotes, counters, images, and other things.
|
// TODO: Implement counters, images, and other things.
|
||||||
|
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content_data.type = ContentData::Type::String;
|
content_data.type = ContentData::Type::String;
|
||||||
content_data.data = builder.to_string().release_value_but_fixme_should_propagate_errors();
|
content_data.data = MUST(builder.to_string());
|
||||||
|
|
||||||
if (content_style_value.has_alt_text()) {
|
if (content_style_value.has_alt_text()) {
|
||||||
StringBuilder alt_text_builder;
|
StringBuilder alt_text_builder;
|
||||||
|
@ -677,7 +717,7 @@ CSS::ContentData StyleProperties::content() const
|
||||||
// TODO: Implement counters
|
// TODO: Implement counters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content_data.alt_text = alt_text_builder.to_string().release_value_but_fixme_should_propagate_errors();
|
content_data.alt_text = MUST(alt_text_builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return content_data;
|
return content_data;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue