Formateo Markdown
Pipeline de formateo Markdown para canales salientes.
OpenClaw formatea Markdown saliente convirtiéndolo a una representación
intermedia compartida (IR) antes de renderizar salida específica del canal. El IR preserva
el texto fuente intacto mientras lleva spans de estilo/enlace, para que el chunking y rendering puedan
mantenerse consistentes entre canales.
Objetivos
- Consistencia: Un paso de parseo, múltiples renderizadores.
- Chunking seguro: Dividir texto antes de renderizar, para que el formateo inline nunca
se rompa entre chunks.
- Matching de canal: Mapear el mismo IR a Slack mrkdwn, Telegram HTML, y Signal
style spans sin re-parsear Markdown.
Pipeline
1. Parsear Markdown -> IR
- IR es texto plano más style spans (bold/italic/strikethrough/code/spoiler) y link spans.
- Los offsets son unidades de código UTF-16, para que los Signal style spans coincidan con su API.
- Las tablas solo se parsean cuando el canal opta por conversión de tablas.
2. Chunk IR (format-first)
- Dividir texto IR antes de renderizar.
- El formateo inline nunca se divide entre límites de chunk; los spans se cortan por chunk.
3. Renderizado por canal
- ''Slack:'' tokens mrkdwn (bold/italic/strike/code), links como ''<url|label>''.
- ''Telegram:'' tags HTML (''<b>'', ''<i>'', ''<s>'', ''<code>'', ''<pre><code>'', ''<a href>'').
- ''Signal:'' Texto plano + ''text-style'' spans; los links se convierten en ''label (url)'' cuando los labels difieren.
Ejemplo de IR
Markdown de entrada:
Hello **world** — see [docs ](https: //docs.openclaw.ai).
IR (esquemático):
{ "text": "Hello world — see docs.", "styles": [ { "start": 6, "end": 11, "style": "bold" } ], "links": [ { "start": 19, "end": 23, "href": "https://docs.openclaw.ai" } ] }Dónde se usa
- Los adaptadores salientes de Slack, Telegram, y Signal renderizan desde IR.
- Otros canales (WhatsApp, iMessage, MS Teams, Discord) todavía usan texto plano o
sus propias reglas de formateo, con conversión de tablas Markdown aplicada antes
del chunking cuando está habilitado.
Manejo de tablas
Las tablas Markdown no son consistentemente soportadas entre clientes de chat. Usa
''markdown.tables'' para controlar conversión por canal (y por cuenta).
- ''code'': Renderizar tablas como bloques de código (predeterminado para la mayoría de canales).
- ''bullets'': Convertir cada fila a bullet points (predeterminado para Signal + WhatsApp).
- ''off'': Deshabilitar parseo y conversión de tablas; el texto de tabla crudo pasa a través.
Claves de config:
channels: discord: markdown: tables: code accounts: work: markdown: tables: off
Reglas de chunking
- Los límites de chunk vienen de adaptadores/config de canal y aplican al texto IR.
- Los code fences se mantienen como chunks únicos con newlines finales, para que los canales
los rendericen correctamente.
- Los prefijos de lista y prefijos de blockquote son parte del texto IR, para que el chunking
no divida a medio prefijo.
ReferenceConceptsMarkdownFormattingPage.step06.p6
ReferenceConceptsMarkdownFormattingPage.step06.p7
ReferenceConceptsMarkdownFormattingPage.step06.p8
ReferenceConceptsMarkdownFormattingPage.step06.p9
Política de enlaces
- ''Slack:'' ''[label](url)'' -> ''<url|label>''; URLs simples permanecen simples. Los autolinks
están deshabilitados durante el parsing para evitar doble enlace.
- ''Telegram:'' ''[label](url)'' -> ''<a href="url">label</a>'' (modo parse HTML).
- ''Signal:'' ''[label](url)'' -> ''label (url)'' a menos que el label coincida con la URL.
Spoilers
Las etiquetas spoiler (''||spoiler||'') solo se parsean para Signal, donde se mapean a
rangos de estilo Spoiler. Otros canales las tratan como texto plano.
Cómo agregar o actualizar un formateador de canal
1. ''Parsear una vez:'' Usa el helper compartido ''markdownToIR(...)'' con
opciones apropiadas para el canal (autolinks, estilos de encabezado, prefijos de blockquote).
2. ''Renderizar:'' Usa ''renderMarkdownWithMarkers(...)'' y un mapa de tokens de estilo
de renderizador implementado (o rangos de estilo Signal).
3. ''Dividir:'' Llama ''chunkMarkdownIR(...)'' antes de renderizar; renderiza cada chunk.
4. Conectar adaptador: Actualiza el adaptador de salida del canal para usar el nuevo chunker
y renderizador.
5. Probar: Agrega o actualiza pruebas de formateo y pruebas de entrega de salida (si
el canal usa chunking).
Errores comunes
- Los marcadores de corchetes angulares (''<@U123>'', ''<#C123>'', ''<https://...>'') deben
preservarse; escapa de forma segura el HTML crudo.
- El HTML de Telegram necesita texto escapado fuera de las etiquetas para evitar corrupción de markup.
- Los rangos de estilo Signal dependen de offsets UTF-16; no uses offsets de code point.
- Preserva las newlines finales para code fences para que las etiquetas de cierre aparezcan en
sus propias líneas.