# Kernkonzepte ## Projektübersicht Sphinx-basiertes Dokumentationssystem für Transport- und Hängefördersysteme. JSON-gesteuerter Build erzeugt aus modularen Textbausteinen mehrsprachige PDF-Dokumentationen (250+ Seiten). Zwei-Repo-Architektur: allgemeine Ressourcen (Base-Repo) + projektspezifische Anpassungen (Projekt-Repo). Auftraggeber: Firma Schönenberger Umsetzung: Mista GmbH ## Architektur ### Zwei-Repo-Trennung - **transport-docs-base** (Gitea): Alle wiederverwendbaren Inhalte – Module, Kapitelgerüste, Assets, Glossar, Sphinx-Extensions, LaTeX-Templates, Hilfsskripte. Semver-versioniert (VERSION-Datei). - **projekt-kunde-xyz** (pro Anlage): anlage.json (ERP-Export), projektspezifische Bilder, Overrides, Zusatzkapitel, conf.py, build.py. Das Base-Repo wird beim Build als Mount/Share unter `transport-docs-base/` bereitgestellt. ### Technologie-Stack | Komponente | Technologie | |------------------|--------------------------------------------------| | Build-System | Sphinx (Python) | | Textformat | reStructuredText (rST) | | Templating | Jinja2 (Rahmenkapitel, Titelseite) | | PDF-Erzeugung | LaTeX (pdflatex/lualatex) | | Versionierung | Git (Gitea auf Hetzner) | | Konfiguration | JSON (ERP-Export) + YAML (Modul-Metadaten) | | CI/Automatisierung | Gitea Actions oder n8n | | Bildkonvertierung | ezdxf → SVG, Pillow (Optimierung) | ## Repo-Struktur ### Base-Repo: transport-docs-base ``` transport-docs-base/ ├── conf_base.py # Sphinx-Basiskonfiguration (wird importiert) ├── VERSION # Semver der Dokumentationsbasis ├── _ext/ │ ├── anlagen_builder.py # Hauptextension: JSON → Buchstruktur │ ├── localized_figure.py # Sprachauflösung für Bilder │ └── glossary_loader.py # CSV → Glossar-Direktive ├── _templates/ │ ├── latex/ │ │ ├── preamble.tex # Firmen-CI: Fonts, Farben, Kopfzeilen │ │ ├── titlepage.tex # Titelseite-Template (Jinja2) │ │ └── maketitle.tex │ └── common/ │ └── header_footer.rst ├── assets/ │ ├── shared/ # Sprachneutrale Bilder (~90%) │ │ ├── photos/ │ │ │ ├── weiche_typ_a_foto_01.jpg │ │ │ ├── hubstation_foto_01.jpg │ │ │ └── antrieb_sew_foto_01.jpg │ │ ├── drawings/ # Technische Zeichnungen (DXF → SVG/PDF) │ │ │ ├── weiche_typ_a_layout.svg │ │ │ └── hubstation_schnitt.pdf │ │ ├── symbols/ # ISO 7010 Sicherheitssymbole │ │ │ ├── W001_warnung.svg │ │ │ └── M004_augenschutz.svg │ │ └── diagrams/ # Schaltpläne, Pneumatik │ │ └── stromlaufplan_weiche_a.pdf │ └── localized/ # Sprachspezifische Bilder │ ├── de/ │ │ ├── screenshots/ │ │ │ └── hmi_hauptmenu.png │ │ └── diagramme/ │ │ └── risikograph_weiche_a.svg │ ├── en/ │ │ ├── screenshots/ │ │ │ └── hmi_hauptmenu.png │ │ └── diagramme/ │ │ └── risikograph_weiche_a.svg │ └── fr/ │ └── ... ├── modules/ # Textbausteine pro Maschinentyp │ ├── weiche_typ_a/ │ │ ├── meta.yaml # Abhängigkeiten + Kapitelzuordnung │ │ ├── beschreibung.de.rst │ │ ├── beschreibung.en.rst │ │ ├── risikomatrix.de.rst │ │ ├── risikomatrix.en.rst │ │ ├── wartung.de.rst │ │ └── images/ │ │ └── montage_detail_01.jpg │ ├── hubstation/ │ │ ├── meta.yaml │ │ ├── beschreibung.de.rst │ │ ├── technische_daten.de.rst │ │ ├── wartung.de.rst │ │ └── images/ │ │ └── hubmechanik_detail.jpg │ ├── antrieb_sew/ │ │ ├── meta.yaml │ │ └── ... │ └── steuerung_siemens_s7/ │ ├── meta.yaml │ └── ... ├── chapters/ # Rahmenkapitel (Gerüst) │ ├── 01_einleitung/ │ │ ├── template.de.rst # Jinja2-Template mit Platzhaltern │ │ └── template.en.rst │ ├── 02_sicherheit/ │ │ ├── allgemein.de.rst # Immer dabei │ │ ├── allgemein.en.rst │ │ ├── normen_ce.de.rst # EU-Konformität │ │ └── normen_ukca.en.rst # UK-spezifisch │ ├── 03_anlagenbeschreibung/ │ │ └── template.de.rst # Hier werden Module eingefügt │ ├── 04_betrieb/ │ │ └── template.de.rst │ ├── 05_wartung/ │ │ ├── allgemein.de.rst │ │ └── schmierplan_template.de.rst │ ├── 06_ersatzteile/ │ │ └── template.de.rst │ └── 07_anhang/ │ └── template.de.rst ├── glossary/ │ ├── terms.de.csv # "Begriff;Definition;Kategorie" │ ├── terms.en.csv │ └── terms.fr.csv ├── styles/ │ ├── firma_logo.pdf │ ├── firma_logo_sw.pdf │ └── color_scheme.yaml # CI-Farben für LaTeX und SVG ├── scripts/ │ ├── dxf2svg.py # DXF → SVG Konvertierung │ ├── optimize_images.py # Bildoptimierung vor Commit │ └── validate_modules.py # Prüft meta.yaml Konsistenz ``` ### Projekt-Repo: projekt-kunde-xyz ``` projekt-kunde-xyz-2026/ ├── conf.py # Importiert conf_base.py vom Base-Repo ├── anlage.json # ERP-Export: Maschinenauswahl + Metadaten ├── build.py # Hauptbuild-Skript ├── Makefile ├── README.md ├── images/ # Projektspezifische Bilder │ ├── aufstellplan_halle3.pdf │ ├── foto_abnahme_01.jpg │ └── kundenlogo.pdf ├── overrides/ # Projektspezifische Überschreibungen │ ├── modules/ │ │ └── weiche_typ_a/ │ │ └── beschreibung.de.rst # Überschreibt Basis wenn vorhanden │ └── chapters/ │ └── 01_einleitung/ │ └── template.de.rst # Kundenspezifische Einleitung ├── additional/ # Kapitel die NUR dieses Projekt hat │ ├── sonderausfuehrung_xyz.de.rst │ └── sonderausfuehrung_xyz.en.rst └── transport-docs-base/ ──────────── # Symlink/Mount zum Base-Repo (Share) ``` ### anlage.json (ERP-Export) Steuert die Zusammenstellung. Enthält Projektmetadaten, Zielsprachen, Normenregion, Liste verbauter Maschinen und Referenzen auf Zusatzkapitel. **Beispiel:** ```json { "projekt": { "nummer": "P-2026-0042", "kunde": "Müller Automotive GmbH", "kunde_logo": "images/kundenlogo.pdf", "standort": "Werk Ingolstadt, Halle 3", "sprachen": ["de", "en"], "normen_region": "EU", "base_version": ">=1.0.0" }, "maschinen": [ { "modul": "weiche_typ_a", "anzahl": 4, "positionen": ["W01", "W02", "W03", "W04"], "variante": "standard" }, { "modul": "hubstation", "anzahl": 2, "positionen": ["H01", "H02"], "variante": "schwerlast", "optionen": ["hydraulisch"] }, { "modul": "antrieb_sew", "anzahl": 12, "positionen": ["A01-A12"] }, { "modul": "steuerung_siemens_s7", "anzahl": 1, "positionen": ["SPS01"], "optionen": ["profinet", "hmi_tp700"] } ], "zusatz_kapitel": [ "additional/sonderausfuehrung_xyz" ] } ``` ### meta.yaml (Modul-Metadaten) Pro Maschinentyp-Modul. Definiert Bezeichner, mehrsprachigen Namen, Kapitelzuordnung, Bildreferenzen und Abhängigkeiten. **Beispiel** (`modules/weiche_typ_a/meta.yaml`): ```yaml module: weiche_typ_a display_name: de: "Weiche Typ A" en: "Switch Type A" chapters: - 02_sicherheit: sections: [risikomatrix] - 03_anlagenbeschreibung: sections: [beschreibung, technische_daten] - 05_wartung: sections: [wartung, schmierplan] images: shared: - photos/weiche_typ_a_foto_01.jpg - drawings/weiche_typ_a_layout.svg - diagrams/stromlaufplan_weiche_a.pdf localized: - diagramme/risikograph_weiche_a.svg - screenshots/hmi_hauptmenu.png module_local: - montage_detail_01.jpg requires: - antrieb_sew ``` ### conf.py (Projekt-Konfiguration) Importiert die Basiskonfiguration vom gemounteten Base-Repo und setzt projektspezifische Overrides. **Beispiel** (`projekt-kunde-xyz-2026/conf.py`): ```python import sys import os from pathlib import Path # ══ Pfad zum Base-Repo (Share/Mount) ══ BASE_DOCS = Path(os.environ.get( "DOCS_BASE_PATH", Path(__file__).parent / "transport-docs-base" )) # Extensions und Basiskonfiguration importieren sys.path.insert(0, str(BASE_DOCS / "_ext")) sys.path.insert(0, str(BASE_DOCS)) from conf_base import * # noqa: F401, F403 # ══ Projektspezifische Overrides ══ project = "Anlagendokumentation P-2026-0042" release = "1.0" author = "Mista GmbH" copyright = "2026, Mista GmbH" # Bildpfade: Projekt → Overrides → Base (Reihenfolge = Priorität) image_search_path = [ "images", # Projektbilder "overrides", # Überschreibungen str(BASE_DOCS / "assets" / "shared"), # Sprachneutrale Basis str(BASE_DOCS / "assets" / "localized"), # Sprachspezifische Basis str(BASE_DOCS / "modules"), # Modulbilder ] # Sphinx-Extensions aus Base-Repo laden extensions += [ "anlagen_builder", "localized_figure", "glossary_loader", ] # Glossar-Pfad glossary_csv_path = str(BASE_DOCS / "glossary") # LaTeX-Templates aus Base-Repo templates_path.insert(0, str(BASE_DOCS / "_templates")) # LaTeX-spezifisch latex_elements = { "preamble": open(BASE_DOCS / "_templates" / "latex" / "preamble.tex").read(), "maketitle": open(BASE_DOCS / "_templates" / "latex" / "maketitle.tex").read(), "papersize": "a4paper", "pointsize": "11pt", } ``` ### Override-Mechanismus Suchreihenfolge beim Build: 1. `projekt/overrides/` (projektspezifisch) 2. `transport-docs-base/modules/` bzw. `chapters/` (allgemein) Ermöglicht kundenspezifische Anpassungen ohne Base-Repo-Änderung. ### Versionskontrolle Base-Repo hat Semver in `VERSION`. Projekt-Repo kann `"base_version": ">=2.1.0"` in anlage.json setzen. build.py prüft Kompatibilität vor dem Build. ## Mehrsprachigkeit ### Drei Ebenen 1. **Textbausteine**: Dateinamenskonvention `{name}.{lang}.rst`. Fallback auf `de` bei fehlender Übersetzung. 2. **Bilder**: `localized-figure`-Direktive löst `assets/localized/{lang}/pfad/bild.png` auf. Fallback auf `de`. Optional: Jinja2-SVG-Templates für Diagramme mit Text. 3. **Glossar**: CSV pro Sprache (`terms.{lang}.csv`), `glossary_loader.py` erzeugt Sphinx-Glossardirektiven. Im Text via `:term:`Fachbegriff`` verlinkt. ### Sprachspezifische Normen Gesteuert über `normen_region` in anlage.json. Kapitel 02_sicherheit enthält z.B. `normen_ce.de.rst` (EU) und `normen_ukca.en.rst` (UK), Build wählt nach Region. ## Bildverwaltung | Kategorie | Pfad | Beispiele | |------------------|-----------------------------------|----------------------------------------------| | Sprachneutral | `assets/shared/{typ}/` | Fotos, DXF/SVG-Zeichnungen, ISO-Symbole | | Sprachspezifisch | `assets/localized/{lang}/{typ}/` | HMI-Screenshots, Risikographen, Typenschilder| | Modulspezifisch | `modules/{modul}/images/` | Montagedetails | | Projektspezifisch| `projekt/images/` | Aufstellpläne, Abnahmefotos, Kundenlogo | Formate: SVG/PDF für Zeichnungen (vektoriell), JPG für Fotos (max 2000px, 85% Qualität). ## Build-Prozess ``` anlage.json ──→ build.py │ ├─ Phase 1: Konfiguration einlesen, Versionscheck ├─ Phase 2: Abhängigkeiten auflösen (meta.yaml, transitiv) │ Overrides anwenden (Projekt > Base) │ Fehlende Module/Bilder/Übersetzungen melden ├─ Phase 3: Sphinx-Quellen generieren (index.rst, toctrees) │ Glossar aus CSV erzeugen │ Jinja2-Templates mit Projektdaten füllen └─ Phase 4: sphinx-build -b latex → pdflatex → PDF (pro Sprache) Ausgabe: _output/P-2026-0042_Dokumentation_DE.pdf _output/P-2026-0042_Documentation_EN.pdf ``` ## Sphinx-Extensions (zu implementieren) ### anlagen_builder.py - Liest anlage.json + meta.yaml aller referenzierten Module - Löst Abhängigkeiten auf (topologisch, transitiv) - Generiert toctree-Einträge pro Kapitel - Wendet Override-Logik an ### localized_figure.py - Neue Direktive `.. localized-figure::` - Löst Bildpfad nach Build-Sprache auf - Fallback: `de` wenn Sprachversion fehlt ### glossary_loader.py - Liest `terms.{lang}.csv` (Semikolon-getrennt) - Erzeugt `.. glossary::` Blöcke - Ermöglicht `:term:` Verlinkung im gesamten Dokument ## Hilfsskripte - `scripts/dxf2svg.py` – DXF → SVG Konvertierung (ezdxf) - `scripts/optimize_images.py` – Bildoptimierung vor Commit (Pillow, max 2000px) - `scripts/validate_modules.py` – Prüft meta.yaml-Konsistenz, fehlende Dateien/Übersetzungen ## Infrastruktur - Hetzner-Server: Gitea (Repos), n8n (CI-Automatisierung), Nextcloud (Dateiablage) - Build-Umgebung: Python 3.11+, Sphinx, LaTeX-Distribution (texlive) - CI: Gitea Actions oder n8n-Webhook → Build → PDF nach Nextcloud ## Umsetzungsphasen | Phase | Beschreibung | Aufwand | |-------|---------------------------------------------------------------|-----------| | 1 | PoC: Ein Modul, ein Kapitel, zwei Sprachen, PDF | 2–3 Tage | | 2 | Base-Repo aufsetzen: Sphinx, Extensions, LaTeX-CI | 3–5 Tage | | 3 | Erste 5–10 Module migrieren, Glossar aufbauen | 1–2 Wochen| | 4 | JSON-Export aus ERP definieren, build.py fertigstellen | 2–3 Tage | | 5 | Pilotprojekt: Erste vollständige Anlagendokumentation | 1 Woche | | 6 | CI/CD: Automatischer Build via Gitea Actions oder n8n | 1–2 Tage | ## Coding-Konventionen - Python: Type Hints, Docstrings, pyright-kompatibel - rST: Eine Datei pro Section, Dateiname = Section-Slug - YAML: 2 Spaces Einrückung, keine Tabs - Commits: Conventional Commits (`feat:`, `fix:`, `docs:`) - Bilder: Dateinamen lowercase, Underscores, beschreibend (`weiche_typ_a_foto_01.jpg`)