CJK autolink boundary handling keeps `**` in the URL when a bold URL is followed by CJK punctuation
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- Mezza giornata
- Idoneità per principianti
- 50/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- react, typescript
- Ambito
- frontend, internationalization
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- TypeScript
- Stelle
- 5.7k
- Fork
- 313
- Merge medio
- 1g 19h
- PR unite (30g)
- 24
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di vercel/streamdown
-
remend: unclosed `$$` in a table cell is closed on a new line when an earlier line has mathForse già presa @orinnz l’ha presa 14 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
vercel/streamdown#652 ·
I maintainer di solito rispondono entro 1 giorno
-
The word-fade engine ships with every app, whether or not it animatesForse già presa @xyrolle l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 1/100
vercel/streamdown#681 ·
I maintainer di solito rispondono entro 1 giorno
-
Mermaid's UI ships in the main bundle although the chart is lazy-loadedForse già presa @xyrolle l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 20/100
vercel/streamdown#679 ·
I maintainer di solito rispondono entro 1 giorno
-
Animation: CJK paragraphs only animate their first batch, and queued words pop in when isAnimating turns falseForse già presa @sleitor l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
vercel/streamdown#669 ·
I maintainer di solito rispondono entro 1 giorno
-
Mermaid shows an error for a partial chart while its fence is still streamingForse già presa @slavco86 l’ha presa 3 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 25/100
vercel/streamdown#667 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di vercel/streamdown
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 83/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
ranxianglei/billion-context#3583 ·
I maintainer di solito rispondono entro 1 giorno
-
bug:new
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
callstackincubator/simlock#673 ·
I maintainer di solito rispondono entro 1 giorno
-
documentation v3
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
anomalyco/opencode#56380 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno