fix(web): chat 气泡按段落拆分——兼容 no<p> 的 \n\n 双换行多段, 不再挤一个气泡
- 她(LLM)常产出 \n\n(双换行)分隔多段 而非 design 约定的 <p> 标签(看最近消息原文 <p>数0, 全\n\n) - splitParagraphs: 优先按 <p> 提取; 无完整<p>时按 /\n\s*\n/ 拆段(保留action/narration块, 不拆单\n句内换行) - 修: 之前只认<p>, 她\n\n多段被塞进一个气泡(whitespace-pre-wrap 显示双换行挤一个气泡), 主人反馈几个双换行挤一个气泡 - npm run build 绿
This commit is contained in:
1 parent
a054a55ce9
commit
bdd9d752e1
1 file changed
+16
-2
@@ -168,8 +168,22 @@ export function MessageBubble({
|
||||
* Non-greedy + multi-line so a tag may span newlines; a still-streaming,
|
||||
* unclosed `<p>` simply does not match and stays out until it closes. */
|
||||
function splitParagraphs(content: string): string[] {
|
||||
const re = /<p[^>]*>([\s\S]*?)<\/p>/g;
|
||||
return [...content.matchAll(re)].map((m) => m[1]);
|
||||
// Preferred: the agent wraps each paragraph in <p>…</p> (design/07 §2). When it
|
||||
// emits plain \n\n runs instead (the model often does), split on those too so
|
||||
// each logical paragraph becomes its own bubble. But never cut inside an
|
||||
// <action>…</action> / <narration>…</narration> block, and never split on a
|
||||
// single \n (that is an in-line break, kept inside the paragraph).
|
||||
const pRe = /<p[^>]*>([\s\S]*?)<\/p>/g;
|
||||
const pSegments = [...content.matchAll(pRe)].map((m) => m[1].trim());
|
||||
if (pSegments.length > 0) return pSegments;
|
||||
|
||||
// Keep non-<p> content (action/narration + body) so we don't strip the tags.
|
||||
const segments: string[] = [];
|
||||
for (const part of content.split(/\n\s*\n/)) {
|
||||
if (!part.trim()) continue;
|
||||
segments.push(part.trim());
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
|
||||
/** Chat-mode body: a Miuix surface shell around a whitespace-preserving span,
|
||||
|
||||
Reference in new issue
Block a user