mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-27 11:48:59 +00:00
LibWeb: Implement Node.lookupNamespaceURI()
This method takes a prefix and returns the namespace URI associated with it on the given node, or null if no namespace is found.
This commit is contained in:
parent
d106b6eae2
commit
27d429a85f
Notes:
sideshowbarker
2024-07-18 23:46:13 +09:00
Author: https://github.com/tcl3
Commit: 27d429a85f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/693
5 changed files with 166 additions and 1 deletions
20
Tests/LibWeb/Text/expected/DOM/Node-lookupNamespaceURI.txt
Normal file
20
Tests/LibWeb/Text/expected/DOM/Node-lookupNamespaceURI.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
documentFragment.lookupNamespaceURI(null): null
|
||||
documentFragment.lookupNamespaceURI(""): null
|
||||
documentFragment.lookupNamespaceURI("foo"): null
|
||||
documentFragment.lookupNamespaceURI("xml"): null
|
||||
documentFragment.lookupNamespaceURI("xmlns"): null
|
||||
docType.lookupNamespaceURI(null): null
|
||||
docType.lookupNamespaceURI(""): null
|
||||
docType.lookupNamespaceURI("foo"): null
|
||||
docType.lookupNamespaceURI("xml"): null
|
||||
docType.lookupNamespaceURI("xmlns"): null
|
||||
element.lookupNamespaceURI(null): null
|
||||
element.lookupNamespaceURI(""): null
|
||||
element.lookupNamespaceURI("foo"): null
|
||||
element.lookupNamespaceURI("xml"): http://www.w3.org/XML/1998/namespace
|
||||
element.lookupNamespaceURI("xmlns"): http://www.w3.org/2000/xmlns/
|
||||
After setting element attribute xmlns:bar='exampleNamespaceURI'
|
||||
element.lookupNamespaceURI(null): null
|
||||
element.lookupNamespaceURI(""): null
|
||||
element.lookupNamespaceURI("foo"): null
|
||||
element.lookupNamespaceURI("bar"): exampleNamespaceURI
|
43
Tests/LibWeb/Text/input/DOM/Node-lookupNamespaceURI.html
Normal file
43
Tests/LibWeb/Text/input/DOM/Node-lookupNamespaceURI.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
function testLookupNamespaceURI(node, prefix, name) {
|
||||
let prefixName = prefix;
|
||||
if (prefixName !== null)
|
||||
prefixName = `"${prefix}"`;
|
||||
|
||||
println(`${name}.lookupNamespaceURI(${prefixName}): ${node.lookupNamespaceURI(prefix)}`);
|
||||
}
|
||||
|
||||
test(() => {
|
||||
const documentFragment = document.createDocumentFragment();
|
||||
testLookupNamespaceURI(documentFragment, null, "documentFragment");
|
||||
testLookupNamespaceURI(documentFragment, "", "documentFragment");
|
||||
testLookupNamespaceURI(documentFragment, "foo", "documentFragment");
|
||||
testLookupNamespaceURI(documentFragment, "xml", "documentFragment");
|
||||
testLookupNamespaceURI(documentFragment, "xmlns", "documentFragment");
|
||||
|
||||
const docType = document.doctype;
|
||||
testLookupNamespaceURI(docType, null, "docType");
|
||||
testLookupNamespaceURI(docType, "", "docType");
|
||||
testLookupNamespaceURI(docType, "foo", "docType");
|
||||
testLookupNamespaceURI(docType, "xml", "docType");
|
||||
testLookupNamespaceURI(docType, "xmlns", "docType");
|
||||
|
||||
const element = document.createElementNS("namespace", "prefix:element");
|
||||
element.setAttribute("bar", "value");
|
||||
testLookupNamespaceURI(element, null, "element");
|
||||
testLookupNamespaceURI(element, "", "element");
|
||||
testLookupNamespaceURI(element, "foo", "element");
|
||||
testLookupNamespaceURI(element, "xml", "element");
|
||||
testLookupNamespaceURI(element, "xmlns", "element");
|
||||
|
||||
const XMLNS_NS = "http://www.w3.org/2000/xmlns/";
|
||||
element.setAttributeNS(XMLNS_NS, 'xmlns:bar', 'exampleNamespaceURI');
|
||||
println("After setting element attribute xmlns:bar='exampleNamespaceURI'");
|
||||
testLookupNamespaceURI(element, null, "element");
|
||||
testLookupNamespaceURI(element, "", "element");
|
||||
testLookupNamespaceURI(element, "foo", "element");
|
||||
testLookupNamespaceURI(element, "bar", "element");
|
||||
});
|
||||
</script>
|
|
@ -25,6 +25,7 @@
|
|||
#include <LibWeb/DOM/IDLEventListener.h>
|
||||
#include <LibWeb/DOM/LiveNodeList.h>
|
||||
#include <LibWeb/DOM/MutationType.h>
|
||||
#include <LibWeb/DOM/NamedNodeMap.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
#include <LibWeb/DOM/NodeIterator.h>
|
||||
#include <LibWeb/DOM/ProcessingInstruction.h>
|
||||
|
@ -43,6 +44,7 @@
|
|||
#include <LibWeb/Layout/Node.h>
|
||||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Layout/Viewport.h>
|
||||
#include <LibWeb/Namespace.h>
|
||||
#include <LibWeb/Painting/Paintable.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
|
||||
|
@ -1634,6 +1636,103 @@ bool Node::is_equal_node(Node const* other_node) const
|
|||
return true;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#locate-a-namespace
|
||||
Optional<String> Node::locate_a_namespace(Optional<String> const& prefix) const
|
||||
{
|
||||
// To locate a namespace for a node using prefix, switch on the interface node implements:
|
||||
|
||||
// Element
|
||||
if (is<Element>(*this)) {
|
||||
// 1. If prefix is "xml", then return the XML namespace.
|
||||
if (prefix == "xml")
|
||||
return Web::Namespace::XML.to_string();
|
||||
|
||||
// 2. If prefix is "xmlns", then return the XMLNS namespace.
|
||||
if (prefix == "xmlns")
|
||||
return Web::Namespace::XMLNS.to_string();
|
||||
|
||||
// 3. If its namespace is non-null and its namespace prefix is prefix, then return namespace.
|
||||
auto& element = verify_cast<Element>(*this);
|
||||
if (element.namespace_uri().has_value() && element.prefix() == prefix)
|
||||
return element.namespace_uri()->to_string();
|
||||
|
||||
// 4. If it has an attribute whose namespace is the XMLNS namespace, namespace prefix is "xmlns", and local name is prefix,
|
||||
// or if prefix is null and it has an attribute whose namespace is the XMLNS namespace, namespace prefix is null,
|
||||
// and local name is "xmlns", then return its value if it is not the empty string, and null otherwise.
|
||||
if (auto* attributes = element.attributes()) {
|
||||
for (size_t i = 0; i < attributes->length(); ++i) {
|
||||
auto& attr = *attributes->item(i);
|
||||
if (attr.namespace_uri() == Web::Namespace::XMLNS) {
|
||||
if ((attr.prefix() == "xmlns" && attr.local_name() == prefix) || (!prefix.has_value() && !attr.prefix().has_value() && attr.local_name() == "xmlns")) {
|
||||
auto value = attr.value();
|
||||
if (!value.is_empty())
|
||||
return value;
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. If its parent element is null, then return null.
|
||||
auto* parent_element = element.parent_element();
|
||||
if (!element.parent_element())
|
||||
return {};
|
||||
|
||||
// 6. Return the result of running locate a namespace on its parent element using prefix.
|
||||
return parent_element->locate_a_namespace(prefix);
|
||||
}
|
||||
|
||||
// Document
|
||||
if (is<Document>(*this)) {
|
||||
// 1. If its document element is null, then return null.
|
||||
auto* document_element = verify_cast<Document>(*this).document_element();
|
||||
if (!document_element)
|
||||
return {};
|
||||
|
||||
// 2. Return the result of running locate a namespace on its document element using prefix.
|
||||
return document_element->locate_a_namespace(prefix);
|
||||
}
|
||||
|
||||
// DocumentType
|
||||
// DocumentFragment
|
||||
if (is<DocumentType>(*this) || is<DocumentFragment>(*this)) {
|
||||
// Return null.
|
||||
return {};
|
||||
}
|
||||
|
||||
// Attr
|
||||
if (is<Attr>(*this)) {
|
||||
// 1. If its element is null, then return null.
|
||||
auto* element = verify_cast<Attr>(*this).owner_element();
|
||||
if (!element)
|
||||
return {};
|
||||
|
||||
// 2. Return the result of running locate a namespace on its element using prefix.
|
||||
return element->locate_a_namespace(prefix);
|
||||
}
|
||||
|
||||
// Otherwise
|
||||
// 1. If its parent element is null, then return null.
|
||||
auto* parent_element = this->parent_element();
|
||||
if (!parent_element)
|
||||
return {};
|
||||
|
||||
// 2. Return the result of running locate a namespace on its parent element using prefix.
|
||||
return parent_element->locate_a_namespace(prefix);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
|
||||
Optional<String> Node::lookup_namespace_uri(Optional<String> prefix) const
|
||||
{
|
||||
// 1. If prefix is the empty string, then set it to null.
|
||||
if (prefix.has_value() && prefix->is_empty())
|
||||
prefix = {};
|
||||
|
||||
// 2. Return the result of running locate a namespace for this using prefix.
|
||||
return locate_a_namespace(prefix);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#in-a-document-tree
|
||||
bool Node::in_a_document_tree() const
|
||||
{
|
||||
|
|
|
@ -695,6 +695,9 @@ public:
|
|||
ErrorOr<String> accessible_name(Document const&) const;
|
||||
ErrorOr<String> accessible_description(Document const&) const;
|
||||
|
||||
Optional<String> locate_a_namespace(Optional<String> const& prefix) const;
|
||||
Optional<String> lookup_namespace_uri(Optional<String> prefix) const;
|
||||
|
||||
protected:
|
||||
Node(JS::Realm&, Document&, NodeType);
|
||||
Node(Document&, NodeType);
|
||||
|
|
|
@ -55,7 +55,7 @@ interface Node : EventTarget {
|
|||
boolean contains(Node? other);
|
||||
|
||||
[FIXME] DOMString? lookupPrefix(DOMString? namespace);
|
||||
[FIXME] DOMString? lookupNamespaceURI(DOMString? prefix);
|
||||
DOMString? lookupNamespaceURI(DOMString? prefix);
|
||||
[FIXME] boolean isDefaultNamespace(DOMString? namespace);
|
||||
|
||||
[ImplementedAs=pre_insert, CEReactions] Node insertBefore(Node node, Node? child);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue