Fix code block rendering: escape newlines/tabs in syntax highlighter output
highlight_sx/python/bash produced SX string literals with literal newline and tab characters, breaking the wire format parser. Add centralized _escape() helper that properly escapes \n, \t, \r (plus existing \\ and " escaping). Code blocks now render with correct indentation and syntax highlighting in both server and client renders. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,12 +8,22 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def _escape(text: str) -> str:
|
||||||
|
"""Escape a token for embedding in an SX string literal."""
|
||||||
|
return (text
|
||||||
|
.replace("\\", "\\\\")
|
||||||
|
.replace('"', '\\"')
|
||||||
|
.replace("\n", "\\n")
|
||||||
|
.replace("\t", "\\t")
|
||||||
|
.replace("\r", "\\r"))
|
||||||
|
|
||||||
|
|
||||||
def highlight_sx(code: str) -> str:
|
def highlight_sx(code: str) -> str:
|
||||||
"""Highlight s-expression source code as sx with Tailwind spans."""
|
"""Highlight s-expression source code as sx with Tailwind spans."""
|
||||||
tokens = _tokenize_sx(code)
|
tokens = _tokenize_sx(code)
|
||||||
parts = []
|
parts = []
|
||||||
for kind, text in tokens:
|
for kind, text in tokens:
|
||||||
escaped = text.replace("\\", "\\\\").replace('"', '\\"')
|
escaped = _escape(text)
|
||||||
if kind == "comment":
|
if kind == "comment":
|
||||||
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
||||||
elif kind == "string":
|
elif kind == "string":
|
||||||
@@ -94,7 +104,7 @@ def highlight_python(code: str) -> str:
|
|||||||
tokens = _tokenize_python(code)
|
tokens = _tokenize_python(code)
|
||||||
parts = []
|
parts = []
|
||||||
for kind, text in tokens:
|
for kind, text in tokens:
|
||||||
escaped = text.replace("\\", "\\\\").replace('"', '\\"')
|
escaped = _escape(text)
|
||||||
if kind == "comment":
|
if kind == "comment":
|
||||||
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
||||||
elif kind == "string":
|
elif kind == "string":
|
||||||
@@ -176,7 +186,7 @@ def highlight_bash(code: str) -> str:
|
|||||||
tokens = _tokenize_bash(code)
|
tokens = _tokenize_bash(code)
|
||||||
parts = []
|
parts = []
|
||||||
for kind, text in tokens:
|
for kind, text in tokens:
|
||||||
escaped = text.replace("\\", "\\\\").replace('"', '\\"')
|
escaped = _escape(text)
|
||||||
if kind == "comment":
|
if kind == "comment":
|
||||||
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
parts.append(f'(span :class "text-stone-400 italic" "{escaped}")')
|
||||||
elif kind == "string":
|
elif kind == "string":
|
||||||
|
|||||||
Reference in New Issue
Block a user