From 9c6534c7463027cfdfe18782a36ce74f57f5fa7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 19 Aug 2026 14:24:00 +0000 Subject: [PATCH] render markdown in your own chat bubbles, and let you copy them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Your own messages were plain `whitespace-pre-wrap`, so pasting a fenced block gave you back the backticks and none of the formatting — the one place in the app where markdown was written and never read. The usual reason to leave user text alone is that rendering changes what was typed: `a_b_c` becomes italic, a leading `#` becomes a heading. That is real, and the answer is the Copy button beside it, which copies the RAW text. The original is one click away and nothing you wrote can be lost to a renderer. Same remark plugins, components and sanitize schema as the assistant's, deliberately — a code block should look identical whoever wrote it, and the schema already strips script, iframe, object, embed and form, so pasted HTML is inert either way. The copy button appears on hover rather than always, unlike the assistant's: a reply is something you copy out of, while your own message is something you already have, so the control earns its place only when reached for. Co-Authored-By: Claude Opus 5 --- .../apps/Chat/components/MessageBubble.tsx | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/workspaces/officerdev/src/apps/Chat/components/MessageBubble.tsx b/src/workspaces/officerdev/src/apps/Chat/components/MessageBubble.tsx index 4881be90..0ef3780c 100644 --- a/src/workspaces/officerdev/src/apps/Chat/components/MessageBubble.tsx +++ b/src/workspaces/officerdev/src/apps/Chat/components/MessageBubble.tsx @@ -140,13 +140,40 @@ export const MessageBubble = ({ message, onAnswer, onRetry, onDecidePlan, defaul return ( <> {metadata && } -
+
{message.images?.map((img, i) => ( {img.filename} ))} - {/* break-words, or a pasted URL or base64 blob pushes the bubble past max-w and out of the pane. */} -
{text}
+ {/* YOUR OWN MESSAGE IS RENDERED AS MARKDOWN TOO. + + It used to be `whitespace-pre-wrap` plain text, so pasting a fenced block gave you the + backticks and none of the formatting — the one place in the app where markdown was + written and not read. + + The reason this is usually left plain is that rendering changes what you typed: + `a_b_c` becomes italic, a leading `#` becomes a heading. That is real, and the answer + is the Copy button below, which copies the RAW text — so the original is never more + than one click away and nothing you wrote can be lost to a renderer. + + Same plugins, components and sanitize schema as the assistant's, deliberately: a code + block should look identical whoever wrote it. `break-words` stays, or a pasted URL or + base64 blob pushes the bubble past max-w and out of the pane. */} +
+ + {text} + +
+ {/* Hidden until hover, unlike the assistant's. A reply is something you copy out of; your + own message is something you already have, so the control earns its place only when + reached for. */} +
+ +