pytex-preprocessor 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. pytex/__init__.py +87 -0
  2. pytex/commands/__init__.py +51 -0
  3. pytex/commands/biblatex.py +98 -0
  4. pytex/commands/builtin.py +598 -0
  5. pytex/commands/captions.py +56 -0
  6. pytex/commands/cleveref.py +43 -0
  7. pytex/commands/colors.py +60 -0
  8. pytex/commands/conditionals.py +62 -0
  9. pytex/commands/counters.py +85 -0
  10. pytex/commands/definitions.py +109 -0
  11. pytex/commands/floats.py +93 -0
  12. pytex/commands/font.py +138 -0
  13. pytex/commands/fontawesome.py +88 -0
  14. pytex/commands/fontspec.py +75 -0
  15. pytex/commands/geometry.py +25 -0
  16. pytex/commands/glossaries.py +126 -0
  17. pytex/commands/graphics.py +68 -0
  18. pytex/commands/hooks.py +58 -0
  19. pytex/commands/hyperref.py +57 -0
  20. pytex/commands/lengths.py +200 -0
  21. pytex/commands/listings.py +63 -0
  22. pytex/commands/mdframed.py +43 -0
  23. pytex/commands/picture.py +32 -0
  24. pytex/commands/setspace.py +38 -0
  25. pytex/commands/tables.py +123 -0
  26. pytex/helpers/__init__.py +3 -0
  27. pytex/helpers/coerce.py +13 -0
  28. pytex/helpers/parenting.py +13 -0
  29. pytex/helpers/sanitize.py +54 -0
  30. pytex/helpers/with_package.py +61 -0
  31. pytex/interface/__init__.py +3 -0
  32. pytex/interface/control_sequence.py +29 -0
  33. pytex/interface/package.py +52 -0
  34. pytex/interface/tex.py +41 -0
  35. pytex/model/__init__.py +25 -0
  36. pytex/model/color.py +203 -0
  37. pytex/model/concat.py +31 -0
  38. pytex/model/control_sequence.py +72 -0
  39. pytex/model/document.py +120 -0
  40. pytex/model/document_class.py +29 -0
  41. pytex/model/empty.py +19 -0
  42. pytex/model/environment.py +30 -0
  43. pytex/model/image.py +137 -0
  44. pytex/model/include.py +21 -0
  45. pytex/model/length.py +54 -0
  46. pytex/model/math.py +401 -0
  47. pytex/model/package.py +132 -0
  48. pytex/model/raw.py +61 -0
  49. pytex/packages.py +221 -0
  50. pytex/registry.py +49 -0
  51. pytex_builder/__init__.py +8 -0
  52. pytex_builder/build.py +175 -0
  53. pytex_builder/console.py +77 -0
  54. pytex_builder/render.py +90 -0
  55. pytex_builder/tectonic.py +370 -0
  56. pytex_hsrtreport/__init__.py +116 -0
  57. pytex_hsrtreport/assets/fonts/Blender/Blender-Bold.ttf +0 -0
  58. pytex_hsrtreport/assets/fonts/Blender/Blender-BoldItalic.ttf +0 -0
  59. pytex_hsrtreport/assets/fonts/Blender/Blender-Book.ttf +0 -0
  60. pytex_hsrtreport/assets/fonts/Blender/Blender-BookItalic.ttf +0 -0
  61. pytex_hsrtreport/assets/fonts/Blender/Blender-Medium.ttf +0 -0
  62. pytex_hsrtreport/assets/fonts/Blender/Blender-MediumItalic.ttf +0 -0
  63. pytex_hsrtreport/assets/fonts/Blender/Blender-Strong.ttf +0 -0
  64. pytex_hsrtreport/assets/fonts/Blender/Blender-Thin.ttf +0 -0
  65. pytex_hsrtreport/assets/fonts/Blender/Blender-ThinItalic.ttf +0 -0
  66. pytex_hsrtreport/assets/fonts/DIN/DIN-Black.ttf +0 -0
  67. pytex_hsrtreport/assets/fonts/DIN/DIN-Bold.ttf +0 -0
  68. pytex_hsrtreport/assets/fonts/DIN/DIN-BoldItalic.ttf +0 -0
  69. pytex_hsrtreport/assets/fonts/DIN/DIN-Italic.ttf +0 -0
  70. pytex_hsrtreport/assets/fonts/DIN/DIN-Medium.ttf +0 -0
  71. pytex_hsrtreport/assets/fonts/DIN/DIN-Regular.ttf +0 -0
  72. pytex_hsrtreport/assets/fonts/Times New Roman.ttf +0 -0
  73. pytex_hsrtreport/assets/logos/ASTA.svg +79 -0
  74. pytex_hsrtreport/assets/logos/DUMMY.png +0 -0
  75. pytex_hsrtreport/assets/logos/DUMMY_FOOT.png +0 -0
  76. pytex_hsrtreport/assets/logos/ECHO.svg +226 -0
  77. pytex_hsrtreport/assets/logos/HSRT.pdf +0 -0
  78. pytex_hsrtreport/assets/logos/INF.pdf +0 -0
  79. pytex_hsrtreport/assets/logos/STUPA.pdf +0 -0
  80. pytex_hsrtreport/assets/logos/Skyline.pdf +0 -0
  81. pytex_hsrtreport/boxes.py +215 -0
  82. pytex_hsrtreport/citations.py +21 -0
  83. pytex_hsrtreport/cleveref_names.py +47 -0
  84. pytex_hsrtreport/colors.py +30 -0
  85. pytex_hsrtreport/document.py +307 -0
  86. pytex_hsrtreport/fonts.py +66 -0
  87. pytex_hsrtreport/glossary.py +61 -0
  88. pytex_hsrtreport/hyperref_config.py +49 -0
  89. pytex_hsrtreport/listings.py +90 -0
  90. pytex_hsrtreport/logos.py +234 -0
  91. pytex_hsrtreport/pagebreak.py +67 -0
  92. pytex_hsrtreport/pagesetup.py +33 -0
  93. pytex_hsrtreport/tex/pagesetup.tex +76 -0
  94. pytex_hsrtreport/titlepage.py +136 -0
  95. pytex_hsrtreport/variants.py +24 -0
  96. pytex_hsrtreport/voting.py +96 -0
  97. pytex_hsrtreport/watermark.py +63 -0
  98. pytex_hsrtreport/wordcount.py +33 -0
  99. pytex_koma/__init__.py +90 -0
  100. pytex_koma/commands.py +296 -0
  101. pytex_koma/document.py +138 -0
  102. pytex_markdown/__init__.py +62 -0
  103. pytex_markdown/convert.py +271 -0
  104. pytex_markdown/escape.py +11 -0
  105. pytex_preprocessor-0.1.0.dist-info/METADATA +82 -0
  106. pytex_preprocessor-0.1.0.dist-info/RECORD +119 -0
  107. pytex_preprocessor-0.1.0.dist-info/WHEEL +5 -0
  108. pytex_preprocessor-0.1.0.dist-info/entry_points.txt +2 -0
  109. pytex_preprocessor-0.1.0.dist-info/top_level.txt +7 -0
  110. pytex_protocol/__init__.py +37 -0
  111. pytex_protocol/convert.py +202 -0
  112. pytex_protocol/document.py +91 -0
  113. pytex_protocol/entries.py +96 -0
  114. pytex_protocol/frontmatter.py +80 -0
  115. pytex_protocol/header.py +139 -0
  116. pytex_protocol/shortcodes.py +130 -0
  117. pytex_protocol/signatures.py +84 -0
  118. pytex_tikz/__init__.py +25 -0
  119. pytex_tikz/tikz.py +272 -0
@@ -0,0 +1,271 @@
1
+ # pyright: reportAny=false, reportExplicitAny=false
2
+ """Convert a marko Markdown AST into native PyTeX ``TeX`` nodes.
3
+
4
+ Block elements map to the standard pytex library (headings, lists, quotes,
5
+ code, rules); inline elements map to text-formatting commands. GitHub-style
6
+ callouts (``> [!NOTE]`` ...) become HSRT ``ColoredBox`` presets, which is why
7
+ this module depends on ``pytex_hsrtreport``.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from typing import TYPE_CHECKING, Any, Final, cast
14
+
15
+ from pytex.commands.builtin import (
16
+ Bold,
17
+ Chapter,
18
+ Emph,
19
+ Enumerate,
20
+ Itemize,
21
+ Newline,
22
+ Noindent,
23
+ Paragraph,
24
+ Part,
25
+ Quote,
26
+ Rule,
27
+ Section,
28
+ Subparagraph,
29
+ Subsection,
30
+ Subsubsection,
31
+ Texttt,
32
+ Verbatim,
33
+ )
34
+ from pytex.commands.hyperref import Href
35
+ from pytex.interface.tex import TeX
36
+ from pytex.model.concat import Concat
37
+ from pytex.model.empty import Empty
38
+ from pytex.model.image import IncludeImage
39
+ from pytex.model.raw import Raw, pytex_namespace
40
+ from pytex_hsrtreport.boxes import ImportantBox, InfoBox, SuccessBox, WarningBox
41
+
42
+ from .escape import escape_latex
43
+
44
+ __all__ = ["MarkdownConverter"]
45
+
46
+ if TYPE_CHECKING:
47
+ from collections.abc import Callable
48
+
49
+ # Heading commands ordered from the broadest division downward. The default
50
+ # `base_level` of 0 maps Markdown ``#`` (level 1) to ``Section``.
51
+ HEADINGS: Final[tuple[Callable[..., TeX], ...]] = (
52
+ Part,
53
+ Chapter,
54
+ Section,
55
+ Subsection,
56
+ Subsubsection,
57
+ Paragraph,
58
+ Subparagraph,
59
+ )
60
+ SECTION_INDEX: Final[int] = 2 # index of Section in HEADINGS
61
+
62
+ CALLOUT_RE: Final[re.Pattern[str]] = re.compile(r"^\s*\[!(\w+)\]\s*", re.IGNORECASE)
63
+ CALLOUTS: Final[dict[str, Callable[[TeX | str], TeX]]] = {
64
+ "NOTE": InfoBox,
65
+ "INFO": InfoBox,
66
+ "TIP": SuccessBox,
67
+ "HINT": SuccessBox,
68
+ "SUCCESS": SuccessBox,
69
+ "IMPORTANT": ImportantBox,
70
+ "WARNING": WarningBox,
71
+ "CAUTION": WarningBox,
72
+ "DANGER": WarningBox,
73
+ "ERROR": WarningBox,
74
+ }
75
+
76
+ PARBREAK: Final[TeX] = Raw("\n\n")
77
+
78
+
79
+ def _kind(node: object) -> str:
80
+ return type(node).__name__
81
+
82
+
83
+ def _children(node: object) -> list[object]:
84
+ ch = getattr(node, "children", None)
85
+ return cast("list[object]", ch) if isinstance(ch, list) else []
86
+
87
+
88
+ def _text(node: object) -> str | None:
89
+ """Return a node's literal text payload, or ``None`` for container nodes."""
90
+ ch = getattr(node, "children", None)
91
+ return ch if isinstance(ch, str) else None
92
+
93
+
94
+ class MarkdownConverter:
95
+ """Walk a marko AST, producing a single ``TeX`` tree.
96
+
97
+ Subclass to add domain-specific blocks/inlines (see
98
+ ``pytex_protocol.convert.ProtocolConverter``).
99
+ """
100
+
101
+ base_level: int
102
+ callouts: bool
103
+
104
+ def __init__(self, *, base_level: int = 0, callouts: bool = True) -> None:
105
+ self.base_level = base_level
106
+ self.callouts = callouts
107
+
108
+ # -- inline -----------------------------------------------------------
109
+
110
+ def inline(self, node: object) -> TeX:
111
+ kind = _kind(node)
112
+ text = _text(node)
113
+ if text is not None:
114
+ # RawText / CodeSpan / Literal etc. carry a plain string.
115
+ if kind == "CodeSpan":
116
+ return Texttt(Raw(escape_latex(text)))
117
+ return Raw(escape_latex(text))
118
+
119
+ if kind == "StrongEmphasis":
120
+ return Bold(self.inlines(node))
121
+ if kind == "Emphasis":
122
+ return Emph(self.inlines(node))
123
+ if kind == "Link":
124
+ dest = str(getattr(node, "dest", ""))
125
+ return Href(dest, self.inlines(node))
126
+ if kind == "Image":
127
+ return IncludeImage(str(getattr(node, "dest", "")))
128
+ if kind == "LineBreak":
129
+ # Hard break -> newline; soft break -> a plain space.
130
+ soft = bool(getattr(node, "soft", False))
131
+ return Raw(" ") if soft else Newline()
132
+
133
+ # Unknown inline: recurse if it has children, else drop.
134
+ kids = _children(node)
135
+ return self.inlines(node) if kids else Empty
136
+
137
+ def inlines(self, node: object) -> TeX:
138
+ return Concat(*(self.inline(c) for c in _children(node)))
139
+
140
+ # -- blocks -----------------------------------------------------------
141
+
142
+ def _heading(self, node: object) -> TeX:
143
+ level = int(getattr(node, "level", 1))
144
+ idx = SECTION_INDEX + (level - 1) + self.base_level
145
+ idx = max(0, min(idx, len(HEADINGS) - 1))
146
+ return HEADINGS[idx](self.inlines(node))
147
+
148
+ def _list(self, node: object) -> TeX:
149
+ items = [self._list_item(c) for c in _children(node) if _kind(c) == "ListItem"]
150
+ factory = Enumerate if bool(getattr(node, "ordered", False)) else Itemize
151
+ return factory(*items)
152
+
153
+ def _list_item(self, node: object) -> TeX:
154
+ kids = _children(node)
155
+ # Tight item: a lone paragraph -> inline its content (no extra break).
156
+ if len(kids) == 1 and _kind(kids[0]) == "Paragraph":
157
+ return self.inlines(kids[0])
158
+ return self.blocks(kids)
159
+
160
+ def _quote(self, node: object) -> TeX:
161
+ kids = _children(node)
162
+ callout = self._as_callout(kids) if self.callouts else None
163
+ if callout is not None:
164
+ return callout
165
+ return Quote(self.blocks(kids))
166
+
167
+ def _as_callout(self, kids: list[object]) -> TeX | None:
168
+ if not kids or _kind(kids[0]) != "Paragraph":
169
+ return None
170
+ inner = _children(kids[0])
171
+ first_text = _text(inner[0]) if inner else None
172
+ if first_text is None:
173
+ return None
174
+ match = CALLOUT_RE.match(first_text)
175
+ if match is None:
176
+ return None
177
+ box = CALLOUTS.get(match.group(1).upper())
178
+ if box is None:
179
+ return None
180
+ # Rebuild the first paragraph with the marker stripped, keep the rest.
181
+ stripped = first_text[match.end() :]
182
+ head = Concat(
183
+ Raw(escape_latex(stripped)),
184
+ *(self.inline(c) for c in inner[1:]),
185
+ )
186
+ body_blocks = [head, *(self.block(b) for b in kids[1:])]
187
+ return box(Concat(*_interleave(body_blocks)))
188
+
189
+ def _code(self, node: object) -> TeX:
190
+ # Code blocks hold a single RawText child; fall back to a direct string.
191
+ text = _text(node)
192
+ if text is None:
193
+ kids = _children(node)
194
+ text = _text(kids[0]) if kids else ""
195
+ return Verbatim((text or "").rstrip("\n"))
196
+
197
+ def _rule(self, _node: object) -> TeX:
198
+ return Concat(Noindent(), Rule(r"\linewidth", "0.4pt"))
199
+
200
+ def _eval_comment(self, node: object) -> TeX:
201
+ """Evaluate a ``[//]: # "EXPR"`` Markdown comment as a pytex expression.
202
+
203
+ This mirrors the ``\\iffalse{pytex(EXPR)}\\fi`` escape hatch in raw TeX:
204
+ ``EXPR`` is evaluated with the Registry namespace. A ``TeX`` result is
205
+ spliced into the tree as-is; anything else is stringified into ``Raw``.
206
+ """
207
+ title = getattr(node, "title", None)
208
+ if not isinstance(title, str):
209
+ return Empty
210
+ expr = _strip_md_title(title)
211
+ if not expr:
212
+ return Empty
213
+ result: Any = eval(expr, pytex_namespace())
214
+ return result if isinstance(result, TeX) else Raw(str(result))
215
+
216
+ def block(self, node: object) -> TeX:
217
+ kind = _kind(node)
218
+ if kind == "Heading":
219
+ return self._heading(node)
220
+ if kind == "Paragraph":
221
+ return self.inlines(node)
222
+ if kind == "List":
223
+ return self._list(node)
224
+ if kind == "Quote":
225
+ return self._quote(node)
226
+ if kind in ("FencedCode", "CodeBlock"):
227
+ return self._code(node)
228
+ if kind == "ThematicBreak":
229
+ return self._rule(node)
230
+ if kind == "LinkRefDef":
231
+ # `[//]: # "EXPR"` is the Markdown-comment escape hatch: evaluate it.
232
+ # Any other link reference definition renders to nothing.
233
+ if (
234
+ getattr(node, "label", None) == "//"
235
+ and getattr(node, "dest", None) == "#"
236
+ ):
237
+ return self._eval_comment(node)
238
+ return Empty
239
+ if kind == "BlankLine":
240
+ return Empty
241
+ # Container we do not special-case (e.g. nested Document).
242
+ kids = _children(node)
243
+ return self.blocks(kids) if kids else Empty
244
+
245
+ def blocks(self, nodes: list[object]) -> TeX:
246
+ out = [self.block(n) for n in nodes if _kind(n) not in ("BlankLine",)]
247
+ return Concat(*_interleave(out))
248
+
249
+
250
+ def _strip_md_title(title: str) -> str:
251
+ """Strip the delimiters marko keeps around a link-ref-def title.
252
+
253
+ Titles arrive quoted (``"..."``, ``'...'``) or parenthesised (``(...)``).
254
+ """
255
+ t = title.strip()
256
+ if len(t) >= 2 and (
257
+ (t[0] in "\"'" and t[-1] == t[0]) or (t[0] == "(" and t[-1] == ")")
258
+ ):
259
+ return t[1:-1].strip()
260
+ return t
261
+
262
+
263
+ def _interleave(blocks: list[TeX]) -> list[TeX]:
264
+ """Join block nodes with paragraph breaks, dropping empties."""
265
+ kept = [b for b in blocks if b is not Empty]
266
+ joined: list[TeX] = []
267
+ for i, b in enumerate(kept):
268
+ if i:
269
+ joined.append(PARBREAK)
270
+ joined.append(b)
271
+ return joined
@@ -0,0 +1,11 @@
1
+ """LaTeX text escaping (re-exported from pytex core).
2
+
3
+ The canonical implementation lives in :mod:`pytex.helpers.sanitize` so the
4
+ markdown converter and :func:`pytex.helpers.sanitize.Sanitize` stay in sync.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from pytex.helpers.sanitize import escape_latex
10
+
11
+ __all__ = ["escape_latex"]
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytex-preprocessor
3
+ Version: 0.1.0
4
+ Summary: Type-safe LaTeX document generation with Python
5
+ Author-email: Frederik Beimgraben <frederik@beimgraben.net>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: pydantic
9
+ Requires-Dist: marko
10
+ Provides-Extra: dev
11
+ Requires-Dist: pytest; extra == "dev"
12
+ Requires-Dist: ruff; extra == "dev"
13
+ Requires-Dist: basedpyright; extra == "dev"
14
+
15
+ # pytex
16
+
17
+ ## Install
18
+
19
+ ```sh
20
+ python -m venv venv && . venv/bin/activate
21
+ pip install -e . # add [dev] for pytest
22
+ ```
23
+
24
+ `SVG` conversion needs `inkscape`. Compiling to PDF needs `tectonic` — if it
25
+ is not on `PATH`, `pytex --build` downloads a self-contained binary into a
26
+ temp folder and reuses it on later runs. Resolving glossaries/acronyms needs
27
+ `makeindex` from a TeX distribution (e.g. TeX Live).
28
+
29
+ ## The `pytex` command
30
+
31
+ ```sh
32
+ pytex example.tex.py # render -> example.out.tex
33
+ pytex example.tex.py --build # render + compile -> build/example.out.pdf
34
+ ```
35
+
36
+ The input is either:
37
+
38
+ - a `.py` file exposing a module-level `__pytex__` variable that is a `TeX`
39
+ node (e.g. a `Document`) — it is rendered, or
40
+ - a `.tex` file — wrapped in `IncludeTeX` (so `\iffalse pytex(...) \fi`
41
+ replacements are evaluated) and rendered.
42
+
43
+ ### Options
44
+
45
+ | Flag | Default | Meaning |
46
+ | --- | --- | --- |
47
+ | `-o`, `--output` | `<input>.out.tex` | rendered LaTeX output path |
48
+ | `-b`, `--build` | off | compile the rendered `.tex` to PDF with tectonic |
49
+ | `--build-dir DIR` | `build` | directory for artifacts and tectonic output |
50
+ | `--no-shell-escape` | shell-escape on | disable shell-escape |
51
+
52
+ Shell-escape is enabled by default because inline images decode their base64
53
+ payloads at compile time. The build runs tectonic, then `makeindex` (for
54
+ `glossaries`/acronyms), then reruns tectonic when an index changed.
55
+
56
+ Output is minimal and color-tagged (`==>`, `note:`, `warning:`, `error:`),
57
+ following tectonic's style; on failure it points at the likely cause and the
58
+ log file. Set `NO_COLOR` to disable color.
59
+
60
+ ## Markdown
61
+
62
+ `pytex_markdown` converts Markdown to native `TeX` nodes (via `marko`):
63
+
64
+ ```py
65
+ from pytex_markdown import Markdown, IncludeMarkdown
66
+
67
+ body = Markdown("# Title\n\nText with **bold**, `code`, [a link](https://x).")
68
+ body = IncludeMarkdown("notes.md", base_level=-1) # base_level=-1: # -> \chapter
69
+ ```
70
+
71
+ Headings, emphasis, inline/fenced code, lists, links, images, block quotes and
72
+ thematic breaks map to the standard pytex library; text is LaTeX-escaped.
73
+ GitHub-style callouts become HSRT colored boxes (so the module depends on
74
+ `pytex_hsrtreport`):
75
+
76
+ ```md
77
+ > [!NOTE] -> InfoBox > [!IMPORTANT] -> ImportantBox
78
+ > [!TIP] -> SuccessBox > [!WARNING] -> WarningBox
79
+ ```
80
+
81
+ Both factories are registered, so they are usable from `\iffalse pytex(...) \fi`
82
+ replacements in `.tex` sources too.
@@ -0,0 +1,119 @@
1
+ pytex/__init__.py,sha256=xHI6AMoZCJCGK9c4hFjrL_ELizCbHslycBSCDGI7BaA,1310
2
+ pytex/packages.py,sha256=UBntFiOSNB8d0Ge1_x0-6xZaqeqqgnCh3240DTmcJWo,7685
3
+ pytex/registry.py,sha256=T2H3b2UdkRae2mxx8VIPiHHyO5YPNgmTePlmk21wTH8,1159
4
+ pytex/commands/__init__.py,sha256=Lxmu96wVU72u_zN5cZCSVwHXZXHZB7xHSYzEua0V9YQ,715
5
+ pytex/commands/biblatex.py,sha256=USNdY6dCjqOc67GsKVpREkYkN_cAdoq69rWWPVZSSe4,2326
6
+ pytex/commands/builtin.py,sha256=RLwhzRVmJp0kYO9ElP6MvJ4iCvsX7drVXGYjk8IINI8,12966
7
+ pytex/commands/captions.py,sha256=Ac35z9hwLMzlazk3ZppktnQ3gnvy8Lp_7Xq2j2jmHMU,1401
8
+ pytex/commands/cleveref.py,sha256=qCfWFeEA-mid4LWmVkOJsmGyAEEROyPdRv1Qkm_QubY,1166
9
+ pytex/commands/colors.py,sha256=MAj7bh5-Q0o1IwOAbZSVotZeeUr7UkijXhNcO-XtQ8Q,1464
10
+ pytex/commands/conditionals.py,sha256=heHgm8dGkbTPXgq3FZu4rPb7HB1tqXu4vlb_ahGsyzQ,1691
11
+ pytex/commands/counters.py,sha256=GFKqAsrJOmicIyaJzAIBpxFpEwTfck5gi1tpp-KUgOg,1972
12
+ pytex/commands/definitions.py,sha256=vf1itpdRwOwZgQRmHqyedmieqpOnit8mi_TPwCuqMDA,2611
13
+ pytex/commands/floats.py,sha256=dIUEVWqCqwyYLdFL4JkS9GBqrA8Equ8_qxzbu5SPw2s,2305
14
+ pytex/commands/font.py,sha256=inHLixHC7PLrDpNw8sdHsA0KS28X_BqwzJUWof_cLEA,2329
15
+ pytex/commands/fontawesome.py,sha256=gRYQjt99-jzsJ8P1zTYQzmt7cod3jOUz8w7HbPRm6fE,1963
16
+ pytex/commands/fontspec.py,sha256=ZnkKnyINwTykM699yGAhHKCEfUzYKRXwDKZopo-_tZk,2128
17
+ pytex/commands/geometry.py,sha256=ZNUM51LlXEBnKxrGOVSAuA5krYftsow4lsSMeIUdQTo,688
18
+ pytex/commands/glossaries.py,sha256=uflPIgPGqiw9TVYoMhVvHDBjfxAuqetoGyqn5bSFv_k,3051
19
+ pytex/commands/graphics.py,sha256=khc_AycTOyRpYYeF3eEWIdPXUibq3RUR2ybmzzSBcvY,1956
20
+ pytex/commands/hooks.py,sha256=MfLe9yctDhyKPNeQm8lHYW8jdTgL6vE13FnO5RSexQo,1399
21
+ pytex/commands/hyperref.py,sha256=1TdnH7hhk72tnnmvAYAGK1BG9viytqUN1tvrQTKWUBc,1353
22
+ pytex/commands/lengths.py,sha256=yTVbbWBvzKazA1qHmPVYO0g31tqB3LwgoWH6pVGbBx4,3619
23
+ pytex/commands/listings.py,sha256=9CAyk0s-dudu6JmVUFHehYuKVCnmjAVxTuM76S6uZWI,1858
24
+ pytex/commands/mdframed.py,sha256=bPAH-3K-VKEzG5IPYjuOkKCxOlxJWL2jqn-5cJUo13Q,1248
25
+ pytex/commands/picture.py,sha256=-t8pGZlLOTwjZXEDBQblQskCU6vEA6Nz60FyetSRo5Y,746
26
+ pytex/commands/setspace.py,sha256=8sotYYhakfh_nCqFXsOnH707qiwYUW96vSYjZ2dJjrw,982
27
+ pytex/commands/tables.py,sha256=whXfqD1JlUt9eKcjF9V69sKDA9Zo4wvio4ms1VopE58,2830
28
+ pytex/helpers/__init__.py,sha256=Varupw-yDql8T8HoGEWSgaKc12KTGSawMz8qXBTlT3c,119
29
+ pytex/helpers/coerce.py,sha256=6fzjJM3Sx4qjHpCklYHfuVo53zq7O8rdGL-5jIq5P3I,250
30
+ pytex/helpers/parenting.py,sha256=SJmviCusqsd15OlpUNWVjr4Yb1ofGg-Qm3JW4UqYA1E,403
31
+ pytex/helpers/sanitize.py,sha256=ddcVWzzeFfaXfuqjWHP7rsUlaq6aOvIlKiTRFojiHmI,1622
32
+ pytex/helpers/with_package.py,sha256=pNQG5jFVAV0UTBVtE9EzD6hSlnjyV0wLsFEsXxit8Bs,1547
33
+ pytex/interface/__init__.py,sha256=cGT2SUvktFgVtVpY8oedAVwSUesIMNXG-AxHI1QMadI,95
34
+ pytex/interface/control_sequence.py,sha256=Bq1benlc9L0LXL5I0tjypyEAj6u3BZMh5cDTRNZ_AUI,644
35
+ pytex/interface/package.py,sha256=RbvwNDWCATr52rLhvoL2EpH2dfWO_NdxtkGn_28ENvk,1248
36
+ pytex/interface/tex.py,sha256=ckv7jdG-aWPLhi2QOOA0xw3Am_NzPfqHQ_iNZW9IcyA,1018
37
+ pytex/model/__init__.py,sha256=W75yifcr4k_OQyKArDxR0KVvWtzW-nTSo-7nXUi3b24,571
38
+ pytex/model/color.py,sha256=I3ynF8MoZpd6He9MT5bra7_SQ-PWfVplNDPF3Mh1Pg0,5732
39
+ pytex/model/concat.py,sha256=RKIkNTZnxzgQMD4qHcfJo-fSKSqvDdGMSQJ861tb1Ws,800
40
+ pytex/model/control_sequence.py,sha256=TQZ3y2TseOfpkTefn4eX5pY5DhxExyJGGA7OL5KOPkY,2115
41
+ pytex/model/document.py,sha256=WveyBHIkF-QHQIjyoQnvKcnMeVCKIVE-fl8iLnKcqAs,4406
42
+ pytex/model/document_class.py,sha256=RP-81WM8lgZFTMTC17MDkik99oNiWWbG4hICD9I_AKs,834
43
+ pytex/model/empty.py,sha256=p5xhEP9Dpa__jeNSQ3PQsmNZYM9Cb5gk71VxigehwM4,286
44
+ pytex/model/environment.py,sha256=Nlvv9q_HC9oDYcsKS8w9qAED6HY1_e7TR9gbeXI5bPA,720
45
+ pytex/model/image.py,sha256=qVnQW4NYZp9B_hbXnl_UBDXVfqMBiqN3GSAYkO0B7ag,4890
46
+ pytex/model/include.py,sha256=mwaJLS0OVV3thUj1gEBqtAlaFJ0Xb2cI7Kvy_sYjOSs,439
47
+ pytex/model/length.py,sha256=265DN6mIu25xWI6rlyByig--Ksd3JdRg6y6EWlgpPoM,1604
48
+ pytex/model/math.py,sha256=WGcMIqAhni5geWokzjKCQJa-EcNNV-MaZkxQsJ9mPd8,8964
49
+ pytex/model/package.py,sha256=za-5KJktchScMDAvcbNWWwr5VweeOC_G6cpK9WvyUWo,3338
50
+ pytex/model/raw.py,sha256=dbk0FM0y0rhGZbBHTmSLXv0U_l2OoXYe1WbxAARHq9s,1658
51
+ pytex_builder/__init__.py,sha256=5ELV_bRSgOu7vNNLk0cEhJi_GioKGYZI2YnO8hoUvIw,203
52
+ pytex_builder/build.py,sha256=oJx-tnsjUyBoZhXybAeILvGTkpHdIWTzx-wiXIBro2s,5426
53
+ pytex_builder/console.py,sha256=oCxXArhaERGWTE4L9G3PKdzkIOIO1DchT_U9vE1Cwu4,2414
54
+ pytex_builder/render.py,sha256=7Vkcpb0DjQJPbW8DQHYUaU-T8RCNrGRYQZd6YYuRa-0,2908
55
+ pytex_builder/tectonic.py,sha256=rkPPC7ly4KcG65T560jETZkM-p3AYamyr45S0d2DKWw,12878
56
+ pytex_hsrtreport/__init__.py,sha256=8mcot0_qo5UX4aLKYyz82i_rDrvVIT1MeZMjmTlHU9g,2387
57
+ pytex_hsrtreport/boxes.py,sha256=yPvOPOAhGqjWR6ctH8DBQ8alsA3uFeZkLYTbG5xe7Tg,7876
58
+ pytex_hsrtreport/citations.py,sha256=rbAQhzjlw9nh2oSWlWVH5TcYCeZ3KtvxQ0qUAUlfUTQ,674
59
+ pytex_hsrtreport/cleveref_names.py,sha256=MGaiYwGMWRbEvpaIUpfRwJttwT5Ox4hTonKFDsfPoHc,1624
60
+ pytex_hsrtreport/colors.py,sha256=ynxrFrW324m6rUX8wX9w_ghBvE7bqt5AH4B-dITNbvg,868
61
+ pytex_hsrtreport/document.py,sha256=BA3NY3P39sfvjp0PBqZFa21d_7niGCkmbHNkElZMS9k,10849
62
+ pytex_hsrtreport/fonts.py,sha256=xLJe958fJIBoZ3zqvYHX8dxSWSWEPwBh_6WqLm0DGD4,2258
63
+ pytex_hsrtreport/glossary.py,sha256=D69fuMfUQz3xslkXlygGXhzSP3VXyIGQgw8pdX65aUw,2063
64
+ pytex_hsrtreport/hyperref_config.py,sha256=4XseOdVPJRJCmWDKSxzhFXk624XKHc8i5oEMGc7l9kY,1651
65
+ pytex_hsrtreport/listings.py,sha256=JKHS2C-Ywj-hf-v2L6Y6HY-Gb4qb1bfRftmpRxZXn4U,2786
66
+ pytex_hsrtreport/logos.py,sha256=2mjvFZS9PYk1FjidXOcN-xDLr6AGadtb-bvxbdkiigs,7425
67
+ pytex_hsrtreport/pagebreak.py,sha256=AqfrfaTUGXk8H_dzwTQDcwluyv6Pm0D1ZMTupby6C8Y,1965
68
+ pytex_hsrtreport/pagesetup.py,sha256=QmKp8auOSFKW8X4QRdzGKjze-sSl1VtseTVsv1cCNOI,1249
69
+ pytex_hsrtreport/titlepage.py,sha256=GyFXg3qo6404QwVuPZkmErclaT-xq4E7lZaeHIXb3oc,4653
70
+ pytex_hsrtreport/variants.py,sha256=J_aas4zAsk7JuqSTxmE96DG7bedvmTQP7Vv0FtW6_0A,514
71
+ pytex_hsrtreport/voting.py,sha256=dTljeyK0_8EL0RAftijZ9IvN1hl3wl37LYV8Cefs6O4,3068
72
+ pytex_hsrtreport/watermark.py,sha256=dadBsWNdqebyP0NEi14t-8L5u_1zODg0-_ugnjJhqdc,2000
73
+ pytex_hsrtreport/wordcount.py,sha256=ibDZmrQz2gwJMPTuqlD9EI77-wwx0XZGV-nAORzGikI,982
74
+ pytex_hsrtreport/assets/fonts/Times New Roman.ttf,sha256=OAFCvGYzLQmw8k3fS8t0s1nJO2hjMdSIoPMVTi18Jrs,834452
75
+ pytex_hsrtreport/assets/fonts/Blender/Blender-Bold.ttf,sha256=2t95G5XPH6VJ28YUE5nqp8z21XRrSc5um3bzvLD8WNM,102504
76
+ pytex_hsrtreport/assets/fonts/Blender/Blender-BoldItalic.ttf,sha256=Bj0Aj9xHuAIAvRzgGN__YMCPxRa9SlW2P_CgWFgpTHU,121796
77
+ pytex_hsrtreport/assets/fonts/Blender/Blender-Book.ttf,sha256=d5TB8IrSwXZjKzgLFAQ81N6IHnOsmpCQS7P_Rod8F_Y,108052
78
+ pytex_hsrtreport/assets/fonts/Blender/Blender-BookItalic.ttf,sha256=EVs9mKxX4RF9YW33oLHUbFqejcWxLX8SNv6IrtTAjs8,123648
79
+ pytex_hsrtreport/assets/fonts/Blender/Blender-Medium.ttf,sha256=JTFFUhMwd5M1eUpeXq1qYtTR5CoXqMTn4zVPAz3VkWo,107340
80
+ pytex_hsrtreport/assets/fonts/Blender/Blender-MediumItalic.ttf,sha256=4n15LmjQn3U3JPghSM6C-Wxw7URoLse_rXlEp34FWsc,122820
81
+ pytex_hsrtreport/assets/fonts/Blender/Blender-Strong.ttf,sha256=BZ8VkSBtqifeejA2JnZ-aDFvk7sJrZwj14wwbwWfwy8,93624
82
+ pytex_hsrtreport/assets/fonts/Blender/Blender-Thin.ttf,sha256=v-RtEL7KKWLtPE0dnzokI3d8drBCLyJ7PDVTMGwQhl0,105140
83
+ pytex_hsrtreport/assets/fonts/Blender/Blender-ThinItalic.ttf,sha256=uaYbbpUTVRJL8-qrRy23RizXNoi38-DxyROJ_MAl47g,120668
84
+ pytex_hsrtreport/assets/fonts/DIN/DIN-Black.ttf,sha256=51xzoHahlbWzQitG_ZQbheegOwvK-QY1ihts06mtxFM,28792
85
+ pytex_hsrtreport/assets/fonts/DIN/DIN-Bold.ttf,sha256=7bGQ2VzdrTdwco75qvsJA-zfm97jRWuKmGgKQ-e4ehg,39948
86
+ pytex_hsrtreport/assets/fonts/DIN/DIN-BoldItalic.ttf,sha256=0cqJA8h-ao7TJhTsDz8ESeCLeC_6de9Pg6tGbfK29qM,26164
87
+ pytex_hsrtreport/assets/fonts/DIN/DIN-Italic.ttf,sha256=4upiRs-zEJQMbGHpbGsTYHcOSNAONPXZulgmnUvk8g0,54688
88
+ pytex_hsrtreport/assets/fonts/DIN/DIN-Medium.ttf,sha256=f-3SstASA2m4xO00c1hpnQeVJG7vVsr8hyRz603BY0Y,28944
89
+ pytex_hsrtreport/assets/fonts/DIN/DIN-Regular.ttf,sha256=YxrqqSXiJmL4kT2I4i7ONB4rlEkwQohWk73Wg7AhD5o,39556
90
+ pytex_hsrtreport/assets/logos/ASTA.svg,sha256=_w_32d7ms1gWgnmrHDW7dc_dcGoQKgWXvuy9-QPWLUI,26458
91
+ pytex_hsrtreport/assets/logos/DUMMY.png,sha256=YGdbldIQEKm1ufnzMM7jfUzvOlyqLwV7ybBrqTLtSfg,430
92
+ pytex_hsrtreport/assets/logos/DUMMY_FOOT.png,sha256=33CK_-RrxaNPyhJk-jDuw3fr931MyQZvNMnYvuc5dsE,432
93
+ pytex_hsrtreport/assets/logos/ECHO.svg,sha256=j8ioe9gKkIvk_tnCT9tR_ZaBqK5uaWygPaFLUi_I9TA,16238
94
+ pytex_hsrtreport/assets/logos/HSRT.pdf,sha256=KE6x7_7yod-kAKimgw-lr5QZg4Ub-T8ZpuKDqJQj-OM,11128
95
+ pytex_hsrtreport/assets/logos/INF.pdf,sha256=pNUxxhg2owm6gVzPVAsR3mBu4T_3CPXvSIDGUJNEQ7A,6863
96
+ pytex_hsrtreport/assets/logos/STUPA.pdf,sha256=Ef7NG7dv32pYsw0VLJKau_gFSeToJVG0ajE3pfTwmRA,10479
97
+ pytex_hsrtreport/assets/logos/Skyline.pdf,sha256=47cA5lLXHygt2SGP_3BFhVeGmywOONEdKsxnV3yj11Q,3040
98
+ pytex_hsrtreport/tex/pagesetup.tex,sha256=TmMd0Mm5LubzsRSZsydaETfOKzaGrczeLoCMMFiMSQ4,3743
99
+ pytex_koma/__init__.py,sha256=2B1cXmfQPXY8hIvjvAKUyBcBb_pK9IFFj8wfdwZ1UEY,1477
100
+ pytex_koma/commands.py,sha256=qBz-vp1ea3aXkcLpYB5HYlcm9rNhSK_f4hvI8D7vKBQ,7296
101
+ pytex_koma/document.py,sha256=-5bIzyoeLvDH2uskdXZa4ASjrlKnjyLmQ6NGF-KOGVo,4690
102
+ pytex_markdown/__init__.py,sha256=kC_dYaf9AHnaXKOAZ6b_PCf1kKRc-wz-AF--7kbNLWA,1659
103
+ pytex_markdown/convert.py,sha256=Qj0K-NKomsd5V2OzBZ1HWYvH4dFYn6unwN6LNaH9e8Q,9116
104
+ pytex_markdown/escape.py,sha256=XatD4wbCB_FKPiPRkGZRkBruUd8UEjXP2CJOeuVSz0k,324
105
+ pytex_protocol/__init__.py,sha256=OQM358IDEspp0hkpbdHX65UBhlSlAzyn2J-yzwCeo5s,1226
106
+ pytex_protocol/convert.py,sha256=Ua66xS8YmQcahlQ5h9jE_BS0DLbMBDtoxop27R27LLg,6914
107
+ pytex_protocol/document.py,sha256=zsL-TCrj-dVqlzous3M1pTNiVXalW7C__S-_2lXGyyk,3255
108
+ pytex_protocol/entries.py,sha256=Jyg8jX-s5tyboaa0Pz6_trA4B9eLGspBtRB4n11WMYQ,2713
109
+ pytex_protocol/frontmatter.py,sha256=7EkH3Rtp-vPluANX_UzN3Ia75IQulNutFiNXArZU3jA,2657
110
+ pytex_protocol/header.py,sha256=fwHg1Vs3CF753tMdszi7QD3tBjjz1gICRZbaCJ-DwRs,4544
111
+ pytex_protocol/shortcodes.py,sha256=pU-vrlMZRVn3A4ujiohACTCCHMu_JS3rbR_z5VE91MA,4195
112
+ pytex_protocol/signatures.py,sha256=QJcpZlZsYme8ltSust6f9okz_5x4BmDX-sI1kB-hsQs,2809
113
+ pytex_tikz/__init__.py,sha256=AY77bmltOi31EDFnzqH1dzV5Z64iB5ytZxPTwhOz6ME,322
114
+ pytex_tikz/tikz.py,sha256=Y-0lzcJ-wWUjtapNOGiuhkd_6AERVGFA1G-to8vmqY4,7105
115
+ pytex_preprocessor-0.1.0.dist-info/METADATA,sha256=YCu8GUhtUs2Kg3OYL8MBB8ZaAY73mCVuz9ZvDXI18AI,2856
116
+ pytex_preprocessor-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
117
+ pytex_preprocessor-0.1.0.dist-info/entry_points.txt,sha256=8wdqfEHIsIKLxbiJjt-WWxCMjaN9qGV-wM6xCLJxkZs,51
118
+ pytex_preprocessor-0.1.0.dist-info/top_level.txt,sha256=WhrJQezWOoP1EGgWbjEmbT6YCHn3JKHv6sKS9Cgj5j8,89
119
+ pytex_preprocessor-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pytex = pytex_builder.build:main
@@ -0,0 +1,7 @@
1
+ pytex
2
+ pytex_builder
3
+ pytex_hsrtreport
4
+ pytex_koma
5
+ pytex_markdown
6
+ pytex_protocol
7
+ pytex_tikz
@@ -0,0 +1,37 @@
1
+ """STUPA/AStA meeting-protocol rendering, built on top of ``pytex_hsrtreport``.
2
+
3
+ Write the minutes in Obsidian-flavoured Markdown - YAML frontmatter for the
4
+ meeting header, ``> [!beschluss]`` / ``> [!abstimmung]`` / ``> [!aufgabe]``
5
+ callouts and inline ``{{shortcodes}}`` for the protocol-specific bits - and
6
+ render it to a PDF that matches the HSRTReport look.
7
+
8
+ from pytex_protocol import IncludeProtocol
9
+ __pytex__ = IncludeProtocol("sitzung.md")
10
+ """
11
+
12
+ from .convert import ProtocolConverter
13
+ from .document import IncludeProtocol, Protocol, render_protocol
14
+ from .entries import ActionItem, Deadline, Decision, Timestamp, Vote
15
+ from .frontmatter import split_frontmatter
16
+ from .header import ProtocolHeader, header_from_meta
17
+ from .shortcodes import expand_inline_shortcodes, expand_shortcode
18
+ from .signatures import SignatureLines, signature_block_from_meta
19
+
20
+ __all__ = [
21
+ "ActionItem",
22
+ "Deadline",
23
+ "Decision",
24
+ "IncludeProtocol",
25
+ "Protocol",
26
+ "ProtocolConverter",
27
+ "ProtocolHeader",
28
+ "SignatureLines",
29
+ "Timestamp",
30
+ "Vote",
31
+ "expand_inline_shortcodes",
32
+ "expand_shortcode",
33
+ "header_from_meta",
34
+ "render_protocol",
35
+ "signature_block_from_meta",
36
+ "split_frontmatter",
37
+ ]