diff --git a/backend/version.py b/backend/version.py index bee357d..576abb2 100644 --- a/backend/version.py +++ b/backend/version.py @@ -1,11 +1,11 @@ # Shinkan Jinkendo Version Information -APP_VERSION = "0.8.94" -BUILD_DATE = "2026-05-11" +APP_VERSION = "0.8.95" +BUILD_DATE = "2026-05-12" DB_SCHEMA_VERSION = "20260511053" MODULE_VERSIONS = { - "legal_documents": "1.2.0", # jsPDF-Download auf LegalPage (oeffentlich) + Admin; Abschnitts-Sortierung/-Einfuegen + "legal_documents": "1.3.0", # P-01: Ausgabe §-Nummerierung pro Abschnitt; Markdown im Fließtext + PDF; gem. legalPdfExport "auth": "1.2.3", # P-05b: reset-password min_length=8 via Pydantic PasswordResetConfirm "profiles": "1.7.0", # exercise_list_prefs JSONB (Standard Übungsfilter); Patch via ProfileUpdate + Json() "tenant_context": "1.0.5", # Plattform-Admin: effective_club ohne Header aus Profil active_club_id wenn Verein existiert @@ -34,6 +34,13 @@ MODULE_VERSIONS = { } CHANGELOG = [ + { + "version": "0.8.95", + "date": "2026-05-12", + "changes": [ + "P-01 Rechtstexte: Abschnitte in der Ausgabe mit fortlaufender §1, §2, … (nur Darstellung/PDF, nicht in der DB); Fließtext mit Markdown (react-markdown) inkl. PDF-Rendering (fett/kursiv, Listen, Links, Codeblöcke).", + ], + }, { "version": "0.8.94", "date": "2026-05-11", diff --git a/frontend/package.json b/frontend/package.json index eb10a77..9ad335a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,9 +10,12 @@ "dependencies": { "jspdf": "^4.2.1", "lucide-react": "^0.344.0", + "marked": "^18.0.3", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-router-dom": "^6.22.0" + "react-markdown": "^10.1.0", + "react-router-dom": "^6.22.0", + "remark-breaks": "^4.0.0" }, "devDependencies": { "@vitejs/plugin-react": "^4.2.1", diff --git a/frontend/src/app.css b/frontend/src/app.css index 4d1c5f8..1b9c9f1 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -291,6 +291,83 @@ ul > li.card + li.card, margin-top: 2px; } +/* Rechtstexte (P-01): Markdown im Fließtext */ +.legal-doc-body { + font-size: 0.95rem; + line-height: 1.55; + color: var(--text1); +} +.legal-doc-body--muted { + color: var(--text3); + font-style: italic; +} +.legal-doc-body p { + margin: 0 0 0.65em; +} +.legal-doc-body p:last-child { + margin-bottom: 0; +} +.legal-doc-body ul, +.legal-doc-body ol { + margin: 0.4em 0 0.65em 1.25rem; + padding: 0; +} +.legal-doc-body li { + margin: 0.2em 0; +} +.legal-doc-body strong { + font-weight: 700; +} +.legal-doc-body em { + font-style: italic; +} +.legal-doc-body code { + font-family: ui-monospace, monospace; + font-size: 0.88em; + background: var(--surface2); + padding: 0.1em 0.35em; + border-radius: 4px; +} +.legal-doc-body pre { + background: var(--surface2); + padding: 10px 12px; + border-radius: 8px; + overflow-x: auto; + margin: 0.65em 0; + font-size: 0.85em; +} +.legal-doc-body pre code { + background: none; + padding: 0; +} +.legal-doc-body blockquote { + margin: 0.5em 0; + padding-left: 12px; + border-left: 3px solid var(--border2); + color: var(--text2); +} +.legal-doc-body a { + color: var(--accent); +} +.legal-doc-body h1, +.legal-doc-body h2, +.legal-doc-body h3, +.legal-doc-body h4 { + font-size: 1em; + font-weight: 700; + margin: 0.75em 0 0.35em; +} +.legal-doc-body h1:first-child, +.legal-doc-body h2:first-child, +.legal-doc-body h3:first-child { + margin-top: 0; +} +.legal-doc-body hr { + border: none; + border-top: 1px solid var(--border); + margin: 0.85em 0; +} + .form-input { width: 100%; min-width: 0; diff --git a/frontend/src/components/LegalDocumentBody.jsx b/frontend/src/components/LegalDocumentBody.jsx new file mode 100644 index 0000000..8838d3d --- /dev/null +++ b/frontend/src/components/LegalDocumentBody.jsx @@ -0,0 +1,25 @@ +import ReactMarkdown from 'react-markdown' +import remarkBreaks from 'remark-breaks' + +/** + * Rechtstext-Absatz aus Markdown (ohne Roht-HTML; Links mit target=_blank). + */ +export default function LegalDocumentBody({ content, muted }) { + if (content == null || content === '') return null + return ( +