69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
|
|
|
|
from collections.abc import Callable
|
|
|
|
from . import default_converters
|
|
|
|
from bs4 import BeautifulSoup
|
|
|
|
class Bozodown():
|
|
|
|
def __init__(self):
|
|
self._converters: dict[str, dict[str, str]] = default_converters.converters.copy()
|
|
self._text_converter: dict[str, str] = default_converters.text_converter.copy()
|
|
self._specific_case_namespaces: dict[str, Callable[[object, str, str], str]] = {
|
|
"bozodown": self._bozodown_render,
|
|
}
|
|
|
|
def render(self, to_parse: str):
|
|
content: str = ""
|
|
while len(to_parse) > 0:
|
|
text, converter = self._get_first_converter(to_parse)
|
|
content += self._render_element(text, converter)
|
|
to_parse = to_parse[len(text):]
|
|
return BeautifulSoup(content, 'html.parser').prettify()
|
|
|
|
|
|
def _render_element(self, text: str, converter: dict[str, str]) -> str:
|
|
code: str = converter.get("code")
|
|
if (code is not None):
|
|
namespace, id = code.split(":")
|
|
func = self._specific_case_namespaces[namespace]
|
|
return func(id, text)
|
|
start: int = len(converter["from_prefix"])
|
|
stop: int = len(text) - len(converter.get("from_suffix", ""))
|
|
if (text[start:stop] == "\n" and converter is self._text_converter):
|
|
return ""
|
|
return f"{converter['to_prefix']}{text[start:stop]}{converter['to_suffix']}"
|
|
|
|
def _bozodown_render(self, id: str, text: str) -> str:
|
|
if (id == "list"):
|
|
print("error: list not supported")
|
|
return ""
|
|
if (id == "block"):
|
|
style, to_parse = text[5:-5].split("---")
|
|
style = style.replace("\n", "")
|
|
content: str = self.render(to_parse)
|
|
return f"<div style='{style}'>{content}</div>"
|
|
|
|
def _get_first_converter(self, text: str) -> tuple[str, dict] | None:
|
|
first_converter_found: dict[str, str] | None = None
|
|
start: int | None = None
|
|
for converter in self._converters.values():
|
|
matching_patern_pos: str = text.find(converter['from_prefix'])
|
|
if (matching_patern_pos != -1):
|
|
if (first_converter_found is None or matching_patern_pos < start):
|
|
first_converter_found = converter
|
|
start = matching_patern_pos
|
|
if (first_converter_found is None):
|
|
return text, self._text_converter
|
|
if (start != 0):
|
|
return text[:start], self._text_converter
|
|
suffix: int = first_converter_found.get("from_suffix", "")
|
|
prefix: int = first_converter_found['from_prefix']
|
|
stop: int = text.find(suffix, start + len(prefix))
|
|
if (stop == -1):
|
|
print(f"error: '{prefix}' was never finished by a '{suffix}'")
|
|
return
|
|
stop += len(suffix)
|
|
return text[start:stop], first_converter_found |