给 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
5
1. 写一个 `remark-chat-directive.mjs` 插件;
6
2. 写一个 `remark-chat-directive.css` 样式;
7
3. 在 `astro.config.ts` 注册插件、在 `BaseHead.astro` 引入 CSS;
8
4. 写文章时用 `:::chat` 包起来。
9
10
开始实现?
11
:::
12
13
:::chat{role="user"}
14
好的,先做吧。
15
:::
16
17
:::chat{role="assistant"}
18
插件已写好。核心逻辑很直接:
19
20
```js
21
visit(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 对象即可。


觉得这篇文章怎么样?给个反应吧!