-
Notifications
You must be signed in to change notification settings - Fork 0
/
render_tex.py
executable file
·100 lines (69 loc) · 2.09 KB
/
render_tex.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from __future__ import annotations
import sys
from pathlib import Path
from typing import Iterable
from pydantic import BaseModel
from yaml import CLoader, load
class Text(BaseModel):
text: str
class ListElement(BaseModel):
id: str
content: list[ContentAtom]
class List(BaseModel):
list: list[ListElement]
class Paragraph(BaseModel):
id: str
content: list[ContentAtom]
ContentAtom = List | Text
ListElement.model_rebuild()
Paragraph.model_rebuild()
class Chapter(BaseModel):
id: str
title: str
paragraphs: list[Paragraph]
class Statute(BaseModel):
chapters: list[Chapter]
def read_statute(filename: str) -> Statute:
with open(filename) as input_file:
data = load(input_file, Loader=CLoader)
return Statute.model_validate(data)
def render_atom(atom: ContentAtom) -> Iterable[str]:
if isinstance(atom, Text):
yield atom.text
return
yield "\\begin{enumerate}"
for item in atom.list:
yield f"\\item[{item.id})]"
for atom in item.content:
yield from render_atom(atom)
yield "\\end{enumerate}"
def render_paragraph(paragraph: Paragraph) -> Iterable[str]:
yield from [
"",
f"\\renewcommand\\thesubsubsection{{\\S~{paragraph.id}}}",
f"\\subsubsection{{\\texorpdfstring{{}}{{§{paragraph.id}}}}}",
"",
]
for atom in paragraph.content:
yield from render_atom(atom)
def render_chapter(chapter: Chapter) -> Iterable[str]:
yield from [
"",
f"\\renewcommand\\thesection{{{chapter.id}}}",
f"\\section{{{chapter.title}}}",
"",
]
for paragraph in chapter.paragraphs:
yield from render_paragraph(paragraph)
def render(statute: Statute) -> str:
lines = []
for chapter in statute.chapters:
lines.extend(render_chapter(chapter))
return "\n".join(lines)
def main() -> None:
statute = read_statute(sys.argv[1])
rendered_statute = render(statute)
template = Path(sys.argv[2]).read_text()
print(template.replace("$body$", rendered_statute))
if __name__ == "__main__":
main()