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"
{content}
" 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