CJK autolink boundary handling keeps `**` in the URL when a bold URL is followed by CJK punctuation
维护者通常 1 天内回复
评估
- 难度
- 3/5
- 预计耗时
- 半天
- 新手友好度
- 50/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- react, typescript
调研方向
Start with the @streamdown/cjk autolink split introduced for #327 and check where it cuts the URL at fullwidth punctuation. Reproduce with the four table inputs, which should show bold plus a link to https://example.com/ for the spaced cases and no bold for the unspaced ones. Done means **https://example.com/**、英語版 renders a span wrapping the link, with no ** in the href, while the #326 and #327 cases still pass.
由索引模型根据 Issue 内容生成。
描述
Bug Description
With @streamdown/cjk enabled, a bare URL wrapped in ** and immediately followed by fullwidth punctuation (e.g. 、, U+3001) renders with ** included in the link URL, and the bold is not applied.
@streamdown/cjk already cuts the autolink at the fullwidth punctuation (#327, fixing #326), so the rest of the sentence is no longer swallowed. However, the closing ** stays inside the link, so the emphasis is never formed. This looks like another case not covered by #327, similar to #623.
The underlying behavior is GFM's autolink literal rule, which remark-gfm follows as specified:
- The URL extends until whitespace or the end of the text.
- Only trailing ASCII punctuation (
?,!,.,,,:,*,_,~) is trimmed from the end of that range.
In English this only happens when the space after the punctuation is missing (**URL**,then), which is rare. In CJK text, punctuation is not followed by a space, so it happens almost every time a bold URL is followed by a comma or period. Fullwidth punctuation is also not in the trimmed set, so adding a space after 、 does not help either.
Steps to Reproduce
Render the code sample below. mode="static" and mode="streaming" produce the same HTML, so this is not related to remend's incomplete-markdown handling.
Expected Behavior
The same output as when there is a space before 、 (attributes stripped; Streamdown renders bold as a span):
<p>日本語版は <span><a href="https://example.com/">https://example.com/</a></span>、英語版は別ページです。</p>
- The link points to
https://example.com/. - The bold is applied to the link.
、英語版は別ページです。is plain text.
Actual Behavior
With @streamdown/cjk (attributes stripped for readability):
<p>日本語版は **<a href="https://example.com/**">https://example.com/**</a>、英語版は別ページです。</p>
Without @streamdown/cjk, the link swallows the rest of the sentence (the #326 behavior):
<p>日本語版は **<a href="https://example.com/**%E3%80%81...">https://example.com/**、英語版は別ページです。</a></p>
The same rule applied to other inputs:
| Input | Result |
|---|---|
See **https://example.com/**, then more |
bold + link to https://example.com/ |
See **https://example.com/**,then more |
link to https://example.com/**,then, no bold |
日本語版は **https://example.com/** 、英語版 |
bold + link to https://example.com/ |
日本語版は **https://example.com/**、 英語版 |
link to https://example.com/**, no bold |
Code Sample
import { Streamdown } from 'streamdown';
import { cjk } from '@streamdown/cjk';
const markdown = '日本語版は **https://example.com/**、英語版は別ページです。';
export default function App() {
return <Streamdown plugins={{ cjk }}>{markdown}</Streamdown>;
}
Streamdown Version
streamdown 2.7.0; @streamdown/cjk 1.0.4
React Version
19.3.0
Node.js Version
24.21.0
Browser(s)
No response
Operating System
None
Additional Context
A possible fix in the autolink split from #327: when the URL is cut at fullwidth punctuation, also trim trailing * / _ / ~ from the URL and let the emphasis be formed, as GFM does for ASCII punctuation. Adding fullwidth punctuation to the trimmed set would also cover the case with a space after 、.
LLM output often bolds URLs in Japanese and Chinese, so this shows up regularly in chat UIs.
- 主要语言
- TypeScript
- 星标
- 5.7k
- 派生
- 313
- 平均合并
- 1 天 19 小时
- 30 天内合并 PR
- 24
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
vercel/streamdown 的其他 Issue
-
remend: unclosed `$$` in a table cell is closed on a new line when an earlier line has math可能已有人在做 @orinnz 于 14 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 85/100
vercel/streamdown#652 ·
维护者通常 1 天内回复
-
The word-fade engine ships with every app, whether or not it animates可能已有人在做 @xyrolle 今天认领。 未关闭
难度 4/5 3-5 天 新手友好度 1/100
vercel/streamdown#681 ·
维护者通常 1 天内回复
-
Mermaid's UI ships in the main bundle although the chart is lazy-loaded可能已有人在做 @xyrolle 今天认领。 未关闭
难度 4/5 3-5 天 新手友好度 20/100
vercel/streamdown#679 ·
维护者通常 1 天内回复
-
Animation: CJK paragraphs only animate their first batch, and queued words pop in when isAnimating turns false可能已有人在做 @sleitor 于 1 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 35/100
vercel/streamdown#669 ·
维护者通常 1 天内回复
-
Mermaid shows an error for a partial chart while its fence is still streaming可能已有人在做 @slavco86 于 4 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 25/100
vercel/streamdown#667 · 1 条评论 ·
维护者通常 1 天内回复
查看 vercel/streamdown 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
polarsource/polar#15580 ·
维护者通常 1 天内回复
-
accepted bug via-triage
难度 2/5 1-3 小时 新手友好度 69/100
pingdotgg/t3code#20931 · 1 条评论 ·
维护者通常 1 天内回复
-
bug/1-unconfirmed kind/bug
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 83/100
-
难度 2/5 1-3 小时 新手友好度 72/100
ranxianglei/billion-context#3583 ·
维护者通常 1 天内回复