* fix(streamdown-code): fall back to plain text for unknown/truncated language identifiers
When a code block's language identifier is unrecognised by Shiki (e.g.
'rus' from a network-truncated 'rust'), createHighlighter throws a
ShikiError. Previously the .catch() block only logged the error and
left subscribers hanging, causing a permanent React render-cycle stall.
Fix: resolve the language to the 'text' fallback *before* calling
getHighlighter() when the identifier is not in the bundledLanguages
set. This prevents the exception entirely and ensures the code block
renders with plain-text highlighting instead of breaking.
Fixes#433
* Add changeset for unknown language fallback fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add test for unknown/truncated language fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix TypeScript error: widen safeLanguage type to include SpecialLanguage
`'text'` is a SpecialLanguage in Shiki, not a BundledLanguage, so the
type annotations for getHighlighter and getHighlighterCacheKey need to
accept both.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix formatting: remove trailing comma, use double quotes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Dmitrii Troitskii <jsleitor@gmail.com>
Co-authored-by: Hayden Bleasel <hello@haydenbleasel.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: support custom shiki themes in code blocks
Add support for custom shiki theme objects (ThemeRegistrationAny-compatible)
in addition to built-in BundledTheme string names.
- Add CustomTheme interface and ThemeInput type alias
- Widen theme types across CodePluginOptions, CodeHighlighterPlugin,
HighlightOptions, StreamdownProps, and StreamdownContextType
- Extract theme names from objects for cache keys and codeToTokens
- Pass theme objects to createHighlighter for registration
- Add tests for custom theme objects and mixed themes
- Full backward compatibility with existing BundledTheme usage
Closes#409
* fix: pass per-call themes to getHighlighter instead of defaultThemes
* fix: resolve duplicate interface properties and type errors in CodeHighlighterPlugin
* Add changeset for custom Shiki themes
* fix: use shiki's ThemeRegistrationAny, deduplicate types, tighten API
- Replace custom CustomTheme interface with shiki's ThemeRegistrationAny
- Remove duplicated type definitions across packages
- Simplify HighlightOptions.themes to [ThemeInput, ThemeInput]
- Remove unsafe cast in createHighlighter call
- Bump changeset to minor (new feature, not patch)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Dmitrii Troitskii <jsleitor@gmail.com>
Co-authored-by: Hayden Bleasel <hello@haydenbleasel.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Plugin trial
* Update docs and tests
* Update homepage add new section
* Update usage.tsx
* Split out CJK plugin
* Extract plugins into new packages
* Misc fixes
* Fix lint / formatting
* Fix: The Streamdown component's memo comparison doesn't compare the plugins prop, preventing re-renders when plugins change while other props stay the same
Co-authored-by: haydenbleasel <hello@haydenbleasel.com>
* Fix: TypeScript type mismatch at line 89 in `index.ts`: the visitor function's `index` parameter is typed as `number | undefined`, but the `visit` function expects `number | null`. The `undefined` type is not assignable to `number | null`.
This commit fixes the issue reported at /vercel/path0/packages/streamdown-cjk/index.ts:89
## TypeScript type incompatibility in visitor callback
**What fails:** TypeScript compiler fails during DTS (type definitions) build in `packages/streamdown-cjk/index.ts` at line 89
**How to reproduce:**
```bash
cd packages/streamdown-cjk
pnpm build
```
**Result:**
```
index.ts(89,3): error TS2769: No overload matches this call.
Overload 1 of 2, '(tree: Root, check: "link", visitor: BuildVisitor<Root, "link">, reverse?: boolean | null | undefined): undefined', gave the following error.
Argument of type '(node: Link, index: number | null, parent?: Parent) => number | undefined' is not assignable to parameter of type 'BuildVisitor<Root, "link">'.
Types of parameters 'index' and 'index' are incompatible.
Type 'number | undefined' is not assignable to type 'number | null'.
Type 'undefined' is not assignable to type 'number | null'.
```
**Root cause:** The visitor callback function passed to the `visit()` function from `unist-util-visit` was declaring the `index` parameter as `number | null`, but the visitor can also receive `undefined` as the index value. The `BuildVisitor` type signature expects the callback to accept `number | null | undefined` to properly match the library's API.
**Fix:** Updated the `index` parameter type annotation on line 89 from `number | null` to `number | null | undefined` to match the actual possible values that the visitor receives and the expected `BuildVisitor` type signature.
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: haydenbleasel <hello@haydenbleasel.com>
* Fix tests
* Remove CDN paths
* Fix tests
* More cleanup
* Remove shiki from main bundle
* Update index.ts
* Cleanup test repo
* Cleanup website
* Delete next-env files
* Update .gitignore
* Fix lockfile
* Upgrade Next and React
* Simplify themes
* Update test site
* Misc fixes
* Type fixes
* Create perky-cobras-punch.md
---------
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>