Skip to content

Commit ff390bb

Browse files
committed
Update docs
1 parent d5af95b commit ff390bb

File tree

5 files changed

+364
-2
lines changed

5 files changed

+364
-2
lines changed

apps/website/content/docs/code-blocks.mdx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,44 @@ Streamdown supports all Shiki themes including:
143143
- `tokyo-night`, `slack-dark`, `slack-ochin`
144144
- And [many more](https://shiki.style/themes)
145145

146+
### Custom theme objects
147+
148+
The `shikiTheme` prop accepts `[ThemeInput, ThemeInput]` where `ThemeInput` is either a bundled theme name (`BundledTheme`) or a custom theme object (`ThemeRegistrationAny`). You can mix and match:
149+
150+
```tsx title="app/page.tsx"
151+
import { Streamdown } from "streamdown";
152+
import { code } from "@streamdown/code";
153+
import myCustomDarkTheme from "./my-dark-theme.json";
154+
155+
export default function Page() {
156+
return (
157+
<Streamdown
158+
plugins={{ code: code }}
159+
shikiTheme={["github-light", myCustomDarkTheme]}
160+
>
161+
{markdown}
162+
</Streamdown>
163+
);
164+
}
165+
```
166+
167+
<Callout type="info">
168+
Bundled theme names (strings) load from Shiki's built-in registry. Custom theme objects follow the `ThemeRegistrationAny` format from Shiki — any VS Code `.tmTheme` or JSON theme file works.
169+
</Callout>
170+
171+
## Custom start line
172+
173+
Set the starting line number for a code block using `startLine=N` in the code fence meta:
174+
175+
````markdown
176+
```typescript startLine=10
177+
const user = await getUser(id);
178+
const profile = await getProfile(user);
179+
```
180+
````
181+
182+
Line numbers begin at the value you specify instead of 1. The value must be a positive integer (>= 1).
183+
146184
## Interactive Features
147185

148186
### Copy Button

apps/website/content/docs/components.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,32 @@ Use `data*` in the attributes array to allow all `data-*` attributes on a tag:
306306
If you provide custom `rehypePlugins`, you'll need to configure `rehype-sanitize` yourself to allow custom tags. See the [Security](/docs/security) documentation for details.
307307
</Callout>
308308

309+
### Plain text tag content
310+
311+
By default, children of custom HTML tags are parsed as markdown. This means underscores, asterisks, and other markdown metacharacters in tag content get formatted unexpectedly — for example, `<mention>some_user_name</mention>` renders with italicized text instead of a literal underscore.
312+
313+
Use the `literalTagContent` prop to treat the children of specific tags as plain text:
314+
315+
```tsx title="app/page.tsx"
316+
<Streamdown
317+
allowedTags={{
318+
mention: ["user_id"],
319+
}}
320+
literalTagContent={["mention"]}
321+
components={{
322+
mention: ({ user_id, children }) => (
323+
<span className="text-blue-600">@{children}</span>
324+
),
325+
}}
326+
>
327+
{markdown}
328+
</Streamdown>
329+
```
330+
331+
<Callout type="warn">
332+
Tags listed in `literalTagContent` must also be listed in `allowedTags`. Otherwise the tag is stripped by the sanitizer before literal content handling applies.
333+
</Callout>
334+
309335
### Security Considerations
310336

311337
When allowing custom HTML tags:

apps/website/content/docs/configuration.mdx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ Streamdown can be configured to suit your needs. This guide will walk you throug
5252
default: "streaming",
5353
options: ["streaming", "static"],
5454
},
55+
dir: {
56+
description:
57+
"Text direction. 'auto' detects per-block using the first strong character algorithm.",
58+
type: '"auto" | "ltr" | "rtl"',
59+
},
5560
}}
5661
/>
5762

@@ -61,8 +66,8 @@ Streamdown can be configured to suit your needs. This guide will walk you throug
6166
type={{
6267
shikiTheme: {
6368
description:
64-
"Light and dark themes for code syntax highlighting. Any Shiki theme name can be used - bundled themes (github-light, github-dark) load instantly, others load from CDN.",
65-
type: "[string, string]",
69+
"Light and dark themes for code syntax highlighting. Accepts bundled theme names or custom theme objects (ThemeRegistrationAny).",
70+
type: "[ThemeInput, ThemeInput]",
6671
default: "['github-light', 'github-dark']",
6772
},
6873
components: {
@@ -74,6 +79,16 @@ Streamdown can be configured to suit your needs. This guide will walk you throug
7479
"Custom HTML tags to allow through sanitization, with their permitted attributes. Use with 'components' to render custom tags like <ref> or <mention>. Only works with default rehype plugins.",
7580
type: "Record<string, string[]>",
7681
},
82+
literalTagContent: {
83+
description:
84+
"Tags whose children are treated as plain text (no markdown parsing). Useful when tag children contain underscores or asterisks that would otherwise be formatted. Tags must also appear in allowedTags.",
85+
type: "string[]",
86+
},
87+
prefix: {
88+
description:
89+
"Tailwind CSS prefix prepended to all utility classes. Enables Tailwind v4 prefix() support. User-supplied className values are also prefixed.",
90+
type: "string",
91+
},
7792
}}
7893
/>
7994

@@ -132,6 +147,16 @@ Math rendering and CJK support require installing separate plugins. See [Mathema
132147
description: "Plugin configuration for math, mermaid, code highlighting, and CJK support. See [Plugins](/docs/plugins).",
133148
type: "PluginConfig",
134149
},
150+
icons: {
151+
description:
152+
"Custom icons to override the defaults used in controls. See the IconMap interface for available keys.",
153+
type: "Partial<IconMap>",
154+
},
155+
translations: {
156+
description:
157+
"Override default English labels for controls and modals. See [Internationalization](/docs/internationalization).",
158+
type: "Partial<StreamdownTranslations>",
159+
},
135160
caret: {
136161
description: "Show a caret indicator at the end of streaming content. See [Carets](/docs/carets).",
137162
type: '"block" | "circle"',
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
title: Internationalization
3+
description: Override default English labels with your own translations.
4+
type: reference
5+
summary: Localize all UI labels in Streamdown controls and modals.
6+
prerequisites:
7+
- /docs/getting-started
8+
related:
9+
- /docs/configuration
10+
- /docs/interactivity
11+
---
12+
13+
Streamdown ships with English labels for all interactive controls — copy buttons, download menus, link modals, and more. Override any label via the `translations` prop.
14+
15+
## Basic usage
16+
17+
Pass a partial translations object to replace specific labels:
18+
19+
```tsx title="app/page.tsx"
20+
<Streamdown
21+
translations={{
22+
copyCode: "Copiar código",
23+
close: "Cerrar",
24+
openLink: "Abrir enlace",
25+
downloadImage: "Descargar imagen",
26+
}}
27+
>
28+
{markdown}
29+
</Streamdown>
30+
```
31+
32+
## Available translation keys
33+
34+
### Code block
35+
36+
<TypeTable
37+
type={{
38+
copyCode: {
39+
description: "Tooltip for the code copy button",
40+
type: "string",
41+
default: '"Copy Code"',
42+
},
43+
downloadFile: {
44+
description: "Tooltip for the file download button",
45+
type: "string",
46+
default: '"Download file"',
47+
},
48+
}}
49+
/>
50+
51+
### Mermaid diagrams
52+
53+
<TypeTable
54+
type={{
55+
downloadDiagram: {
56+
description: "Label for the diagram download button",
57+
type: "string",
58+
default: '"Download diagram"',
59+
},
60+
downloadDiagramAsSvg: {
61+
description: "Download diagram as SVG option",
62+
type: "string",
63+
default: '"Download diagram as SVG"',
64+
},
65+
downloadDiagramAsPng: {
66+
description: "Download diagram as PNG option",
67+
type: "string",
68+
default: '"Download diagram as PNG"',
69+
},
70+
downloadDiagramAsMmd: {
71+
description: "Download diagram as MMD option",
72+
type: "string",
73+
default: '"Download diagram as MMD"',
74+
},
75+
viewFullscreen: {
76+
description: "Toggle fullscreen button label",
77+
type: "string",
78+
default: '"View fullscreen"',
79+
},
80+
exitFullscreen: {
81+
description: "Exit fullscreen button label",
82+
type: "string",
83+
default: '"Exit fullscreen"',
84+
},
85+
mermaidFormatSvg: {
86+
description: "Short format label for SVG",
87+
type: "string",
88+
default: '"SVG"',
89+
},
90+
mermaidFormatPng: {
91+
description: "Short format label for PNG",
92+
type: "string",
93+
default: '"PNG"',
94+
},
95+
mermaidFormatMmd: {
96+
description: "Short format label for MMD",
97+
type: "string",
98+
default: '"MMD"',
99+
},
100+
}}
101+
/>
102+
103+
### Table
104+
105+
<TypeTable
106+
type={{
107+
copyTable: {
108+
description: "Label for the table copy button",
109+
type: "string",
110+
default: '"Copy table"',
111+
},
112+
copyTableAsMarkdown: {
113+
description: "Copy as Markdown option",
114+
type: "string",
115+
default: '"Copy table as Markdown"',
116+
},
117+
copyTableAsCsv: {
118+
description: "Copy as CSV option",
119+
type: "string",
120+
default: '"Copy table as CSV"',
121+
},
122+
copyTableAsTsv: {
123+
description: "Copy as TSV option",
124+
type: "string",
125+
default: '"Copy table as TSV"',
126+
},
127+
downloadTable: {
128+
description: "Label for the table download button",
129+
type: "string",
130+
default: '"Download table"',
131+
},
132+
downloadTableAsCsv: {
133+
description: "Download table as CSV option",
134+
type: "string",
135+
default: '"Download table as CSV"',
136+
},
137+
downloadTableAsMarkdown: {
138+
description: "Download table as Markdown option",
139+
type: "string",
140+
default: '"Download table as Markdown"',
141+
},
142+
tableFormatMarkdown: {
143+
description: "Short format label for Markdown",
144+
type: "string",
145+
default: '"Markdown"',
146+
},
147+
tableFormatCsv: {
148+
description: "Short format label for CSV",
149+
type: "string",
150+
default: '"CSV"',
151+
},
152+
tableFormatTsv: {
153+
description: "Short format label for TSV",
154+
type: "string",
155+
default: '"TSV"',
156+
},
157+
}}
158+
/>
159+
160+
### Image
161+
162+
<TypeTable
163+
type={{
164+
imageNotAvailable: {
165+
description: "Fallback text for broken images",
166+
type: "string",
167+
default: '"Image not available"',
168+
},
169+
downloadImage: {
170+
description: "Tooltip for the image download button",
171+
type: "string",
172+
default: '"Download image"',
173+
},
174+
}}
175+
/>
176+
177+
### Link modal
178+
179+
<TypeTable
180+
type={{
181+
openExternalLink: {
182+
description: "Modal title for external links",
183+
type: "string",
184+
default: '"Open external link?"',
185+
},
186+
externalLinkWarning: {
187+
description: "Warning text in the link modal",
188+
type: "string",
189+
default: '"You\'re about to visit an external website."',
190+
},
191+
close: {
192+
description: "Close button label",
193+
type: "string",
194+
default: '"Close"',
195+
},
196+
copyLink: {
197+
description: "Copy link button label",
198+
type: "string",
199+
default: '"Copy link"',
200+
},
201+
copied: {
202+
description: "Label shown after copying",
203+
type: "string",
204+
default: '"Copied"',
205+
},
206+
openLink: {
207+
description: "Open link button label",
208+
type: "string",
209+
default: '"Open link"',
210+
},
211+
}}
212+
/>
213+
214+
## Partial overrides
215+
216+
The `translations` prop accepts `Partial<StreamdownTranslations>`. Any key you omit falls back to the built-in English default:
217+
218+
```tsx title="app/page.tsx"
219+
// Only override what you need — everything else stays English
220+
<Streamdown translations={{ copyCode: "コピー", close: "閉じる" }}>
221+
{markdown}
222+
</Streamdown>
223+
```
224+
225+
## Access translations in custom components
226+
227+
Use the `useTranslations` hook inside custom components to read the active translations:
228+
229+
```tsx title="app/page.tsx"
230+
import { useTranslations } from "streamdown";
231+
232+
function CustomCodeBlock({ children }) {
233+
const translations = useTranslations();
234+
235+
return (
236+
<div>
237+
<button>{translations.copyCode}</button>
238+
<pre><code>{children}</code></pre>
239+
</div>
240+
);
241+
}
242+
```
243+
244+
## Exported types and values
245+
246+
```tsx
247+
import type { StreamdownTranslations } from "streamdown";
248+
import { defaultTranslations, useTranslations } from "streamdown";
249+
```
250+
251+
- `StreamdownTranslations` — interface with all 37 translation keys
252+
- `defaultTranslations` — the built-in English defaults
253+
- `useTranslations()` — React hook returning the active translations object

0 commit comments

Comments
 (0)