Markdown-Formatierung
OpenClaw formatiert ausgehendes Markdown, indem es in eine gemeinsame Zwischendarstellung (IR) umgewandelt wird, bevor kanalspezifische Ausgabe gerendert wird. Die IR hält den Quelltext intakt und trägt dabei Stil-/Link-Spans, sodass Chunking und Rendering kanalübergreifend konsistent bleiben können.Ziele
- Konsistenz: ein Parse-Schritt, mehrere Renderer.
- Sicheres Chunking: Text vor dem Rendern aufteilen, damit Inline-Formatierung nie über Chunks hinweg bricht.
- Passung pro Kanal: dieselbe IR auf Slack mrkdwn, Telegram HTML und Signal- Stilbereiche abbilden, ohne Markdown erneut zu parsen.
Pipeline
- Markdown -> IR parsen
- Die IR ist Klartext plus Stil-Spans (fett/kursiv/durchgestrichen/code/spoiler) und Link-Spans.
- Offsets sind UTF-16-Codeeinheiten, sodass Signal-Stilbereiche mit seiner API übereinstimmen.
- Tabellen werden nur geparst, wenn ein Kanal sich für die Tabellenkonvertierung entscheidet.
- IR chunking (Format zuerst)
- Chunking erfolgt auf dem IR-Text vor dem Rendern.
- Inline-Formatierung wird nicht über Chunks hinweg geteilt; Spans werden pro Chunk zugeschnitten.
- Pro Kanal rendern
- Slack: mrkdwn-Tokens (fett/kursiv/durchgestrichen/code), Links als
<url|label>. - Telegram: HTML-Tags (
<b>,<i>,<s>,<code>,<pre><code>,<a href>). - Signal: Klartext +
text-style-Bereiche; Links werden zulabel (url), wenn sich das Label unterscheidet.
- Slack: mrkdwn-Tokens (fett/kursiv/durchgestrichen/code), Links als
IR-Beispiel
Eingabe-Markdown:Wo es verwendet wird
- Ausgehende Adapter für Slack, Telegram und Signal rendern aus der IR.
- Andere Kanäle (WhatsApp, iMessage, Microsoft Teams, Discord) verwenden weiterhin Klartext oder ihre eigenen Formatierungsregeln; dabei wird die Markdown-Tabellenkonvertierung vor dem Chunking angewendet, wenn sie aktiviert ist.
Tabellenbehandlung
Markdown-Tabellen werden von Chat-Clients nicht konsistent unterstützt. Verwenden Siemarkdown.tables, um die Konvertierung pro Kanal (und pro Konto) zu steuern.
code: Tabellen als Codeblöcke rendern (Standard für die meisten Kanäle).bullets: jede Zeile in Aufzählungspunkte umwandeln (Standard für Signal + WhatsApp).off: Tabellen-Parsing und -Konvertierung deaktivieren; roher Tabellen-Text wird durchgereicht.
Chunking-Regeln
- Chunk-Limits kommen aus Kanaladaptern/-konfiguration und werden auf den IR-Text angewendet.
- Code-Fences werden als einzelner Block mit abschließendem Zeilenumbruch beibehalten, damit Kanäle sie korrekt rendern.
- Listenpräfixe und Blockquote-Präfixe sind Teil des IR-Textes, sodass Chunking nicht mitten in einem Präfix trennt.
- Inline-Stile (fett/kursiv/durchgestrichen/inline-code/spoiler) werden nie über Chunks hinweg geteilt; der Renderer öffnet Stile in jedem Chunk erneut.
Link-Richtlinie
- Slack:
[label](url)-><url|label>; nackte URLs bleiben nackt. Autolink ist beim Parsen deaktiviert, um doppelte Verlinkung zu vermeiden. - Telegram:
[label](url)-><a href="url">label</a>(HTML-Parse-Modus). - Signal:
[label](url)->label (url), sofern das Label nicht der URL entspricht.
Spoiler
Spoiler-Markierungen (||spoiler||) werden nur für Signal geparst, wo sie auf
SPOILER-Stilbereiche abgebildet werden. Andere Kanäle behandeln sie als Klartext.
So fügen Sie einen Kanal-Formatter hinzu oder aktualisieren ihn
- Einmal parsen: Verwenden Sie den gemeinsamen Helper
markdownToIR(...)mit kanalgeeigneten Optionen (Autolink, Überschriftenstil, Blockquote-Präfix). - Rendern: Implementieren Sie einen Renderer mit
renderMarkdownWithMarkers(...)und einer Stil-Marker-Map (oder Signal-Stilbereichen). - Chunking: Rufen Sie
chunkMarkdownIR(...)vor dem Rendern auf; rendern Sie jeden Chunk. - Adapter verdrahten: Aktualisieren Sie den ausgehenden Kanaladapter, damit er den neuen Chunker und Renderer verwendet.
- Testen: Fügen Sie Formatierungstests hinzu oder aktualisieren Sie sie sowie einen Test für die ausgehende Zustellung, wenn der Kanal Chunking verwendet.
Häufige Stolperfallen
- Slack-Winkelklammer-Tokens (
<@U123>,<#C123>,<https://...>) müssen erhalten bleiben; maskieren Sie rohes HTML sicher. - Telegram-HTML erfordert das Escapen von Text außerhalb von Tags, um fehlerhaftes Markup zu vermeiden.
- Signal-Stilbereiche hängen von UTF-16-Offsets ab; verwenden Sie keine Codepoint-Offsets.
- Behalten Sie abschließende Zeilenumbrüche für eingefasste Codeblöcke bei, damit schließende Marker in ihrer eigenen Zeile landen.