@@ -45,28 +45,38 @@ const SVG_DOT = createSVGIcon(
4545 `<svg width="12" height="12" xmlns="http://www.w3.org/2000/svg" class="${ SVG_DOT_CLASS } " style="margin-left:.25em;margin-top:-.25em"><circle cx="6" cy="6" r="6"/></svg>`
4646) ;
4747
48- // For rendering chat output, we use typical Markdown behavior of passing through raw
49- // HTML (albeit sanitizing afterwards).
50- //
51- // For echoing chat input, we escape HTML. This is not for security reasons but just
52- // because it's confusing if the user is using tag-like syntax to demarcate parts of
53- // their prompt for other reasons (like <User>/<Assistant> for providing examples to the
54- // chat model), and those tags simply vanish.
55- const rendererEscapeHTML = new Renderer ( ) ;
56- rendererEscapeHTML . html = ( html : string ) =>
48+ // 'markdown' renderer (for assistant messages)
49+ const markdownRenderer = new Renderer ( ) ;
50+
51+ // Add some basic Bootstrap styling to markdown tables
52+ markdownRenderer . table = ( header : string , body : string ) => {
53+ return `<table class="table table-striped table-bordered">
54+ <thead>${ header } </thead>
55+ <tbody>${ body } </tbody>
56+ </table>` ;
57+ } ;
58+
59+ // 'semi-markdown' renderer (for user messages)
60+ const semiMarkdownRenderer = new Renderer ( ) ;
61+
62+ // Escape HTML, not for security reasons, but just because it's confusing if the user is
63+ // using tag-like syntax to demarcate parts of their prompt for other reasons (like
64+ // <User>/<Assistant> for providing examples to the model), and those tags vanish.
65+ semiMarkdownRenderer . html = ( html : string ) =>
5766 html
5867 . replaceAll ( "&" , "&" )
5968 . replaceAll ( "<" , "<" )
6069 . replaceAll ( ">" , ">" )
6170 . replaceAll ( '"' , """ )
6271 . replaceAll ( "'" , "'" ) ;
63- const markedEscapeOpts = { renderer : rendererEscapeHTML } ;
6472
6573function contentToHTML ( content : string , content_type : ContentType ) {
6674 if ( content_type === "markdown" ) {
67- return unsafeHTML ( sanitizeHTML ( parse ( content ) as string ) ) ;
75+ const html = parse ( content , { renderer : markdownRenderer } ) ;
76+ return unsafeHTML ( sanitizeHTML ( html as string ) ) ;
6877 } else if ( content_type === "semi-markdown" ) {
69- return unsafeHTML ( sanitizeHTML ( parse ( content , markedEscapeOpts ) as string ) ) ;
78+ const html = parse ( content , { renderer : semiMarkdownRenderer } ) ;
79+ return unsafeHTML ( sanitizeHTML ( html as string ) ) ;
7080 } else if ( content_type === "html" ) {
7181 return unsafeHTML ( sanitizeHTML ( content ) ) ;
7282 } else if ( content_type === "text" ) {
0 commit comments