feat: Markdown→LaTeX w PDF + dopracowanie kosmogramu (PRE-24, PRE-12 etap 4)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m34s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m35s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 35s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 19s
build-render / build (push) Successful in 45s
build / build (push) Successful in 50s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m46s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m33s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 28s
Testy / Kontrola składni wszystkich warstw (push) Successful in 21s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m34s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m35s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 35s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 19s
build-render / build (push) Successful in 45s
build / build (push) Successful in 50s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m46s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m33s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 28s
Testy / Kontrola składni wszystkich warstw (push) Successful in 21s
Dwie rzeczy w jednym PR (na prośbę).
1) MARKDOWN → LATEX w raporcie PDF (usługa render). Tekst od AI to markdown —
świetny w przeglądarce, ale w PDF `**gwiazdki**` i `## kratki` to dosłowny szum.
Nowy markdown_to_latex zamienia je na PRAWDZIWE formatowanie: nagłówki (degradowane
o poziom, żeby wpadły pod nasz \section „Interpretacja natalna", nie obok),
pogrubienia, kursywy, kod, listy punktowe i numerowane, linki (zostaje sam tekst,
URL bezużyteczny w druku).
Skaner liniowy, nie regex na całości — listy i akapity są wielolinijkowe.
Ucieczka znaków LaTeXa działa TAKŻE wewnątrz formatowania: `**wzrost 50%**` daje
`\textbf{wzrost 50\%}`, a nie zakomentowaną resztę linii. Sprawdzone na wrogim
tekście — `\end{document}` i `\input{}` w treści nie wyrywają się z dokumentu
nawet zawinięte w pogrubienie.
2) KOSMOGRAM — etap 4 (dopracowanie):
- Lots na kole: Fortuna ⊗ (jedyny Lot ze standardowym glifem) na promieniu POD
pierścieniem planet i w akcencie — od razu widać, że to punkt wyliczony, nie
ciało. Loty bez glifu (Spirit, Eros…) pomijamy, żeby nie zaśmiecać.
- Tooltipy: natywny <title> w SVG (bez JS-a). Obiekt → nazwa, pozycja, dom,
retrogradacja. Linia aspektu → „Słońce trygon Mars · orb 0.20°" (polskie nazwy
tylko do dymka; obliczenia trzymają angielskie). Fortuna → nazwa i pozycja.
- Stopnie cuspów przy szprychach. W whole sign cuspy są na 0° znaku — wtedy
pomijamy dwanaście zbędnych zer; w systemach kwadratowych (porphyry) stopień
realnie coś mówi, więc go pokazujemy.
Wszystko działa też w motywie druku (PDF): sprawdzone, że mimo Lotów, dymków
i cuspów SVG nadal nie ma zmiennych CSS.
Weryfikacja wizualna (porphyry): Fortuna przy AC, 12 stopni cuspów, 38 dymków
(24 aspekty + 13 obiektów + Fortuna). Testy: +12 markdown (render), +7 etap 4
(prezentacja). Całość: prezentacja 145, render 27.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #37.
This commit is contained in:
@@ -128,3 +128,84 @@ def test_missing_parts_are_simply_absent():
|
||||
def test_wheel_is_optional():
|
||||
assert "includegraphics" not in build(_report())
|
||||
assert "includegraphics" in build(_report(), wheel_pdf="wheel.pdf")
|
||||
|
||||
|
||||
# ─────────────────── Markdown → LaTeX (nie surowy copy-paste) ─────────────
|
||||
|
||||
from app.latex import markdown_to_latex as md
|
||||
|
||||
|
||||
def test_bold_and_italic_become_commands():
|
||||
out = md("To **ważne** i *podkreślone*.")
|
||||
assert r"\textbf{ważne}" in out
|
||||
assert r"\textit{podkreślone}" in out
|
||||
assert "**" not in out and "*" not in out # znaczniki znikają
|
||||
|
||||
|
||||
def test_headings_are_demoted_under_our_section():
|
||||
"""Markdownowe nagłówki idą POD nasz `\\section*` (natalna/predykcje):
|
||||
# → subsection, ## → subsubsection, ### i głębsze → paragraph."""
|
||||
assert r"\subsection*{Tytuł}" in md("# Tytuł")
|
||||
assert r"\subsubsection*{Podtytuł}" in md("## Podtytuł")
|
||||
assert r"\paragraph*{Głębiej}" in md("### Głębiej")
|
||||
assert "#" not in md("## Podtytuł") # kratki znikają
|
||||
|
||||
|
||||
def test_bullet_list_becomes_itemize():
|
||||
out = md("- pierwszy\n- drugi\n- trzeci")
|
||||
assert r"\begin{itemize}" in out and r"\end{itemize}" in out
|
||||
assert out.count(r"\item ") == 3
|
||||
|
||||
|
||||
def test_numbered_list_becomes_enumerate():
|
||||
out = md("1. raz\n2. dwa")
|
||||
assert r"\begin{enumerate}" in out and r"\end{enumerate}" in out
|
||||
assert out.count(r"\item ") == 2
|
||||
|
||||
|
||||
def test_switching_list_type_closes_the_previous():
|
||||
"""Punktory po numerach nie mogą wpaść do jednego środowiska."""
|
||||
out = md("1. numer\n- punkt")
|
||||
assert r"\end{enumerate}" in out and r"\begin{itemize}" in out
|
||||
|
||||
|
||||
def test_inline_code_becomes_texttt():
|
||||
assert r"\texttt{kod}" in md("użyj `kod` tutaj")
|
||||
|
||||
|
||||
def test_link_keeps_text_drops_url():
|
||||
out = md("zobacz [stronę](https://example.com/x)")
|
||||
assert "stronę" in out
|
||||
assert "example.com" not in out and "http" not in out
|
||||
|
||||
|
||||
def test_paragraphs_are_separated():
|
||||
out = md("Pierwszy akapit.\n\nDrugi akapit.")
|
||||
assert "Pierwszy akapit." in out and "Drugi akapit." in out
|
||||
assert out.count("\n\n") >= 1
|
||||
|
||||
|
||||
def test_special_chars_inside_formatting_are_escaped():
|
||||
"""Ucieczka LaTeXa działa TAKŻE wewnątrz pogrubienia — inaczej `%` w bold
|
||||
zakomentowałby resztę linii."""
|
||||
out = md("**wzrost 50% & więcej**")
|
||||
assert r"\textbf{wzrost 50\% \& więcej}" in out
|
||||
|
||||
|
||||
def test_no_markdown_markers_leak_through():
|
||||
"""Żaden surowy znacznik markdown nie ma trafić do PDF."""
|
||||
out = md("## Tytuł\n\n**b** i *i* oraz `c`\n\n- lista")
|
||||
for marker in ("##", "**", "`"):
|
||||
assert marker not in out
|
||||
|
||||
|
||||
def test_bold_before_italic_not_two_italics():
|
||||
"""`**x**` to pogrubienie, nie dwie kursywy — kolejność w regexie."""
|
||||
out = md("**mocno**")
|
||||
assert r"\textbf{mocno}" in out
|
||||
assert r"\textit{" not in out
|
||||
|
||||
|
||||
def test_empty_and_none_are_safe():
|
||||
assert md("") == ""
|
||||
assert md(None) == ""
|
||||
|
||||
Reference in New Issue
Block a user