Bläddra i källkod

LibWeb: Implement the `HTMLAnchorElement.relList` attribute

This returns a DOMTokenList that reflects the `rel` attribute.
Tim Ledbetter 1 år sedan
förälder
incheckning
b7fd39c2e6

+ 6 - 0
Tests/LibWeb/Text/expected/HTML/relList-attribute.txt

@@ -0,0 +1,6 @@
+a.relList initial length: 0
+a.relList always returns the same value: true
+a.relList for after setting rel to "whatever": whatever
+a.relList for after setting rel to "prefetch": prefetch
+a.relList contains "prefetch": true
+a.relList contains "whatever": false

+ 26 - 0
Tests/LibWeb/Text/input/HTML/relList-attribute.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script src="../include.js"></script>
+<script>
+    function relListTest(tagName) {
+        const element = document.createElement(tagName);
+        const relList = element.relList;
+        println(`${tagName}.relList initial length: ${relList.length}`);
+        println(`${tagName}.relList always returns the same value: ${relList === element.relList}`);
+        element.rel = "whatever";
+        println(`${tagName}.relList for after setting rel to "whatever": ${relList}`);
+        element.relList = "prefetch";
+        println(`${tagName}.relList for after setting rel to "prefetch": ${relList}`);
+        println(`${tagName}.relList contains "prefetch": ${relList.contains("prefetch")}`);
+        println(`${tagName}.relList contains "whatever": ${relList.contains("whatever")}`);        
+    }
+
+    test(() => {
+        const tagNamesToTest = [
+            "a",
+        ];
+
+        for (const tagName of tagNamesToTest) {
+            relListTest(tagName);
+        }
+    });
+</script>

+ 13 - 0
Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp

@@ -7,6 +7,7 @@
 
 #include <LibWeb/ARIA/Roles.h>
 #include <LibWeb/Bindings/HTMLAnchorElementPrototype.h>
+#include <LibWeb/DOM/DOMTokenList.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/HTML/AttributeNames.h>
 #include <LibWeb/HTML/HTMLAnchorElement.h>
@@ -38,6 +39,9 @@ void HTMLAnchorElement::attribute_changed(FlyString const& name, Optional<String
     HTMLElement::attribute_changed(name, value);
     if (name == HTML::AttributeNames::href) {
         set_the_url();
+    } else if (name == HTML::AttributeNames::rel) {
+        if (m_rel_list)
+            m_rel_list->associated_attribute_changed(value.value_or(String {}));
     }
 }
 
@@ -123,6 +127,15 @@ Optional<ARIA::Role> HTMLAnchorElement::default_role() const
     return ARIA::Role::generic;
 }
 
+// https://html.spec.whatwg.org/multipage/text-level-semantics.html#dom-a-rellist
+JS::GCPtr<DOM::DOMTokenList> HTMLAnchorElement::rel_list()
+{
+    // The IDL attribute relList must reflect the rel content attribute.
+    if (!m_rel_list)
+        m_rel_list = DOM::DOMTokenList::create(*this, HTML::AttributeNames::rel);
+    return m_rel_list;
+}
+
 // https://html.spec.whatwg.org/multipage/text-level-semantics.html#dom-a-text
 String HTMLAnchorElement::text() const
 {

+ 4 - 0
Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h

@@ -24,6 +24,8 @@ public:
     String target() const { return get_attribute_value(HTML::AttributeNames::target); }
     String download() const { return get_attribute_value(HTML::AttributeNames::download); }
 
+    JS::GCPtr<DOM::DOMTokenList> rel_list();
+
     String text() const;
     void set_text(String const&);
 
@@ -68,6 +70,8 @@ private:
     }
 
     virtual Optional<ARIA::Role> default_role() const override;
+
+    JS::GCPtr<DOM::DOMTokenList> m_rel_list;
 };
 
 }

+ 1 - 1
Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.idl

@@ -11,7 +11,7 @@ interface HTMLAnchorElement : HTMLElement {
     [CEReactions, Reflect] attribute DOMString download;
     [CEReactions, Reflect] attribute DOMString ping;
     [CEReactions, Reflect] attribute DOMString rel;
-    // FIXME: [SameObject, PutForwards=value] readonly attribute DOMTokenList relList;
+    [SameObject, PutForwards=value] readonly attribute DOMTokenList relList;
     [CEReactions, Reflect] attribute DOMString hreflang;
     [CEReactions, Reflect] attribute DOMString type;