Fügt Markdown-Formatierungs-Unterstützung zu osTicket 1.18.x Ticket-Threads hinzu mit benutzerfreundlicher Editor-Oberfläche, Live-Vorschau und automatischer Format-Erkennung.
Ohne dieses Plugin: Ticket-Antworten können nur als Plain-Text oder über den WYSIWYG-HTML-Editor formatiert werden. Technische Inhalte wie Code-Snippets oder strukturierte Dokumentation sind umständlich zu erstellen.
Mit diesem Plugin: Markdown-Syntax wird direkt im Editor unterstützt - mit Live-Vorschau, Toolbar-Buttons und Tastatur-Shortcuts. Code-Blöcke, Listen und Links sind in Sekunden formatiert.
Technische Support-Teams:
Markdown für Code-Blöcke und strukturierte Dokumentation verwenden - ideal für Software-Support, DevOps und IT-Teams.
API-Integrationen:
Tickets per API mit Markdown-Inhalten erstellen. Auto-Erkennung erkennt Markdown-Syntax auch ohne expliziten format-Parameter.
Interne Notizen:
Schnelle Formatierung für interne Staff-Notizen ohne WYSIWYG-Komplexität - Listen, Code-Snippets und Links in Sekunden.
Copy-Paste von GitHub/GitLab:
Markdown-Inhalte aus Issue-Trackern lassen sich nahtlos in osTicket-Tickets einfügen und werden korrekt gerendert.
Screenshots und Bilder:
Screenshots direkt aus der Zwischenablage oder per Drag & Drop in Ticket-Antworten einfügen - ideal für Bug-Reports und technische Dokumentation.
Textbausteine im Markdown-Format:
Bestehende HTML-Textbausteine (Canned Responses) werden beim Einfügen automatisch in sauberes Markdown umgewandelt - kein manuelles Nachformatieren nötig.
Gemischte Teams:
Der Format-Umschalter erlaubt jedem Agent, sein bevorzugtes Format zu wählen - Markdown, HTML oder Plain-Text pro Antwort.
| Anforderung | Version | Hinweise |
|---|---|---|
| osTicket | 1.18.x | Plugin erweitert ThreadEntryBody-Klasse |
| PHP | 7.4+ | Empfohlen: PHP 8.1+ für beste Performance |
| jQuery | Beliebig | In osTicket standardmäßig enthalten |
| Parsedown | 1.7.4 | Im Plugin enthalten (vendor/) |
markdown-support-Ordner nach /include/plugins/ auf deinem osTicket-Server hochFinaler Pfad: /pfad/zu/osticket/include/plugins/markdown-support/
cd /pfad/zu/osticket/include/plugins
git clone https://github.com/markus-michalski/osticket-markdown-support.git markdown-support
Das Plugin konfiguriert automatisch den Static-Asset-Zugriff (.htaccess-Update) und erstellt Backups von gepatchten Core-Dateien.
Tipp: Das Plugin erstellt automatisch ein Backup der gepatchten Core-Datei. Bei Deaktivierung wird das Original wiederhergestellt.
| Einstellung | Beschreibung | Standard | Wann ändern |
|---|---|---|---|
| Markdown-Unterstützung aktivieren | Plugin global aktivieren/deaktivieren | An | Zum temporären Deaktivieren |
| Standard Thread-Entry-Format | Standard-Format für neue Einträge | Markdown | Wenn HTML oder Text bevorzugt |
| Format-Wechsel erlauben | Nutzer können zwischen Formaten wechseln | An | Wenn Format fixiert sein soll |
| Markdown-Syntax auto-konvertieren | Automatisch Markdown-Muster erkennen | Aus | Bei API-Tickets ohne format-Parameter |
| Live-Vorschau anzeigen | Echtzeit-Vorschau-Bereich anzeigen | An | Bei Performance-Problemen deaktivieren |
| Markdown-Toolbar anzeigen | Formatierungs-Buttons anzeigen | An | Wenn Agents Markdown-Experten sind |
"Markdown-Syntax auto-konvertieren" funktioniert nur, wenn "Markdown-Unterstützung aktivieren" ebenfalls aktiv ist.
Für technische Teams:
Standard-Format: Markdown, Format-Wechsel: An, Auto-Konvertierung: Aus, Vorschau: An, Toolbar: An
Für API-lastige Workflows:
Standard-Format: Markdown, Auto-Konvertierung: An (wenn API kein format-Feld sendet)
Für gemischte Teams (Markdown + HTML):
Standard-Format: HTML, Format-Wechsel: An, Toolbar: An
| Button | Markdown | Shortcut | Beschreibung |
|---|---|---|---|
| B | **text** |
Strg+B | Text fett |
| I | *text* |
Strg+I | Text kursiv |
| H | ## text |
Strg+H | Überschrift (wechselt H1-H6) |
| Link | [text](url) |
Strg+K | Link einfügen |
<> |
`code` |
- | Inline-Code |
{ } |
```lang |
- | Code-Block |
| Liste | - item |
- | Unsortierte Liste |
| 1. | 1. item |
- | Sortierte Liste |
| Zitat | > quote |
- | Blockzitat |
| Linie | --- |
- | Horizontale Linie |
| Bild |  |
- | Bild hochladen und einfügen |
Bilder können auf drei Wegen direkt in den Markdown-Editor eingefügt werden:
| Methode | Beschreibung |
|---|---|
| Drag & Drop | Bilddatei aus dem Dateimanager in den Editor ziehen |
| Zwischenablage | Screenshot mit Strg+V direkt einfügen |
| Toolbar-Button | Bild-Icon in der Toolbar klicken - öffnet nativen Datei-Dialog |
Das Plugin lädt das Bild über osTickets Draft-Attachment-API hoch und fügt automatisch die Markdown-Bildsyntax  an der Cursorposition ein.
Unterstützte Bildformate: JPEG, PNG, GIF, WebP, BMP. SVG wird aus Sicherheitsgründen blockiert.
Während des Uploads wird ein Platzhalter
![Uploading image-1...]()angezeigt. Mehrere Bilder können parallel hochgeladen werden.
Das Plugin integriert sich nahtlos mit osTickets Textbaustein-System (Canned Responses). Beim Einfügen eines Textbausteins wird der HTML-Inhalt automatisch in sauberes Markdown konvertiert, sofern der Markdown-Modus aktiv ist.
Unterstützte Konvertierungen:
| HTML-Element | Markdown-Ergebnis |
|---|---|
<h1> bis <h6> |
# bis ###### |
<strong>, <b> |
**fett** |
<em>, <i> |
*kursiv* |
<a href="..."> |
[Text](URL) |
<img> |
 |
<blockquote> |
> Zitat |
<ul>, <ol> |
- Item / 1. Item |
<pre><code> |
Code-Block mit Backticks |
<code> |
`Inline-Code` |
<hr> |
--- |
So funktioniert es:
Die Konvertierung erfolgt komplett clientseitig - keine zusätzlichen Server-Requests nötig. Bestehende HTML-Textbausteine müssen nicht angepasst werden.
"Originalnachricht" und "Letzte Nachricht" werden ebenfalls korrekt konvertiert -
<blockquote>wird zu Markdown-Zitaten (> ...).
Der Live-Vorschau-Bereich zeigt Echtzeit-Rendering des Markdown-Inhalts über einen Server-seitigen API-Endpoint. Aktualisiert automatisch mit 500ms Debouncing.
# Überschrift 1
## Überschrift 2
### Überschrift 3
**Fetter Text**
*Kursiver Text*
~~Durchgestrichen~~
`Inline-Code`
- Unsortierte Liste
- Element 2
- Unterelement
1. Sortierte Liste
2. Element 2
```php
<?php
echo "Hallo Welt!";
?>
```
| Spalte 1 | Spalte 2 |
|----------|----------|
| Wert 1 | Wert 2 |

Beim Erstellen von Tickets über die osTicket API das format-Feld verwenden:
POST /api/tickets.json
{
"name": "Max Mustermann",
"email": "max@example.com",
"subject": "Ticket mit Markdown",
"message": "## Problem\n\nDer Server antwortet **nicht**.\n\n```bash\nping server.example.com\n```",
"format": "markdown"
}
Falls die API-Integration kein format-Feld sendet, aber Markdown-Syntax enthält:
Das Plugin nutzt gewichtetes Pattern-Matching:
| Pattern | Punkte | Beispiel |
|---|---|---|
| Code-Blöcke | 20 | ```code``` |
| Überschriften | 15 | # Titel |
| Links | 15 | [Text](url) |
| Listen | 12 | - Item |
| Fett/Kursiv | 10/8 | **fett**, *kursiv* |
| Inline-Code | 5 | `code` |
Schwellenwert: 5 Punkte (bewusst niedrig für minimale false-negatives)
| Format-Wert | Beschreibung |
|---|---|
text |
Plain-Text (keine Formatierung) |
html |
HTML-WYSIWYG-Editor |
markdown |
Markdown-Editor mit Live-Vorschau |
Das Plugin nutzt zwei osTicket Signals und Output-Buffer-Injection:
| Signal / Mechanismus | Handler | Zweck |
|---|---|---|
object.view |
AssetInjector |
CSS/JS Assets in Seite injizieren |
threadentry.created |
ThreadEntryHandler |
Format-Erkennung und Auto-Konvertierung |
ob_start() Callback |
AssetInjector |
CSS vor </head>, JS vor </body> injizieren |
enable() Override |
CorePatcher |
ThreadEntryBody per Reflection erweitern, Core-Datei patchen |
disable() Override |
CorePatcher |
Backup der Core-Datei wiederherstellen |
Symptome:
Prüfung:
Lösung:
chmod 755 /pfad/zu/osticket/include/plugins/markdown-support
chmod 644 /pfad/zu/osticket/include/plugins/markdown-support/*.php
Symptome:
Prüfung:
/include/.htaccess prüfenLösung:
Plugin erneut aktivieren (Deaktivieren -> Aktivieren). Das Plugin aktualisiert /include/.htaccess automatisch:
<FilesMatch "\.(js|css|map|json|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|otf)$">
Require all granted
Allow from all
</FilesMatch>
NGINX-Nutzer müssen die Konfiguration manuell anpassen - siehe Technische Details.
Symptome:
Prüfung:
tail -f /pfad/zu/osticket/include/ost-errors.logvendor/erusev/parsedown/Parsedown.php existiert?Lösung:
Parsedown.php not found -> Plugin erneut von Releases herunterladenThreadEntryBody class not found -> osTicket 1.18.x erforderlichReflectionClass not found -> PHP-Reflection-Extension fehltSymptome:
![Uploading image-1...]() bleibt stehenPrüfung:
upload_max_filesize und post_max_size prüfenLösung:
Symptome:
<p>, <strong>, <blockquote> Tags sind sichtbarPrüfung:
markdown-editor.js Version aktuell? (Network-Tab prüfen)Lösung:
Symptome:
Prüfung:
markdown-editor.js lädt mit 200 OK?typeof jQuery in KonsoleLösung:
Seite hart neu laden (Strg+Umschalt+R). Das Plugin nutzt MutationObserver für dynamisch geladene Textareas.
Symptome:
Prüfung:
Plugin-Konfiguration: "Format-Wechsel erlauben" und "Markdown-Unterstützung aktivieren" müssen beide An sein.
Lösung:
Admin Panel -> Plugins -> Markdown Support -> Konfigurieren -> beide Optionen aktivieren.
markdown-support/
+-- plugin.php # Plugin-Metadaten
+-- class.MarkdownPlugin.php # Haupt-Plugin-Klasse
+-- config.php # Admin-Konfiguration
+-- markdown-body.php # MarkdownThreadEntryBody-Klasse
+-- markdown-preview.php # API-Endpoint für Live-Preview
+-- MarkdownDetector.php # Markdown-Syntax-Erkennung
+-- TicketFormatHandler.php # Format-Bestimmung
+-- composer.json # Abhängigkeiten
+-- phpunit.xml.dist # PHPUnit-Konfiguration
+--
+-- src/ # Service-Klassen (v2.0 Refactoring)
| +-- Config/
| | +-- ConfigCache.php # Singleton für Konfiguration
| +-- Core/
| | +-- CorePatcher.php # Reflection + Core-File-Patching
| +-- Signal/
| | +-- ThreadEntryHandler.php # Signal-Handler für Einträge
| +-- Asset/
| | +-- AssetInjector.php # CSS/JS Output-Buffer-Injection
| | +-- AssetDeployer.php # Asset-Deployment + .htaccess
| +-- Format/
| +-- MarkdownSanitizer.php # Unified XSS-Prevention
| +-- MarkdownDetectorInterface.php
| +-- FormatHandlerInterface.php
+--
+-- css/
| +-- markdown-editor.css # Editor-Styling (~840 Zeilen)
+-- js/
| +-- markdown-editor.js # Editor JavaScript (~2200 Zeilen)
+-- vendor/
| +-- erusev/parsedown/Parsedown.php # Markdown-Parser (1.7.4)
+-- tests/
| +-- Unit/ # 77 Unit-Tests
| +-- Integration/ # 24 Integration-Tests
+-- i18n/
+-- de_DE/ # Deutsche Übersetzung
Die HTML-zu-Markdown-Konvertierung erfolgt clientseitig im Browser. Der eingebaute Konverter verarbeitet HTML-Elemente rekursiv über das DOM und erzeugt sauberes Markdown ohne externe Abhängigkeiten.
Technische Details der Konvertierung:
document.createElement('div') als sicheren DOM-Parserdocument.createElement('textarea') sicher dekodiertDas v2.0 Refactoring hat die monolithische Plugin-Klasse in dedizierte Services aufgeteilt:
| Service | Aufgabe |
|---|---|
| ConfigCache | Singleton - cached Plugin-Config statisch (löst osTicket-Problem: Signal-Callbacks erhalten neue Plugin-Instanzen ohne Config) |
| CorePatcher | Erweitert ThreadEntryBody::$types per Reflection, patcht class.thread.php für Markdown-Support |
| AssetInjector | Output-Buffer-Injection: CSS vor </head>, JS deferred vor </body> |
| AssetDeployer | .htaccess-Update, markdown-preview.php nach /api/ kopieren |
| ThreadEntryHandler | Signal-Handler: Format-Erkennung, Newline-Restoration, DB-Update |
| MarkdownSanitizer | Unified XSS-Prevention (javascript: URLs, data: URIs, Event-Handler) |
Das Plugin erweitert osTickets ThreadEntryBody-Klasse via PHP Reflection:
// CorePatcher::extendThreadEntryTypes()
$reflection = new ReflectionClass('ThreadEntryBody');
$property = $reflection->getProperty('formats');
$property->setAccessible(true);
$formats = $property->getValue(null);
$formats['markdown'] = 'Markdown';
$property->setValue(null, $formats);
Zusätzlich wird class.thread.php gepatcht, um MarkdownThreadEntryBody als Format-Handler zu registrieren. Ein Backup wird mit .markdown-backup Suffix erstellt und bei Deaktivierung automatisch wiederhergestellt.
Layer 1 - Parsedown SafeMode:
Escaped Inline-HTML in Markdown. <script>, <iframe>, <object> werden blockiert.
Layer 2 - MarkdownSanitizer:
Entfernt javascript: URLs, data: URIs, on* Event-Handler, IE expression() CSS.
Layer 3 - Format::sanitize:
osTickets Standard-XSS-Filter mit Whitelist-basierter HTML-Tag-Filterung.
Bild-Upload-Sicherheit (v2.1):
| Schutzmaßnahme | Beschreibung |
|---|---|
| MIME-Type-Whitelist | Nur JPEG, PNG, GIF, WebP, BMP - SVG blockiert (XSS-Vektor) |
| URL-Validierung | Server-URLs werden gegen javascript: und unbekannte Schemata geprüft |
| Alt-Text-Sanitierung | Dateinamen werden von Markdown-Sonderzeichen []() bereinigt |
| CSRF-Token-Prüfung | Upload wird abgebrochen, wenn kein gültiger Token vorhanden |
| Error-Response-Bereinigung | HTML wird aus Fehlermeldungen gestrippt, Länge auf 200 Zeichen begrenzt |
Getestete XSS-Vektoren:
<script> Tags<img src=x onerror=alert(1)>[Link](javascript:alert(1))java%09script:)data:text/html;base64,...)Apache wird automatisch konfiguriert. Für NGINX manuell hinzufügen:
location ~* ^/include/plugins/markdown-support/(css|js)/.*\.(css|js|map)$ {
allow all;
access_log off;
expires 30d;
}
101 Tests, 296 Assertions (PHPUnit 9.6):
| Kategorie | Tests | Fokus |
|---|---|---|
| Security | 20 | XSS-Prevention (kritisch) |
| Unit | 57 | Rendering, Edge Cases, Config |
| Integration | 24 | Plugin-Lifecycle, Signals, Assets |
composer test # Tests ausführen
F: Funktioniert Markdown im Client-Portal?
A: Markdown-formatierte Ticket-Antworten werden korrekt im Client-Portal gerendert. Clients können jedoch nicht im Markdown-Format schreiben (nur Staff).
F: Kann ich Markdown als Standard-Format setzen?
A: Ja, in der Plugin-Konfiguration: "Standard Thread-Entry-Format" auf Markdown setzen.
F: Was passiert, wenn ich das Plugin deaktiviere?
A: Bestehende Markdown-formatierte Einträge werden als roher Markdown-Text angezeigt. Keine Daten gehen verloren - bei erneutem Aktivieren werden sie wieder korrekt gerendert. Die gepatchte Core-Datei wird aus dem Backup wiederhergestellt.
F: Kann ich Markdown und HTML im gleichen Ticket mischen?
A: Ja, jede Ticket-Antwort kann ihr eigenes Format haben. Der Format-Umschalter erlaubt den Wechsel pro Eintrag.
F: Muss ich meine Textbausteine für Markdown umschreiben?
A: Nein. Bestehende HTML-Textbausteine werden beim Einfügen automatisch in Markdown konvertiert. Die Originale bleiben unverändert in der Datenbank.
F: Was passiert mit Textbaustein-Anhängen?
A: Anhänge werden in beiden Modi (Markdown und HTML) korrekt verarbeitet und dem Ticket-Entwurf zugeordnet.
F: Funktioniert die Konvertierung auch für "Originalnachricht" und "Letzte Nachricht"?
A: Ja. Diese osTicket-Optionen liefern HTML mit <blockquote>-Tags, die korrekt in Markdown-Blockzitate (> ...) konvertiert werden.
F: Kann ich die automatische Konvertierung deaktivieren?
A: Die Konvertierung ist an den Editor-Modus gekoppelt. Wenn du den HTML-Modus (Redactor) verwendest, bleibt das Standard-Verhalten erhalten - keine Konvertierung.
F: Welche Bildformate werden unterstützt?
A: JPEG, PNG, GIF, WebP und BMP. SVG wird aus Sicherheitsgründen (XSS-Vektor) blockiert.
F: Wo werden die hochgeladenen Bilder gespeichert?
A: Die Bilder werden über osTickets Draft-Attachment-System gespeichert - gleicher Mechanismus wie im HTML-Editor. Sie werden dem Ticket-Draft zugeordnet und beim Absenden der Antwort automatisch verknüpft.
F: Kann ich mehrere Bilder gleichzeitig hochladen?
A: Ja, beim Drag & Drop und über den Datei-Dialog können mehrere Bilder gleichzeitig ausgewählt werden. Jedes Bild erhält einen eigenen Upload-Indikator.
F: Was passiert mit dem Bild, wenn ich die Antwort verwerfe?
A: Das Bild bleibt als Draft-Attachment gespeichert. osTicket bereinigt verwaiste Draft-Attachments automatisch.
F: Unterstützt das Plugin GitHub-Flavored Markdown (GFM)?
A: Teilweise. Parsedown unterstützt Fenced Code Blocks, Tabellen und Autolinks. Task-Listen (- [ ]) und Emoji-Shortcuts (:smile:) werden nicht unterstützt.
F: Kann ich HTML innerhalb von Markdown verwenden?
A: Nein, aus Sicherheitsgründen. Parsedown läuft im SafeMode, der Inline-HTML blockiert. Für HTML den HTML-Format-Editor nutzen.
F: Ist Syntax-Highlighting für Code-Blöcke verfügbar?
A: Nicht standardmäßig. Parsedown generiert <pre><code> Blöcke ohne Highlighting. Eine externe Library wie Prism.js oder Highlight.js kann hinzugefügt werden.
F: Funktioniert das mit osTicket 1.17 oder älter?
A: Nein. Das Plugin benötigt osTicket 1.18.x für die ThreadEntryBody-Klassen-Struktur.
F: Ist es kompatibel mit dem API Endpoints Plugin?
A: Ja. Die Plugins arbeiten nahtlos zusammen. format=markdown in API-Requests wird korrekt verarbeitet.
F: Ist es kompatibel mit PHP 8.x?
A: Ja. Das Plugin ist mit PHP 7.4, 8.0, 8.1, 8.2 und 8.3 getestet. Die CI-Pipeline testet alle Versionen.
F: Beeinträchtigt das Plugin die Lade-Performance?
A: Minimal. Markdown-Parsing ist sehr schnell (~1-2ms pro Eintrag). Kein Rendering-Cache nötig, da Parsedown schnell genug ist.
F: Wie groß können Markdown-Einträge sein?
A: Parsedown hat keine Größenbeschränkung. osTickets DB-Limit für ost_thread_entry.body ist MEDIUMTEXT (16 MB).
Dieses Plugin wird unter der GNU General Public License v2 veröffentlicht, kompatibel mit osTicket Core.
Details siehe LICENSE.
Für Fragen oder Probleme erstelle bitte ein Issue auf GitHub:
Issue Tracker: https://github.com/markus-michalski/osticket-markdown-support/issues
Beim Melden von Problemen bitte angeben:
php -v)Entwickelt von Markus Michalski
Beiträge willkommen!
Siehe CHANGELOG.md für Versionshistorie.