mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 19:59:17 +00:00
LibWeb: Implement the translate attribute
This commit is contained in:
parent
4b3715ccba
commit
279913a223
Notes:
github-actions[bot]
2025-05-23 12:35:07 +00:00
Author: https://github.com/Calme1709
Commit: 279913a223
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4855
Reviewed-by: https://github.com/gmta ✅
24 changed files with 399 additions and 1 deletions
|
@ -3327,6 +3327,36 @@ IntersectionObserver::IntersectionObserverRegistration& Element::get_intersectio
|
|||
return *registration_iterator;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#translation-mode
|
||||
Element::TranslationMode Element::translation_mode() const
|
||||
{
|
||||
// Each element (even non-HTML elements) has a translation mode, which is in either the translate-enabled state or
|
||||
// the no-translate state.
|
||||
|
||||
// If an HTML element's translate attribute is in the Yes state, then the element's translation mode is in the
|
||||
// translate-enabled state;
|
||||
// NOTE: The attribute is in the Yes state if the attribute is present and its value is the empty string or is a
|
||||
// ASCII-case-insensitive match for "yes".
|
||||
auto maybe_translate_attribute = attribute(HTML::AttributeNames::translate);
|
||||
if (maybe_translate_attribute.has_value() && (maybe_translate_attribute.value().is_empty() || maybe_translate_attribute.value().equals_ignoring_ascii_case("yes"sv)))
|
||||
return TranslationMode::TranslateEnabled;
|
||||
|
||||
// otherwise, if the element's translate attribute is in the No state, then the element's translation mode is in
|
||||
// the no-translate state.
|
||||
if (maybe_translate_attribute.has_value() && maybe_translate_attribute.value().equals_ignoring_ascii_case("no"sv)) {
|
||||
return TranslationMode::NoTranslate;
|
||||
}
|
||||
|
||||
// Otherwise, either the element's translate attribute is in the Inherit state, or the element is not an HTML
|
||||
// element and thus does not have a translate attribute; in either case, the element's translation mode is in the
|
||||
// same state as its parent element's, if any.
|
||||
if (auto parent = parent_element())
|
||||
return parent->translation_mode();
|
||||
|
||||
// or in the translate-enabled state, if the element's parent element is null
|
||||
return TranslationMode::TranslateEnabled;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#the-directionality
|
||||
Element::Directionality Element::directionality() const
|
||||
{
|
||||
|
|
|
@ -378,6 +378,12 @@ public:
|
|||
CSSPixelPoint scroll_offset(ScrollOffsetFor type) const { return m_scroll_offset[to_underlying(type)]; }
|
||||
void set_scroll_offset(ScrollOffsetFor type, CSSPixelPoint offset) { m_scroll_offset[to_underlying(type)] = offset; }
|
||||
|
||||
enum class TranslationMode {
|
||||
TranslateEnabled,
|
||||
NoTranslate
|
||||
};
|
||||
TranslationMode translation_mode() const;
|
||||
|
||||
enum class Dir {
|
||||
Ltr,
|
||||
Rtl,
|
||||
|
|
|
@ -299,6 +299,7 @@ namespace AttributeNames {
|
|||
__ENUMERATE_HTML_ATTRIBUTE(text, "text") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(title, "title") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(topmargin, "topmargin") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(translate, "translate") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(truespeed, "truespeed") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(type, "type") \
|
||||
__ENUMERATE_HTML_ATTRIBUTE(usemap, "usemap") \
|
||||
|
|
|
@ -104,6 +104,25 @@ bool HTMLElement::is_potentially_render_blocking()
|
|||
return is_implicitly_potentially_render_blocking();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#dom-translate
|
||||
bool HTMLElement::translate() const
|
||||
{
|
||||
// The translate IDL attribute must, on getting, return true if the element's translation mode is
|
||||
// translate-enabled, and false otherwise
|
||||
return translation_mode() == TranslationMode::TranslateEnabled;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#dom-translate
|
||||
void HTMLElement::set_translate(bool new_value)
|
||||
{
|
||||
// On setting, it must set the content attribute's value to "yes" if the new value is true, and set the content
|
||||
// attribute's value to "no" otherwise.
|
||||
if (new_value)
|
||||
MUST(set_attribute(HTML::AttributeNames::translate, "yes"_string));
|
||||
else
|
||||
MUST(set_attribute(HTML::AttributeNames::translate, "no"_string));
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/dom.html#dom-dir
|
||||
StringView HTMLElement::dir() const
|
||||
{
|
||||
|
|
|
@ -82,6 +82,9 @@ public:
|
|||
|
||||
Optional<String> title() const { return attribute(HTML::AttributeNames::title); }
|
||||
|
||||
bool translate() const;
|
||||
void set_translate(bool);
|
||||
|
||||
StringView dir() const;
|
||||
void set_dir(String const&);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ interface HTMLElement : Element {
|
|||
// metadata attributes
|
||||
[Reflect, CEReactions] attribute DOMString title;
|
||||
[Reflect, CEReactions] attribute DOMString lang;
|
||||
[FIXME, CEReactions] attribute boolean translate;
|
||||
[CEReactions] attribute boolean translate;
|
||||
[CEReactions] attribute DOMString dir;
|
||||
|
||||
// user interaction
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass In the default case, ie. with no translate attribute in the page, javascript will detect the translation mode of text as translate-enabled.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass If the translate attribute is set to yes, javascript will detect the translation mode of text as translate-enabled.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass If the translate attribute is set to no, javascript will detect the translation mode of text as no-translate.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass If the translate attribute is set to no, javascript will detect the translation mode of elements inside that element with no translate flag as no-translate.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass If the translate attribute is set to yes on an element inside an element with the translate attribute set to no, javascript will detect the translation mode of text in the inner element as translate-enabled.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass If the translate attribute is set to a null string, javascript will detect the translation mode of text as translate-enabled.
|
|
@ -0,0 +1,6 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 1 tests
|
||||
|
||||
1 Pass
|
||||
Pass keyword yes
|
|
@ -0,0 +1,10 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 5 tests
|
||||
|
||||
5 Pass
|
||||
Pass No parent node
|
||||
Pass DocumentFragment parent node
|
||||
Pass ShadowRoot parent node whose shadow host has translate=yes
|
||||
Pass ShadowRoot parent node whose shadow host has translate=no
|
||||
Pass Document parent node
|
|
@ -0,0 +1,8 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 3 tests
|
||||
|
||||
3 Pass
|
||||
Pass Non-HTML elements default to translate-enabled
|
||||
Pass Non-HTML elements inherit their parent's translation-enabled state
|
||||
Pass Non-HTML elements inherit their parent's no-translation state
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>no translate attribute</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test"><div id="box"> </div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_true(document.getElementById('box').translate);
|
||||
}, "In the default case, ie. with no translate attribute in the page, javascript will detect the translation mode of text as translate-enabled.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>translate=yes</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test"><div id="box" translate="yes"> </div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_true(document.getElementById('box').translate);
|
||||
}, "If the translate attribute is set to yes, javascript will detect the translation mode of text as translate-enabled.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>translate=no</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test"><div id="box" translate="no"> </div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_false(document.getElementById('box').translate);
|
||||
}, "If the translate attribute is set to no, javascript will detect the translation mode of text as no-translate.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>translate inherits no</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test"><div id="box" translate="no"> <span id="spantest"> </span></div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_false(document.getElementById('spantest').translate);
|
||||
}, "If the translate attribute is set to no, javascript will detect the translation mode of elements inside that element with no translate flag as no-translate.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>translate=yes inside translate=no</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test"><div id="box" translate="no"> <span id="spantest" translate="yes"> </span></div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_true(document.getElementById('spantest').translate);
|
||||
}, "If the translate attribute is set to yes on an element inside an element with the translate attribute set to no, javascript will detect the translation mode of text in the inner element as translate-enabled.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" >
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>translate=""</title>
|
||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
||||
<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<style type='text/css'>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="test" translate="no"><div id="box" translate=""> </div></div>
|
||||
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
assert_true(document.getElementById('box').translate);
|
||||
}, "If the translate attribute is set to a null string, javascript will detect the translation mode of text as translate-enabled.");
|
||||
</script>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/#attr-translate">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/#enumerated-attribute">
|
||||
<meta name="assert" content="@translate values are ASCII case-insensitive">
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<!--
|
||||
We wrap the <span> elements under test with <div> elements so the invalid
|
||||
value default (inherit) can be distinguished from true through the IDL
|
||||
attribute. The inherit state would otherwise yield true because inheritance
|
||||
would go all the way to :root, whose translation mode is translate-enabled
|
||||
because it’s also in the inherit state.
|
||||
-->
|
||||
<div translate="no"><span translate="yes"></span></div>
|
||||
<div translate="no"><span translate="YeS"></span></div>
|
||||
<div translate="no"><span translate="yeſ"></span></div>
|
||||
<script>
|
||||
const span = document.querySelectorAll("span");
|
||||
|
||||
test(() => {
|
||||
assert_equals(span[0].translate, true, "lowercase valid");
|
||||
assert_equals(span[1].translate, true, "mixed case valid");
|
||||
assert_equals(span[2].translate, false, "non-ASCII invalid");
|
||||
}, "keyword yes");
|
||||
</script>
|
|
@ -0,0 +1,33 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>The translate attribute inherit state when there's no parent element</title>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const div = document.createElement("div");
|
||||
assert_true(div.translate);
|
||||
}, 'No parent node');
|
||||
|
||||
test(() => {
|
||||
const div = document.createElement("div");
|
||||
const frag = document.createDocumentFragment();
|
||||
frag.append(div);
|
||||
assert_true(div.translate);
|
||||
}, 'DocumentFragment parent node');
|
||||
|
||||
for (const translateValue of ['yes', 'no']) {
|
||||
test(() => {
|
||||
const div = document.createElement("div");
|
||||
const myElement = document.createElement("my-element");
|
||||
myElement.setAttribute('translate', translateValue);
|
||||
myElement.attachShadow({mode: 'open'});
|
||||
myElement.shadowRoot.append(div);
|
||||
assert_true(div.translate);
|
||||
}, `ShadowRoot parent node whose shadow host has translate=${translateValue}`);
|
||||
}
|
||||
|
||||
test(() => {
|
||||
assert_true(document.documentElement.translate);
|
||||
}, 'Document parent node');
|
||||
</script>
|
|
@ -0,0 +1,46 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Non-HTML elements have a translation mode</title>
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const svgContainer = document.createElement("svg");
|
||||
const foreignObject = document.createElement("foreignObject");
|
||||
svgContainer.appendChild(foreignObject);
|
||||
const div = document.createElement("div");
|
||||
foreignObject.appendChild(div);
|
||||
|
||||
assert_true(div.translate);
|
||||
}, 'Non-HTML elements default to translate-enabled');
|
||||
|
||||
test(() => {
|
||||
const outerDiv = document.createElement("div");
|
||||
outerDiv.translate = true;
|
||||
assert_true(outerDiv.translate);
|
||||
|
||||
const svgContainer = document.createElement("svg");
|
||||
outerDiv.appendChild(svgContainer);
|
||||
const foreignObject = document.createElement("foreignObject");
|
||||
svgContainer.appendChild(foreignObject);
|
||||
const div = document.createElement("div");
|
||||
foreignObject.appendChild(div);
|
||||
|
||||
assert_true(div.translate);
|
||||
}, "Non-HTML elements inherit their parent's translation-enabled state");
|
||||
|
||||
test(() => {
|
||||
const outerDiv = document.createElement("div");
|
||||
outerDiv.translate = false;
|
||||
assert_false(outerDiv.translate);
|
||||
|
||||
const svgContainer = document.createElement("svg");
|
||||
outerDiv.appendChild(svgContainer);
|
||||
const foreignObject = document.createElement("foreignObject");
|
||||
svgContainer.appendChild(foreignObject);
|
||||
const div = document.createElement("div");
|
||||
foreignObject.appendChild(div);
|
||||
|
||||
assert_false(div.translate);
|
||||
}, "Non-HTML elements inherit their parent's no-translation state");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue