# Copyright (C) 2002-2004 TechGame Networks, LLC. # # This library is free software; you can redistribute it and/or # modify it under the terms of the BSD style License as found in the # LICENSE file included with this distribution. # # Modified by Dirk Holtwick , 2007-2008 # ruff: noqa: N802, N803, N815, N816, N999 from __future__ import annotations from typing import TYPE_CHECKING, Callable, ClassVar from xhtml2pdf.w3c import css if TYPE_CHECKING: from typing_extensions import Self # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~ Definitions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class CSSDOMElementInterface(css.CSSElementInterfaceAbstract): """An implementation of css.CSSElementInterfaceAbstract for xml.dom Element Nodes.""" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~ Constants / Variables / Etc. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ style = None _pseudoStateHandlerLookup: ClassVar[dict[str, Callable[[Self], bool]]] = { "first-child": lambda self: not bool(self.getPreviousSibling()), "not-first-child": lambda self: bool(self.getPreviousSibling()), "last-child": lambda self: not bool(self.getNextSibling()), "not-last-child": lambda self: bool(self.getNextSibling()), "middle-child": lambda self: not bool(self.getPreviousSibling()) and not bool( self.getNextSibling() ), "not-middle-child": lambda self: bool(self.getPreviousSibling()) or bool( self.getNextSibling() ), # XXX 'first-line': } # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~ Definitions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def __init__(self, domElement, cssParser=None) -> None: self.domElement = domElement # print self.domElement.attributes if cssParser is not None: self.onCSSParserVisit(cssParser) def onCSSParserVisit(self, cssParser): styleSrc = self.getStyleAttr() if styleSrc: style = cssParser.parseInline(styleSrc) self.setInlineStyle(style) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def matchesNode(self, namespace_tagName): namespace, tagName = namespace_tagName if tagName not in ("*", self.domElement.tagName): return False if namespace in (None, "", "*"): # matches any namespace return True # full compare return namespace == self.domElement.namespaceURI def getAttr(self, name, default=NotImplemented): attr_value = self.domElement.attributes.get(name) if attr_value is not None: return attr_value.value return default def getIdAttr(self): return self.getAttr("id", "") def getClassAttr(self): return self.getAttr("class", "") def getStyleAttr(self): return self.getAttr("style", None) def inPseudoState(self, name, params=()): handler = self._pseudoStateHandlerLookup.get(name, lambda _: False) return handler(self) def iterXMLParents(self, *, includeSelf=False): klass = type(self) current = self.domElement if not includeSelf: current = current.parentNode while (current is not None) and (current.nodeType == current.ELEMENT_NODE): yield klass(current) current = current.parentNode def getPreviousSibling(self): sibling = self.domElement.previousSibling while sibling: if sibling.nodeType == sibling.ELEMENT_NODE: return sibling sibling = sibling.previousSibling return None def getNextSibling(self): sibling = self.domElement.nextSibling while sibling: if sibling.nodeType == sibling.ELEMENT_NODE: return sibling sibling = sibling.nextSibling return None def getInlineStyle(self): return self.style def setInlineStyle(self, style): self.style = style