0
# Component Overrides
1
2
Powerful system for replacing any HTML tag with custom React components, including props injection and component mapping.
3
4
## Capabilities
5
6
### Override System
7
8
Flexible mechanism to replace any HTML tag rendered by markdown with custom React components or modified props.
9
10
```typescript { .api }
11
interface Override {
12
/** React component to replace the default HTML tag */
13
component?: React.ElementType;
14
/** Props to inject into the rendered element */
15
props?: object;
16
}
17
18
type Overrides = {
19
/** Override any standard HTML tag */
20
[tag in HTMLTags]?: Override | React.ElementType;
21
} & {
22
/** Override custom components by name */
23
[customComponent: string]: Override | React.ElementType;
24
};
25
26
type HTMLTags = keyof React.JSX.IntrinsicElements;
27
```
28
29
**Usage Examples:**
30
31
```typescript
32
import Markdown from "markdown-to-jsx";
33
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
34
35
// Component replacement
36
const CustomLink = ({ href, children, ...props }) => (
37
<a
38
href={href}
39
target="_blank"
40
rel="noopener noreferrer"
41
className="external-link"
42
{...props}
43
>
44
{children} π
45
</a>
46
);
47
48
// Props injection
49
const markdownOptions = {
50
overrides: {
51
// Replace component entirely
52
a: CustomLink,
53
54
// Component with props
55
h1: {
56
component: "h2",
57
props: { className: "main-title" }
58
},
59
60
// Props only (keeps original tag)
61
p: {
62
props: { className: "paragraph" }
63
},
64
65
// Code block with syntax highlighting
66
code: {
67
component: ({ className, children, ...props }) => {
68
const lang = className?.replace('lang-', '') || 'text';
69
return (
70
<SyntaxHighlighter language={lang} {...props}>
71
{children}
72
</SyntaxHighlighter>
73
);
74
}
75
}
76
}
77
};
78
79
function App() {
80
return (
81
<Markdown options={markdownOptions}>
82
# This becomes h2 with class "main-title"
83
84
This paragraph gets the "paragraph" class.
85
86
[This link](https://example.com) opens in new tab with icon.
87
88
```javascript
89
// This code gets syntax highlighting
90
const hello = "world";
91
```
92
</Markdown>
93
);
94
}
95
```
96
97
### Component Replacement
98
99
Replace any HTML tag with a custom React component while preserving all functionality.
100
101
```typescript { .api }
102
/**
103
* Replace HTML tag with custom component
104
* Component receives all standard HTML attributes plus children
105
*/
106
type ComponentOverride = React.ElementType;
107
108
// Usage in overrides
109
const overrides = {
110
tagName: CustomComponent
111
};
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
// Custom heading component
118
const CustomHeading = ({ level, id, children, ...props }) => {
119
const Tag = `h${level}`;
120
return (
121
<Tag
122
id={id}
123
className={`heading-${level}`}
124
{...props}
125
>
126
<span className="heading-icon">#</span>
127
{children}
128
</Tag>
129
);
130
};
131
132
// Custom image component with lazy loading
133
const LazyImage = ({ src, alt, title, ...props }) => {
134
return (
135
<img
136
src={src}
137
alt={alt}
138
title={title}
139
loading="lazy"
140
className="responsive-image"
141
{...props}
142
/>
143
);
144
};
145
146
// Custom list component
147
const CustomList = ({ ordered, start, children, ...props }) => {
148
const Tag = ordered ? "ol" : "ul";
149
return (
150
<Tag
151
start={start}
152
className={`list ${ordered ? 'ordered' : 'unordered'}`}
153
{...props}
154
>
155
{children}
156
</Tag>
157
);
158
};
159
160
const options = {
161
overrides: {
162
h1: CustomHeading,
163
h2: CustomHeading,
164
h3: CustomHeading,
165
img: LazyImage,
166
ul: CustomList,
167
ol: CustomList
168
}
169
};
170
```
171
172
### Props Injection
173
174
Add or modify props for HTML elements without changing the component type.
175
176
```typescript { .api }
177
/**
178
* Props injection configuration
179
* Props are merged with existing attributes, with override props taking precedence
180
*/
181
interface PropsOverride {
182
props: object;
183
component?: React.ElementType; // Optional component replacement
184
}
185
```
186
187
**Usage Examples:**
188
189
```typescript
190
const options = {
191
overrides: {
192
// Add classes to all paragraphs
193
p: {
194
props: { className: "prose-paragraph" }
195
},
196
197
// Style all blockquotes
198
blockquote: {
199
props: {
200
className: "quote",
201
style: {
202
borderLeft: "4px solid #ccc",
203
paddingLeft: "1rem",
204
fontStyle: "italic"
205
}
206
}
207
},
208
209
// Make all tables responsive
210
table: {
211
props: {
212
className: "table-responsive",
213
style: { width: "100%" }
214
}
215
},
216
217
// Add target to all links
218
a: {
219
props: {
220
target: "_blank",
221
rel: "noopener noreferrer"
222
}
223
}
224
}
225
};
226
227
// Markdown content
228
const content = `
229
# Title
230
231
This is a paragraph that will get the "prose-paragraph" class.
232
233
> This blockquote gets custom styling.
234
235
| Col 1 | Col 2 |
236
|-------|-------|
237
| A | B |
238
239
[This link](https://example.com) opens in new tab.
240
`;
241
```
242
243
### Class Name Merging
244
245
Override props are intelligently merged with existing attributes, with special handling for className.
246
247
```typescript
248
// Built-in classes are preserved and merged
249
const options = {
250
overrides: {
251
code: {
252
props: { className: "custom-code" }
253
}
254
}
255
};
256
257
// Fenced code block with language
258
const markdown = `
259
\`\`\`javascript
260
const code = "example";
261
\`\`\`
262
`;
263
264
// Results in: <code className="lang-javascript custom-code">
265
```
266
267
### Advanced Override Patterns
268
269
Complex override scenarios for sophisticated component replacement and prop manipulation.
270
271
**Usage Examples:**
272
273
```typescript
274
// Conditional component based on props
275
const SmartImage = ({ alt, src, ...props }) => {
276
const isExternal = src.startsWith('http');
277
278
if (isExternal) {
279
return (
280
<figure className="external-image">
281
<img src={src} alt={alt} {...props} />
282
<figcaption>External: {alt}</figcaption>
283
</figure>
284
);
285
}
286
287
return <img src={src} alt={alt} {...props} />;
288
};
289
290
// Dynamic component based on content
291
const SmartCode = ({ className, children, ...props }) => {
292
const language = className?.replace('lang-', '');
293
294
// Inline code
295
if (!language) {
296
return <code className="inline-code" {...props}>{children}</code>;
297
}
298
299
// Block code with syntax highlighting
300
return (
301
<SyntaxHighlighter
302
language={language}
303
className="code-block"
304
{...props}
305
>
306
{children}
307
</SyntaxHighlighter>
308
);
309
};
310
311
// Wrapper component that adds functionality
312
const InteractiveHeading = ({ children, id, ...props }) => {
313
const handleClick = () => {
314
navigator.clipboard.writeText(`#${id}`);
315
};
316
317
return (
318
<h2 id={id} onClick={handleClick} className="interactive-heading" {...props}>
319
{children}
320
<button className="copy-link" aria-label="Copy link">π</button>
321
</h2>
322
);
323
};
324
325
const advancedOptions = {
326
overrides: {
327
img: SmartImage,
328
code: SmartCode,
329
h2: InteractiveHeading
330
}
331
};
332
```
333
334
### Override Validation
335
336
TypeScript provides compile-time validation for override configurations to prevent common mistakes.
337
338
```typescript
339
const options = {
340
overrides: {
341
// β Valid - React component
342
p: CustomParagraph,
343
344
// β Valid - HTML tag string
345
h1: "h2",
346
347
// β Valid - Override object
348
a: {
349
component: CustomLink,
350
props: { className: "link" }
351
},
352
353
// β TypeScript error - invalid override
354
span: { invalidProp: true },
355
356
// β TypeScript error - not a valid HTML tag
357
invalidTag: CustomComponent
358
}
359
};
360
```