@saiansh2525/react-native-nitro-markdown 0.3.2
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 +468 -0
- package/android/CMakeLists.txt +40 -0
- package/android/build.gradle +92 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/cpp-adapter.cpp +7 -0
- package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +61 -0
- package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +27 -0
- package/cpp/CMakeLists.txt +46 -0
- package/cpp/bindings/HybridMarkdownParser.cpp +114 -0
- package/cpp/bindings/HybridMarkdownParser.hpp +28 -0
- package/cpp/bindings/HybridMarkdownSession.cpp +0 -0
- package/cpp/core/MD4CParser.cpp +440 -0
- package/cpp/core/MD4CParser.hpp +21 -0
- package/cpp/core/MarkdownSessionCore.cpp +0 -0
- package/cpp/core/MarkdownTypes.hpp +124 -0
- package/cpp/md4c/md4c.c +6610 -0
- package/cpp/md4c/md4c.h +410 -0
- package/ios/HybridMarkdownSession.swift +64 -0
- package/lib/commonjs/Markdown.nitro.js +6 -0
- package/lib/commonjs/Markdown.nitro.js.map +1 -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 +98 -0
- package/lib/commonjs/headless.js.map +1 -0
- package/lib/commonjs/index.js +226 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/markdown-stream.js +32 -0
- package/lib/commonjs/markdown-stream.js.map +1 -0
- package/lib/commonjs/markdown.js +385 -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 +184 -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 +114 -0
- package/lib/commonjs/renderers/list.js.map +1 -0
- package/lib/commonjs/renderers/math.js +137 -0
- package/lib/commonjs/renderers/math.js.map +1 -0
- package/lib/commonjs/renderers/paragraph.js +37 -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/Markdown.nitro.js +4 -0
- package/lib/module/Markdown.nitro.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 +90 -0
- package/lib/module/headless.js.map +1 -0
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/markdown-stream.js +27 -0
- package/lib/module/markdown-stream.js.map +1 -0
- package/lib/module/markdown.js +380 -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 +179 -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 +107 -0
- package/lib/module/renderers/list.js.map +1 -0
- package/lib/module/renderers/math.js +131 -0
- package/lib/module/renderers/math.js.map +1 -0
- package/lib/module/renderers/paragraph.js +32 -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 +13 -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 +61 -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 +60 -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 +61 -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 +60 -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 +19 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +82 -0
- package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +56 -0
- package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +25 -0
- 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 +35 -0
- package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +41 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +93 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +45 -0
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +43 -0
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +26 -0
- 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 +22 -0
- package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +65 -0
- 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 +87 -0
- package/package.json +134 -0
- package/react-native-nitro-markdown.podspec +42 -0
- package/src/Markdown.nitro.ts +12 -0
- package/src/MarkdownContext.ts +98 -0
- package/src/MarkdownSession.ts +8 -0
- package/src/default-markdown-renderer.tsx +261 -0
- package/src/headless.ts +171 -0
- package/src/index.ts +52 -0
- package/src/markdown-stream.tsx +32 -0
- package/src/markdown.tsx +521 -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 +204 -0
- package/src/renderers/link.tsx +33 -0
- package/src/renderers/list.tsx +123 -0
- package/src/renderers/math.tsx +147 -0
- package/src/renderers/paragraph.tsx +45 -0
- package/src/renderers/table.tsx +370 -0
- package/src/specs/MarkdownSession.nitro.ts +14 -0
- package/src/theme.ts +243 -0
- package/src/use-markdown-stream.ts +83 -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
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
<p align="center">
|
|
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" />
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
# react-native-nitro-markdown 🚀
|
|
7
|
+
|
|
8
|
+
> The fastest Markdown parser for React Native. Period.
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/react-native-nitro-markdown)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
[](https://nitro.margelo.com)
|
|
13
|
+
|
|
14
|
+
**react-native-nitro-markdown** is a high-performance Markdown parser built on **[md4c](https://github.com/mity/md4c)** (C++) and **[Nitro Modules](https://nitro.margelo.com)**. It parses complex Markdown, GFM, and LaTeX Math into a structured AST **synchronously** via JSI, bypassing the React Native Bridge entirely.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## ⚡ Why Nitro? (Benchmarks)
|
|
19
|
+
|
|
20
|
+
We benchmarked this library against the most popular JavaScript parsers on a real mobile device (iPhone 15 Pro, Release Mode) using a heavy **237KB** Markdown document.
|
|
21
|
+
|
|
22
|
+
| Parser | Time (ms) | Speedup | Frame Drops (60fps) |
|
|
23
|
+
| :-------------------------- | :--------- | :---------------- | :-------------------- |
|
|
24
|
+
| **🚀 Nitro Markdown (C++)** | **~29 ms** | **1x (Baseline)** | **~1 frame** (Smooth) |
|
|
25
|
+
| 📋 CommonMark (JS) | ~82 ms | 2.8x slower | ~5 frames (Jank) |
|
|
26
|
+
| 🏗️ Markdown-It (JS) | ~118 ms | 4.0x slower | ~7 frames (Jank) |
|
|
27
|
+
| 💨 Marked (JS) | ~400 ms | 13.5x slower | ~24 frames (Freeze) |
|
|
28
|
+
|
|
29
|
+
> **Takeaway:** JavaScript parsers trigger Garbage Collection pauses. Nitro uses C++ to parse efficiently with zero-copy overhead, keeping your UI thread responsive.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📦 Installation
|
|
34
|
+
|
|
35
|
+
Choose your preferred package manager to install the package and its core dependency (`react-native-nitro-modules`).
|
|
36
|
+
|
|
37
|
+
### **1. Install Dependencies**
|
|
38
|
+
|
|
39
|
+
**npm**
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install react-native-nitro-markdown react-native-nitro-modules
|
|
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
|
+
|
|
48
|
+
**Yarn**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
yarn add react-native-nitro-markdown react-native-nitro-modules
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Bun**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bun add react-native-nitro-markdown react-native-nitro-modules
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**pnpm**
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm add react-native-nitro-markdown react-native-nitro-modules
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### **2. Install Native Pods (iOS)**
|
|
67
|
+
|
|
68
|
+
**Standard**
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd ios && pod install
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### **3. Expo Users**
|
|
75
|
+
|
|
76
|
+
If you are using Expo, you must run a **Prebuild** (Development Build) because this package contains native C++ code.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bunx expo install react-native-nitro-markdown react-native-nitro-modules
|
|
80
|
+
bunx expo prebuild
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 💻 Usage
|
|
86
|
+
|
|
87
|
+
### Option 1: Batteries Included (Simplest)
|
|
88
|
+
|
|
89
|
+
Use the `Markdown` component with built-in premium dark-mode styling:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { Markdown } from "react-native-nitro-markdown";
|
|
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`:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { Markdown, lightMarkdownTheme } from "react-native-nitro-markdown";
|
|
109
|
+
|
|
110
|
+
<Markdown theme={lightMarkdownTheme}>{"# Light Mode Markdown"}</Markdown>;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Available presets:
|
|
114
|
+
|
|
115
|
+
- `defaultMarkdownTheme` / `darkMarkdownTheme` - Modern dark theme
|
|
116
|
+
- `lightMarkdownTheme` - Clean light theme
|
|
117
|
+
- `minimalMarkdownTheme` - Bare minimum styling for a clean slate
|
|
118
|
+
|
|
119
|
+
### Option 3: Custom Theming
|
|
120
|
+
|
|
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>;
|
|
146
|
+
```
|
|
147
|
+
|
|
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:**
|
|
219
|
+
|
|
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`
|
|
227
|
+
|
|
228
|
+
### Option 7: Style Props on Individual Renderers
|
|
229
|
+
|
|
230
|
+
All built-in renderers accept a `style` prop for fine-grained overrides:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
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
|
|
242
|
+
|
|
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
|
+
getFlattenedText,
|
|
269
|
+
} from "react-native-nitro-markdown/headless";
|
|
270
|
+
|
|
271
|
+
const ast = parseMarkdown("# Hello World");
|
|
272
|
+
const text = getTextContent(ast); // "Hello World"
|
|
273
|
+
const fullText = getFlattenedText(ast); // "Hello World\n\n" (Normalized with line breaks)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Option 10: High-Performance Streaming (LLMs)
|
|
277
|
+
|
|
278
|
+
When streaming text token-by-token (e.g., from ChatGPT or Gemini):
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import {
|
|
282
|
+
MarkdownStream,
|
|
283
|
+
useMarkdownSession,
|
|
284
|
+
} from "react-native-nitro-markdown";
|
|
285
|
+
|
|
286
|
+
export function AIResponseStream() {
|
|
287
|
+
const session = useMarkdownSession();
|
|
288
|
+
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
session.getSession().append("Hello **Nitro**!");
|
|
291
|
+
return () => session.clear();
|
|
292
|
+
}, [session]);
|
|
293
|
+
|
|
294
|
+
return (
|
|
295
|
+
<MarkdownStream session={session.getSession()} options={{ gfm: true }} />
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Option 11: Extracting Plain Text
|
|
301
|
+
|
|
302
|
+
You can extract the plain text representation (with proper line breaks) using the `onParseComplete` callback. This is useful for "Copy All" buttons or TTS.
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
<Markdown
|
|
306
|
+
onParseComplete={(result) => {
|
|
307
|
+
console.log(result.text); // "Hello World\n\nThis is bold text."
|
|
308
|
+
console.log(result.ast); // Full AST
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
{markdown}
|
|
312
|
+
</Markdown>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 🎨 Using Context in Custom Renderers
|
|
318
|
+
|
|
319
|
+
Access theme and context in custom renderers:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import {
|
|
323
|
+
useMarkdownContext,
|
|
324
|
+
MarkdownContext,
|
|
325
|
+
} from "react-native-nitro-markdown";
|
|
326
|
+
|
|
327
|
+
const MyCustomRenderer = ({ children }) => {
|
|
328
|
+
const { theme, stylingStrategy } = useMarkdownContext();
|
|
329
|
+
|
|
330
|
+
return <View style={{ padding: theme.spacing.m }}>{children}</View>;
|
|
331
|
+
};
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## 🛠️ Exported Utilities
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
// Parser and utilities
|
|
340
|
+
export {
|
|
341
|
+
parseMarkdown,
|
|
342
|
+
parseMarkdownWithOptions,
|
|
343
|
+
getTextContent,
|
|
344
|
+
getFlattenedText,
|
|
345
|
+
} from "./headless";
|
|
346
|
+
|
|
347
|
+
// Theme presets
|
|
348
|
+
export {
|
|
349
|
+
defaultMarkdownTheme,
|
|
350
|
+
lightMarkdownTheme,
|
|
351
|
+
darkMarkdownTheme,
|
|
352
|
+
minimalMarkdownTheme,
|
|
353
|
+
mergeThemes,
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// Context
|
|
357
|
+
export { useMarkdownContext, MarkdownContext };
|
|
358
|
+
|
|
359
|
+
// Individual renderers
|
|
360
|
+
export {
|
|
361
|
+
Heading,
|
|
362
|
+
Paragraph,
|
|
363
|
+
Link,
|
|
364
|
+
Blockquote,
|
|
365
|
+
HorizontalRule,
|
|
366
|
+
CodeBlock,
|
|
367
|
+
InlineCode,
|
|
368
|
+
List,
|
|
369
|
+
ListItem,
|
|
370
|
+
TaskListItem,
|
|
371
|
+
TableRenderer,
|
|
372
|
+
Image,
|
|
373
|
+
MathInline,
|
|
374
|
+
MathBlock,
|
|
375
|
+
};
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## 🛠️ Headless vs. Non-Headless
|
|
381
|
+
|
|
382
|
+
| Feature | **Headless** (`/headless`) | **Non-Headless** (`default`) |
|
|
383
|
+
| :-------------- | :-------------------------- | :--------------------------------- |
|
|
384
|
+
| **Logic** | Raw C++ md4c Parser | Parser + Full UI Renderer |
|
|
385
|
+
| **Output** | JSON AST Tree | React Native Views |
|
|
386
|
+
| **Best For** | Search Indexing, Custom UIs | Fast Implementation, Documentation |
|
|
387
|
+
| **JS Overhead** | ~4 KB | ~60 KB |
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
### Basic Parsing API
|
|
392
|
+
|
|
393
|
+
The parsing is synchronous and instant. It returns a fully typed JSON AST:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { parseMarkdown } from "react-native-nitro-markdown/headless";
|
|
397
|
+
|
|
398
|
+
const ast = parseMarkdown(`
|
|
399
|
+
# Hello World
|
|
400
|
+
This is **bold** text and a [link](https://github.com).
|
|
401
|
+
`);
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Options
|
|
405
|
+
|
|
406
|
+
| Option | Type | Default | Description |
|
|
407
|
+
| :----- | :-------- | :------ | :----------------------------------------------------------------------------- |
|
|
408
|
+
| `gfm` | `boolean` | `false` | Enable GitHub Flavored Markdown (Tables, Strikethrough, Autolinks, TaskLists). |
|
|
409
|
+
| `math` | `boolean` | `false` | Enable LaTeX Math support (`$` and `$$`). |
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 📐 AST Structure
|
|
414
|
+
|
|
415
|
+
The parser returns a `MarkdownNode` tree:
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
export interface MarkdownNode {
|
|
419
|
+
type: NodeType;
|
|
420
|
+
content?: string;
|
|
421
|
+
children?: MarkdownNode[];
|
|
422
|
+
level?: number;
|
|
423
|
+
href?: string;
|
|
424
|
+
checked?: boolean;
|
|
425
|
+
language?: string;
|
|
426
|
+
align?: "left" | "center" | "right";
|
|
427
|
+
isHeader?: boolean;
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 🧮 LaTeX Math Support
|
|
434
|
+
|
|
435
|
+
We parse math delimiters (`$` and `$$`) natively using the `MD_FLAG_LATEXMATHSPANS` flag in `md4c`.
|
|
436
|
+
|
|
437
|
+
To render the math, use a library like `react-native-mathjax-svg`:
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
case 'math_inline':
|
|
441
|
+
return <MathView math={node.content} style={styles.math} />;
|
|
442
|
+
case 'math_block':
|
|
443
|
+
return <MathView math={node.content} style={styles.mathBlock} />;
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 📊 Package Size
|
|
449
|
+
|
|
450
|
+
| Metric | Size |
|
|
451
|
+
| :------------------- | :------ |
|
|
452
|
+
| **Packed (tarball)** | ~75 kB |
|
|
453
|
+
| **Unpacked** | ~325 kB |
|
|
454
|
+
| **Total files** | 55 |
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 🤝 Contributing
|
|
459
|
+
|
|
460
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
461
|
+
|
|
462
|
+
## 📄 License
|
|
463
|
+
|
|
464
|
+
MIT
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
Built with ❤️ using [Nitro Modules](https://nitro.margelo.com) and [md4c](https://github.com/mity/md4c).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.22.1)
|
|
2
|
+
project(NitroMarkdown)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_C_STANDARD 11)
|
|
7
|
+
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
8
|
+
|
|
9
|
+
# Define the path to our C++ sources
|
|
10
|
+
set(CPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../cpp")
|
|
11
|
+
|
|
12
|
+
# Collect source files
|
|
13
|
+
file(GLOB MD4C_SOURCES "${CPP_ROOT}/md4c/*.c")
|
|
14
|
+
file(GLOB CORE_SOURCES "${CPP_ROOT}/core/*.cpp")
|
|
15
|
+
file(GLOB BINDING_SOURCES "${CPP_ROOT}/bindings/*.cpp")
|
|
16
|
+
|
|
17
|
+
# Create the shared library with our sources
|
|
18
|
+
add_library(${PROJECT_NAME} SHARED
|
|
19
|
+
${MD4C_SOURCES}
|
|
20
|
+
${CORE_SOURCES}
|
|
21
|
+
${BINDING_SOURCES}
|
|
22
|
+
# JNI adapter
|
|
23
|
+
src/main/cpp/cpp-adapter.cpp
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Include directories
|
|
27
|
+
target_include_directories(${PROJECT_NAME} PRIVATE
|
|
28
|
+
"${CPP_ROOT}/md4c"
|
|
29
|
+
"${CPP_ROOT}/core"
|
|
30
|
+
"${CPP_ROOT}/bindings"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Preprocessor definitions
|
|
34
|
+
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
|
35
|
+
MD4C_USE_UTF8=1
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Include Nitro autolinking (adds nitrogen sources, definitions, and links)
|
|
39
|
+
include(${CMAKE_CURRENT_SOURCE_DIR}/../nitrogen/generated/android/NitroMarkdown+autolinking.cmake)
|
|
40
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.10.1"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def reactNativeArchitectures() {
|
|
13
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
14
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
|
+
apply from: '../nitrogen/generated/android/NitroMarkdown+autolinking.gradle'
|
|
24
|
+
|
|
25
|
+
if (isNewArchitectureEnabled()) {
|
|
26
|
+
apply plugin: "com.facebook.react"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def getExtOrDefault(name) {
|
|
30
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroMarkdown_" + name]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def getExtOrIntegerDefault(name) {
|
|
34
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroMarkdown_" + name]).toInteger()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
android {
|
|
38
|
+
namespace "com.nitromarkdown"
|
|
39
|
+
|
|
40
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
41
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
42
|
+
|
|
43
|
+
defaultConfig {
|
|
44
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
45
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
46
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
47
|
+
|
|
48
|
+
externalNativeBuild {
|
|
49
|
+
cmake {
|
|
50
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
51
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
52
|
+
abiFilters (*reactNativeArchitectures())
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
externalNativeBuild {
|
|
58
|
+
cmake {
|
|
59
|
+
path "CMakeLists.txt"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
buildFeatures {
|
|
64
|
+
buildConfig true
|
|
65
|
+
prefab true
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
compileOptions {
|
|
69
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
70
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
sourceSets {
|
|
74
|
+
main {
|
|
75
|
+
java.srcDirs += ["src/main/java"]
|
|
76
|
+
if (isNewArchitectureEnabled()) {
|
|
77
|
+
java.srcDirs += ["${project.buildDir}/generated/source/codegen/java"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
repositories {
|
|
84
|
+
mavenCentral()
|
|
85
|
+
google()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
dependencies {
|
|
89
|
+
//noinspection GradleDynamicVersion
|
|
90
|
+
implementation "com.facebook.react:react-native:+"
|
|
91
|
+
implementation project(":react-native-nitro-modules")
|
|
92
|
+
}
|
|
@@ -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
|
+
}
|