react-native-marked 8.1.1 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +354 -354
  3. package/dist/commonjs/components/MDImage.js +3 -3
  4. package/dist/commonjs/components/MDImage.js.map +1 -1
  5. package/dist/commonjs/components/MDList.js.map +1 -1
  6. package/dist/commonjs/components/MDSvg.js.map +1 -1
  7. package/dist/commonjs/components/MDTable.js.map +1 -1
  8. package/dist/commonjs/hooks/useMarkdown.js.map +1 -1
  9. package/dist/commonjs/hooks/useMarkdownWithComponents.js.map +1 -1
  10. package/dist/commonjs/index.js.map +1 -1
  11. package/dist/commonjs/lib/Markdown.js.map +1 -1
  12. package/dist/commonjs/lib/Parser.js +4 -4
  13. package/dist/commonjs/lib/Parser.js.map +1 -1
  14. package/dist/commonjs/lib/ReactComponentRegistry.js.map +1 -1
  15. package/dist/commonjs/lib/ReactComponentTokenizer.js.map +1 -1
  16. package/dist/commonjs/lib/Renderer.js.map +1 -1
  17. package/dist/commonjs/lib/types.js.map +1 -1
  18. package/dist/commonjs/theme/colors.js.map +1 -1
  19. package/dist/commonjs/theme/spacing.js.map +1 -1
  20. package/dist/commonjs/theme/styles.js.map +1 -1
  21. package/dist/commonjs/theme/types.js.map +1 -1
  22. package/dist/commonjs/utils/handlers.js.map +1 -1
  23. package/dist/commonjs/utils/svg.js.map +1 -1
  24. package/dist/commonjs/utils/table.js.map +1 -1
  25. package/dist/commonjs/utils/url.js.map +1 -1
  26. package/dist/module/components/MDImage.js +3 -3
  27. package/dist/module/components/MDImage.js.map +1 -1
  28. package/dist/module/components/MDList.js.map +1 -1
  29. package/dist/module/components/MDSvg.js.map +1 -1
  30. package/dist/module/components/MDTable.js.map +1 -1
  31. package/dist/module/hooks/useMarkdown.js.map +1 -1
  32. package/dist/module/hooks/useMarkdownWithComponents.js.map +1 -1
  33. package/dist/module/index.js.map +1 -1
  34. package/dist/module/lib/Markdown.js.map +1 -1
  35. package/dist/module/lib/Parser.js +4 -4
  36. package/dist/module/lib/Parser.js.map +1 -1
  37. package/dist/module/lib/ReactComponentRegistry.js.map +1 -1
  38. package/dist/module/lib/ReactComponentTokenizer.js.map +1 -1
  39. package/dist/module/lib/Renderer.js.map +1 -1
  40. package/dist/module/lib/types.js.map +1 -1
  41. package/dist/module/theme/colors.js.map +1 -1
  42. package/dist/module/theme/spacing.js.map +1 -1
  43. package/dist/module/theme/styles.js.map +1 -1
  44. package/dist/module/theme/types.js.map +1 -1
  45. package/dist/module/utils/handlers.js.map +1 -1
  46. package/dist/module/utils/svg.js.map +1 -1
  47. package/dist/module/utils/table.js.map +1 -1
  48. package/dist/module/utils/url.js.map +1 -1
  49. package/package.json +175 -175
  50. package/src/components/MDImage.tsx +90 -90
  51. package/src/components/MDList.tsx +46 -46
  52. package/src/components/MDSvg.tsx +108 -108
  53. package/src/components/MDTable.tsx +60 -60
  54. package/src/hooks/useMarkdown.ts +51 -51
  55. package/src/hooks/useMarkdownWithComponents.tsx +89 -89
  56. package/src/index.ts +43 -43
  57. package/src/lib/Markdown.tsx +53 -53
  58. package/src/lib/Parser.tsx +316 -316
  59. package/src/lib/ReactComponentRegistry.tsx +52 -52
  60. package/src/lib/ReactComponentTokenizer.ts +149 -149
  61. package/src/lib/Renderer.tsx +238 -238
  62. package/src/lib/types.ts +87 -87
  63. package/src/theme/colors.ts +31 -31
  64. package/src/theme/spacing.ts +10 -10
  65. package/src/theme/styles.ts +198 -198
  66. package/src/theme/types.ts +33 -33
  67. package/src/utils/handlers.ts +9 -9
  68. package/src/utils/svg.ts +14 -14
  69. package/src/utils/table.ts +29 -29
  70. package/src/utils/url.ts +22 -22
package/README.md CHANGED
@@ -1,354 +1,354 @@
1
- # react-native-marked
2
-
3
- [![GitHub license](https://img.shields.io/github/license/gmsgowtham/react-native-marked)](https://github.com/gmsgowtham/react-native-marked/blob/main/LICENSE)
4
- [![CI](https://github.com/gmsgowtham/react-native-marked/actions/workflows/build.yml/badge.svg)](https://github.com/gmsgowtham/react-native-marked/actions/workflows/build.yml)
5
- [![Coverage Status](https://coveralls.io/repos/github/gmsgowtham/react-native-marked/badge.svg?branch=main)](https://coveralls.io/github/gmsgowtham/react-native-marked?branch=main)
6
- [![npm](https://img.shields.io/npm/v/react-native-marked)](https://www.npmjs.com/package/react-native-marked)
7
- [![npm](https://img.shields.io/npm/dw/react-native-marked)](https://www.npmjs.com/package/react-native-marked)
8
-
9
- Markdown renderer for React Native powered by
10
- [marked.js](https://marked.js.org/) with built-in theming support
11
-
12
- ## Installation
13
-
14
- #### For React Native 0.76 and above, please use the latest version.
15
- ```sh
16
- yarn add react-native-marked react-native-svg
17
- ```
18
-
19
- #### For React Native 0.75 and below, please use version 6.
20
- ```sh
21
- yarn add react-native-marked@6.0.7 react-native-svg
22
- ```
23
-
24
- ## Usage
25
-
26
- ### Using Component
27
-
28
- ```tsx
29
- import * as React from "react";
30
- import Markdown from "react-native-marked";
31
-
32
- const ExampleComponent = () => {
33
- return (
34
- <Markdown
35
- value={`# Hello world`}
36
- flatListProps={{
37
- initialNumToRender: 8,
38
- }}
39
- />
40
- );
41
- };
42
-
43
- export default ExampleComponent;
44
- ```
45
-
46
- #### [Props](https://github.com/gmsgowtham/react-native-marked/blob/main/src/lib/types.ts#L17)
47
-
48
- | Prop | Description | Type | Optional? |
49
- |---------------|----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
50
- | value | Markdown value | string | false |
51
- | flatListProps | Props for customizing the underlying FlatList used | `Omit<FlatListProps<ReactNode>, 'data' \| 'renderItem' \| 'horizontal'>`<br><br><br>(`'data'`, `'renderItem'`, and `'horizontal'` props are omitted and cannot be overridden.) | true |
52
- | styles | Styles for parsed components | [MarkedStyles](src/theme/types.ts) | true |
53
- | theme | Props for customizing colors and spacing for all components,and it will get overridden with custom component style applied via 'styles' prop | [UserTheme](src/theme/types.ts) | true |
54
- | baseUrl | A prefix url for any relative link | string | true |
55
- | renderer | Custom component Renderer | [RendererInterface](src/lib/types.ts) | true |
56
- | hooks | Hooks run during parsing to transform tokens | [Marked Hooks](https://marked.js.org/using_pro#hooks) | true |
57
-
58
-
59
- ### Using hook
60
-
61
- `useMarkdown` hook will return list of elements that can be rendered using a list component of your choice.
62
-
63
- ```tsx
64
- import React, { Fragment } from "react";
65
- import { ScrollView, useColorScheme } from "react-native";
66
- import { useMarkdown, type useMarkdownHookOptions } from "react-native-marked";
67
-
68
- const CustomComponent = () => {
69
- const colorScheme = useColorScheme();
70
- const options: useMarkdownHookOptions = {
71
- colorScheme
72
- }
73
- const elements = useMarkdown("# Hello world", options);
74
- return (
75
- <ScrollView>
76
- {elements.map((element, index) => {
77
- return <Fragment key={`demo_${index}`}>{element}</Fragment>
78
- })}
79
- </ScrollView>
80
- );
81
- };
82
- ```
83
-
84
- #### Options
85
-
86
- | Option | Description | Type | Optional? |
87
- |-------------|----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|-----------|
88
- | colorScheme | Device color scheme ("dark" or "light") | ColorSchemeName | false |
89
- | styles | Styles for parsed components | [MarkedStyles](src/theme/types.ts) | true |
90
- | theme | Props for customizing colors and spacing for all components,and it will get overridden with custom component style applied via 'styles' prop | [UserTheme](src/theme/types.ts) | true |
91
- | baseUrl | A prefix url for any relative link | string | true |
92
- | renderer | Custom component Renderer | [RendererInterface](src/lib/types.ts) | true |
93
- | tokenizer | Generate custom tokens | [MarkedTokenizer<CustomToken>](src/lib/types.ts) | true |
94
- | hooks | Hooks run during parsing to transform tokens |
95
- [Marked Hooks](https://marked.js.org/using_pro#hooks) | true |
96
-
97
-
98
- ## Examples
99
-
100
- - CodeSandbox: https://codesandbox.io/s/react-native-marked-l2hpi3?file=/src/App.js
101
-
102
- ## Supported elements
103
-
104
- - [x] Headings (1 to 6)
105
- - [x] Paragraph
106
- - [x] Emphasis (bold, italic, and strikethrough)
107
- - [x] Link
108
- - [x] Image
109
- - [x] Blockquote
110
- - [x] Inline Code
111
- - [x] Code Block
112
- - [x] List (ordered, unordered)
113
- - [x] Horizontal Rule
114
- - [x] Table
115
- - [x] React Components (via `useMarkdownWithComponents`)
116
- - [ ] HTML
117
-
118
- Ref: [CommonMark](https://commonmark.org/help/)
119
-
120
- > HTML will be treated as plain text. Please refer [issue#290](https://github.com/gmsgowtham/react-native-marked/issues/290) for a potential solution
121
-
122
- ## Advanced
123
-
124
- ### Embedding React Components in Markdown
125
-
126
- You can embed React components directly in your markdown using JSX-style syntax. This is useful for adding interactive elements like buttons, custom info boxes, or any other React component.
127
-
128
- ```tsx
129
- import React, { Fragment } from "react";
130
- import { Pressable, ScrollView, Text, View } from "react-native";
131
- import {
132
- ReactComponentRegistryProvider,
133
- useMarkdownWithComponents,
134
- type ReactComponentRegistry,
135
- } from "react-native-marked";
136
-
137
- // Define your components
138
- const components: ReactComponentRegistry = {
139
- Button: ({ props }) => (
140
- <Pressable onPress={() => console.log("Pressed!")}>
141
- <Text>{String(props.label ?? "Click me")}</Text>
142
- </Pressable>
143
- ),
144
- InfoBox: ({ props, children }) => (
145
- <View style={{ backgroundColor: "#E3F2FD", padding: 16 }}>
146
- {props.title && <Text style={{ fontWeight: "bold" }}>{String(props.title)}</Text>}
147
- <Text>{children}</Text>
148
- </View>
149
- ),
150
- };
151
-
152
- const markdown = `
153
- # Hello World
154
-
155
- Click the button below:
156
-
157
- <Button label="Get Started" />
158
-
159
- <InfoBox title="Note">
160
- This is an info box with **markdown** content.
161
- </InfoBox>
162
- `;
163
-
164
- function MarkdownContent() {
165
- const elements = useMarkdownWithComponents(markdown);
166
- return (
167
- <ScrollView>
168
- {elements.map((element, index) => (
169
- <Fragment key={index}>{element}</Fragment>
170
- ))}
171
- </ScrollView>
172
- );
173
- }
174
-
175
- export default function App() {
176
- return (
177
- <ReactComponentRegistryProvider components={components}>
178
- <MarkdownContent />
179
- </ReactComponentRegistryProvider>
180
- );
181
- }
182
- ```
183
-
184
- #### Component Syntax
185
-
186
- - **Self-closing:** `<ComponentName prop="value" />`
187
- - **With children:** `<ComponentName>content</ComponentName>`
188
- - **Props:** Supports string (`"value"`), number (`{42}`), and boolean (`{true}`) props
189
-
190
- #### Component Registry
191
-
192
- Components must be registered via `ReactComponentRegistryProvider`. Unregistered components are automatically removed from the output.
193
-
194
- ### Using custom components
195
-
196
- > Custom components can be used to override elements, i.e. Code Highlighting, Fast Image integration
197
-
198
- #### Example
199
-
200
- ```tsx
201
- import React, { ReactNode, Fragment } from "react";
202
- import { Text, ScrollView } from "react-native";
203
- import type { ImageStyle, TextStyle } from "react-native";
204
- import Markdown, { Renderer, useMarkdown } from "react-native-marked";
205
- import type { RendererInterface } from "react-native-marked";
206
- import FastImage from "react-native-fast-image";
207
-
208
- class CustomRenderer extends Renderer implements RendererInterface {
209
- constructor() {
210
- super();
211
- }
212
-
213
- codespan(text: string, _styles?: TextStyle): ReactNode {
214
- return (
215
- <Text key={this.getKey()} style={{ backgroundColor: "#ff0000" }}>
216
- {text}
217
- </Text>
218
- );
219
- }
220
-
221
- image(uri: string, _alt?: string, _style?: ImageStyle): ReactNode {
222
- return (
223
- <FastImage
224
- key={this.getKey()}
225
- style={{ width: 200, height: 200 }}
226
- source={{ uri: uri }}
227
- resizeMode={FastImage.resizeMode.contain}
228
- />
229
- );
230
- }
231
- }
232
-
233
- const renderer = new CustomRenderer();
234
-
235
- const ExampleComponent = () => {
236
- return (
237
- <Markdown
238
- value={"`Hello world`"}
239
- flatListProps={{
240
- initialNumToRender: 8,
241
- }}
242
- renderer={renderer}
243
- />
244
- );
245
- };
246
-
247
- // Alternate using hook
248
- const ExampleComponentWithHook = () => {
249
- const elements = useMarkdown("`Hello world`", { renderer });
250
-
251
- return (
252
- <ScrollView>
253
- {elements.map((element, index) => {
254
- return <Fragment key={`demo_${index}`}>{element}</Fragment>
255
- })}
256
- </ScrollView>
257
- )
258
- }
259
-
260
- export default ExampleComponent;
261
- ```
262
-
263
- > Please refer to [RendererInterface](src/lib/types.ts) for all the overrides
264
-
265
- > Note:
266
- >
267
- > For `key` property for a component, you can use the `getKey` method from Renderer class.
268
-
269
- #### Example
270
-
271
- Overriding default codespan tokenizer to include LaTeX.
272
-
273
- ```tsx
274
-
275
- import React, { ReactNode } from "react";
276
- import Markdown, { Renderer, MarkedTokenizer, MarkedLexer } from "react-native-marked";
277
- import type { RendererInterface, CustomToken } from "react-native-marked";
278
-
279
- class CustomTokenizer extends Tokenizer {
280
- codespan(src: string): Tokens.Codespan | undefined {
281
- const match = src.match(/^\$+([^\$\n]+?)\$+/);
282
- if (match?.[1]) {
283
- return {
284
- type: "codespan",
285
- raw: match[0],
286
- text: match[1].trim(),
287
- };
288
- }
289
-
290
- return super.codespan(src);
291
- }
292
- }
293
-
294
- class CustomRenderer extends Renderer implements RendererInterface {
295
- codespan(text: string, styles?: TextStyle): ReactNode {
296
- return (
297
- <Text style={styles} key={"key-1"}>
298
- {text}
299
- </Text>
300
- )
301
- }
302
- }
303
-
304
- const renderer = new CustomRenderer();
305
- const tokenizer = new CustomTokenizer();
306
-
307
- const ExampleComponent = () => {
308
- return (
309
- <Markdown
310
- value={"$ latex code $\n\n` other code `"}
311
- flatListProps={{
312
- initialNumToRender: 8,
313
- }}
314
- renderer={renderer}
315
- tokenizer={tokenizer}
316
- />
317
- );
318
- };
319
- ```
320
-
321
- #### Example
322
-
323
- ## Screenshots
324
-
325
- | Dark Theme | Light Theme |
326
- |:-------------------------------------------------------------:|:----------------------------------------------------------------:|
327
- | ![Dark theme](assets/dark-theme-01.png?raw=true 'Dark Theme') | ![Light theme](assets/light-theme-01.png?raw=true 'Light Theme') |
328
-
329
- ## Contributing
330
-
331
- See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
332
- repository and the development workflow.
333
-
334
- ## License
335
-
336
- MIT
337
-
338
- ---
339
-
340
- Made with
341
- [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
342
-
343
- ## Built using
344
-
345
- - [Marked](https://marked.js.org/)
346
- - [@jsamr/react-native-li](https://github.com/jsamr/react-native-li)
347
- - [react-native-reanimated-table](https://github.com/dohooo/react-native-reanimated-table)
348
- - [react-native-svg](https://github.com/software-mansion/react-native-svg)
349
- - [svg-parser](https://github.com/Rich-Harris/svg-parser)
350
- - [github-slugger](https://github.com/Flet/github-slugger)
351
- - [html-entities](https://github.com/mdevils/html-entities)
352
-
353
-
354
- <a href="https://www.buymeacoffee.com/gmsgowtham" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="width: 120px !important;" ></a>
1
+ # react-native-marked
2
+
3
+ [![GitHub license](https://img.shields.io/github/license/gmsgowtham/react-native-marked)](https://github.com/gmsgowtham/react-native-marked/blob/main/LICENSE)
4
+ [![CI](https://github.com/gmsgowtham/react-native-marked/actions/workflows/build.yml/badge.svg)](https://github.com/gmsgowtham/react-native-marked/actions/workflows/build.yml)
5
+ [![Coverage Status](https://coveralls.io/repos/github/gmsgowtham/react-native-marked/badge.svg?branch=main)](https://coveralls.io/github/gmsgowtham/react-native-marked?branch=main)
6
+ [![npm](https://img.shields.io/npm/v/react-native-marked)](https://www.npmjs.com/package/react-native-marked)
7
+ [![npm](https://img.shields.io/npm/dw/react-native-marked)](https://www.npmjs.com/package/react-native-marked)
8
+
9
+ Markdown renderer for React Native powered by
10
+ [marked.js](https://marked.js.org/) with built-in theming support
11
+
12
+ ## Installation
13
+
14
+ #### For React Native 0.76 and above, please use the latest version.
15
+ ```sh
16
+ yarn add react-native-marked react-native-svg
17
+ ```
18
+
19
+ #### For React Native 0.75 and below, please use version 6.
20
+ ```sh
21
+ yarn add react-native-marked@6.0.7 react-native-svg
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Using Component
27
+
28
+ ```tsx
29
+ import * as React from "react";
30
+ import Markdown from "react-native-marked";
31
+
32
+ const ExampleComponent = () => {
33
+ return (
34
+ <Markdown
35
+ value={`# Hello world`}
36
+ flatListProps={{
37
+ initialNumToRender: 8,
38
+ }}
39
+ />
40
+ );
41
+ };
42
+
43
+ export default ExampleComponent;
44
+ ```
45
+
46
+ #### [Props](https://github.com/gmsgowtham/react-native-marked/blob/main/src/lib/types.ts#L17)
47
+
48
+ | Prop | Description | Type | Optional? |
49
+ |---------------|----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
50
+ | value | Markdown value | string | false |
51
+ | flatListProps | Props for customizing the underlying FlatList used | `Omit<FlatListProps<ReactNode>, 'data' \| 'renderItem' \| 'horizontal'>`<br><br><br>(`'data'`, `'renderItem'`, and `'horizontal'` props are omitted and cannot be overridden.) | true |
52
+ | styles | Styles for parsed components | [MarkedStyles](src/theme/types.ts) | true |
53
+ | theme | Props for customizing colors and spacing for all components,and it will get overridden with custom component style applied via 'styles' prop | [UserTheme](src/theme/types.ts) | true |
54
+ | baseUrl | A prefix url for any relative link | string | true |
55
+ | renderer | Custom component Renderer | [RendererInterface](src/lib/types.ts) | true |
56
+ | hooks | Hooks run during parsing to transform tokens | [Marked Hooks](https://marked.js.org/using_pro#hooks) | true |
57
+
58
+
59
+ ### Using hook
60
+
61
+ `useMarkdown` hook will return list of elements that can be rendered using a list component of your choice.
62
+
63
+ ```tsx
64
+ import React, { Fragment } from "react";
65
+ import { ScrollView, useColorScheme } from "react-native";
66
+ import { useMarkdown, type useMarkdownHookOptions } from "react-native-marked";
67
+
68
+ const CustomComponent = () => {
69
+ const colorScheme = useColorScheme();
70
+ const options: useMarkdownHookOptions = {
71
+ colorScheme
72
+ }
73
+ const elements = useMarkdown("# Hello world", options);
74
+ return (
75
+ <ScrollView>
76
+ {elements.map((element, index) => {
77
+ return <Fragment key={`demo_${index}`}>{element}</Fragment>
78
+ })}
79
+ </ScrollView>
80
+ );
81
+ };
82
+ ```
83
+
84
+ #### Options
85
+
86
+ | Option | Description | Type | Optional? |
87
+ |-------------|----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|-----------|
88
+ | colorScheme | Device color scheme ("dark" or "light") | ColorSchemeName | false |
89
+ | styles | Styles for parsed components | [MarkedStyles](src/theme/types.ts) | true |
90
+ | theme | Props for customizing colors and spacing for all components,and it will get overridden with custom component style applied via 'styles' prop | [UserTheme](src/theme/types.ts) | true |
91
+ | baseUrl | A prefix url for any relative link | string | true |
92
+ | renderer | Custom component Renderer | [RendererInterface](src/lib/types.ts) | true |
93
+ | tokenizer | Generate custom tokens | [MarkedTokenizer<CustomToken>](src/lib/types.ts) | true |
94
+ | hooks | Hooks run during parsing to transform tokens |
95
+ [Marked Hooks](https://marked.js.org/using_pro#hooks) | true |
96
+
97
+
98
+ ## Examples
99
+
100
+ - CodeSandbox: https://codesandbox.io/s/react-native-marked-l2hpi3?file=/src/App.js
101
+
102
+ ## Supported elements
103
+
104
+ - [x] Headings (1 to 6)
105
+ - [x] Paragraph
106
+ - [x] Emphasis (bold, italic, and strikethrough)
107
+ - [x] Link
108
+ - [x] Image
109
+ - [x] Blockquote
110
+ - [x] Inline Code
111
+ - [x] Code Block
112
+ - [x] List (ordered, unordered)
113
+ - [x] Horizontal Rule
114
+ - [x] Table
115
+ - [x] React Components (via `useMarkdownWithComponents`)
116
+ - [ ] HTML
117
+
118
+ Ref: [CommonMark](https://commonmark.org/help/)
119
+
120
+ > HTML will be treated as plain text. Please refer [issue#290](https://github.com/gmsgowtham/react-native-marked/issues/290) for a potential solution
121
+
122
+ ## Advanced
123
+
124
+ ### Embedding React Components in Markdown
125
+
126
+ You can embed React components directly in your markdown using JSX-style syntax. This is useful for adding interactive elements like buttons, custom info boxes, or any other React component.
127
+
128
+ ```tsx
129
+ import React, { Fragment } from "react";
130
+ import { Pressable, ScrollView, Text, View } from "react-native";
131
+ import {
132
+ ReactComponentRegistryProvider,
133
+ useMarkdownWithComponents,
134
+ type ReactComponentRegistry,
135
+ } from "react-native-marked";
136
+
137
+ // Define your components
138
+ const components: ReactComponentRegistry = {
139
+ Button: ({ props }) => (
140
+ <Pressable onPress={() => console.log("Pressed!")}>
141
+ <Text>{String(props.label ?? "Click me")}</Text>
142
+ </Pressable>
143
+ ),
144
+ InfoBox: ({ props, children }) => (
145
+ <View style={{ backgroundColor: "#E3F2FD", padding: 16 }}>
146
+ {props.title && <Text style={{ fontWeight: "bold" }}>{String(props.title)}</Text>}
147
+ <Text>{children}</Text>
148
+ </View>
149
+ ),
150
+ };
151
+
152
+ const markdown = `
153
+ # Hello World
154
+
155
+ Click the button below:
156
+
157
+ <Button label="Get Started" />
158
+
159
+ <InfoBox title="Note">
160
+ This is an info box with **markdown** content.
161
+ </InfoBox>
162
+ `;
163
+
164
+ function MarkdownContent() {
165
+ const elements = useMarkdownWithComponents(markdown);
166
+ return (
167
+ <ScrollView>
168
+ {elements.map((element, index) => (
169
+ <Fragment key={index}>{element}</Fragment>
170
+ ))}
171
+ </ScrollView>
172
+ );
173
+ }
174
+
175
+ export default function App() {
176
+ return (
177
+ <ReactComponentRegistryProvider components={components}>
178
+ <MarkdownContent />
179
+ </ReactComponentRegistryProvider>
180
+ );
181
+ }
182
+ ```
183
+
184
+ #### Component Syntax
185
+
186
+ - **Self-closing:** `<ComponentName prop="value" />`
187
+ - **With children:** `<ComponentName>content</ComponentName>`
188
+ - **Props:** Supports string (`"value"`), number (`{42}`), and boolean (`{true}`) props
189
+
190
+ #### Component Registry
191
+
192
+ Components must be registered via `ReactComponentRegistryProvider`. Unregistered components are automatically removed from the output.
193
+
194
+ ### Using custom components
195
+
196
+ > Custom components can be used to override elements, i.e. Code Highlighting, Fast Image integration
197
+
198
+ #### Example
199
+
200
+ ```tsx
201
+ import React, { ReactNode, Fragment } from "react";
202
+ import { Text, ScrollView } from "react-native";
203
+ import type { ImageStyle, TextStyle } from "react-native";
204
+ import Markdown, { Renderer, useMarkdown } from "react-native-marked";
205
+ import type { RendererInterface } from "react-native-marked";
206
+ import FastImage from "react-native-fast-image";
207
+
208
+ class CustomRenderer extends Renderer implements RendererInterface {
209
+ constructor() {
210
+ super();
211
+ }
212
+
213
+ codespan(text: string, _styles?: TextStyle): ReactNode {
214
+ return (
215
+ <Text key={this.getKey()} style={{ backgroundColor: "#ff0000" }}>
216
+ {text}
217
+ </Text>
218
+ );
219
+ }
220
+
221
+ image(uri: string, _alt?: string, _style?: ImageStyle): ReactNode {
222
+ return (
223
+ <FastImage
224
+ key={this.getKey()}
225
+ style={{ width: 200, height: 200 }}
226
+ source={{ uri: uri }}
227
+ resizeMode={FastImage.resizeMode.contain}
228
+ />
229
+ );
230
+ }
231
+ }
232
+
233
+ const renderer = new CustomRenderer();
234
+
235
+ const ExampleComponent = () => {
236
+ return (
237
+ <Markdown
238
+ value={"`Hello world`"}
239
+ flatListProps={{
240
+ initialNumToRender: 8,
241
+ }}
242
+ renderer={renderer}
243
+ />
244
+ );
245
+ };
246
+
247
+ // Alternate using hook
248
+ const ExampleComponentWithHook = () => {
249
+ const elements = useMarkdown("`Hello world`", { renderer });
250
+
251
+ return (
252
+ <ScrollView>
253
+ {elements.map((element, index) => {
254
+ return <Fragment key={`demo_${index}`}>{element}</Fragment>
255
+ })}
256
+ </ScrollView>
257
+ )
258
+ }
259
+
260
+ export default ExampleComponent;
261
+ ```
262
+
263
+ > Please refer to [RendererInterface](src/lib/types.ts) for all the overrides
264
+
265
+ > Note:
266
+ >
267
+ > For `key` property for a component, you can use the `getKey` method from Renderer class.
268
+
269
+ #### Example
270
+
271
+ Overriding default codespan tokenizer to include LaTeX.
272
+
273
+ ```tsx
274
+
275
+ import React, { ReactNode } from "react";
276
+ import Markdown, { Renderer, MarkedTokenizer, MarkedLexer } from "react-native-marked";
277
+ import type { RendererInterface, CustomToken } from "react-native-marked";
278
+
279
+ class CustomTokenizer extends Tokenizer {
280
+ codespan(src: string): Tokens.Codespan | undefined {
281
+ const match = src.match(/^\$+([^\$\n]+?)\$+/);
282
+ if (match?.[1]) {
283
+ return {
284
+ type: "codespan",
285
+ raw: match[0],
286
+ text: match[1].trim(),
287
+ };
288
+ }
289
+
290
+ return super.codespan(src);
291
+ }
292
+ }
293
+
294
+ class CustomRenderer extends Renderer implements RendererInterface {
295
+ codespan(text: string, styles?: TextStyle): ReactNode {
296
+ return (
297
+ <Text style={styles} key={"key-1"}>
298
+ {text}
299
+ </Text>
300
+ )
301
+ }
302
+ }
303
+
304
+ const renderer = new CustomRenderer();
305
+ const tokenizer = new CustomTokenizer();
306
+
307
+ const ExampleComponent = () => {
308
+ return (
309
+ <Markdown
310
+ value={"$ latex code $\n\n` other code `"}
311
+ flatListProps={{
312
+ initialNumToRender: 8,
313
+ }}
314
+ renderer={renderer}
315
+ tokenizer={tokenizer}
316
+ />
317
+ );
318
+ };
319
+ ```
320
+
321
+ #### Example
322
+
323
+ ## Screenshots
324
+
325
+ | Dark Theme | Light Theme |
326
+ |:-------------------------------------------------------------:|:----------------------------------------------------------------:|
327
+ | ![Dark theme](assets/dark-theme-01.png?raw=true 'Dark Theme') | ![Light theme](assets/light-theme-01.png?raw=true 'Light Theme') |
328
+
329
+ ## Contributing
330
+
331
+ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
332
+ repository and the development workflow.
333
+
334
+ ## License
335
+
336
+ MIT
337
+
338
+ ---
339
+
340
+ Made with
341
+ [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
342
+
343
+ ## Built using
344
+
345
+ - [Marked](https://marked.js.org/)
346
+ - [@jsamr/react-native-li](https://github.com/jsamr/react-native-li)
347
+ - [react-native-reanimated-table](https://github.com/dohooo/react-native-reanimated-table)
348
+ - [react-native-svg](https://github.com/software-mansion/react-native-svg)
349
+ - [svg-parser](https://github.com/Rich-Harris/svg-parser)
350
+ - [github-slugger](https://github.com/Flet/github-slugger)
351
+ - [html-entities](https://github.com/mdevils/html-entities)
352
+
353
+
354
+ <a href="https://www.buymeacoffee.com/gmsgowtham" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="width: 120px !important;" ></a>