547 lines
11 KiB
Python
547 lines
11 KiB
Python
|
# encoding: utf-8
|
|||
|
"""
|
|||
|
https://dom.spec.whatwg.org/
|
|||
|
|
|||
|
Other URL:
|
|||
|
- https://fr.wikipedia.org/wiki/Document_Object_Model
|
|||
|
"""
|
|||
|
|
|||
|
from enum import Enum
|
|||
|
|
|||
|
from tree import Node, Tree
|
|||
|
|
|||
|
|
|||
|
# Move exceptions in a specific file ?
|
|||
|
class DOMException(Exception):
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
class IndexSizeError(DOMException):
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
# Move Enums in a specific file ?
|
|||
|
class NodeFilter(Enum):
|
|||
|
SHOW_ALL = 0xffffffff
|
|||
|
|
|||
|
|
|||
|
class ShadowRootMode(Enum):
|
|||
|
open = 1
|
|||
|
closed = 2
|
|||
|
|
|||
|
|
|||
|
class SlotAssignmentMode(Enum):
|
|||
|
manual = 1
|
|||
|
named = 2
|
|||
|
|
|||
|
|
|||
|
class Document(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._implementation = None
|
|||
|
self._URL = None
|
|||
|
self._documentURI = None
|
|||
|
self._compatMode = None
|
|||
|
self._characterSet = None
|
|||
|
self._charset = None
|
|||
|
self._inputEncoding = None
|
|||
|
self._contentType = None
|
|||
|
self._doctype = None
|
|||
|
self._documentElement = None
|
|||
|
|
|||
|
@property
|
|||
|
def implementation(self):
|
|||
|
return self._implementation
|
|||
|
|
|||
|
@property
|
|||
|
def URL(self):
|
|||
|
return self._URL
|
|||
|
|
|||
|
@property
|
|||
|
def documentURI(self):
|
|||
|
return self._documentURI
|
|||
|
|
|||
|
@property
|
|||
|
def compatMode(self):
|
|||
|
return self._compatMode
|
|||
|
|
|||
|
@property
|
|||
|
def characterSet(self):
|
|||
|
return self._characterSet
|
|||
|
|
|||
|
@property
|
|||
|
def charset(self):
|
|||
|
return self._charset
|
|||
|
|
|||
|
@property
|
|||
|
def inputEncoding(self):
|
|||
|
return self._inputEncoding
|
|||
|
|
|||
|
@property
|
|||
|
def contentType(self):
|
|||
|
return self._contentType
|
|||
|
|
|||
|
@property
|
|||
|
def doctype(self):
|
|||
|
return self._doctype
|
|||
|
|
|||
|
@property
|
|||
|
def documentElement(self):
|
|||
|
return self._documentElement
|
|||
|
|
|||
|
def getElementsByTagName(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getElementsByTagNameNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getElementsByClassName(self, classNames):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createElement(self, localName, options={}):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createElementNS(self, namespace, qualifiedName, options={}):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createDocumentFragment(self):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createTextNode(self, data):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createCDATASection(self, data):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createComment(self, data):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createProcessingInstruction(self, target, data):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def importNode(self, node, deep=False):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def adoptNode(self, node):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createAttribute(self, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createAttributeNS(self, namespace, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createEvent(self, interface):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createRange(self):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createNodeIterator(self, root, whatToShow=0xffffffff, filter=None):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def createTreeWalker(self, root, whatToShow=0xffffffff, filter=None):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
class DocumentType(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._name = None
|
|||
|
self._publicId = None
|
|||
|
self._systemId = None
|
|||
|
|
|||
|
@property
|
|||
|
def length(self):
|
|||
|
return 0
|
|||
|
|
|||
|
@property
|
|||
|
def name(self):
|
|||
|
return self._name
|
|||
|
|
|||
|
@property
|
|||
|
def publicId(self):
|
|||
|
return self._publicId
|
|||
|
|
|||
|
@property
|
|||
|
def systemId(self):
|
|||
|
return self._systemId
|
|||
|
|
|||
|
|
|||
|
class DocumentFragment(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
|
|||
|
|
|||
|
class Element(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._namespaceURI = None
|
|||
|
self._prefix = None
|
|||
|
self._localName = None
|
|||
|
self._tagName = None
|
|||
|
self._classList = None
|
|||
|
self._attributes = []
|
|||
|
self._shadowRoot = None
|
|||
|
self.id = None
|
|||
|
self.className = None
|
|||
|
self.slot = None
|
|||
|
|
|||
|
@property
|
|||
|
def namespaceURI(self):
|
|||
|
return self.namespaceURI
|
|||
|
|
|||
|
@property
|
|||
|
def prefix(self):
|
|||
|
return self._prefix
|
|||
|
|
|||
|
@property
|
|||
|
def localName(self):
|
|||
|
return self._localName
|
|||
|
|
|||
|
@property
|
|||
|
def tagName(self):
|
|||
|
return self._tagName
|
|||
|
|
|||
|
@property
|
|||
|
def classList(self):
|
|||
|
return self._classList
|
|||
|
|
|||
|
@property
|
|||
|
def attributes(self):
|
|||
|
return self._attributes
|
|||
|
|
|||
|
@property
|
|||
|
def shadowRoot(self):
|
|||
|
return self._shadowRoot
|
|||
|
|
|||
|
def hasAttributes(self):
|
|||
|
return len(self._attributes) > 0
|
|||
|
|
|||
|
def getAttributeNames(self):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getAttribute(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getAttributeNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def setAttribute(self, qualifiedName, value):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def setAttributeNS(self, namespace, localName, value):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def removeAttribute(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def removeAttributeNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def toggleAttribute(self, qualifiedName, force):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def hasAttribute(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def hasAttributeNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getAttributeNode(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getAttributeNodeNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def setAttributeNode(self, qualifiedName, value):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def setAttributeNodeNS(self, namespace, localName, value):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def removeAttributeNode(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def attachShadow(self, init):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def closest(self, namespace, selectors):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def matches(self, namespace, selectors):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def webkitMatchesSelector(self, selectors):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getElementsByTagName(self, qualifiedName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getElementsByTagNameNS(self, namespace, localName):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def getElementsByClassName(self, classNames):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def insertAdjacentElement(self, where, element):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def insertAdjacentText(self, where, data):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def in_a_document_tree(self):
|
|||
|
"""
|
|||
|
An element is in a document tree if its root is a document.
|
|||
|
"""
|
|||
|
return isinstance(self.root, Document)
|
|||
|
|
|||
|
def in_a_document(self):
|
|||
|
"""
|
|||
|
An element is in a document if it is in a document tree.
|
|||
|
"""
|
|||
|
return self.in_a_document_tree()
|
|||
|
|
|||
|
def connected(self):
|
|||
|
"""
|
|||
|
An element is connected if its shadow-including root is a document.
|
|||
|
|
|||
|
The shadow-including root of an object is its root’s host’s shadow-including
|
|||
|
root, if the object’s root is a shadow root; otherwise its root.
|
|||
|
"""
|
|||
|
if isinstance(self.root, ShadowRoot):
|
|||
|
return self.root.host.root
|
|||
|
return self.root
|
|||
|
|
|||
|
|
|||
|
class CharacterData(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self.data = ""
|
|||
|
|
|||
|
@property
|
|||
|
def length(self):
|
|||
|
return len(self.data)
|
|||
|
|
|||
|
def _verify_offset(self, offset):
|
|||
|
if offset > self.length:
|
|||
|
raise(IndexSizeError(
|
|||
|
f"Given offset ({offset}) is bigger than data length ({self.length})."
|
|||
|
))
|
|||
|
|
|||
|
def sub_string(self, offset, count):
|
|||
|
# TODO
|
|||
|
self.verify_offset(offset)
|
|||
|
|
|||
|
def append_data(self, data):
|
|||
|
# TODO
|
|||
|
self.data += data
|
|||
|
|
|||
|
def insert_data(self, offset, data):
|
|||
|
# TODO
|
|||
|
self.verify_offset(offset)
|
|||
|
|
|||
|
def delete_data(self, offset, count):
|
|||
|
# TODO
|
|||
|
self.verify_offset(offset)
|
|||
|
|
|||
|
def replace_data(self, offset, count, data):
|
|||
|
# TODO
|
|||
|
self.verify_offset(offset)
|
|||
|
|
|||
|
|
|||
|
class Attr(Node):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._namespaceURI = None
|
|||
|
self._prefix = None
|
|||
|
self._localName = None
|
|||
|
self._name = None
|
|||
|
self._value = None
|
|||
|
self._ownerElement = None
|
|||
|
self._specified = None
|
|||
|
|
|||
|
@property
|
|||
|
def length(self):
|
|||
|
return 0
|
|||
|
|
|||
|
@property
|
|||
|
def namespaceURI(self):
|
|||
|
return self._namespaceURI
|
|||
|
|
|||
|
@property
|
|||
|
def prefix(self):
|
|||
|
return self._prefix
|
|||
|
|
|||
|
@property
|
|||
|
def localName(self):
|
|||
|
return self._localName
|
|||
|
|
|||
|
@property
|
|||
|
def name(self):
|
|||
|
return self._name
|
|||
|
|
|||
|
@property
|
|||
|
def value(self):
|
|||
|
return self._value
|
|||
|
|
|||
|
@property
|
|||
|
def ownerElement(self):
|
|||
|
return self._ownerElement
|
|||
|
|
|||
|
@property
|
|||
|
def specified(self):
|
|||
|
return self._specified
|
|||
|
|
|||
|
|
|||
|
class ShadowRoot(DocumentFragment):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._mode = None
|
|||
|
self._delegateFocus = None
|
|||
|
self._slotAssignment = None
|
|||
|
self._host = None
|
|||
|
self.onslotchange = None
|
|||
|
|
|||
|
@property
|
|||
|
def mode(self):
|
|||
|
return self._mode
|
|||
|
|
|||
|
@property
|
|||
|
def delegateFocus(self):
|
|||
|
return self._delegateFocus
|
|||
|
|
|||
|
@property
|
|||
|
def slotAssignment(self):
|
|||
|
return self._slotAssignment
|
|||
|
|
|||
|
@property
|
|||
|
def host(self):
|
|||
|
return self._host
|
|||
|
|
|||
|
@property
|
|||
|
def namespaceURI(self):
|
|||
|
return self._namespaceURI
|
|||
|
|
|||
|
|
|||
|
|
|||
|
class Text(CharacterData):
|
|||
|
def __init__(self, data=""):
|
|||
|
super().__init__(self)
|
|||
|
self.data = data
|
|||
|
|
|||
|
@property
|
|||
|
def wholeText(self):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
def splitText(self, offset):
|
|||
|
# TODO
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
class CDATASection(Text):
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
class ProcessingInstruction(CharacterData):
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self._target = None
|
|||
|
|
|||
|
@property
|
|||
|
def target(self):
|
|||
|
return self._target
|
|||
|
|
|||
|
|
|||
|
class Comment(CharacterData):
|
|||
|
def __init__(self, data=""):
|
|||
|
super().__init__(self)
|
|||
|
self.data = data
|
|||
|
|
|||
|
|
|||
|
class NodeTree(Tree):
|
|||
|
"""
|
|||
|
A node tree is constrained as follows, expressed as a relationship between a node
|
|||
|
and its potential children:
|
|||
|
Document
|
|||
|
In tree order
|
|||
|
1. Zero or more ProcessingInstruction or Comment nodes.
|
|||
|
2. Optionally one DocumentType node.
|
|||
|
3. Zero or more ProcessingInstruction or Comment nodes.
|
|||
|
4. Optionally one Element node.
|
|||
|
5. Zero or more ProcessingInstruction or Comment nodes.
|
|||
|
DocumentFragment
|
|||
|
Element
|
|||
|
Zero or more Element or CharacterData nodes.
|
|||
|
DocumentType
|
|||
|
CharacterData
|
|||
|
Attr
|
|||
|
No children.
|
|||
|
"""
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
class DocumentTree:
|
|||
|
"""
|
|||
|
A document tree is a node tree whose root is a document.
|
|||
|
"""
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self.root = Document()
|
|||
|
|
|||
|
|
|||
|
class ShadowTree:
|
|||
|
"""
|
|||
|
A shadow tree is a node tree whose root is a shadow root.
|
|||
|
|
|||
|
A shadow root is always attached to another node tree through its host. A shadow
|
|||
|
tree is therefore never alone. The node tree of a shadow root’s host is sometimes
|
|||
|
referred to as the light tree.
|
|||
|
"""
|
|||
|
def __init__(self):
|
|||
|
super().__init__(self)
|
|||
|
self.root = ShadowRoot()
|