Source code for domilite.render
import contextlib
import dataclasses as dc
import io
from collections.abc import Iterator
from typing import TYPE_CHECKING
from .flags import Flag
from .flags import auto
if TYPE_CHECKING:
from domilite.dom_tag import dom_tag # noqa F401
__all__ = ["RenderFlags"]
[docs]
class RenderFlags(Flag):
"""Settings for rendering tags"""
#: Render tags with indentation across multiple lines.
PRETTY = auto()
#: Use XHTML semantics.
XHTML = auto()
class ContextFlags(Flag):
#: Currently rendering a comment, don't render sub-comments
COMMENT = auto()
@dc.dataclass
class RenderStream:
buffer: io.StringIO = dc.field(default_factory=io.StringIO, init=False)
current_indent: int = dc.field(default=0, init=False)
indent_text: str = " "
flags: RenderFlags = RenderFlags(0)
context: ContextFlags = ContextFlags(0)
def write(self, text: str) -> None:
for i, line in enumerate(text.splitlines()):
if i:
self.newline()
self.buffer.write(line)
def newline(self) -> None:
self.buffer.write("\n" + self.indent_text * self.current_indent)
def getvalue(self) -> str:
return self.buffer.getvalue()
@contextlib.contextmanager
def indented(self) -> Iterator[None]:
self.current_indent += 1
yield
self.current_indent -= 1
@contextlib.contextmanager
def comment(self) -> Iterator[None]:
is_comment = self.context & ContextFlags.COMMENT
self.context |= ContextFlags.COMMENT
yield
if not is_comment:
self.context &= ~ContextFlags.COMMENT
@contextlib.contextmanager
def parts(self, joiner: str = " ") -> Iterator["RenderParts"]:
parts = RenderParts(self, joiner=joiner)
yield parts
parts.close()
@dc.dataclass
class RenderParts:
stream: RenderStream
joiner: str = " "
parts: list[str] = dc.field(default_factory=list, init=False)
@property
def flags(self) -> RenderFlags:
return self.stream.flags
def append(self, item: str) -> None:
self.parts.append(item)
def prepend(self, item: str) -> None:
self.parts.insert(0, item)
def close(self) -> None:
self.stream.write(self.joiner.join(self.parts))