59ba0555bb
C1: LaTeX escaping спецсимволов (& % $ # _ { } ~ ^ \)
C2: text.capitalize() → first char uppercase only
C3: run_xelatex проверяет returncode
C4: парсинг лога при ошибке второго прохода
W1: Удалены мёртвые счётчики section/subsection/subsubsection
W2: text.upper() вычисляется один раз
W3: Единая сигнатура хендлеров (r, tok) для всех
W4: Джэгged строки таблицы паддятся до max колонок
W5: Пустой lang в code fence → без [language=]
W6: hr() вынесен из code.py в hr.py
W7: Валидация обязательных полей front matter
W8: Имя вуза конфигурируется через front matter
W9: -> None аннотация main()
W10: \n в конце END_DOCUMENT
+ Dockerfile: добавлен texlive-fonts-recommended
67 lines
1.6 KiB
Python
67 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from md2gost.handlers import (
|
|
bullet_list,
|
|
fence,
|
|
heading,
|
|
hr,
|
|
image,
|
|
ordered_list,
|
|
paragraph,
|
|
table,
|
|
)
|
|
from md2gost.handlers.inline import render_inline
|
|
from md2gost.latex import END_DOCUMENT, PREAMBLE, render_titlepage
|
|
|
|
from markdown_it.token import Token
|
|
|
|
|
|
_BLOCK = {
|
|
"heading_open": heading,
|
|
"paragraph_open": paragraph,
|
|
"bullet_list_open": bullet_list,
|
|
"ordered_list_open": ordered_list,
|
|
"table_open": table,
|
|
"hr": hr,
|
|
}
|
|
|
|
_INLINE = {
|
|
"fence": fence,
|
|
"image": image,
|
|
"inline": render_inline,
|
|
}
|
|
|
|
|
|
class Renderer:
|
|
def __init__(self, tokens: list[Token], front_matter: dict[str, str]) -> None:
|
|
self.tokens = tokens
|
|
self.fm = front_matter
|
|
self.pos = 0
|
|
self.current_heading = ""
|
|
|
|
def render(self) -> str:
|
|
parts: list[str] = [PREAMBLE, render_titlepage(self.fm), "\\setcounter{page}{2}"]
|
|
|
|
while self.pos < len(self.tokens):
|
|
tok = self.tokens[self.pos]
|
|
prev_pos = self.pos
|
|
tt = tok.type
|
|
|
|
if tt in _BLOCK:
|
|
result = _BLOCK[tt](self, tok)
|
|
parts.append(result)
|
|
if self.current_heading == "СОДЕРЖАНИЕ":
|
|
parts.append("\\newpage\n\\tableofcontents\n\\newpage")
|
|
elif tt in _INLINE:
|
|
result = _INLINE[tt](self, tok)
|
|
parts.append(result)
|
|
else:
|
|
self.pos += 1
|
|
continue
|
|
|
|
if self.pos == prev_pos:
|
|
self.pos += 1
|
|
|
|
parts.append(END_DOCUMENT)
|
|
return "\n\n".join(parts)
|