docs: clarify wrapForFrac and streaming math-fence rationale

Address two Copilot review comments on PR #17175.

- `wrapForFrac` doc said "additive operators or whitespace" but the
  implementation also matches `*` and `/`. The wider behaviour is the
  one we want (nested products and fractions need parens to disambiguate
  inline `/`), so the doc is updated to match instead of tightening the
  regex.

- `fenceOpenAt` was flagged as "overly conservative" vs. `markdown.tsx`,
  which falls back to paragraph rendering for unclosed `$$` openers.
  Mirroring that fallback in the streaming chunker would prematurely
  commit a paragraph rendering of the unclosed opener to the monotonic
  stable prefix, where it would be frozen and become wrong the moment
  the closer streams in. The asymmetry is deliberate; document why so
  it isn't "fixed" again later.

Made-with: Cursor
This commit is contained in:
Austin Pickett 2026-04-28 21:43:32 -04:00
parent cb039ac000
commit 3379f88ea4
2 changed files with 19 additions and 4 deletions

View file

@ -42,6 +42,18 @@ import { Md } from './markdown.js'
// snippets like ` ```\n$$x$$\n``` ` (math example inside a code block)
// don't double-count. A `$$x$$` line that opens AND closes on its own
// produces zero net toggles; that's `len >= 4` plus `endsDollar`.
//
// NB: this is INTENTIONALLY more conservative than `markdown.tsx`'s
// parser, which falls back to paragraph rendering when an `$$` opener
// has no matching closer. The renderer can do that safely because it
// always sees the full text on every call. The streaming chunker
// cannot — once a chunk is committed to the monotonic stable prefix it
// is frozen, so prematurely deciding "this `$$` is just prose" would
// permanently commit a paragraph rendering that becomes wrong the
// instant the closer streams in. Treating any unmatched `$$` opener
// as still-open keeps the boundary parked behind it until the closer
// arrives (or the stream ends and the non-streaming `<Md>` takes over,
// at which point the renderer's fallback kicks in correctly).
const fenceOpenAt = (s: string, end: number) => {
let codeOpen = false
let mathOpen = false