给 Astro 博客加上 ChatGPT 对话样式
预计 10 min read
前言
这篇博客本身就是用新加的 :::chat 指令写成的。内容记录了我与 ChatGPT 的一段真实开发对话——关于如何为 Astro 博客添加 ChatGPT 风格的对话展示。
对话
我想做一个博客内容是我与 ChatGPT 的对话,页面也是与 GPT 对话的形式进行展示,我应该怎么做这种呢?
我查看了你的项目结构,你用的是 Astro + Markdown 内容集合。最省事的方案是复用你现有的 :::callout 指令机制,再做一个 :::chat 容器指令。
这样每轮对话只需要写:
1:::chat{role="user"}2你的问题ChatGPT 的回答
1内容支持完整 markdown:代码块、列表、加粗、表格都能正常解析。2
3具体做法分四步:4
51. 写一个 `remark-chat-directive.mjs` 插件;62. 写一个 `remark-chat-directive.css` 样式;73. 在 `astro.config.ts` 注册插件、在 `BaseHead.astro` 引入 CSS;84. 写文章时用 `:::chat` 包起来。9
10开始实现?11:::12
13:::chat{role="user"}14好的,先做吧。15:::16
17:::chat{role="assistant"}18插件已写好。核心逻辑很直接:19
20```js21visit(tree, (node) => {22 if (node.type !== "containerDirective") return;23 if (node.name !== "chat") return;24
25 const role = (node.attributes.role || "assistant").toLowerCase();26 const safeRole = role === "user" ? "user" : "assistant";27
28 node.children = [29 { /* 头像 */ },30 { /* 气泡内容 */ },31 ];32
33 data.hName = "div";34 data.hProperties = { class: `chat-msg chat-${safeRole}` };35});这里复用了你现有 callout 插件的 containerDirective 渲染管线,所以没有新依赖。
:::
现在的 ChatGPT 的回复是没有气泡的,只有人员是有气泡的。
明白,改成 ChatGPT 现在的样子:用户有气泡,ChatGPT 回复纯文本无气泡。
只改 CSS 里 .chat-assistant .chat-bubble 部分:
1.chat-assistant .chat-bubble {2 background: transparent;3 color: var(--fontc);4 padding: 0;5 border-radius: 0;6 max-width: none;7}保留头像,去掉背景和边框。深浅色自动跟随主题。
将上面内容进行编写成博客文件的内容吧。
已整理成这篇博客。你现在看到的就是最终效果:
- user 消息靠右,带主色气泡;
- assistant 消息靠左,只显示绿色头像 + 纯文本;
- 所有代码块、列表、引用都能正常渲染。
把这整个对话过程本身写成博客,也是个不错的使用场景。
写法示例
1:::chat{role="user"}2我想用 Rust 写一个最小的 HTTP 服务器3:::4
5:::chat{role="assistant"}6用标准库 `std::net::TcpListener` 就够了。7:::实现要点
几个关键文件:
| 文件 | 作用 |
|---|---|
src/components/mdrenders/remark-chat-directive.mjs | 解析 :::chat{role} 指令 |
src/styles/remark-chat-directive.css | 气泡与头像样式 |
astro.config.ts | 注册 remark 插件 |
src/components/BaseHead.astro | 全局引入样式 |
头像目前是写死的 SVG:user 为人形图标,assistant 为 OpenAI logo。如果你想换成自己的头像图片,修改插件里的 avatars 对象即可。
觉得这篇文章怎么样?给个反应吧!