pytex-preprocessor 0.4.3__tar.gz → 0.4.4__tar.gz

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 (133) hide show
  1. {pytex_preprocessor-0.4.3/src/pytex_preprocessor.egg-info → pytex_preprocessor-0.4.4}/PKG-INFO +1 -1
  2. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/pyproject.toml +1 -1
  3. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/builtin.py +15 -0
  4. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/helpers/sanitize.py +5 -0
  5. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/packages.py +4 -0
  6. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_markdown/convert.py +28 -2
  7. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4/src/pytex_preprocessor.egg-info}/PKG-INFO +1 -1
  8. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/LICENSE +0 -0
  9. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/README.md +0 -0
  10. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/setup.cfg +0 -0
  11. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/__init__.py +0 -0
  12. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/__init__.py +0 -0
  13. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/biblatex.py +0 -0
  14. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/captions.py +0 -0
  15. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/cleveref.py +0 -0
  16. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/colors.py +0 -0
  17. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/conditionals.py +0 -0
  18. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/counters.py +0 -0
  19. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/definitions.py +0 -0
  20. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/floats.py +0 -0
  21. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/font.py +0 -0
  22. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/fontawesome.py +0 -0
  23. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/fontspec.py +0 -0
  24. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/geometry.py +0 -0
  25. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/glossaries.py +0 -0
  26. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/graphics.py +0 -0
  27. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/hooks.py +0 -0
  28. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/hyperref.py +0 -0
  29. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/lengths.py +0 -0
  30. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/listings.py +0 -0
  31. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/mdframed.py +0 -0
  32. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/picture.py +0 -0
  33. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/setspace.py +0 -0
  34. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/commands/tables.py +0 -0
  35. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/helpers/__init__.py +0 -0
  36. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/helpers/coerce.py +0 -0
  37. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/helpers/parenting.py +0 -0
  38. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/helpers/with_package.py +0 -0
  39. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/interface/__init__.py +0 -0
  40. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/interface/control_sequence.py +0 -0
  41. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/interface/package.py +0 -0
  42. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/interface/tex.py +0 -0
  43. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/__init__.py +0 -0
  44. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/color.py +0 -0
  45. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/comment.py +0 -0
  46. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/concat.py +0 -0
  47. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/control_sequence.py +0 -0
  48. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/document.py +0 -0
  49. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/document_class.py +0 -0
  50. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/empty.py +0 -0
  51. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/environment.py +0 -0
  52. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/image.py +0 -0
  53. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/include.py +0 -0
  54. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/length.py +0 -0
  55. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/math.py +0 -0
  56. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/package.py +0 -0
  57. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/model/raw.py +0 -0
  58. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/registry.py +0 -0
  59. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex/template.py +0 -0
  60. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_analyze/__init__.py +0 -0
  61. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_analyze/analyze.py +0 -0
  62. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_analyze/optimize.py +0 -0
  63. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/__init__.py +0 -0
  64. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/build.py +0 -0
  65. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/console.py +0 -0
  66. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/render.py +0 -0
  67. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/tectonic.py +0 -0
  68. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/tex2py.py +0 -0
  69. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/tree.py +0 -0
  70. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_builder/variants.py +0 -0
  71. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/__init__.py +0 -0
  72. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Bold.ttf +0 -0
  73. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BoldItalic.ttf +0 -0
  74. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Book.ttf +0 -0
  75. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BookItalic.ttf +0 -0
  76. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Medium.ttf +0 -0
  77. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-MediumItalic.ttf +0 -0
  78. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Strong.ttf +0 -0
  79. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Thin.ttf +0 -0
  80. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-ThinItalic.ttf +0 -0
  81. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Black.ttf +0 -0
  82. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Bold.ttf +0 -0
  83. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-BoldItalic.ttf +0 -0
  84. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Italic.ttf +0 -0
  85. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Medium.ttf +0 -0
  86. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Regular.ttf +0 -0
  87. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/fonts/Times New Roman.ttf +0 -0
  88. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/ASTA.svg +0 -0
  89. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/DUMMY.png +0 -0
  90. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/DUMMY_FOOT.png +0 -0
  91. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/ECHO.svg +0 -0
  92. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/HSRT.pdf +0 -0
  93. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/INF.pdf +0 -0
  94. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/STUPA.pdf +0 -0
  95. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/assets/logos/Skyline.pdf +0 -0
  96. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/boxes.py +0 -0
  97. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/citations.py +0 -0
  98. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/cleveref_names.py +0 -0
  99. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/colors.py +0 -0
  100. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/document.py +0 -0
  101. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/fonts.py +0 -0
  102. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/glossary.py +0 -0
  103. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/hyperref_config.py +0 -0
  104. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/listings.py +0 -0
  105. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/logos.py +0 -0
  106. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/pagebreak.py +0 -0
  107. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/pagesetup.py +0 -0
  108. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/tex/pagesetup.tex +0 -0
  109. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/titlepage.py +0 -0
  110. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/variants.py +0 -0
  111. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/voting.py +0 -0
  112. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/watermark.py +0 -0
  113. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_hsrtreport/wordcount.py +0 -0
  114. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_koma/__init__.py +0 -0
  115. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_koma/commands.py +0 -0
  116. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_koma/document.py +0 -0
  117. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_markdown/__init__.py +0 -0
  118. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_markdown/escape.py +0 -0
  119. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_preprocessor.egg-info/SOURCES.txt +0 -0
  120. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_preprocessor.egg-info/dependency_links.txt +0 -0
  121. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_preprocessor.egg-info/entry_points.txt +0 -0
  122. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_preprocessor.egg-info/requires.txt +0 -0
  123. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_preprocessor.egg-info/top_level.txt +0 -0
  124. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/__init__.py +0 -0
  125. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/convert.py +0 -0
  126. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/document.py +0 -0
  127. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/entries.py +0 -0
  128. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/frontmatter.py +0 -0
  129. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/header.py +0 -0
  130. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/shortcodes.py +0 -0
  131. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_protocol/signatures.py +0 -0
  132. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_tikz/__init__.py +0 -0
  133. {pytex_preprocessor-0.4.3 → pytex_preprocessor-0.4.4}/src/pytex_tikz/tikz.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytex-preprocessor
3
- Version: 0.4.3
3
+ Version: 0.4.4
4
4
  Summary: Type-safe LaTeX document generation with Python
5
5
  Author-email: Frederik Beimgraben <frederik@beimgraben.net>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pytex-preprocessor"
7
- version = "0.4.3"
7
+ version = "0.4.4"
8
8
  authors = [
9
9
  { name="Frederik Beimgraben", email="frederik@beimgraben.net" },
10
10
  ]
@@ -1,8 +1,10 @@
1
+ from ..helpers.with_package import with_package
1
2
  from ..interface.tex import TeX
2
3
  from ..model.concat import Concat
3
4
  from ..model.control_sequence import ControlSequence, Parameter
4
5
  from ..model.environment import Environment
5
6
  from ..model.raw import Raw
7
+ from ..packages import EUROSYM
6
8
  from ..registry import Registry
7
9
 
8
10
  __all__ = [
@@ -24,6 +26,7 @@ __all__ = [
24
26
  "Emph",
25
27
  "EndAccSupp",
26
28
  "Enumerate",
29
+ "Euro",
27
30
  "FlushLeft",
28
31
  "FlushRight",
29
32
  "Footnote",
@@ -235,6 +238,18 @@ def Newline() -> TeX:
235
238
  return Raw("\\\\")
236
239
 
237
240
 
241
+ @Registry.add
242
+ @with_package(EUROSYM)
243
+ def Euro() -> TeX:
244
+ """Euro sign via ``eurosym``'s ``\\euro{}``.
245
+
246
+ eurosym ships its own glyph, so it renders even when the text font (e.g.
247
+ DIN) has no euro glyph. The trailing empty group stops the macro from
248
+ gobbling a following space, keeping ``50\\euro{} each`` spaced correctly.
249
+ """
250
+ return ControlSequence("euro", (Parameter(Raw("")),))
251
+
252
+
238
253
  @Registry.add
239
254
  def Linebreak(n: int | None = None) -> TeX:
240
255
  if n is None:
@@ -34,6 +34,11 @@ ESCAPES: Final[dict[str, str]] = {
34
34
  "}": r"\}",
35
35
  "~": r"\textasciitilde{}",
36
36
  "^": r"\textasciicircum{}",
37
+ # babel ngerman (always loaded) makes `"` an active shorthand char, so a
38
+ # literal double quote would be swallowed/mangled. `\textquotedbl{}` is a
39
+ # font-encoding macro (T1/textcomp), not a shorthand, so it prints an
40
+ # upright double quote untouched; the empty group stops space-gobbling.
41
+ '"': r"\textquotedbl{}",
37
42
  }
38
43
 
39
44
 
@@ -113,6 +113,9 @@ ARYDSHLN: Package = DefinePackage("arydshln")
113
113
  LMODERN: Package = DefinePackage("lmodern")
114
114
  HYPHENAT: Package = DefinePackage("hyphenat")
115
115
  FP: Package = DefinePackage("fp")
116
+ # Ships its own euro glyph, so `\euro{}` renders independent of the text font
117
+ # (e.g. DIN, whose font set lacks a euro glyph and would otherwise tofu).
118
+ EUROSYM: Package = DefinePackage("eurosym")
116
119
 
117
120
 
118
121
  class Packages(Enum):
@@ -219,3 +222,4 @@ class Packages(Enum):
219
222
  LMODERN = LMODERN
220
223
  HYPHENAT = HYPHENAT
221
224
  FP = FP
225
+ EUROSYM = EUROSYM
@@ -18,6 +18,7 @@ from pytex.commands.builtin import (
18
18
  Chapter,
19
19
  Emph,
20
20
  Enumerate,
21
+ Euro,
21
22
  Itemize,
22
23
  Newline,
23
24
  Noindent,
@@ -102,6 +103,11 @@ CALLOUTS: Final[dict[str, Callable[[TeX | str], TeX]]] = {
102
103
  "ERROR": WarningBox,
103
104
  }
104
105
 
106
+ # U+20AC EURO SIGN. The DIN text font has no euro glyph, so the raw char would
107
+ # render as tofu; we splice in a real ``Euro`` node (eurosym ``\euro{}``) which
108
+ # ships its own glyph and registers the package requirement.
109
+ EURO_SIGN: Final[str] = "€"
110
+
105
111
  PARBREAK: Final[TeX] = Raw("\n\n")
106
112
 
107
113
  # GFM cell alignment -> tabularx ``X`` column spec. ``X`` columns share the
@@ -147,6 +153,26 @@ def _escape_text(text: str) -> str:
147
153
  return "".join(out)
148
154
 
149
155
 
156
+ def _prose(text: str) -> TeX:
157
+ """Escape prose, splitting literal euro signs into ``Euro`` nodes.
158
+
159
+ Each ``€`` becomes a real :func:`Euro` node (eurosym ``\\euro{}``) instead
160
+ of a raw char so the preamble auto-loads ``eurosym`` and the glyph renders
161
+ even under the DIN font. Text between the euros keeps its arrow/escape
162
+ handling, and the split preserves surrounding spacing exactly (e.g. ``50€``
163
+ stays glyph-adjacent, ``€ 50`` keeps its space).
164
+ """
165
+ if EURO_SIGN not in text:
166
+ return Raw(_escape_text(text))
167
+ parts: list[TeX] = []
168
+ for i, segment in enumerate(text.split(EURO_SIGN)):
169
+ if i:
170
+ parts.append(Euro())
171
+ if segment:
172
+ parts.append(Raw(_escape_text(segment)))
173
+ return Concat(*parts)
174
+
175
+
150
176
  class MarkdownConverter:
151
177
  """Walk a marko AST, producing a single ``TeX`` tree.
152
178
 
@@ -170,7 +196,7 @@ class MarkdownConverter:
170
196
  # RawText / CodeSpan / Literal etc. carry a plain string.
171
197
  if kind == "CodeSpan":
172
198
  return Texttt(Raw(escape_latex(text)))
173
- return Raw(_escape_text(text))
199
+ return _prose(text)
174
200
 
175
201
  if kind == "StrongEmphasis":
176
202
  return Bold(self.inlines(node))
@@ -246,7 +272,7 @@ class MarkdownConverter:
246
272
  # Rebuild the first paragraph with the marker stripped, keep the rest.
247
273
  stripped = first_text[match.end() :]
248
274
  head = Concat(
249
- Raw(_escape_text(stripped)),
275
+ _prose(stripped),
250
276
  *(self.inline(c) for c in inner[1:]),
251
277
  )
252
278
  body_blocks = [head, *(self.block(b) for b in kids[1:])]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytex-preprocessor
3
- Version: 0.4.3
3
+ Version: 0.4.4
4
4
  Summary: Type-safe LaTeX document generation with Python
5
5
  Author-email: Frederik Beimgraben <frederik@beimgraben.net>
6
6
  License: GNU GENERAL PUBLIC LICENSE