Problem
Streamdown 2.5.0 internally uses remark-gfm with a default empty config {}. This means remark-gfm's strikethrough extension runs with singleTilde: true by default, causing a single ~ character to be parsed as strikethrough instead of being rendered as a plain character.
In AI chat scenarios, model output frequently contains ~ as a range separator or path component (e.g. 25~30, ~500ms, C:\Users\~\Documents). These get incorrectly rendered as striethrough.
Reproduction
import { Streamdown } from streamdown;
<Streamdown mode=static>25~30, 31~35</Streamdown>
Expected: 25~30, 31~35 (plain text)
Actual: 25<del>30, 31</del>35 (strikethrough)
Cause
In node_modules/streamdown/dist/chunk-BO2N2NFS.js, the default remark plugins are:
var Ks = { gfm: [remarkGfm, {}], codeMeta: un };
remark-gfm's strikethrough extension defaults to singleTilde: true, which allows ~text~ to trigger strikethrough. Additionally, @streamdown/cjk further relaxes CJK boundary matching for strikethrough, making it even easier to accidentally trigger in Chinese text.
Expected Behavior
Streamdown should either:
- Provide a way to configure
remark-gfm options (e.g. singleTilde: false), or
- Default
singleTilde to false, consistent with GitHub's own behavior: GitHub only renders ~~text~~ as strikethrough; a single ~ is treated as a plain character.
Current Workaround
Currently, consumers cannot override this because Streamdown's remarkPlugins prop appends to the internal plugin list rather than replacing it. The internal remark-gfm instance with singleTilde: true always runs first.
Problem
Streamdown 2.5.0 internally uses
remark-gfmwith a default empty config{}. This meansremark-gfm's strikethrough extension runs withsingleTilde: trueby default, causing a single~character to be parsed as strikethrough instead of being rendered as a plain character.In AI chat scenarios, model output frequently contains
~as a range separator or path component (e.g.25~30,~500ms,C:\Users\~\Documents). These get incorrectly rendered as striethrough.Reproduction
Expected:
25~30, 31~35(plain text)Actual:
25<del>30, 31</del>35(strikethrough)Cause
In
node_modules/streamdown/dist/chunk-BO2N2NFS.js, the default remark plugins are:remark-gfm's strikethrough extension defaults tosingleTilde: true, which allows~text~to trigger strikethrough. Additionally,@streamdown/cjkfurther relaxes CJK boundary matching for strikethrough, making it even easier to accidentally trigger in Chinese text.Expected Behavior
Streamdown should either:
remark-gfmoptions (e.g.singleTilde: false), orsingleTildetofalse, consistent with GitHub's own behavior: GitHub only renders~~text~~as strikethrough; a single~is treated as a plain character.Current Workaround
Currently, consumers cannot override this because Streamdown's
remarkPluginsprop appends to the internal plugin list rather than replacing it. The internalremark-gfminstance withsingleTilde: truealways runs first.