react-native-markdown-renderer
v4.1.1
Published
Markdown renderer for react-native, with CommonMark spec support + adds syntax extensions & sugar (URL autolinking, typographer).
Maintainers
Readme
React Native Markdown Renderer
A 100% CommonMark-compatible markdown renderer for React Native using native components (not WebView). All elements are rendered as native React Native components that can be overwritten when needed.
npm: react-native-markdown-renderer | GitHub: mientjan/react-native-markdown-renderer | Changelog: CHANGELOG.md
Installation
npm install react-native-markdown-rendererRequirements
| Dependency | Version | | ------------ | ---------- | | React | >= 18.0.0 | | React Native | >= 0.73.0 |
Basic Usage
import React from 'react';
import Markdown from 'react-native-markdown-renderer';
const App = () => (
<Markdown>
{`# Hello World
This is **bold** and *italic* text.
- Item 1
- Item 2
`}
</Markdown>
);Examples
The example/ directory contains an Expo app with multiple screens demonstrating key features:
| Screen | Description | Source |
|--------|-------------|--------|
| Basic Markdown | Default rendering | BasicExample.tsx |
| From .md File | Load markdown from a file asset | MarkdownFileExample.tsx |
| Custom Styles | Override default styles | CustomStylesExample.tsx |
| Custom Rules | Replace render rules | CustomRulesExample.tsx |
| Custom Renderer | Provide a custom AstRenderer | CustomRendererExample.tsx |
To run the example app:
cd example
npm install
npx expo startTypeScript Support
This library is written in TypeScript and ships with full type definitions.
import Markdown, {
AstRenderer,
renderRules,
styles,
PluginContainer,
type MarkdownProps,
type RenderRules,
type ASTNode,
type RenderFunction,
type MarkdownStyles,
} from 'react-native-markdown-renderer';Custom Styles
By default, custom styles are deep-merged with the built-in defaults — so you only need to specify properties you want to override. Set mergeStyle={false} to replace entire style objects instead.
import Markdown from 'react-native-markdown-renderer';
const customStyles = {
heading1: { fontSize: 40, color: '#333' }, // keeps default fontWeight, lineHeight, etc.
strong: { fontWeight: '800' },
paragraph: { marginVertical: 8 },
};
const App = () => (
<Markdown style={customStyles}>
{'# Styled Heading\n\n**Bold text** in a paragraph.'}
</Markdown>
);Custom Render Rules
import React from 'react';
import { Text, View } from 'react-native';
import Markdown from 'react-native-markdown-renderer';
import type { ASTNode, RenderRules } from 'react-native-markdown-renderer';
const customRules: Partial<RenderRules> = {
heading1: (node: ASTNode, children, parent, styles) => (
<View key={node.key} style={{ backgroundColor: '#eee', padding: 10 }}>
<Text style={{ fontSize: 28 }}>{children}</Text>
</View>
),
};
const App = () => (
<Markdown rules={customRules}>
{'# Custom Heading'}
</Markdown>
);Plugins
This library uses markdown-it as its parser. Any markdown-it plugin can be used:
import Markdown, { PluginContainer } from 'react-native-markdown-renderer';
import markdownItCheckbox from 'markdown-it-checkbox';
const plugins = [new PluginContainer(markdownItCheckbox)];
const App = () => (
<Markdown plugins={plugins}>
{'- [ ] Unchecked\n- [x] Checked'}
</Markdown>
);Handling Links
By default, links open via Linking.openURL(). Use the onLinkPress prop to customize:
const App = () => (
<Markdown onLinkPress={(url) => {
console.log('Link pressed:', url);
// return nothing to prevent default behavior
}}>
{'[Visit Example](https://example.com)'}
</Markdown>
);Image Validation
Control which image URL schemes are allowed. Images with unrecognized schemes get the defaultImageHandler prepended, or are skipped entirely when set to null:
<Markdown
allowedImageHandlers={['https://', 'data:image/png;base64']}
defaultImageHandler={null} // skip images that don't match
>
{''}
</Markdown>Preview Mode
Limit how many top-level elements render — useful for content previews:
import { Text } from 'react-native';
<Markdown
maxTopLevelChildren={3}
topLevelMaxExceededItem={<Text key="more">Read more...</Text>}
>
{longMarkdownContent}
</Markdown>Props
| Prop | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| children | string \| string[] | — | Markdown content to render (required) |
| rules | RenderRules | — | Custom render rules for element types |
| style | Partial<MarkdownStyles> | — | Custom styles (merged with defaults by default) |
| mergeStyle | boolean | true | Deep-merge custom styles with defaults per key. Set false for shallow replace |
| onLinkPress | (url: string) => boolean \| void | — | Custom link press handler. Falls back to Linking.openURL() |
| renderer | AstRenderer \| ((nodes) => ReactElement) | — | Fully custom renderer (overrides rules/style) |
| markdownit | MarkdownIt | MarkdownIt({ typographer: true }) | Custom markdown-it instance |
| plugins | PluginContainer[] | [] | markdown-it plugins |
| debugPrintTree | boolean | false | Log the AST tree structure to the console |
| maxTopLevelChildren | number \| null | null | Limit rendered top-level children (preview mode) |
| topLevelMaxExceededItem | ReactNode | <Text>...</Text> | Shown when maxTopLevelChildren is exceeded |
| allowedImageHandlers | string[] | ['data:image/png;base64', ..., 'https://', 'http://'] | Allowed image URL prefixes |
| defaultImageHandler | string \| null | 'http://' | Prepended to images with unrecognized schemes. null to skip |
Syntax Support
- Headings (1-6)
- Emphasis (bold, italic, ~~strikethrough~~)
- Blockquotes
- Lists (ordered and unordered)
- Code (inline and blocks)
- Tables
- Links
- Images
- Horizontal rules
- Typographic replacements
- Plugins for extra syntax support via markdown-it plugins
Documentation
For comprehensive documentation, visit the Wiki:
What's New in v4.1.0
onLinkPressprop — custom link press handler instead of hardcodedLinking.openURL()mergeStyleprop (defaulttrue) — deep-merge custom styles with defaults per keydebugPrintTreeprop — log AST tree structure to console for debuggingmaxTopLevelChildren+topLevelMaxExceededItem— preview mode to limit rendered childrenallowedImageHandlers+defaultImageHandler— validate image URLs before rendering- Image accessibility —
accessibilityLabelfrom image alt text - Hardbreak fix — renders as
<Text>{'\n'}</Text>instead of<View>(fixes Android crash inside Text) - Code block fix — trims trailing newline from
code_blockandfencecontent - Ordered list fix — respects the
startattribute (e.g.57. foorenders as 57)
Migration from v3 to v4
Breaking Changes
- Minimum React 18.0.0 (was 16.2.0)
- Minimum React Native 0.73.0 (was 0.50.4)
react-native-fit-imageremoved - The defaultimagerender rule now uses React Native's built-in<Image>. If you need auto-sizing, provide a customimagerender rule.prop-typesremoved - Use TypeScript for type checking.- Class component replaced with function component - The
<Markdown>component is now a function component. Any code relying on class refs will break. markdown-itupgraded from ^8 to ^14 - Custom markdown-it plugins should verify compatibility.- Package entry points changed -
mainpoints tolib/commonjs/,moduletolib/module/,typestolib/typescript/.
License
MIT
