snail/domtree.py

547 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 roots hosts shadow-including
root, if the objects 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 roots host is sometimes
referred to as the light tree.
"""
def __init__(self):
super().__init__(self)
self.root = ShadowRoot()