feat: escape HTML in user messages (#782)
- Add HTML escaping for user messages in Markdown mode - Fix agent mention link rendering order issue - Plain mode remains unchanged (uses React elements) Tested: - User messages: <div> now displays as <div> - Agent mentions render correctly as clickable links in Markdown mode Co-authored-by: 郭皓楠 <guohaonan@MacBook-Neo.local>
This commit is contained in:
committed by
GitHub
co-authored by
郭皓楠
parent
086cf26cd7
commit
b59040ff18
@@ -19,6 +19,15 @@ const buildMentionUrl = (name: string): string => {
|
|||||||
return `https://opencode.ai/docs/agents/#${encoded}`;
|
return `https://opencode.ai/docs/agents/#${encoded}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const escapeHtml = (text: string): string => {
|
||||||
|
return text
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
};
|
||||||
|
|
||||||
const normalizeUserMessageRenderingMode = (mode: unknown): 'markdown' | 'plain' => {
|
const normalizeUserMessageRenderingMode = (mode: unknown): 'markdown' | 'plain' => {
|
||||||
return mode === 'markdown' ? 'markdown' : 'plain';
|
return mode === 'markdown' ? 'markdown' : 'plain';
|
||||||
};
|
};
|
||||||
@@ -99,12 +108,18 @@ const UserTextPart: React.FC<UserTextPartProps> = ({ part, messageId, agentMenti
|
|||||||
}, [collapseZoneHeight, hasActiveSelectionInElement, isExpanded, isTruncated]);
|
}, [collapseZoneHeight, hasActiveSelectionInElement, isExpanded, isTruncated]);
|
||||||
|
|
||||||
const processedMarkdownContent = React.useMemo(() => {
|
const processedMarkdownContent = React.useMemo(() => {
|
||||||
if (!agentMention?.token || !textContent.includes(agentMention.token)) {
|
let content = textContent;
|
||||||
return textContent;
|
|
||||||
|
// Step 1: First escape HTML to protect against XSS and ensure HTML tags display as text
|
||||||
|
content = escapeHtml(content);
|
||||||
|
|
||||||
|
// Step 2: Then insert agent mention links (after escaping, so <a> tags won't be escaped)
|
||||||
|
if (agentMention?.token && content.includes(agentMention.token)) {
|
||||||
|
const mentionHtml = `<a href="${buildMentionUrl(agentMention.name)}" class="text-primary hover:underline" target="_blank" rel="noopener noreferrer">${agentMention.token}</a>`;
|
||||||
|
content = content.replace(agentMention.token, mentionHtml);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mentionHtml = `<a href="${buildMentionUrl(agentMention.name)}" class="text-primary hover:underline" target="_blank" rel="noopener noreferrer">${agentMention.token}</a>`;
|
return content;
|
||||||
return textContent.replace(agentMention.token, mentionHtml);
|
|
||||||
}, [agentMention, textContent]);
|
}, [agentMention, textContent]);
|
||||||
|
|
||||||
const plainTextContent = React.useMemo(() => {
|
const plainTextContent = React.useMemo(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user