Source code for inscriptis.model.css

"""Implement basic CSS support for inscriptis.

- The :class:`~inscriptis.model.html_element.HtmlElement` class
  encapsulates all CSS properties of a single HTML element.
- :class:`CssParse` parses CSS specifications and translates them into the
  corresponding HtmlElements used by Inscriptis for rendering HTML pages.
"""
from contextlib import suppress
from re import compile as re_compile

from inscriptis.html_properties import (
    Display,
    WhiteSpace,
    HorizontalAlignment,
    VerticalAlignment,
)
from inscriptis.model.html_element import HtmlElement


[docs] class CssParse: """Parse CSS specifications and applies them to HtmlElements. The attribute `display: none`, for instance, is translated to :attr:`HtmlElement.display=Display.none`. """ # used to separate value and unit from each other RE_UNIT = re_compile(r"(-?[0-9.]+)(\w+)")
[docs] @staticmethod def attr_style(style_attribute: str, html_element: HtmlElement): """Apply the provided style attributes to the given HtmlElement. Args: style_attribute: The attribute value of the given style sheet. Example: display: none html_element: The HtmlElement to which the given style is applied. """ for style_directive in style_attribute.lower().split(";"): if ":" not in style_directive: continue key, value = (s.strip() for s in style_directive.split(":", 1)) try: apply_style = getattr( CssParse, "attr_" + key.replace("-webkit-", "").replace("-", "_") ) apply_style(value, html_element) except AttributeError: pass
@staticmethod def _get_em(length: str) -> int: """Convert length specifications into em. This function takes a length specification (e.g., 2em, 2px, etc.) and transforms it into em. Args: length: the length specification. Returns: the length in em. """ _m = CssParse.RE_UNIT.search(length) value = float(_m.group(1)) unit = _m.group(2) if unit not in ("em", "qem", "rem"): return int(round(value / 8)) return int(round(value)) # ------------------------------------------------------------------------ # css styles # ------------------------------------------------------------------------
[docs] @staticmethod def attr_display(value: str, html_element: HtmlElement): """Apply the given display value.""" if html_element.display == Display.none: return if value == "block": html_element.display = Display.block elif value == "none": html_element.display = Display.none else: html_element.display = Display.inline
[docs] @staticmethod def attr_white_space(value: str, html_element: HtmlElement): """Apply the given white-space value.""" if value in ("normal", "nowrap"): html_element.whitespace = WhiteSpace.normal elif value in ("pre", "pre-line", "pre-wrap"): html_element.whitespace = WhiteSpace.pre
[docs] @staticmethod def attr_margin_top(value: str, html_element: HtmlElement): """Apply the given top margin.""" with suppress(ValueError): html_element.margin_before = CssParse._get_em(value)
[docs] @staticmethod def attr_margin_bottom(value: str, html_element: HtmlElement): """Apply the provided bottom margin.""" with suppress(ValueError): html_element.margin_after = CssParse._get_em(value)
[docs] @staticmethod def attr_padding_left(value: str, html_element: HtmlElement): """Apply the given left padding_inline.""" with suppress(ValueError): html_element.padding_inline = CssParse._get_em(value)
[docs] @staticmethod def attr_horizontal_align(value: str, html_element: HtmlElement): """Apply the provided horizontal alignment.""" with suppress(KeyError): html_element.align = HorizontalAlignment[value]
[docs] @staticmethod def attr_vertical_align(value: str, html_element: HtmlElement): """Apply the given vertical alignment.""" with suppress(KeyError): html_element.valign = VerticalAlignment[value]
# register aliases attr_margin_before = attr_margin_top attr_margin_after = attr_margin_bottom attr_padding_start = attr_padding_left