Initial commit
This commit is contained in:
130
env/lib/python3.10/site-packages/draftjs_exporter/dom.py
vendored
Normal file
130
env/lib/python3.10/site-packages/draftjs_exporter/dom.py
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
import re
|
||||
from typing import Any, Optional
|
||||
|
||||
from draftjs_exporter.engines.base import DOMEngine
|
||||
from draftjs_exporter.types import HTML, Element, Props, RenderableType
|
||||
from draftjs_exporter.utils.module_loading import import_string
|
||||
|
||||
# https://gist.github.com/yahyaKacem/8170675
|
||||
_first_cap_re = re.compile(r"(.)([A-Z][a-z]+)")
|
||||
_all_cap_re = re.compile("([a-z0-9])([A-Z])")
|
||||
|
||||
|
||||
class DOM:
|
||||
"""
|
||||
Component building API, abstracting the DOM implementation.
|
||||
"""
|
||||
|
||||
HTML5LIB = "draftjs_exporter.engines.html5lib.DOM_HTML5LIB"
|
||||
LXML = "draftjs_exporter.engines.lxml.DOM_LXML"
|
||||
STRING = "draftjs_exporter.engines.string.DOMString"
|
||||
STRING_COMPAT = "draftjs_exporter.engines.string_compat.DOMStringCompat"
|
||||
|
||||
dom: DOMEngine = None # type: ignore
|
||||
|
||||
@staticmethod
|
||||
def camel_to_dash(camel_cased_str: str) -> str:
|
||||
sub2 = _first_cap_re.sub(r"\1-\2", camel_cased_str)
|
||||
dashed_case_str = _all_cap_re.sub(r"\1-\2", sub2).lower()
|
||||
return dashed_case_str.replace("--", "-")
|
||||
|
||||
@classmethod
|
||||
def use(cls, engine: str) -> None:
|
||||
"""
|
||||
Choose which DOM implementation to use.
|
||||
"""
|
||||
cls.dom = import_string(engine)
|
||||
|
||||
@classmethod
|
||||
def create_element(
|
||||
cls,
|
||||
type_: RenderableType = None,
|
||||
props: Optional[Props] = None,
|
||||
*elt_children: Optional[Element],
|
||||
) -> Element:
|
||||
"""
|
||||
Signature inspired by React.createElement.
|
||||
createElement(
|
||||
string/Component type,
|
||||
[dict props],
|
||||
[children ...]
|
||||
)
|
||||
https://facebook.github.io/react/docs/top-level-api.html#react.createelement
|
||||
"""
|
||||
# Create an empty document fragment.
|
||||
if not type_:
|
||||
return cls.dom.create_tag("fragment")
|
||||
|
||||
if props is None:
|
||||
props = {}
|
||||
|
||||
# If the first element of children is a list, we use it as the list.
|
||||
if len(elt_children) and isinstance(elt_children[0], (list, tuple)):
|
||||
children = elt_children[0]
|
||||
else:
|
||||
children = elt_children
|
||||
|
||||
# The children prop is the first child if there is only one.
|
||||
props["children"] = children[0] if len(children) == 1 else children
|
||||
|
||||
if callable(type_):
|
||||
# Function component, via def or lambda.
|
||||
elt = type_(props)
|
||||
else:
|
||||
# Raw tag, as a string.
|
||||
attributes = {}
|
||||
|
||||
# Never render those attributes on a raw tag.
|
||||
props.pop("children", None)
|
||||
props.pop("block", None)
|
||||
props.pop("blocks", None)
|
||||
props.pop("entity", None)
|
||||
props.pop("inline_style_range", None)
|
||||
|
||||
# Convert style object to style string, like the DOM would do.
|
||||
if "style" in props and isinstance(props["style"], dict):
|
||||
rules = [
|
||||
f"{DOM.camel_to_dash(s)}: {v};"
|
||||
for s, v in props["style"].items()
|
||||
]
|
||||
props["style"] = "".join(rules)
|
||||
|
||||
# Convert props to HTML attributes.
|
||||
for key in props:
|
||||
if props[key] is False:
|
||||
props[key] = "false"
|
||||
|
||||
if props[key] is True:
|
||||
props[key] = "true"
|
||||
|
||||
if props[key] is not None:
|
||||
attributes[key] = str(props[key])
|
||||
|
||||
elt = cls.dom.create_tag(type_, attributes)
|
||||
|
||||
# Append the children inside the element.
|
||||
for child in children:
|
||||
if child not in (None, ""):
|
||||
cls.append_child(elt, child)
|
||||
|
||||
# If elt is "empty", create a fragment anyway to add children.
|
||||
if elt in (None, ""):
|
||||
elt = cls.dom.create_tag("fragment")
|
||||
|
||||
return elt
|
||||
|
||||
@classmethod
|
||||
def parse_html(cls, markup: HTML) -> Element:
|
||||
return cls.dom.parse_html(markup)
|
||||
|
||||
@classmethod
|
||||
def append_child(cls, elt: Element, child: Element) -> Any:
|
||||
return cls.dom.append_child(elt, child)
|
||||
|
||||
@classmethod
|
||||
def render(cls, elt: Element) -> HTML:
|
||||
return cls.dom.render(elt)
|
||||
|
||||
@classmethod
|
||||
def render_debug(cls, elt: Element) -> HTML:
|
||||
return cls.dom.render_debug(elt)
|
||||
Reference in New Issue
Block a user