react-native-nitro-markdown 0.1.1 → 0.2.1

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 (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -84
  3. package/android/src/main/cpp/cpp-adapter.cpp +1 -1
  4. package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +61 -0
  5. package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +5 -1
  6. package/cpp/bindings/HybridMarkdownParser.cpp +2 -2
  7. package/cpp/bindings/HybridMarkdownParser.hpp +2 -2
  8. package/cpp/bindings/HybridMarkdownSession.cpp +0 -0
  9. package/cpp/core/MarkdownSessionCore.cpp +0 -0
  10. package/ios/HybridMarkdownSession.swift +64 -0
  11. package/lib/commonjs/MarkdownContext.js +21 -0
  12. package/lib/commonjs/MarkdownContext.js.map +1 -0
  13. package/lib/commonjs/MarkdownSession.js +11 -0
  14. package/lib/commonjs/MarkdownSession.js.map +1 -0
  15. package/lib/commonjs/default-markdown-renderer.js +220 -0
  16. package/lib/commonjs/default-markdown-renderer.js.map +1 -0
  17. package/lib/commonjs/headless.js +50 -0
  18. package/lib/commonjs/headless.js.map +1 -0
  19. package/lib/commonjs/index.js +185 -13
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/markdown-stream.js +32 -0
  22. package/lib/commonjs/markdown-stream.js.map +1 -0
  23. package/lib/commonjs/markdown.js +326 -0
  24. package/lib/commonjs/markdown.js.map +1 -0
  25. package/lib/commonjs/package.json +1 -0
  26. package/lib/commonjs/renderers/blockquote.js +36 -0
  27. package/lib/commonjs/renderers/blockquote.js.map +1 -0
  28. package/lib/commonjs/renderers/code.js +92 -0
  29. package/lib/commonjs/renderers/code.js.map +1 -0
  30. package/lib/commonjs/renderers/heading.js +62 -0
  31. package/lib/commonjs/renderers/heading.js.map +1 -0
  32. package/lib/commonjs/renderers/horizontal-rule.js +27 -0
  33. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -0
  34. package/lib/commonjs/renderers/image.js +159 -0
  35. package/lib/commonjs/renderers/image.js.map +1 -0
  36. package/lib/commonjs/renderers/link.js +37 -0
  37. package/lib/commonjs/renderers/link.js.map +1 -0
  38. package/lib/commonjs/renderers/list.js +114 -0
  39. package/lib/commonjs/renderers/list.js.map +1 -0
  40. package/lib/commonjs/renderers/math.js +151 -0
  41. package/lib/commonjs/renderers/math.js.map +1 -0
  42. package/lib/commonjs/renderers/paragraph.js +44 -0
  43. package/lib/commonjs/renderers/paragraph.js.map +1 -0
  44. package/lib/commonjs/renderers/table.js +283 -0
  45. package/lib/commonjs/renderers/table.js.map +1 -0
  46. package/lib/commonjs/specs/MarkdownSession.nitro.js +6 -0
  47. package/lib/commonjs/specs/MarkdownSession.nitro.js.map +1 -0
  48. package/lib/commonjs/theme.js +58 -0
  49. package/lib/commonjs/theme.js.map +1 -0
  50. package/lib/commonjs/use-markdown-stream.js +71 -0
  51. package/lib/commonjs/use-markdown-stream.js.map +1 -0
  52. package/lib/module/MarkdownContext.js +17 -0
  53. package/lib/module/MarkdownContext.js.map +1 -0
  54. package/lib/module/MarkdownSession.js +7 -0
  55. package/lib/module/MarkdownSession.js.map +1 -0
  56. package/lib/module/default-markdown-renderer.js +215 -0
  57. package/lib/module/default-markdown-renderer.js.map +1 -0
  58. package/lib/module/headless.js +44 -0
  59. package/lib/module/headless.js.map +1 -0
  60. package/lib/module/index.js +36 -10
  61. package/lib/module/index.js.map +1 -1
  62. package/lib/module/markdown-stream.js +27 -0
  63. package/lib/module/markdown-stream.js.map +1 -0
  64. package/lib/module/markdown.js +321 -0
  65. package/lib/module/markdown.js.map +1 -0
  66. package/lib/module/package.json +1 -0
  67. package/lib/module/renderers/blockquote.js +31 -0
  68. package/lib/module/renderers/blockquote.js.map +1 -0
  69. package/lib/module/renderers/code.js +86 -0
  70. package/lib/module/renderers/code.js.map +1 -0
  71. package/lib/module/renderers/heading.js +57 -0
  72. package/lib/module/renderers/heading.js.map +1 -0
  73. package/lib/module/renderers/horizontal-rule.js +22 -0
  74. package/lib/module/renderers/horizontal-rule.js.map +1 -0
  75. package/lib/module/renderers/image.js +154 -0
  76. package/lib/module/renderers/image.js.map +1 -0
  77. package/lib/module/renderers/link.js +32 -0
  78. package/lib/module/renderers/link.js.map +1 -0
  79. package/lib/module/renderers/list.js +107 -0
  80. package/lib/module/renderers/list.js.map +1 -0
  81. package/lib/module/renderers/math.js +145 -0
  82. package/lib/module/renderers/math.js.map +1 -0
  83. package/lib/module/renderers/paragraph.js +39 -0
  84. package/lib/module/renderers/paragraph.js.map +1 -0
  85. package/lib/module/renderers/table.js +278 -0
  86. package/lib/module/renderers/table.js.map +1 -0
  87. package/lib/module/specs/MarkdownSession.nitro.js +4 -0
  88. package/lib/module/specs/MarkdownSession.nitro.js.map +1 -0
  89. package/lib/module/theme.js +54 -0
  90. package/lib/module/theme.js.map +1 -0
  91. package/lib/module/use-markdown-stream.js +66 -0
  92. package/lib/module/use-markdown-stream.js.map +1 -0
  93. package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -0
  94. package/lib/typescript/commonjs/MarkdownContext.d.ts +26 -0
  95. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/MarkdownSession.d.ts +4 -0
  97. package/lib/typescript/commonjs/MarkdownSession.d.ts.map +1 -0
  98. package/lib/typescript/commonjs/default-markdown-renderer.d.ts +10 -0
  99. package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -0
  100. package/lib/typescript/commonjs/headless.d.ts +50 -0
  101. package/lib/typescript/commonjs/headless.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/index.d.ts +34 -0
  103. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  104. package/lib/typescript/commonjs/markdown-stream.d.ts +15 -0
  105. package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -0
  106. package/lib/typescript/commonjs/markdown.d.ts +29 -0
  107. package/lib/typescript/commonjs/markdown.d.ts.map +1 -0
  108. package/lib/typescript/commonjs/package.json +1 -0
  109. package/lib/typescript/commonjs/renderers/blockquote.d.ts +9 -0
  110. package/lib/typescript/commonjs/renderers/blockquote.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/renderers/code.d.ts +15 -0
  112. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/renderers/heading.d.ts +10 -0
  114. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +3 -0
  116. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/renderers/image.d.ts +11 -0
  118. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/renderers/link.d.ts +10 -0
  120. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/renderers/list.d.ts +22 -0
  122. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/renderers/math.d.ts +15 -0
  124. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/renderers/paragraph.d.ts +15 -0
  126. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/renderers/table.d.ts +10 -0
  128. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +12 -0
  130. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/theme.d.ts +52 -0
  132. package/lib/typescript/commonjs/theme.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/use-markdown-stream.d.ts +22 -0
  134. package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -0
  135. package/lib/typescript/module/Markdown.nitro.d.ts +13 -0
  136. package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -0
  137. package/lib/typescript/module/MarkdownContext.d.ts +26 -0
  138. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -0
  139. package/lib/typescript/module/MarkdownSession.d.ts +4 -0
  140. package/lib/typescript/module/MarkdownSession.d.ts.map +1 -0
  141. package/lib/typescript/module/default-markdown-renderer.d.ts +10 -0
  142. package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -0
  143. package/lib/typescript/module/headless.d.ts +50 -0
  144. package/lib/typescript/module/headless.d.ts.map +1 -0
  145. package/lib/typescript/module/index.d.ts +34 -0
  146. package/lib/typescript/module/index.d.ts.map +1 -0
  147. package/lib/typescript/module/markdown-stream.d.ts +15 -0
  148. package/lib/typescript/module/markdown-stream.d.ts.map +1 -0
  149. package/lib/typescript/module/markdown.d.ts +29 -0
  150. package/lib/typescript/module/markdown.d.ts.map +1 -0
  151. package/lib/typescript/module/package.json +1 -0
  152. package/lib/typescript/module/renderers/blockquote.d.ts +9 -0
  153. package/lib/typescript/module/renderers/blockquote.d.ts.map +1 -0
  154. package/lib/typescript/module/renderers/code.d.ts +15 -0
  155. package/lib/typescript/module/renderers/code.d.ts.map +1 -0
  156. package/lib/typescript/module/renderers/heading.d.ts +10 -0
  157. package/lib/typescript/module/renderers/heading.d.ts.map +1 -0
  158. package/lib/typescript/module/renderers/horizontal-rule.d.ts +3 -0
  159. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -0
  160. package/lib/typescript/module/renderers/image.d.ts +11 -0
  161. package/lib/typescript/module/renderers/image.d.ts.map +1 -0
  162. package/lib/typescript/module/renderers/link.d.ts +10 -0
  163. package/lib/typescript/module/renderers/link.d.ts.map +1 -0
  164. package/lib/typescript/module/renderers/list.d.ts +22 -0
  165. package/lib/typescript/module/renderers/list.d.ts.map +1 -0
  166. package/lib/typescript/module/renderers/math.d.ts +15 -0
  167. package/lib/typescript/module/renderers/math.d.ts.map +1 -0
  168. package/lib/typescript/module/renderers/paragraph.d.ts +15 -0
  169. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -0
  170. package/lib/typescript/module/renderers/table.d.ts +10 -0
  171. package/lib/typescript/module/renderers/table.d.ts.map +1 -0
  172. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +12 -0
  173. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -0
  174. package/lib/typescript/module/theme.d.ts +52 -0
  175. package/lib/typescript/module/theme.d.ts.map +1 -0
  176. package/lib/typescript/module/use-markdown-stream.d.ts +22 -0
  177. package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -0
  178. package/nitro.json +5 -2
  179. package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +3 -2
  180. package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +1 -1
  181. package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +17 -5
  182. package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +4 -4
  183. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  184. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +91 -0
  185. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +70 -0
  186. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void.kt +80 -0
  187. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +78 -0
  188. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/NitroMarkdownOnLoad.kt +1 -1
  189. package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +2 -2
  190. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +28 -4
  191. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +72 -6
  192. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +11 -4
  193. package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +11 -3
  194. package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +16 -3
  195. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.cpp +11 -0
  196. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +108 -0
  197. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  198. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +59 -0
  199. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +190 -0
  200. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +3 -3
  201. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +4 -4
  202. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +26 -0
  203. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +67 -0
  204. package/nitrogen/generated/shared/c++/ParserOptions.hpp +22 -14
  205. package/package.json +45 -15
  206. package/react-native-nitro-markdown.podspec +5 -5
  207. package/src/MarkdownContext.ts +41 -0
  208. package/src/MarkdownSession.ts +8 -0
  209. package/src/default-markdown-renderer.tsx +266 -0
  210. package/src/headless.ts +106 -0
  211. package/src/index.ts +41 -59
  212. package/src/markdown-stream.tsx +32 -0
  213. package/src/markdown.tsx +415 -0
  214. package/src/renderers/blockquote.tsx +31 -0
  215. package/src/renderers/code.tsx +88 -0
  216. package/src/renderers/heading.tsx +66 -0
  217. package/src/renderers/horizontal-rule.tsx +20 -0
  218. package/src/renderers/image.tsx +160 -0
  219. package/src/renderers/link.tsx +38 -0
  220. package/src/renderers/list.tsx +125 -0
  221. package/src/renderers/math.tsx +164 -0
  222. package/src/renderers/paragraph.tsx +53 -0
  223. package/src/renderers/table.tsx +345 -0
  224. package/src/specs/MarkdownSession.nitro.ts +16 -0
  225. package/src/theme.ts +52 -0
  226. package/src/use-markdown-stream.ts +83 -0
  227. package/ios/NitroMarkdown-Bridging-Header.h +0 -14
  228. package/lib/commonjs/MarkdownJS.reference.js +0 -114
  229. package/lib/commonjs/MarkdownJS.reference.js.map +0 -1
  230. package/lib/module/MarkdownJS.reference.js +0 -107
  231. package/lib/module/MarkdownJS.reference.js.map +0 -1
  232. package/lib/typescript/Markdown.nitro.d.ts.map +0 -1
  233. package/lib/typescript/MarkdownJS.reference.d.ts +0 -33
  234. package/lib/typescript/MarkdownJS.reference.d.ts.map +0 -1
  235. package/lib/typescript/index.d.ts +0 -22
  236. package/lib/typescript/index.d.ts.map +0 -1
  237. package/src/MarkdownJS.reference.ts +0 -122
  238. /package/lib/typescript/{Markdown.nitro.d.ts → commonjs/Markdown.nitro.d.ts} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 João Paulo C. Marra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  <p align="center">
2
2
  <img src="./readme/demo.gif" alt="react-native-nitro-markdown demo" width="300" />
3
+ <img src="./readme/stream-demo.gif" alt="react-native-nitro-markdown stream demo" width="300" />
3
4
  </p>
4
5
 
5
6
  # react-native-nitro-markdown 🚀
@@ -41,6 +42,9 @@ Choose your preferred package manager to install the package and its core depend
41
42
  npm install react-native-nitro-markdown react-native-nitro-modules
42
43
  ```
43
44
 
45
+ > **Note:** If you want to use **Math** (LaTeX) or certain **Image** features, you should also install the optional peer dependencies:
46
+ > `npm install react-native-svg react-native-mathjax-svg`
47
+
44
48
  **Yarn**
45
49
 
46
50
  ```bash
@@ -80,112 +84,166 @@ npx expo prebuild
80
84
 
81
85
  ## 💻 Usage
82
86
 
83
- ### Basic Parsing
84
-
85
- The parsing is synchronous and instant. It returns a fully typed JSON AST.
87
+ ### Option 1: Batteries Included (Simplest)
86
88
 
87
- ```typescript
88
- import { parseMarkdown } from "react-native-nitro-markdown";
89
+ Use the `Markdown` component with built-in premium dark-mode styling:
89
90
 
90
- const markdown = `
91
- # Hello World
92
- This is **bold** text and a [link](https://github.com).
93
- `;
91
+ ```tsx
92
+ import { Markdown } from "react-native-nitro-markdown";
94
93
 
95
- const ast = parseMarkdown(markdown);
96
- console.log(ast);
97
- // Output: { type: "document", children: [...] }
94
+ export function MyComponent() {
95
+ return (
96
+ <Markdown options={{ gfm: true }}>
97
+ {"# Hello World\nThis is **bold** text."}
98
+ </Markdown>
99
+ );
100
+ }
98
101
  ```
99
102
 
100
- ### Advanced Options (GFM & Math)
103
+ ### Option 2: Custom Renderers
101
104
 
102
- Enable GitHub Flavored Markdown (Tables, TaskLists) or LaTeX Math support.
105
+ Override specific node types while keeping defaults for everything else:
103
106
 
104
- ```typescript
105
- import { parseMarkdown } from "react-native-nitro-markdown";
107
+ ```tsx
108
+ import {
109
+ Markdown,
110
+ Heading,
111
+ type CustomRenderers,
112
+ } from "react-native-nitro-markdown";
113
+ import MathJax from "react-native-mathjax-svg";
114
+
115
+ const renderers: CustomRenderers = {
116
+ // Custom styled heading
117
+ heading: ({ node, children }) => (
118
+ <Heading level={node.level ?? 1}>
119
+ <Text style={{ color: "pink" }}>{children}</Text>
120
+ </Heading>
121
+ ),
122
+ // Custom math renderer
123
+ math_inline: ({ node }) => <MathJax fontSize={16}>{node.content}</MathJax>,
124
+ math_block: ({ node }) => <MathJax fontSize={20}>{node.content}</MathJax>,
125
+ };
126
+
127
+ <Markdown renderers={renderers} options={{ gfm: true, math: true }}>
128
+ {markdown}
129
+ </Markdown>;
130
+ ```
106
131
 
107
- const ast = parseMarkdown(markdown, {
108
- gfm: true, // Tables, Strikethrough, Autolinks, TaskLists
109
- math: true, // $E=mc^2$ and $$block$$
110
- wiki: true, // [[WikiLinks]]
111
- });
132
+ ### Option 3: Custom Theming
133
+
134
+ You can easily customize the look and feel of the default components by passing a `theme` object. This allows you to match your app's brand without writing custom renderers for everything.
135
+
136
+ ```tsx
137
+ import { Markdown } from "react-native-nitro-markdown";
138
+
139
+ const myTheme = {
140
+ colors: {
141
+ text: "#2D3748",
142
+ heading: "#1A202C",
143
+ link: "#3182CE",
144
+ tableBorder: "#E2E8F0",
145
+ tableHeader: "#F7FAFC",
146
+ },
147
+ spacing: {
148
+ m: 16,
149
+ },
150
+ };
151
+
152
+ <Markdown theme={myTheme}>{"# Custom Branded Markdown"}</Markdown>;
153
+
154
+ > **Tip:** The default theme is optimized for Dark Mode. For Light Mode, pass a custom theme object or check out the [theme source](packages/react-native-nitro-markdown/src/theme.ts) to see all available tokens.
112
155
  ```
113
156
 
114
- ---
157
+ ### Option 4: Headless (Minimal Bundle)
115
158
 
116
- ## 🎨 Rendering
159
+ For maximum control, data processing, or minimal JS overhead:
117
160
 
118
- This library is a **Parser Only**. It gives you the raw data (AST) so you can render it with native components (`<Text>`, `<View>`) for maximum performance.
161
+ ```tsx
162
+ /**
163
+ * Only imports the parser.
164
+ * Zero UI overhead, purely synchronous AST generation.
165
+ */
166
+ import { parseMarkdown } from "react-native-nitro-markdown/headless";
167
+
168
+ const ast = parseMarkdown("# Hello World");
169
+ ```
119
170
 
120
- Here is a simple recursive renderer example:
171
+ ### Option 5: High-Performance Streaming (LLMs)
172
+
173
+ When streaming text token-by-token (e.g., from ChatGPT or Gemini), re-parsing the entire document in JavaScript for every token is too slow.
174
+
175
+ **Nitro Markdown** enables **Native Streaming** via JSI. The text buffer is maintained in C++ and updates are pushed directly to the native view, bypassing React completely.
121
176
 
122
177
  ```tsx
123
- import React from "react";
124
- import { Text, View, StyleSheet } from "react-native";
125
- import { parseMarkdown, type MarkdownNode } from "react-native-nitro-markdown";
178
+ import {
179
+ MarkdownStream,
180
+ useMarkdownSession,
181
+ } from "react-native-nitro-markdown";
182
+
183
+ export function AIResponseStream() {
184
+ // 1. Create a native session
185
+ const session = useMarkdownSession();
126
186
 
127
- export function MarkdownView({ content }: { content: string }) {
128
- const ast = parseMarkdown(content, { gfm: true });
187
+ useEffect(() => {
188
+ // 2. Append chunks directly to C++ (Zero-Latency)
189
+ // Example: Socket.on('data', (chunk) => session.getSession().append(chunk));
129
190
 
191
+ session.getSession().append("Hello **Nitro**!");
192
+
193
+ return () => session.clear();
194
+ }, [session]);
195
+
196
+ // 3. Render the localized stream component
130
197
  return (
131
- <View style={styles.container}>
132
- <Renderer node={ast} />
133
- </View>
198
+ <MarkdownStream session={session.getSession()} options={{ gfm: true }} />
134
199
  );
135
200
  }
201
+ ```
136
202
 
137
- function Renderer({ node }: { node: MarkdownNode }) {
138
- switch (node.type) {
139
- case "document":
140
- return (
141
- <View>
142
- {node.children?.map((child, i) => (
143
- <Renderer key={i} node={child} />
144
- ))}
145
- </View>
146
- );
147
-
148
- case "heading":
149
- return (
150
- <Text style={styles.h1}>
151
- {node.children?.map((c, i) => (
152
- <Renderer key={i} node={c} />
153
- ))}
154
- </Text>
155
- );
156
-
157
- case "paragraph":
158
- return (
159
- <Text style={styles.p}>
160
- {node.children?.map((child, i) => (
161
- <Renderer key={i} node={child} />
162
- ))}
163
- </Text>
164
- );
165
-
166
- case "text":
167
- return <Text>{node.content}</Text>;
168
-
169
- case "bold":
170
- return (
171
- <Text style={styles.bold}>
172
- {node.children?.map((c, i) => (
173
- <Renderer key={i} node={c} />
174
- ))}
175
- </Text>
176
- );
177
-
178
- // Handle 'table', 'code_block', 'math_inline' etc...
179
- default:
180
- return null;
181
- }
182
- }
203
+ ---
204
+
205
+ ## 🛠️ Headless vs. Non-Headless
206
+
207
+ | Feature | **Headless** (`/headless`) | **Non-Headless** (`default`) |
208
+ | :-------------- | :-------------------------- | :--------------------------------- |
209
+ | **Logic** | Raw C++ md4c Parser | Parser + Full UI Renderer |
210
+ | **Output** | JSON AST Tree | React Native Views |
211
+ | **Best For** | Search Indexing, Custom UIs | Fast Implementation, Documentation |
212
+ | **JS Overhead** | ~4 KB | ~60 KB |
213
+
214
+ ---
215
+
216
+ ### Basic Parsing API
217
+ The parsing is synchronous and instant. It returns a fully typed JSON AST. We recommend using the `/headless` entry point if you only need the parser.
218
+
219
+ ```typescript
220
+ import { parseMarkdown } from "react-native-nitro-markdown/headless";
221
+
222
+ const ast = parseMarkdown(`
223
+ # Hello World
224
+ This is **bold** text and a [link](https://github.com).
225
+ `);
226
+ console.log(ast);
227
+ // Output: { type: "document", children: [...] }
228
+ ```
229
+
230
+ ### Options
231
+
232
+ | Option | Type | Default | Description |
233
+ | :--- | :--- | :--- | :--- |
234
+ | `gfm` | `boolean` | `false` | Enable GitHub Flavored Markdown (Tables, Strikethrough, Autolinks, TaskLists). |
235
+ | `math` | `boolean` | `false` | Enable LaTeX Math support (`$` and `$$`). |
183
236
 
184
- const styles = StyleSheet.create({
185
- container: { padding: 16 },
186
- h1: { fontSize: 24, fontWeight: "bold", marginVertical: 8 },
187
- p: { fontSize: 16, lineHeight: 24, marginBottom: 8 },
188
- bold: { fontWeight: "700" },
237
+ ### Parser Options (GFM & Math)
238
+
239
+ Enable GitHub Flavored Markdown (Tables, TaskLists) or LaTeX Math support.
240
+
241
+ ```typescript
242
+ import { parseMarkdownWithOptions } from "react-native-nitro-markdown/headless";
243
+
244
+ const ast = parseMarkdownWithOptions(markdown, {
245
+ gfm: true, // Tables (supports complex nested content!), Strikethrough, Autolinks, TaskLists
246
+ math: true, // $E=mc^2$ and $$block$$
189
247
  });
190
248
  ```
191
249
 
@@ -2,6 +2,6 @@
2
2
  #include "NitroMarkdownOnLoad.hpp"
3
3
 
4
4
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
5
- return margelo::nitro::NitroMarkdown::initialize(vm);
5
+ return margelo::nitro::Markdown::initialize(vm);
6
6
  }
7
7
 
@@ -0,0 +1,61 @@
1
+ package com.margelo.nitro.com.nitromarkdown
2
+
3
+ class HybridMarkdownSession : HybridMarkdownSessionSpec() {
4
+ private var buffer = StringBuilder()
5
+ private val listeners = mutableMapOf<Long, () -> Unit>()
6
+ private var nextListenerId = 0L
7
+ private val lock = Any()
8
+
9
+ override var highlightPosition: Double = 0.0
10
+ set(value) {
11
+ synchronized(lock) { field = value }
12
+ // No notify for highlighting to avoid flood
13
+ }
14
+
15
+
16
+
17
+ override val memorySize: Long
18
+ get() = buffer.length.toLong()
19
+
20
+ override fun append(chunk: String) {
21
+ synchronized(lock) {
22
+ buffer.append(chunk)
23
+ }
24
+ notifyListeners()
25
+ }
26
+
27
+ override fun clear() {
28
+ synchronized(lock) {
29
+ buffer.clear()
30
+ highlightPosition = 0.0
31
+ }
32
+ notifyListeners()
33
+ }
34
+
35
+ override fun getAllText(): String {
36
+ synchronized(lock) {
37
+ return buffer.toString()
38
+ }
39
+ }
40
+
41
+ override fun addListener(listener: () -> Unit): () -> Unit {
42
+ val id: Long
43
+ synchronized(lock) {
44
+ id = nextListenerId++
45
+ listeners[id] = listener
46
+ }
47
+ return {
48
+ synchronized(lock) {
49
+ listeners.remove(id)
50
+ }
51
+ }
52
+ }
53
+
54
+ private fun notifyListeners() {
55
+ val currentListeners: Collection<() -> Unit>
56
+ synchronized(lock) {
57
+ currentListeners = listeners.values.toList()
58
+ }
59
+ currentListeners.forEach { it() }
60
+ }
61
+ }
@@ -4,6 +4,7 @@ import com.facebook.react.TurboReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.module.model.ReactModuleInfoProvider
7
+ import com.facebook.react.uimanager.ViewManager
7
8
 
8
9
  class NitroMarkdownPackage : TurboReactPackage() {
9
10
  companion object {
@@ -19,5 +20,8 @@ class NitroMarkdownPackage : TurboReactPackage() {
19
20
  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
20
21
  return ReactModuleInfoProvider { emptyMap() }
21
22
  }
22
- }
23
23
 
24
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
25
+ return emptyList()
26
+ }
27
+ }
@@ -2,7 +2,7 @@
2
2
  #include <sstream>
3
3
  #include <iomanip>
4
4
 
5
- namespace margelo::nitro::NitroMarkdown {
5
+ namespace margelo::nitro::Markdown {
6
6
 
7
7
  std::string HybridMarkdownParser::parse(const std::string& text) {
8
8
  InternalParserOptions opts;
@@ -109,4 +109,4 @@ std::string HybridMarkdownParser::nodeToJson(const std::shared_ptr<InternalMarkd
109
109
  return json.str();
110
110
  }
111
111
 
112
- } // namespace margelo::nitro::NitroMarkdown
112
+ } // namespace margelo::nitro::Markdown
@@ -4,7 +4,7 @@
4
4
  #include "../core/MD4CParser.hpp"
5
5
  #include <memory>
6
6
 
7
- namespace margelo::nitro::NitroMarkdown {
7
+ namespace margelo::nitro::Markdown {
8
8
 
9
9
  using InternalMarkdownNode = ::NitroMarkdown::MarkdownNode;
10
10
  using InternalParserOptions = ::NitroMarkdown::ParserOptions;
@@ -25,4 +25,4 @@ private:
25
25
  std::string nodeToJson(const std::shared_ptr<InternalMarkdownNode>& node);
26
26
  };
27
27
 
28
- } // namespace margelo::nitro::NitroMarkdown
28
+ } // namespace margelo::nitro::Markdown
File without changes
File without changes
@@ -0,0 +1,64 @@
1
+ import Foundation
2
+ import NitroModules
3
+
4
+ class HybridMarkdownSession: HybridMarkdownSessionSpec {
5
+ private var buffer = ""
6
+ private var listeners: [UUID: () -> Void] = [:]
7
+ private let lock = NSLock()
8
+
9
+ private(set) var version: Int = 0
10
+
11
+ var highlightPosition: Double = 0
12
+
13
+
14
+
15
+ var memorySize: Int {
16
+ return buffer.utf8.count + MemoryLayout<HybridMarkdownSession>.size
17
+ }
18
+
19
+ func append(chunk: String) throws {
20
+ lock.lock()
21
+ buffer += chunk
22
+ version += 1
23
+ lock.unlock()
24
+ notifyListeners()
25
+ }
26
+
27
+ func clear() throws {
28
+ lock.lock()
29
+ buffer = ""
30
+ highlightPosition = 0
31
+ version += 1
32
+ lock.unlock()
33
+ notifyListeners()
34
+ }
35
+
36
+ func getAllText() throws -> String {
37
+ lock.lock()
38
+ defer { lock.unlock() }
39
+ return buffer
40
+ }
41
+
42
+ func addListener(listener: @escaping () -> Void) throws -> () -> Void {
43
+ let id = UUID()
44
+ lock.lock()
45
+ listeners[id] = listener
46
+ lock.unlock()
47
+
48
+ return { [weak self] in
49
+ self?.lock.lock()
50
+ self?.listeners.removeValue(forKey: id)
51
+ self?.lock.unlock()
52
+ }
53
+ }
54
+
55
+ private func notifyListeners() {
56
+ lock.lock()
57
+ let currentListeners = Array(listeners.values)
58
+ lock.unlock()
59
+
60
+ for listener in currentListeners {
61
+ listener()
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useMarkdownContext = exports.MarkdownContext = void 0;
7
+ var _react = require("react");
8
+ var _theme = require("./theme.js");
9
+ /**
10
+ * Object mapping node types to custom renderers.
11
+ */
12
+
13
+ // Context for custom renderers and theme
14
+
15
+ const MarkdownContext = exports.MarkdownContext = /*#__PURE__*/(0, _react.createContext)({
16
+ renderers: {},
17
+ theme: _theme.defaultMarkdownTheme
18
+ });
19
+ const useMarkdownContext = () => (0, _react.useContext)(MarkdownContext);
20
+ exports.useMarkdownContext = useMarkdownContext;
21
+ //# sourceMappingURL=MarkdownContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","_theme","MarkdownContext","exports","createContext","renderers","theme","defaultMarkdownTheme","useMarkdownContext","useContext"],"sourceRoot":"../../src","sources":["MarkdownContext.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AAoBA;AACA;AACA;;AAKA;;AAMO,MAAME,eAAe,GAAAC,OAAA,CAAAD,eAAA,gBAAG,IAAAE,oBAAa,EAAuB;EACjEC,SAAS,EAAE,CAAC,CAAC;EACbC,KAAK,EAAEC;AACT,CAAC,CAAC;AAEK,MAAMC,kBAAkB,GAAGA,CAAA,KAAM,IAAAC,iBAAU,EAACP,eAAe,CAAC;AAACC,OAAA,CAAAK,kBAAA,GAAAA,kBAAA","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createMarkdownSession = createMarkdownSession;
7
+ var _reactNativeNitroModules = require("react-native-nitro-modules");
8
+ function createMarkdownSession() {
9
+ return _reactNativeNitroModules.NitroModules.createHybridObject("MarkdownSession");
10
+ }
11
+ //# sourceMappingURL=MarkdownSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNativeNitroModules","require","createMarkdownSession","NitroModules","createHybridObject"],"sourceRoot":"../../src","sources":["MarkdownSession.ts"],"mappings":";;;;;;AAAA,IAAAA,wBAAA,GAAAC,OAAA;AAKO,SAASC,qBAAqBA,CAAA,EAAoB;EACvD,OAAOC,qCAAY,CAACC,kBAAkB,CAAkB,iBAAiB,CAAC;AAC5E","ignoreList":[]}