Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 71 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- πŸ–ΌοΈ Inline and block image rendering
- πŸŒ™ Dark Mode support
- βš™οΈ Custom renderers and styles for flexible UI customization
- 🧩 Supports Remark plugins to enhance capabilities

## Installation

Expand All @@ -62,33 +63,33 @@ This is a **Markdown** example with [a link](https://reactnative.dev).

export default function App() {
return (
<Markdown
markdown={markdown}
customRenderers={{
// Override default renderers for mdast nodes.
// Checkout https://github.com/imwithye/react-native-remark/blob/main/src/renderers/index.tsx
// for the default renderers.
InlineCodeRenderer: ({ node }) => (
<Text style={{ color: "blue" }}>{node.value}</Text>
),
ThematicBreakRenderer: () => (
<View style={{ height: 5, backgroundColor: "red" }} />
),
}}
customStyles={{
// Override default styles
// Checkout https://github.com/imwithye/react-native-remark/blob/main/src/themes/default.tsx
// for the default styles.
inlineCode: {
color: "red",
},
text: {
color: "red",
},
}}
onCodeCopy={(code) => Clipboard.setStringAsync(code)}
onLinkPress={(url) => Linking.openURL(url)}
/>
<Markdown
markdown={markdown}
customRenderers={{
// Override default renderers for mdast nodes.
// Checkout https://github.com/imwithye/react-native-remark/blob/main/src/renderers/index.tsx
// for the default renderers.
InlineCodeRenderer: ({ node }) => (
<Text style={{ color: "blue" }}>{node.value}</Text>
),
ThematicBreakRenderer: () => (
<View style={{ height: 5, backgroundColor: "red" }} />
),
}}
customStyles={{
// Override default styles
// Checkout https://github.com/imwithye/react-native-remark/blob/main/src/themes/default.tsx
// for the default styles.
inlineCode: {
color: "red",
},
text: {
color: "red",
},
}}
onCodeCopy={(code) => Clipboard.setStringAsync(code)}
onLinkPress={(url) => Linking.openURL(url)}
/>
);
}
```
Expand All @@ -110,9 +111,11 @@ index?: number;

Checkout [renderers](./src/renderers/) for the default implementations. To ensure type safety when creating custom renderers, you can use the `RendererArgs<MdastType>` props interface.

Note that the library ships with renderers for the `remark-gfm` plugin since we think it is often used. You don't need to pass custom renderers (though you can!) for this plugin.

## Supported Themes

Themes are pre-defined style collections that provide consistent visual styling for markdown content. Currently, we support two built-in themes:
Themes are pre-defined style collections that provide consistent visual styling for markdown content. Currently, we support two built-in themes:

1. default
2. serif
Expand All @@ -124,7 +127,7 @@ To use a theme, you can follow this pattern:
import { themes } from "react-native-remark"
const { serifTheme } = themes;

// Thene you can use it with
// Then you can use it with
<Markdown theme={serifTheme} ... />
```

Expand All @@ -134,28 +137,45 @@ Custom styles will override the selected theme's default styles.

Checkout [default.tsx](./src/themes/default.tsx) for default styles.

| Style Key | Description | Example Markdown Element |
|-------------------|---------------------------------------|-------------------------------|
| `blockquote` | Styles for blockquotes | `> This is a blockquote` |
| `borderColor` | Default border color used globally | Borders, thematic breaks |
| `break` | Line break styling (empty by default) | Line breaks |
| `codeBlock` | Styles for code blocks | ```code``` blocks |
| `container` | Container layout spacing | Root container layout |
| `delete` | Deleted text style | ~~strikethrough~~ text |
| `emphasis` | Italic text style | *italic* or _italic_ |
| `footnoteReference` | Style for footnote references | Footnote markers |
| `heading` | Heading styles (h1, h2, h3...) | # Heading |
| `image` | Image styling | Inline or block images |
| `inlineCode` | Inline code styling | `inline code` |
| `link` | Link styling | [link](url) |
| `linkReference` | Reference-style links | [reference][id] |
| `list` | List container styling | Lists (`- item` or `1. item`) |
| `listItem` | List item styling | Each list item |
| `paragraph` | Paragraph text styling | Normal paragraphs |
| `strong` | Bold text style | **bold** |
| `tableCell` | Table cell text styling | Table cell contents |
| `text` | General text style | Plain text |
| `thematicBreak` | Horizontal rule styling | --- |
| Style Key | Description | Example Markdown Element |
| ------------------- | ------------------------------------- | ----------------------------- |
| `blockquote` | Styles for blockquotes | `> This is a blockquote` |
| `borderColor` | Default border color used globally | Borders, thematic breaks |
| `break` | Line break styling (empty by default) | Line breaks |
| `codeBlock` | Styles for code blocks | `code` blocks |
| `container` | Container layout spacing | Root container layout |
| `delete` | Deleted text style | ~~strikethrough~~ text |
| `emphasis` | Italic text style | *italic* or _italic_ |
| `footnoteReference` | Style for footnote references | Footnote markers |
| `heading` | Heading styles (h1, h2, h3...) | # Heading |
| `image` | Image styling | Inline or block images |
| `inlineCode` | Inline code styling | `inline code` |
| `link` | Link styling | [link](url) |
| `linkReference` | Reference-style links | [reference][id] |
| `list` | List container styling | Lists (`- item` or `1. item`) |
| `listItem` | List item styling | Each list item |
| `paragraph` | Paragraph text styling | Normal paragraphs |
| `strong` | Bold text style | **bold** |
| `tableCell` | Table cell text styling | Table cell contents |
| `text` | General text style | Plain text |
| `thematicBreak` | Horizontal rule styling | --- |

## Remark plugins usage

You can inject Remark plugins _via_ the `remarkPlugins` prop. For example, you can use `remark-cjk-friendly` to add support for bold (`**`) with Chinese, Japanese and Korean alphabets by doing the following:

```jsx
import remarkCjkFriendly from "remark-cjk-friendly";
import remarkGfm from "remark-gfm";

<Markdown remarkPlugins={[remarkGfm, remarkCjkFriendly]} /* ... */ />;
```

Note that:

- though `remark-gfm` is supported out of the box, you'll need to add the plugin manually when injecting other Remark plugins
- when using plugins that add support for additional nodes, you'll need to inject the required renderers using the `customRenderers` prop
- ⚠️ asynchronous plugins aren't supported yet; passing any asynchronous plugin will result in a crash ⚠️

## Quick Look

Expand All @@ -177,4 +197,3 @@ By interacting with this repository, organization, or community you agree to abi
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=imwithye/react-native-remark&type=Date" width="100%" />
</picture>
</a>

52 changes: 38 additions & 14 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import {
ActionSheetProvider,
useActionSheet,
} from "@expo/react-native-action-sheet";
import { Markdown } from "@react-native-remark";
import { themes } from "@react-native-remark";
import { Markdown, themes } from "@react-native-remark";
import {
createStaticNavigation,
useNavigation,
} from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import {
ActivityIndicator,
Alert,
Expand All @@ -19,6 +18,8 @@ import {
ScrollView,
useColorScheme,
} from "react-native";
import remarkCjkFriendly from "remark-cjk-friendly";
import remarkGfm from "remark-gfm";

const { defaultTheme, githubTheme, serifTheme } = themes;

Expand All @@ -30,11 +31,23 @@ const HomeScreen = () => {
const colorScheme = useColorScheme();
const navigation = useNavigation();
const { showActionSheetWithOptions } = useActionSheet();
const [url, setUrl] = useState(URL);
const [markdown, setMarkdown] = useState("");
const [theme, setTheme] = useState(defaultTheme);
const [loading, setLoading] = useState(false);

const loadMarkdown = useCallback((url: string) => {
setLoading(true);

const controller = new AbortController();

fetch(url, { signal: controller.signal })
.then((res) => res.text())
.then((text) => setMarkdown(text))
.finally(() => setTimeout(() => setLoading(false), 1000));

return controller;
}, []);

useEffect(() => {
navigation.setOptions({
headerTintColor: colorScheme === "dark" ? "white" : "black",
Expand Down Expand Up @@ -103,7 +116,11 @@ const HomeScreen = () => {
url: `${BASE_URL}/04_pytorch.md`,
},
{
title: "5. Load from URL",
title: "5. Bug fixing with CJK plugin",
url: `${BASE_URL}/05_cjk_plugin_example.md`,
},
{
title: "6. Load from URL",
url: "",
},
];
Expand All @@ -115,28 +132,34 @@ const HomeScreen = () => {
},
(idx?: number) => {
if (!idx || idx === cancelButtonIndex) return;

if (idx === options.length - 1) {
Alert.prompt("Load Markdown from URL", "", (url) => {
setUrl(url);
loadMarkdown(url);
});
return;
}
setUrl(options[idx].url);

loadMarkdown(options[idx].url);
},
);
}}
/>
),
});
}, [colorScheme, navigation, showActionSheetWithOptions, setTheme, setUrl]);
}, [
colorScheme,
navigation,
showActionSheetWithOptions,
setTheme,
loadMarkdown,
]);

useEffect(() => {
setLoading(true);
fetch(url)
.then((res) => res.text())
.then((text) => setMarkdown(text))
.finally(() => setTimeout(() => setLoading(false), 1000));
}, [url]);
const controller = loadMarkdown(URL);

return () => controller.abort();
}, [loadMarkdown]);

return (
<ScrollView
Expand All @@ -153,6 +176,7 @@ const HomeScreen = () => {
<Markdown
markdown={markdown}
theme={theme}
remarkPlugins={[remarkGfm, remarkCjkFriendly]}
onLinkPress={(url) => Linking.openURL(url)}
/>
Comment thread
LouisDvr marked this conversation as resolved.
)}
Expand Down
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"expo-status-bar": "~2.2.3",
"react": "19.0.0",
"react-native": "0.79.4",
"react-native-remark": "file:../"
"react-native-remark": "file:../",
"remark-cjk-friendly": "^2.0.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
Loading