react-native-nitro-markdown 0.1.2 → 0.3.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.
- package/LICENSE +21 -0
- package/README.md +293 -119
- package/android/src/main/cpp/cpp-adapter.cpp +1 -1
- package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +61 -0
- package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +5 -1
- package/cpp/bindings/HybridMarkdownParser.cpp +2 -2
- package/cpp/bindings/HybridMarkdownParser.hpp +2 -2
- package/cpp/bindings/HybridMarkdownSession.cpp +0 -0
- package/cpp/core/MarkdownSessionCore.cpp +0 -0
- package/ios/HybridMarkdownSession.swift +64 -0
- package/lib/commonjs/MarkdownContext.js +17 -0
- package/lib/commonjs/MarkdownContext.js.map +1 -0
- package/lib/commonjs/MarkdownSession.js +11 -0
- package/lib/commonjs/MarkdownSession.js.map +1 -0
- package/lib/commonjs/default-markdown-renderer.js +217 -0
- package/lib/commonjs/default-markdown-renderer.js.map +1 -0
- package/lib/commonjs/headless.js +61 -0
- package/lib/commonjs/headless.js.map +1 -0
- package/lib/commonjs/index.js +220 -13
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/markdown-stream.js +32 -0
- package/lib/commonjs/markdown-stream.js.map +1 -0
- package/lib/commonjs/markdown.js +377 -0
- package/lib/commonjs/markdown.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/renderers/blockquote.js +36 -0
- package/lib/commonjs/renderers/blockquote.js.map +1 -0
- package/lib/commonjs/renderers/code.js +99 -0
- package/lib/commonjs/renderers/code.js.map +1 -0
- package/lib/commonjs/renderers/heading.js +63 -0
- package/lib/commonjs/renderers/heading.js.map +1 -0
- package/lib/commonjs/renderers/horizontal-rule.js +29 -0
- package/lib/commonjs/renderers/horizontal-rule.js.map +1 -0
- package/lib/commonjs/renderers/image.js +163 -0
- package/lib/commonjs/renderers/image.js.map +1 -0
- package/lib/commonjs/renderers/link.js +35 -0
- package/lib/commonjs/renderers/link.js.map +1 -0
- package/lib/commonjs/renderers/list.js +118 -0
- package/lib/commonjs/renderers/list.js.map +1 -0
- package/lib/commonjs/renderers/math.js +127 -0
- package/lib/commonjs/renderers/math.js.map +1 -0
- package/lib/commonjs/renderers/paragraph.js +39 -0
- package/lib/commonjs/renderers/paragraph.js.map +1 -0
- package/lib/commonjs/renderers/table.js +290 -0
- package/lib/commonjs/renderers/table.js.map +1 -0
- package/lib/commonjs/specs/MarkdownSession.nitro.js +6 -0
- package/lib/commonjs/specs/MarkdownSession.nitro.js.map +1 -0
- package/lib/commonjs/theme.js +191 -0
- package/lib/commonjs/theme.js.map +1 -0
- package/lib/commonjs/use-markdown-stream.js +71 -0
- package/lib/commonjs/use-markdown-stream.js.map +1 -0
- package/lib/module/MarkdownContext.js +12 -0
- package/lib/module/MarkdownContext.js.map +1 -0
- package/lib/module/MarkdownSession.js +7 -0
- package/lib/module/MarkdownSession.js.map +1 -0
- package/lib/module/default-markdown-renderer.js +212 -0
- package/lib/module/default-markdown-renderer.js.map +1 -0
- package/lib/module/headless.js +54 -0
- package/lib/module/headless.js.map +1 -0
- package/lib/module/index.js +18 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/markdown-stream.js +27 -0
- package/lib/module/markdown-stream.js.map +1 -0
- package/lib/module/markdown.js +372 -0
- package/lib/module/markdown.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/renderers/blockquote.js +31 -0
- package/lib/module/renderers/blockquote.js.map +1 -0
- package/lib/module/renderers/code.js +93 -0
- package/lib/module/renderers/code.js.map +1 -0
- package/lib/module/renderers/heading.js +58 -0
- package/lib/module/renderers/heading.js.map +1 -0
- package/lib/module/renderers/horizontal-rule.js +24 -0
- package/lib/module/renderers/horizontal-rule.js.map +1 -0
- package/lib/module/renderers/image.js +158 -0
- package/lib/module/renderers/image.js.map +1 -0
- package/lib/module/renderers/link.js +30 -0
- package/lib/module/renderers/link.js.map +1 -0
- package/lib/module/renderers/list.js +111 -0
- package/lib/module/renderers/list.js.map +1 -0
- package/lib/module/renderers/math.js +121 -0
- package/lib/module/renderers/math.js.map +1 -0
- package/lib/module/renderers/paragraph.js +34 -0
- package/lib/module/renderers/paragraph.js.map +1 -0
- package/lib/module/renderers/table.js +285 -0
- package/lib/module/renderers/table.js.map +1 -0
- package/lib/module/specs/MarkdownSession.nitro.js +4 -0
- package/lib/module/specs/MarkdownSession.nitro.js.map +1 -0
- package/lib/module/theme.js +186 -0
- package/lib/module/theme.js.map +1 -0
- package/lib/module/use-markdown-stream.js +66 -0
- package/lib/module/use-markdown-stream.js.map +1 -0
- package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/MarkdownContext.d.ts +65 -0
- package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/MarkdownSession.d.ts +4 -0
- package/lib/typescript/commonjs/MarkdownSession.d.ts.map +1 -0
- package/lib/typescript/commonjs/default-markdown-renderer.d.ts +10 -0
- package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -0
- package/lib/typescript/commonjs/headless.d.ts +57 -0
- package/lib/typescript/commonjs/headless.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +22 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/markdown-stream.d.ts +15 -0
- package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -0
- package/lib/typescript/commonjs/markdown.d.ts +47 -0
- package/lib/typescript/commonjs/markdown.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/renderers/blockquote.d.ts +9 -0
- package/lib/typescript/commonjs/renderers/blockquote.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/code.d.ts +19 -0
- package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/heading.d.ts +10 -0
- package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/image.d.ts +13 -0
- package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/link.d.ts +10 -0
- package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/list.d.ts +26 -0
- package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/math.d.ts +14 -0
- package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/paragraph.d.ts +10 -0
- package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -0
- package/lib/typescript/commonjs/renderers/table.d.ts +12 -0
- package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +12 -0
- package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme.d.ts +65 -0
- package/lib/typescript/commonjs/theme.d.ts.map +1 -0
- package/lib/typescript/commonjs/use-markdown-stream.d.ts +22 -0
- package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -0
- package/lib/typescript/module/Markdown.nitro.d.ts +13 -0
- package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -0
- package/lib/typescript/module/MarkdownContext.d.ts +65 -0
- package/lib/typescript/module/MarkdownContext.d.ts.map +1 -0
- package/lib/typescript/module/MarkdownSession.d.ts +4 -0
- package/lib/typescript/module/MarkdownSession.d.ts.map +1 -0
- package/lib/typescript/module/default-markdown-renderer.d.ts +10 -0
- package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -0
- package/lib/typescript/module/headless.d.ts +57 -0
- package/lib/typescript/module/headless.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +22 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/markdown-stream.d.ts +15 -0
- package/lib/typescript/module/markdown-stream.d.ts.map +1 -0
- package/lib/typescript/module/markdown.d.ts +47 -0
- package/lib/typescript/module/markdown.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/renderers/blockquote.d.ts +9 -0
- package/lib/typescript/module/renderers/blockquote.d.ts.map +1 -0
- package/lib/typescript/module/renderers/code.d.ts +19 -0
- package/lib/typescript/module/renderers/code.d.ts.map +1 -0
- package/lib/typescript/module/renderers/heading.d.ts +10 -0
- package/lib/typescript/module/renderers/heading.d.ts.map +1 -0
- package/lib/typescript/module/renderers/horizontal-rule.d.ts +8 -0
- package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -0
- package/lib/typescript/module/renderers/image.d.ts +13 -0
- package/lib/typescript/module/renderers/image.d.ts.map +1 -0
- package/lib/typescript/module/renderers/link.d.ts +10 -0
- package/lib/typescript/module/renderers/link.d.ts.map +1 -0
- package/lib/typescript/module/renderers/list.d.ts +26 -0
- package/lib/typescript/module/renderers/list.d.ts.map +1 -0
- package/lib/typescript/module/renderers/math.d.ts +14 -0
- package/lib/typescript/module/renderers/math.d.ts.map +1 -0
- package/lib/typescript/module/renderers/paragraph.d.ts +10 -0
- package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -0
- package/lib/typescript/module/renderers/table.d.ts +12 -0
- package/lib/typescript/module/renderers/table.d.ts.map +1 -0
- package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +12 -0
- package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -0
- package/lib/typescript/module/theme.d.ts +65 -0
- package/lib/typescript/module/theme.d.ts.map +1 -0
- package/lib/typescript/module/use-markdown-stream.d.ts +22 -0
- package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -0
- package/nitro.json +5 -2
- package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +3 -2
- package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +1 -1
- package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +17 -5
- package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +4 -4
- package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +91 -0
- package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/NitroMarkdownOnLoad.kt +1 -1
- package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +2 -2
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +28 -4
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +72 -6
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +11 -4
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +11 -3
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +16 -3
- package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +108 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +59 -0
- package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +190 -0
- package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +3 -3
- package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +67 -0
- package/nitrogen/generated/shared/c++/ParserOptions.hpp +22 -14
- package/package.json +45 -7
- package/react-native-nitro-markdown.podspec +5 -5
- package/src/MarkdownContext.ts +98 -0
- package/src/MarkdownSession.ts +8 -0
- package/src/default-markdown-renderer.tsx +261 -0
- package/src/headless.ts +116 -0
- package/src/index.ts +47 -60
- package/src/markdown-stream.tsx +32 -0
- package/src/markdown.tsx +497 -0
- package/src/renderers/blockquote.tsx +30 -0
- package/src/renderers/code.tsx +112 -0
- package/src/renderers/heading.tsx +66 -0
- package/src/renderers/horizontal-rule.tsx +23 -0
- package/src/renderers/image.tsx +175 -0
- package/src/renderers/link.tsx +33 -0
- package/src/renderers/list.tsx +131 -0
- package/src/renderers/math.tsx +141 -0
- package/src/renderers/paragraph.tsx +47 -0
- package/src/renderers/table.tsx +370 -0
- package/src/specs/MarkdownSession.nitro.ts +16 -0
- package/src/theme.ts +243 -0
- package/src/use-markdown-stream.ts +83 -0
- package/ios/NitroMarkdown-Bridging-Header.h +0 -14
- package/lib/commonjs/MarkdownJS.reference.js +0 -114
- package/lib/commonjs/MarkdownJS.reference.js.map +0 -1
- package/lib/module/MarkdownJS.reference.js +0 -107
- package/lib/module/MarkdownJS.reference.js.map +0 -1
- package/lib/typescript/Markdown.nitro.d.ts.map +0 -1
- package/lib/typescript/MarkdownJS.reference.d.ts +0 -33
- package/lib/typescript/MarkdownJS.reference.d.ts.map +0 -1
- package/lib/typescript/index.d.ts +0 -22
- package/lib/typescript/index.d.ts.map +0 -1
- package/src/MarkdownJS.reference.ts +0 -122
- /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,159 +84,330 @@ npx expo prebuild
|
|
|
80
84
|
|
|
81
85
|
## 💻 Usage
|
|
82
86
|
|
|
83
|
-
###
|
|
87
|
+
### Option 1: Batteries Included (Simplest)
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
Use the `Markdown` component with built-in premium dark-mode styling:
|
|
86
90
|
|
|
87
|
-
```
|
|
88
|
-
import {
|
|
91
|
+
```tsx
|
|
92
|
+
import { Markdown } from "react-native-nitro-markdown";
|
|
89
93
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
export function MyComponent() {
|
|
95
|
+
return (
|
|
96
|
+
<Markdown options={{ gfm: true }}>
|
|
97
|
+
{"# Hello World\nThis is **bold** text."}
|
|
98
|
+
</Markdown>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Option 2: Light Theme / Theme Presets
|
|
104
|
+
|
|
105
|
+
The default theme is optimized for dark mode. For light backgrounds, use the provided `lightMarkdownTheme`:
|
|
94
106
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
```tsx
|
|
108
|
+
import { Markdown, lightMarkdownTheme } from "react-native-nitro-markdown";
|
|
109
|
+
|
|
110
|
+
<Markdown theme={lightMarkdownTheme}>{"# Light Mode Markdown"}</Markdown>;
|
|
98
111
|
```
|
|
99
112
|
|
|
100
|
-
|
|
113
|
+
Available presets:
|
|
101
114
|
|
|
102
|
-
|
|
115
|
+
- `defaultMarkdownTheme` / `darkMarkdownTheme` - Modern dark theme
|
|
116
|
+
- `lightMarkdownTheme` - Clean light theme
|
|
117
|
+
- `minimalMarkdownTheme` - Bare minimum styling for a clean slate
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
import { parseMarkdown } from "react-native-nitro-markdown";
|
|
119
|
+
### Option 3: Custom Theming
|
|
106
120
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
Customize the look and feel by passing a partial `theme` object:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { Markdown } from "react-native-nitro-markdown";
|
|
125
|
+
|
|
126
|
+
const myTheme = {
|
|
127
|
+
colors: {
|
|
128
|
+
text: "#2D3748",
|
|
129
|
+
heading: "#1A202C",
|
|
130
|
+
link: "#3182CE",
|
|
131
|
+
},
|
|
132
|
+
fontFamilies: {
|
|
133
|
+
regular: "Inter",
|
|
134
|
+
heading: "Inter-Bold",
|
|
135
|
+
mono: "JetBrainsMono",
|
|
136
|
+
},
|
|
137
|
+
borderRadius: {
|
|
138
|
+
s: 4,
|
|
139
|
+
m: 8,
|
|
140
|
+
l: 16,
|
|
141
|
+
},
|
|
142
|
+
showCodeLanguage: true, // Toggle code language labels
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
<Markdown theme={myTheme}>{"# Custom Themed Markdown"}</Markdown>;
|
|
112
146
|
```
|
|
113
147
|
|
|
114
|
-
|
|
148
|
+
**Theme Properties:**
|
|
149
|
+
|
|
150
|
+
- `colors` - All color tokens (text, heading, link, code, codeBackground, codeLanguage, etc.)
|
|
151
|
+
- `spacing` - Spacing tokens (xs, s, m, l, xl)
|
|
152
|
+
- `fontSizes` - Font sizes (xs, s, m, l, xl, h1-h6)
|
|
153
|
+
- `fontFamilies` - Font families for regular, heading, and mono text
|
|
154
|
+
- `borderRadius` - Border radius tokens (s, m, l)
|
|
155
|
+
- `showCodeLanguage` - Show/hide code block language labels
|
|
156
|
+
|
|
157
|
+
### Option 4: Style Overrides per Node Type
|
|
158
|
+
|
|
159
|
+
Apply quick style overrides to specific node types without writing custom renderers:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
<Markdown
|
|
163
|
+
styles={{
|
|
164
|
+
heading: { color: "red", fontWeight: "900" },
|
|
165
|
+
code_block: { backgroundColor: "#1a1a2e", borderRadius: 16 },
|
|
166
|
+
blockquote: { borderLeftColor: "#ff6b6b" },
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
{markdown}
|
|
170
|
+
</Markdown>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Option 5: Minimal Styling Strategy
|
|
174
|
+
|
|
175
|
+
Start with a clean slate using the `stylingStrategy` prop:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
<Markdown stylingStrategy="minimal" theme={myLightTheme}>
|
|
179
|
+
{content}
|
|
180
|
+
</Markdown>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This zeros out all spacing and removes opinionated colors, letting you build up from scratch.
|
|
184
|
+
|
|
185
|
+
### Option 6: Custom Renderers
|
|
186
|
+
|
|
187
|
+
Override specific node types with full control. Custom renderers now receive **pre-mapped props** for common values:
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import {
|
|
191
|
+
Markdown,
|
|
192
|
+
CodeBlock,
|
|
193
|
+
type HeadingRendererProps,
|
|
194
|
+
type CodeBlockRendererProps,
|
|
195
|
+
} from "react-native-nitro-markdown";
|
|
196
|
+
|
|
197
|
+
const renderers = {
|
|
198
|
+
// Pre-mapped `level` prop - no need for node.level!
|
|
199
|
+
heading: ({ level, children }: HeadingRendererProps) => (
|
|
200
|
+
<MyHeading level={level}>{children}</MyHeading>
|
|
201
|
+
),
|
|
202
|
+
|
|
203
|
+
// Pre-mapped `content` and `language` - no getTextContent() needed!
|
|
204
|
+
code_block: ({ content, language }: CodeBlockRendererProps) => (
|
|
205
|
+
<CodeBlock
|
|
206
|
+
content={content}
|
|
207
|
+
language={language}
|
|
208
|
+
style={{ borderWidth: 2 }}
|
|
209
|
+
/>
|
|
210
|
+
),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
<Markdown renderers={renderers} options={{ gfm: true }}>
|
|
214
|
+
{markdown}
|
|
215
|
+
</Markdown>;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Pre-mapped Props by Node Type:**
|
|
115
219
|
|
|
116
|
-
|
|
220
|
+
- `heading` → `level` (1-6)
|
|
221
|
+
- `link` → `href`, `title`
|
|
222
|
+
- `image` → `url`, `alt`, `title`
|
|
223
|
+
- `code_block` → `content`, `language`
|
|
224
|
+
- `code_inline` → `content`
|
|
225
|
+
- `list` → `ordered`, `start`
|
|
226
|
+
- `task_list_item` → `checked`
|
|
117
227
|
|
|
118
|
-
|
|
228
|
+
### Option 7: Style Props on Individual Renderers
|
|
119
229
|
|
|
120
|
-
|
|
230
|
+
All built-in renderers accept a `style` prop for fine-grained overrides:
|
|
121
231
|
|
|
122
232
|
```tsx
|
|
123
|
-
import
|
|
124
|
-
|
|
125
|
-
|
|
233
|
+
import { Heading, CodeBlock, InlineCode } from "react-native-nitro-markdown";
|
|
234
|
+
|
|
235
|
+
// Works in custom renderers
|
|
236
|
+
<Heading level={1} style={{ color: "hotpink" }}>Title</Heading>
|
|
237
|
+
<CodeBlock content={code} style={{ borderRadius: 0 }} />
|
|
238
|
+
<InlineCode style={{ backgroundColor: "#ff0" }}>code</InlineCode>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Option 8: Auto Content Extraction for Code
|
|
126
242
|
|
|
127
|
-
|
|
128
|
-
|
|
243
|
+
The `CodeBlock` and `InlineCode` components now accept a `node` prop for automatic content extraction:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
// Before: Manual extraction required
|
|
247
|
+
code_block: ({ node }) => (
|
|
248
|
+
<CodeBlock content={getTextContent(node)} language={node.language} />
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// After: Just pass the node
|
|
252
|
+
code_block: ({ node }) => <CodeBlock node={node} />;
|
|
253
|
+
|
|
254
|
+
// Or use the pre-mapped content prop (recommended)
|
|
255
|
+
code_block: ({ content, language }) => (
|
|
256
|
+
<CodeBlock content={content} language={language} />
|
|
257
|
+
);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Option 9: Headless (Minimal Bundle)
|
|
261
|
+
|
|
262
|
+
For maximum control, data processing, or minimal JS overhead:
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
import {
|
|
266
|
+
parseMarkdown,
|
|
267
|
+
getTextContent,
|
|
268
|
+
} from "react-native-nitro-markdown/headless";
|
|
269
|
+
|
|
270
|
+
const ast = parseMarkdown("# Hello World");
|
|
271
|
+
const text = getTextContent(ast); // "Hello World"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Option 10: High-Performance Streaming (LLMs)
|
|
275
|
+
|
|
276
|
+
When streaming text token-by-token (e.g., from ChatGPT or Gemini):
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
import {
|
|
280
|
+
MarkdownStream,
|
|
281
|
+
useMarkdownSession,
|
|
282
|
+
} from "react-native-nitro-markdown";
|
|
283
|
+
|
|
284
|
+
export function AIResponseStream() {
|
|
285
|
+
const session = useMarkdownSession();
|
|
286
|
+
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
session.getSession().append("Hello **Nitro**!");
|
|
289
|
+
return () => session.clear();
|
|
290
|
+
}, [session]);
|
|
129
291
|
|
|
130
292
|
return (
|
|
131
|
-
<
|
|
132
|
-
<Renderer node={ast} />
|
|
133
|
-
</View>
|
|
293
|
+
<MarkdownStream session={session.getSession()} options={{ gfm: true }} />
|
|
134
294
|
);
|
|
135
295
|
}
|
|
296
|
+
```
|
|
136
297
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
}
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## 🎨 Using Context in Custom Renderers
|
|
301
|
+
|
|
302
|
+
Access theme and context in custom renderers:
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import {
|
|
306
|
+
useMarkdownContext,
|
|
307
|
+
MarkdownContext,
|
|
308
|
+
} from "react-native-nitro-markdown";
|
|
309
|
+
|
|
310
|
+
const MyCustomRenderer = ({ children }) => {
|
|
311
|
+
const { theme, stylingStrategy } = useMarkdownContext();
|
|
183
312
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
h1: { fontSize: 24, fontWeight: "bold", marginVertical: 8 },
|
|
187
|
-
p: { fontSize: 16, lineHeight: 24, marginBottom: 8 },
|
|
188
|
-
bold: { fontWeight: "700" },
|
|
189
|
-
});
|
|
313
|
+
return <View style={{ padding: theme.spacing.m }}>{children}</View>;
|
|
314
|
+
};
|
|
190
315
|
```
|
|
191
316
|
|
|
192
317
|
---
|
|
193
318
|
|
|
319
|
+
## 🛠️ Exported Utilities
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
// Parser and utilities
|
|
323
|
+
export {
|
|
324
|
+
parseMarkdown,
|
|
325
|
+
parseMarkdownWithOptions,
|
|
326
|
+
getTextContent,
|
|
327
|
+
} from "./headless";
|
|
328
|
+
|
|
329
|
+
// Theme presets
|
|
330
|
+
export {
|
|
331
|
+
defaultMarkdownTheme,
|
|
332
|
+
lightMarkdownTheme,
|
|
333
|
+
darkMarkdownTheme,
|
|
334
|
+
minimalMarkdownTheme,
|
|
335
|
+
mergeThemes,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// Context
|
|
339
|
+
export { useMarkdownContext, MarkdownContext };
|
|
340
|
+
|
|
341
|
+
// Individual renderers
|
|
342
|
+
export {
|
|
343
|
+
Heading,
|
|
344
|
+
Paragraph,
|
|
345
|
+
Link,
|
|
346
|
+
Blockquote,
|
|
347
|
+
HorizontalRule,
|
|
348
|
+
CodeBlock,
|
|
349
|
+
InlineCode,
|
|
350
|
+
List,
|
|
351
|
+
ListItem,
|
|
352
|
+
TaskListItem,
|
|
353
|
+
TableRenderer,
|
|
354
|
+
Image,
|
|
355
|
+
MathInline,
|
|
356
|
+
MathBlock,
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## 🛠️ Headless vs. Non-Headless
|
|
363
|
+
|
|
364
|
+
| Feature | **Headless** (`/headless`) | **Non-Headless** (`default`) |
|
|
365
|
+
| :-------------- | :-------------------------- | :--------------------------------- |
|
|
366
|
+
| **Logic** | Raw C++ md4c Parser | Parser + Full UI Renderer |
|
|
367
|
+
| **Output** | JSON AST Tree | React Native Views |
|
|
368
|
+
| **Best For** | Search Indexing, Custom UIs | Fast Implementation, Documentation |
|
|
369
|
+
| **JS Overhead** | ~4 KB | ~60 KB |
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### Basic Parsing API
|
|
374
|
+
|
|
375
|
+
The parsing is synchronous and instant. It returns a fully typed JSON AST:
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { parseMarkdown } from "react-native-nitro-markdown/headless";
|
|
379
|
+
|
|
380
|
+
const ast = parseMarkdown(`
|
|
381
|
+
# Hello World
|
|
382
|
+
This is **bold** text and a [link](https://github.com).
|
|
383
|
+
`);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Options
|
|
387
|
+
|
|
388
|
+
| Option | Type | Default | Description |
|
|
389
|
+
| :----- | :-------- | :------ | :----------------------------------------------------------------------------- |
|
|
390
|
+
| `gfm` | `boolean` | `false` | Enable GitHub Flavored Markdown (Tables, Strikethrough, Autolinks, TaskLists). |
|
|
391
|
+
| `math` | `boolean` | `false` | Enable LaTeX Math support (`$` and `$$`). |
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
194
395
|
## 📐 AST Structure
|
|
195
396
|
|
|
196
|
-
The parser returns a `MarkdownNode` tree
|
|
397
|
+
The parser returns a `MarkdownNode` tree:
|
|
197
398
|
|
|
198
399
|
```typescript
|
|
199
400
|
export interface MarkdownNode {
|
|
200
401
|
type: NodeType;
|
|
201
|
-
// Content for Text/Code/Math
|
|
202
402
|
content?: string;
|
|
203
|
-
// Hierarchy
|
|
204
403
|
children?: MarkdownNode[];
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
language?: string; // Code Blocks
|
|
210
|
-
// Table Props
|
|
404
|
+
level?: number;
|
|
405
|
+
href?: string;
|
|
406
|
+
checked?: boolean;
|
|
407
|
+
language?: string;
|
|
211
408
|
align?: "left" | "center" | "right";
|
|
212
409
|
isHeader?: boolean;
|
|
213
410
|
}
|
|
214
|
-
|
|
215
|
-
export type NodeType =
|
|
216
|
-
| "document"
|
|
217
|
-
| "paragraph"
|
|
218
|
-
| "text"
|
|
219
|
-
| "heading"
|
|
220
|
-
| "bold"
|
|
221
|
-
| "italic"
|
|
222
|
-
| "strikethrough"
|
|
223
|
-
| "link"
|
|
224
|
-
| "image"
|
|
225
|
-
| "code_inline"
|
|
226
|
-
| "code_block"
|
|
227
|
-
| "blockquote"
|
|
228
|
-
| "list"
|
|
229
|
-
| "list_item"
|
|
230
|
-
| "task_list_item"
|
|
231
|
-
| "table"
|
|
232
|
-
| "table_row"
|
|
233
|
-
| "table_cell"
|
|
234
|
-
| "math_inline"
|
|
235
|
-
| "math_block";
|
|
236
411
|
```
|
|
237
412
|
|
|
238
413
|
---
|
|
@@ -241,16 +416,17 @@ export type NodeType =
|
|
|
241
416
|
|
|
242
417
|
We parse math delimiters (`$` and `$$`) natively using the `MD_FLAG_LATEXMATHSPANS` flag in `md4c`.
|
|
243
418
|
|
|
244
|
-
To render the math,
|
|
419
|
+
To render the math, use a library like `react-native-mathjax-svg`:
|
|
245
420
|
|
|
246
421
|
```tsx
|
|
247
|
-
// Inside your switch(node.type)
|
|
248
422
|
case 'math_inline':
|
|
249
423
|
return <MathView math={node.content} style={styles.math} />;
|
|
250
424
|
case 'math_block':
|
|
251
425
|
return <MathView math={node.content} style={styles.mathBlock} />;
|
|
252
426
|
```
|
|
253
427
|
|
|
428
|
+
---
|
|
429
|
+
|
|
254
430
|
## 📊 Package Size
|
|
255
431
|
|
|
256
432
|
| Metric | Size |
|
|
@@ -259,8 +435,6 @@ case 'math_block':
|
|
|
259
435
|
| **Unpacked** | ~325 kB |
|
|
260
436
|
| **Total files** | 55 |
|
|
261
437
|
|
|
262
|
-
> The package includes the [md4c](https://github.com/mity/md4c) C source code (~244 kB) which is compiled natively on iOS and Android. This is a one-time cost that enables the high-performance parsing.
|
|
263
|
-
|
|
264
438
|
---
|
|
265
439
|
|
|
266
440
|
## 🤝 Contributing
|
|
@@ -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::
|
|
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::
|
|
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::
|
|
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::
|
|
28
|
+
} // namespace margelo::nitro::Markdown
|
|
File without changes
|
|
File without changes
|