High-performance, extensible React Native Markdown component with full remark plugin support.
- 🚀 High Performance: Direct AST-to-React Native rendering (no HTML conversion)
- 🔌 Extensible: Full support for remark plugins and custom renderers
- 📦 Lightweight: Only depends on remark-related packages
- 🎨 Customizable: Full control over styles and rendering(Light and Dark mode
- đź’Ş TypeScript: Complete type definitions included
- ⚡ Optimized: Built-in memoization and caching
npm install @hake/react-native-markdown
# or
yarn add @hake/react-native-markdown
# or
bun add @hake/react-native-markdownimport { MarkdownView } from '@hake/react-native-markdown';
function App() {
return (
<MarkdownView>
{`# Hello World
This is **bold** and this is *italic*.
- Item 1
- Item 2
- Item 3`}
</MarkdownView>
);
}import { MarkdownView } from '@hake/react-native-markdown';
<MarkdownView>
{`# Heading 1
## Heading 2
A paragraph with **bold** and *italic* text.
\`\`\`javascript
const code = 'example';
\`\`\``}
</MarkdownView>import { MarkdownView } from '@hake/react-native-markdown';
import type { MarkdownStyles } from '@hake/react-native-markdown';
const customStyles: MarkdownStyles = {
heading: {
fontSize: 28,
fontWeight: 'bold',
color: '#333',
},
paragraph: {
marginBottom: 16,
lineHeight: 24,
},
link: {
color: '#0066cc',
textDecorationLine: 'underline',
},
};
<MarkdownView styles={customStyles}>
{markdownContent}
</MarkdownView>import { MarkdownView } from '@hake/react-native-markdown';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
<MarkdownView
plugins={[
{ plugin: remarkGfm },
{ plugin: remarkMath, options: { /* options */ } },
]}
>
{markdownContent}
</MarkdownView>import { MarkdownView } from '@hake/react-native-markdown';
import type { NodeRenderer } from '@hake/react-native-markdown';
import type { Heading } from 'mdast';
import { Text } from 'react-native';
const customHeadingRenderer: NodeRenderer<Heading> = (node, children) => {
return (
<Text style={{ fontSize: 24, fontWeight: 'bold', color: 'purple' }}>
{children}
</Text>
);
};
<MarkdownView
renderers={{
heading: customHeadingRenderer,
}}
>
{markdownContent}
</MarkdownView>This package supports syntax highlighting for code blocks using react-native-code-highlighter and react-syntax-highlighter.
import { MarkdownView } from '@hake/react-native-markdown';
import { atomOneDarkReasonable } from 'react-syntax-highlighter/dist/esm/styles/hljs';
<MarkdownView
codeHighlighter={{
hljsStyle: atomOneDarkReasonable,
textStyle: { fontSize: 14 },
}}
>
{`\`\`\`javascript
const hello = "world";
console.log(hello);
\`\`\``}
</MarkdownView>Note: All code (both inline and block) is rendered using CodeHighlighter. If hljsStyle is not provided, the default theme will be used.
import { Linking } from 'react-native';
<MarkdownView
onLinkPress={(url) => {
Linking.openURL(url).catch((err) => {
console.error('Failed to open URL:', err);
});
}}
>
{markdownContent}https://raw.githubusercontent.com/GetStream/stream-chat-react-native/master/screenshots/3.png
</MarkdownView>Main component for rendering markdown.
| Prop | Type | Default | Description |
|---|---|---|---|
children |
string |
required | Markdown content to render |
styles |
MarkdownStyles |
undefined |
Custom styles for markdown elements |
renderers |
CustomRenderers |
undefined |
Custom renderers for specific node types |
plugins |
RemarkPlugin[] |
[] |
Remark plugins to use |
debug |
boolean |
false |
Enable debug logging |
maxListDepth |
number |
10 |
Maximum depth for nested lists |
onLinkPress |
(url: string) => void |
undefined |
Callback when a link is pressed |
onImageError |
(error: Error) => void |
undefined |
Callback when an image fails to load |
codeHighlighter |
CodeHighlighterConfig |
undefined |
Configuration for code syntax highlighting |
Interface for customizing markdown element styles. https://raw.githubusercontent.com/GetStream/stream-chat-react-native/master/screenshots/3.png
interface MarkdownStyles {
heading?: TextStyle;
heading1?: TextStyle;
heading2?: TextStyle;
heading3?: TextStyle;
heading4?: TextStyle;
heading5?: TextStyle;
heading6?: TextStyle;
paragraph?: TextStyle;
text?: TextStyle;
strong?: TextStyle;
emphasis?: TextStyle;
code?: TextStyle;
codeBlock?: ViewStyle & { container?: ViewStyle };
inlineCode?: TextStyle;
link?: TextStyle;
image?: ImageStyle;
list?: ViewStyle;
listItem?: ViewStyle;
orderedList?: ViewStyle;
unorderedList?: ViewStyle;
blockquote?: ViewStyle & { text?: TextStyle };
horizontalRule?: ViewStyle;
}Hook for parsing markdown asynchronously.
const { ast, error, isLoading } = useMarkdown(markdown, plugins);Hook for merging custom styles with defaults.
const styles = useMarkdownStyles(customStyles);This package supports the full remark plugin ecosystem. Here are some popular plugins:
- remark-gfm - GitHub Flavored Markdown
- remark-math - Math support
- remark-breaks - Hard line breaks
- remark-frontmatter - Frontmatter support
Example:
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
<MarkdownView plugins={[{ plugin: remarkGfm }, { plugin: remarkMath }]}>
{markdownContent}
</MarkdownView>You can create custom renderers for any node type:
import type { NodeRenderer } from '@hake/react-native-markdown';
import type { Code } from 'mdast';
import { Text } from 'react-native';
const myCodeRenderer: NodeRenderer<Code> = (node, children, context) => {
return (
<Text style={context.styles.code}>
{node.value}
</Text>
);
};
<MarkdownView renderers={{ code: myCodeRenderer }}>
{markdownContent}
</MarkdownView>This package is written in TypeScript and includes full type definitions. All types are exported for use in your code:
import type {
MarkdownViewProps,
MarkdownStyles,
CustomRenderers,
RemarkPlugin,
NodeRenderer,
} from '@hake/react-native-markdown';Contributions are welcome! Please feel free to submit a Pull Request.
MIT



