52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
|
|
from typing import List, Sequence
|
|||
|
|
|
|||
|
|
from draftjs_exporter.command import Command
|
|||
|
|
from draftjs_exporter.constants import INLINE_STYLES
|
|||
|
|
from draftjs_exporter.dom import DOM
|
|||
|
|
from draftjs_exporter.options import Options, OptionsMap
|
|||
|
|
from draftjs_exporter.types import Block, Element
|
|||
|
|
|
|||
|
|
|
|||
|
|
class StyleState:
|
|||
|
|
"""
|
|||
|
|
Handles the creation of inline styles on elements.
|
|||
|
|
Receives inline_style commands, and generates the element's `style`
|
|||
|
|
attribute from those.
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
__slots__ = ("styles", "style_options")
|
|||
|
|
|
|||
|
|
def __init__(self, style_options: OptionsMap) -> None:
|
|||
|
|
self.styles: List[str] = []
|
|||
|
|
self.style_options = style_options
|
|||
|
|
|
|||
|
|
def apply(self, command: Command) -> None:
|
|||
|
|
if command.name == "start_inline_style":
|
|||
|
|
self.styles.append(command.data)
|
|||
|
|
elif command.name == "stop_inline_style":
|
|||
|
|
self.styles.remove(command.data)
|
|||
|
|
|
|||
|
|
def is_empty(self) -> bool:
|
|||
|
|
return not self.styles
|
|||
|
|
|
|||
|
|
def render_styles(
|
|||
|
|
self, decorated_node: Element, block: Block, blocks: Sequence[Block]
|
|||
|
|
) -> Element:
|
|||
|
|
node = decorated_node
|
|||
|
|
if not self.is_empty():
|
|||
|
|
# This will mutate self.styles, but it’s going to be reset after rendering anyway.
|
|||
|
|
self.styles.sort(reverse=True)
|
|||
|
|
|
|||
|
|
# Nest the tags.
|
|||
|
|
for style in self.styles:
|
|||
|
|
options = Options.get(
|
|||
|
|
self.style_options, style, INLINE_STYLES.FALLBACK
|
|||
|
|
)
|
|||
|
|
props = dict(options.props)
|
|||
|
|
props["block"] = block
|
|||
|
|
props["blocks"] = blocks
|
|||
|
|
props["inline_style_range"] = {"style": style}
|
|||
|
|
node = DOM.create_element(options.element, props, node)
|
|||
|
|
|
|||
|
|
return node
|