Files
2026-linux-sumka/markdown_builder.py
2026-09-23 00:46:28 +03:00

60 lines
2.3 KiB
Python

from structure_builder import (
DefinitionElement,
HeadingElement,
ImageElement,
ImportantElement,
OrderedListElement,
ParagraphElement,
Structure,
StructureElement,
UnorderedListElement,
)
from utils import Event, Timeline
class MarkdownBuilder:
"""Render a document structure to Markdown without using AI."""
def __init__(self, timeline: Timeline) -> None:
self._events: dict[int, Event] = {}
for event in timeline.events:
if event.id in self._events:
raise ValueError(f"Duplicate event ID: {event.id}")
self._events[event.id] = event
def _render_image(self, element: ImageElement) -> str:
event = self._events.get(element.event_id)
if event is None or event.type != "vis" or not event.payload:
raise ValueError(
f"Image element references invalid visual event: {element.event_id}"
)
alt = event.text.replace("[", "").replace("]", "").replace("\n", " ")
return f"![{alt}](<{event.payload}>)"
def _render_element(self, element: StructureElement) -> str:
if isinstance(element, HeadingElement):
return f"{'#' * element.level} {element.text}"
if isinstance(element, ParagraphElement):
return element.text
if isinstance(element, UnorderedListElement):
return "\n".join(f"- {item}" for item in element.items)
if isinstance(element, OrderedListElement):
return "\n".join(
f"{index}. {item}"
for index, item in enumerate(element.items, start=1)
)
if isinstance(element, DefinitionElement):
return f"**{element.term}.** {element.text}"
if isinstance(element, ImportantElement):
text = f"**Важно:** {element.text}"
return "\n".join(f"> {line}" for line in text.splitlines())
if isinstance(element, ImageElement):
return self._render_image(element)
raise TypeError(f"Unsupported structure element: {type(element).__name__}")
def build(self, structure: Structure) -> str:
blocks = [self._render_element(element) for element in structure.elements]
if not blocks:
return ""
return "\n\n".join(blocks) + "\n"