章
目
录
在开发AI聊天对话项目时,将聊天内容以Markdown格式输出并进行转换展示是一个常见需求。我在做相关项目时,发现网上资料有限,经过一番研究,总结出了一套实现方法。下面就给大家详细讲讲,主要是借助react-markdown
,搭配remark-gfm
、rehype-highlight
、highlight.js
等插件以及一些CSS样式来完成转换。先看下转换前后的效果图:
一、功能需求与实现思路
在AI聊天对话场景中,我们期望聊天内容能以Markdown格式呈现,像标题、列表、代码块、链接、图片等元素都能正确显示。比如输入一段包含各种Markdown元素的文本,经过处理后,在聊天界面中可以清晰地展示出对应的格式效果。
实现这个功能,关键在于利用合适的工具将Markdown文本转换为React组件。react-markdown
库负责将Markdown文本转化为React组件,remark-gfm
插件用来支持GitHub Flavored Markdown(GFM)的特性,像表格、任务列表等格式都能正常显示。同时,借助rehype-highlight
和highlight.js
实现代码块的语法高亮,再通过自定义CSS样式美化整体展示效果。
二、具体实现步骤
(一)创建ChatMessage组件
在components
文件夹下创建ChatMessage.jsx
组件,这个组件用来处理聊天消息。实现时,需要安装react-markdown
和remark-gfm
这两个库,命令如下:
npm install react-markdown remark-gfm
react-markdown
能把Markdown文本转换为React组件,remark-gfm
则为其添加对GFM格式的支持。以下是ChatMessage.jsx
的代码:
import React from'react';
import ReactMarkdown from'react-markdown';
import remarkGfm from'remark-gfm';
const ChatMessage = ({ message, role }) => {
return (
role === 'assistant'? (
<div className="chat-message">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{message}
</ReactMarkdown>
</div>
) : (
<div className="user-message">
{message}
</div>
)
);
};
export default ChatMessage;
这段代码接收message
(聊天消息内容)和role
(消息产生者)两个参数,根据role
判断是助手消息还是用户消息,分别进行不同的展示。助手消息会通过ReactMarkdown
组件将Markdown格式的message
渲染出来,用户消息则直接显示。
(二)在聊天页面使用组件
在AI聊天页面中引入ChatMessage
组件,假设聊天消息存储在messages
数组中,每个消息对象包含id
、content
(消息内容)和role
等属性,实现代码如下:
import ChatMessage from '@/components/ChatMessage';
{/* 消息区域-添加固定高度和滚动 */}
<div className="flex-1 overflow-y-auto p-4 w-full max-w-4xl mx-auto">
<div className="space-y-4 min-h-[calc(100vh-200px)]">
{messages.map(message => (
<div
key={message.id}
className={`flex flex-row ${message?.role === 'assistant'? 'justify-start' : 'justify-end'} mb-4`}>
<div className={`max-w-[80%] rounded-2xl px-4 py-3 ${message?.role === 'assistant'? 'bg-blue-100 rounded-bl-none' : 'bg-indigo-100 rounded-br-none'}`}>
<div className={`text-gray-800 ${message?.role === 'assistant'? 'text-left' : 'text-right'}`}>
<ChatMessage message={message.content} role={message.role} />
</div>
</div>
</div>
))}
<div ref={endRef} className="h-8" />
</div>
</div>
这段代码遍历messages
数组,根据消息的role
决定消息在页面中的排版位置,并将每个消息传递给ChatMessage
组件进行展示。
(三)美化Markdown格式
为了让Markdown内容展示得更美观,创建一个markdownStyles.css
文件,添加以下样式代码:
/* 消息容器-添加平滑过渡和更现代的阴影 */
.chat-message {
margin: 12px 0;
padding: 16px;
transition: all 0.2s ease;
}
/* 标题-添加渐变颜色和更好的间距 */
.chat-message h1 {
color: #1a1a1a;
border-bottom: 1px solid #eaeaea;
padding-bottom: 8px;
margin-bottom: 16px;
}
.chat-message h2 {
color: #1e40af;
margin-top: 24px;
}
/* 段落-优化行高和字体 */
.chat-message p {
color: #4b5563;
line-height: 1.8;
font-size: 16px;
margin-bottom: 16px;
}
/* 列表-更精致的样式 */
.chat-message ul {
list-style-type: '• ';
padding-left: 24px;
}
.chat-message ol {
padding-left: 24px;
}
/* 代码块-更专业的语法高亮样式 */
.chat-message pre {
background-color: #1e293b;
color: #f8fafc;
border-radius: 8px;
font-family: 'SF Mono', Menlo, monospace;
font-size: 14px;
line-height: 1.5;
margin: 16px 0;
}
/* 内联代码-更突出的样式 */
.chat-message code:not(pre code) {
background-color: #f3f4f6;
color: #dc2626;
border-radius: 4px;
font-size: 90%;
}
/* 链接-更明显的交互效果 */
.chat-message a {
color: #2563eb;
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
}
.chat-message a:hover {
color: #1d4ed8;
text-decoration: underline;
}
/* 表格样式-新增 */
.chat-message table {
width: 100%;
border-collapse: collapse;
margin: 16px 0;
}
.chat-message th,
.chat-message td {
padding: 12px;
border: 1px solid #e5e7eb;
}
.chat-message th {
background-color: #f3f4f6;
}
/* 引用样式-新增 */
.chat-message blockquote {
border-left: 4px solid #2563eb;
background-color: #f8fafc;
padding: 12px 16px;
margin: 16px 0;
color: #4b5563;
}
然后在ChatMessage
组件中引入这个CSS文件,这样就能对Markdown元素进行样式美化,让聊天内容展示更清晰美观。如果觉得样式不符合需求,还可以根据实际情况进行修改。
(四)处理代码块
为了实现代码块的语法高亮,需要安装highlight.js
和rehype-highlight
这两个库,安装命令如下:
npm install highlight.js
npm install rehype-highlight
rehype-highlight
插件用于帮助实现代码块的语法高亮,highlight.js
则是一个流行的语法高亮库,支持多种编程语言。接下来在ChatMessage
组件中引入这两个库并进行配置:
import React from'react';
import ReactMarkdown from'react-markdown';
import remarkGfm from'remark-gfm';
import rehypeHighlight from'rehype-highlight';
import hljs from 'highlight.js';
import './code.css';//引入代码段的css样式
import './markdownStyles.css';
const highlightCode = (node) => {
// 处理代码段的函数
if (node.tagName === 'pre') {
const codeNode = node.children[0];
if (codeNode.tagName === 'code') {
const language = codeNode.properties.className?.[0]?.replace('language-', '');
if (language && hljs.getLanguage(language)) {
const highlightedCode = hljs.highlight(codeNode.children[0].value, { language }).value;
codeNode.children[0].value = highlightedCode;
}
}
}
return node;
};
const ChatMessage = ({ message, role }) => {
return role === 'user'? (
<div>{message}</div>
) : (
<div className="chat-message">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeHighlight, () => highlightCode]}
>
{message}
</ReactMarkdown>
</div>
);
};
export default ChatMessage;
上述代码定义了highlightCode
函数,用于处理代码块的高亮显示。在ReactMarkdown
组件中,通过rehypePlugins
配置rehypeHighlight
和highlightCode
函数,实现代码块的语法高亮。code.css
样式文件可以从highlight.js/styles/atom-one-dark.css
修改而来,根据实际需求调整样式,让代码块展示更美观。
三、总结
通过上述步骤,我们成功在React项目中实现了AI聊天对话的Markdown输出转换和美化。从创建组件处理消息,到利用插件实现Markdown解析和代码高亮,再到通过CSS样式美化展示效果,每个环节紧密配合。如果在实现过程中遇到问题,欢迎交流。希望这篇文章能帮助大家在相关项目开发中少走弯路。