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.
Files changed (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -119
  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 +17 -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 +217 -0
  16. package/lib/commonjs/default-markdown-renderer.js.map +1 -0
  17. package/lib/commonjs/headless.js +61 -0
  18. package/lib/commonjs/headless.js.map +1 -0
  19. package/lib/commonjs/index.js +220 -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 +377 -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 +99 -0
  29. package/lib/commonjs/renderers/code.js.map +1 -0
  30. package/lib/commonjs/renderers/heading.js +63 -0
  31. package/lib/commonjs/renderers/heading.js.map +1 -0
  32. package/lib/commonjs/renderers/horizontal-rule.js +29 -0
  33. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -0
  34. package/lib/commonjs/renderers/image.js +163 -0
  35. package/lib/commonjs/renderers/image.js.map +1 -0
  36. package/lib/commonjs/renderers/link.js +35 -0
  37. package/lib/commonjs/renderers/link.js.map +1 -0
  38. package/lib/commonjs/renderers/list.js +118 -0
  39. package/lib/commonjs/renderers/list.js.map +1 -0
  40. package/lib/commonjs/renderers/math.js +127 -0
  41. package/lib/commonjs/renderers/math.js.map +1 -0
  42. package/lib/commonjs/renderers/paragraph.js +39 -0
  43. package/lib/commonjs/renderers/paragraph.js.map +1 -0
  44. package/lib/commonjs/renderers/table.js +290 -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 +191 -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 +12 -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 +212 -0
  57. package/lib/module/default-markdown-renderer.js.map +1 -0
  58. package/lib/module/headless.js +54 -0
  59. package/lib/module/headless.js.map +1 -0
  60. package/lib/module/index.js +18 -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 +372 -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 +93 -0
  70. package/lib/module/renderers/code.js.map +1 -0
  71. package/lib/module/renderers/heading.js +58 -0
  72. package/lib/module/renderers/heading.js.map +1 -0
  73. package/lib/module/renderers/horizontal-rule.js +24 -0
  74. package/lib/module/renderers/horizontal-rule.js.map +1 -0
  75. package/lib/module/renderers/image.js +158 -0
  76. package/lib/module/renderers/image.js.map +1 -0
  77. package/lib/module/renderers/link.js +30 -0
  78. package/lib/module/renderers/link.js.map +1 -0
  79. package/lib/module/renderers/list.js +111 -0
  80. package/lib/module/renderers/list.js.map +1 -0
  81. package/lib/module/renderers/math.js +121 -0
  82. package/lib/module/renderers/math.js.map +1 -0
  83. package/lib/module/renderers/paragraph.js +34 -0
  84. package/lib/module/renderers/paragraph.js.map +1 -0
  85. package/lib/module/renderers/table.js +285 -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 +186 -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 +65 -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 +57 -0
  101. package/lib/typescript/commonjs/headless.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/index.d.ts +22 -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 +47 -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 +19 -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 +8 -0
  116. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/renderers/image.d.ts +13 -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 +26 -0
  122. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/renderers/math.d.ts +14 -0
  124. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/renderers/paragraph.d.ts +10 -0
  126. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/renderers/table.d.ts +12 -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 +65 -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 +65 -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 +57 -0
  144. package/lib/typescript/module/headless.d.ts.map +1 -0
  145. package/lib/typescript/module/index.d.ts +22 -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 +47 -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 +19 -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 +8 -0
  159. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -0
  160. package/lib/typescript/module/renderers/image.d.ts +13 -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 +26 -0
  165. package/lib/typescript/module/renderers/list.d.ts.map +1 -0
  166. package/lib/typescript/module/renderers/math.d.ts +14 -0
  167. package/lib/typescript/module/renderers/math.d.ts.map +1 -0
  168. package/lib/typescript/module/renderers/paragraph.d.ts +10 -0
  169. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -0
  170. package/lib/typescript/module/renderers/table.d.ts +12 -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 +65 -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 -7
  206. package/react-native-nitro-markdown.podspec +5 -5
  207. package/src/MarkdownContext.ts +98 -0
  208. package/src/MarkdownSession.ts +8 -0
  209. package/src/default-markdown-renderer.tsx +261 -0
  210. package/src/headless.ts +116 -0
  211. package/src/index.ts +47 -60
  212. package/src/markdown-stream.tsx +32 -0
  213. package/src/markdown.tsx +497 -0
  214. package/src/renderers/blockquote.tsx +30 -0
  215. package/src/renderers/code.tsx +112 -0
  216. package/src/renderers/heading.tsx +66 -0
  217. package/src/renderers/horizontal-rule.tsx +23 -0
  218. package/src/renderers/image.tsx +175 -0
  219. package/src/renderers/link.tsx +33 -0
  220. package/src/renderers/list.tsx +131 -0
  221. package/src/renderers/math.tsx +141 -0
  222. package/src/renderers/paragraph.tsx +47 -0
  223. package/src/renderers/table.tsx +370 -0
  224. package/src/specs/MarkdownSession.nitro.ts +16 -0
  225. package/src/theme.ts +243 -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/package.json CHANGED
@@ -1,12 +1,36 @@
1
1
  {
2
2
  "name": "react-native-nitro-markdown",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "description": "High-performance Markdown parser for React Native using Nitro Modules and md4c",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
7
- "types": "lib/typescript/index.d.ts",
7
+ "types": "lib/typescript/commonjs/index.d.ts",
8
8
  "react-native": "src/index.ts",
9
9
  "source": "src/index.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./lib/typescript/module/index.d.ts",
14
+ "default": "./lib/module/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./lib/typescript/commonjs/index.d.ts",
18
+ "default": "./lib/commonjs/index.js"
19
+ },
20
+ "react-native": "./src/index.ts"
21
+ },
22
+ "./headless": {
23
+ "import": {
24
+ "types": "./lib/typescript/module/headless.d.ts",
25
+ "default": "./lib/module/headless.js"
26
+ },
27
+ "require": {
28
+ "types": "./lib/typescript/commonjs/headless.d.ts",
29
+ "default": "./lib/commonjs/headless.js"
30
+ },
31
+ "react-native": "./src/headless.ts"
32
+ }
33
+ },
10
34
  "files": [
11
35
  "src",
12
36
  "lib",
@@ -34,8 +58,8 @@
34
58
  "test": "jest",
35
59
  "test:coverage": "jest --coverage",
36
60
  "benchmark": "node ../../scripts/benchmark-comparison.js",
37
- "prepack": "node -e \"require('fs').copyFileSync('../../README.md','./README.md')\"",
38
- "postpack": "node -e \"const fs=require('fs');if(fs.existsSync('./README.md'))fs.unlinkSync('./README.md')\"",
61
+ "prepack": "node -e \"const fs=require('fs'); fs.copyFileSync('../../README.md','./README.md'); fs.copyFileSync('../../LICENSE','./LICENSE')\"",
62
+ "postpack": "node -e \"const fs=require('fs'); if(fs.existsSync('./README.md'))fs.unlinkSync('./README.md'); if(fs.existsSync('./LICENSE'))fs.unlinkSync('./LICENSE')\"",
39
63
  "test:cpp": "node scripts/test-cpp.js"
40
64
  },
41
65
  "keywords": [
@@ -52,7 +76,7 @@
52
76
  "type": "git",
53
77
  "url": "git+https://github.com/JoaoPauloCMarra/react-native-nitro-markdown.git"
54
78
  },
55
- "author": "",
79
+ "author": "João Paulo C. Marra <joaopaulocmarra@gmail.com>",
56
80
  "license": "MIT",
57
81
  "bugs": {
58
82
  "url": "https://github.com/JoaoPauloCMarra/react-native-nitro-markdown/issues"
@@ -62,12 +86,26 @@
62
86
  "registry": "https://registry.npmjs.org/"
63
87
  },
64
88
  "devDependencies": {
65
- "react-native-nitro-modules": "^0.32.0"
89
+ "@types/react": "^19.2.7",
90
+ "@types/react-native": "^0.73.0",
91
+ "react-native-builder-bob": "^0.40.17",
92
+ "react-native-nitro-modules": "*",
93
+ "typescript": "^5.9.3"
66
94
  },
67
95
  "peerDependencies": {
68
96
  "react": "*",
69
97
  "react-native": ">=0.75.0",
70
- "react-native-nitro-modules": ">=0.31.0"
98
+ "react-native-nitro-modules": "*",
99
+ "react-native-mathjax-svg": ">=0.9.0",
100
+ "react-native-svg": ">=13.0.0"
101
+ },
102
+ "peerDependenciesMeta": {
103
+ "react-native-mathjax-svg": {
104
+ "optional": true
105
+ },
106
+ "react-native-svg": {
107
+ "optional": true
108
+ }
71
109
  },
72
110
  "codegenConfig": {
73
111
  "name": "NitroMarkdownSpec",
@@ -12,19 +12,20 @@ Pod::Spec.new do |s|
12
12
 
13
13
  s.platforms = { :ios => "13.0" }
14
14
  s.source = { :git => "https://github.com/JoaoPauloCMarra/react-native-nitro-markdown.git", :tag => "#{s.version}" }
15
+ s.module_name = "NitroMarkdown"
15
16
 
16
- # All source files including md4c and our C++ implementation
17
17
  s.source_files = [
18
18
  "ios/**/*.{h,m,mm,swift}",
19
19
  "cpp/**/*.{h,hpp,c,cpp}"
20
20
  ]
21
21
 
22
- # Ensure md4c.c is compiled as C, not C++
23
22
  s.pod_target_xcconfig = {
24
23
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
25
24
  "CLANG_CXX_LIBRARY" => "libc++",
26
25
  "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) MD4C_USE_UTF8=1",
27
26
  "HEADER_SEARCH_PATHS" => [
27
+ "\"$(inherited)\"",
28
+ "\"$(PODS_ROOT)/Headers/Private/Yoga\"",
28
29
  "\"$(PODS_TARGET_SRCROOT)/cpp/md4c\"",
29
30
  "\"$(PODS_TARGET_SRCROOT)/cpp/core\"",
30
31
  "\"$(PODS_TARGET_SRCROOT)/cpp/bindings\"",
@@ -33,10 +34,9 @@ Pod::Spec.new do |s|
33
34
  ].join(" ")
34
35
  }
35
36
 
36
- # React Native dependency
37
37
  s.dependency "React-Core"
38
-
39
- # Add Nitro autolinking
38
+ s.dependency "React-Fabric"
39
+
40
40
  load 'nitrogen/generated/ios/NitroMarkdown+autolinking.rb'
41
41
  add_nitrogen_files(s)
42
42
  end
@@ -0,0 +1,98 @@
1
+ import {
2
+ createContext,
3
+ useContext,
4
+ type ReactNode,
5
+ type ComponentType,
6
+ } from "react";
7
+ import {
8
+ defaultMarkdownTheme,
9
+ type MarkdownTheme,
10
+ type NodeStyleOverrides,
11
+ type StylingStrategy,
12
+ } from "./theme";
13
+ import type { MarkdownNode } from "./headless";
14
+
15
+ export interface NodeRendererProps {
16
+ node: MarkdownNode;
17
+ depth: number;
18
+ inListItem: boolean;
19
+ parentIsText?: boolean;
20
+ }
21
+
22
+ export interface BaseCustomRendererProps {
23
+ node: MarkdownNode;
24
+ children: ReactNode;
25
+ Renderer: ComponentType<NodeRendererProps>;
26
+ }
27
+
28
+ export interface EnhancedRendererProps extends BaseCustomRendererProps {
29
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
30
+ href?: string;
31
+ title?: string;
32
+ url?: string;
33
+ alt?: string;
34
+ content?: string;
35
+ language?: string;
36
+ ordered?: boolean;
37
+ start?: number;
38
+ checked?: boolean;
39
+ }
40
+
41
+ export interface HeadingRendererProps extends BaseCustomRendererProps {
42
+ level: 1 | 2 | 3 | 4 | 5 | 6;
43
+ }
44
+
45
+ export interface LinkRendererProps extends BaseCustomRendererProps {
46
+ href: string;
47
+ title?: string;
48
+ }
49
+
50
+ export interface ImageRendererProps extends BaseCustomRendererProps {
51
+ url: string;
52
+ alt?: string;
53
+ title?: string;
54
+ }
55
+
56
+ export interface CodeBlockRendererProps extends BaseCustomRendererProps {
57
+ content: string;
58
+ language?: string;
59
+ }
60
+
61
+ export interface InlineCodeRendererProps extends BaseCustomRendererProps {
62
+ content: string;
63
+ }
64
+
65
+ export interface ListRendererProps extends BaseCustomRendererProps {
66
+ ordered: boolean;
67
+ start?: number;
68
+ }
69
+
70
+ export interface TaskListItemRendererProps extends BaseCustomRendererProps {
71
+ checked: boolean;
72
+ }
73
+
74
+ export interface CustomRendererProps extends EnhancedRendererProps {}
75
+
76
+ export type CustomRenderer = (
77
+ props: EnhancedRendererProps
78
+ ) => ReactNode | undefined;
79
+
80
+ export type CustomRenderers = Partial<
81
+ Record<MarkdownNode["type"], CustomRenderer>
82
+ >;
83
+
84
+ export interface MarkdownContextValue {
85
+ renderers: CustomRenderers;
86
+ theme: MarkdownTheme;
87
+ styles?: NodeStyleOverrides;
88
+ stylingStrategy: StylingStrategy;
89
+ }
90
+
91
+ export const MarkdownContext = createContext<MarkdownContextValue>({
92
+ renderers: {},
93
+ theme: defaultMarkdownTheme,
94
+ styles: undefined,
95
+ stylingStrategy: "opinionated",
96
+ });
97
+
98
+ export const useMarkdownContext = () => useContext(MarkdownContext);
@@ -0,0 +1,8 @@
1
+ import { NitroModules } from "react-native-nitro-modules";
2
+ import type { MarkdownSession as MarkdownSessionSpec } from "./specs/MarkdownSession.nitro";
3
+
4
+ export type MarkdownSession = MarkdownSessionSpec;
5
+
6
+ export function createMarkdownSession(): MarkdownSession {
7
+ return NitroModules.createHybridObject<MarkdownSession>("MarkdownSession");
8
+ }
@@ -0,0 +1,261 @@
1
+ import { type ReactNode, type FC } from "react";
2
+ import { View, Text, StyleSheet } from "react-native";
3
+ import { type MarkdownNode, getTextContent } from "./headless";
4
+ import { Heading } from "./renderers/heading";
5
+ import { Paragraph } from "./renderers/paragraph";
6
+ import { Link } from "./renderers/link";
7
+ import { Blockquote } from "./renderers/blockquote";
8
+ import { HorizontalRule } from "./renderers/horizontal-rule";
9
+ import { CodeBlock, InlineCode } from "./renderers/code";
10
+ import { List, ListItem, TaskListItem } from "./renderers/list";
11
+ import { TableRenderer } from "./renderers/table";
12
+ import { Image } from "./renderers/image";
13
+ import { MathInline, MathBlock } from "./renderers/math";
14
+ import { defaultMarkdownTheme } from "./theme";
15
+
16
+ interface MarkdownRendererProps {
17
+ node: MarkdownNode;
18
+ depth?: number;
19
+ inListItem?: boolean;
20
+ }
21
+
22
+ const isInline = (type: MarkdownNode["type"]): boolean => {
23
+ return (
24
+ type === "text" ||
25
+ type === "bold" ||
26
+ type === "italic" ||
27
+ type === "strikethrough" ||
28
+ type === "link" ||
29
+ type === "code_inline" ||
30
+ type === "soft_break" ||
31
+ type === "line_break" ||
32
+ type === "math_inline" ||
33
+ type === "html_inline"
34
+ );
35
+ };
36
+
37
+ export const DefaultMarkdownRenderer: FC<MarkdownRendererProps> = ({
38
+ node,
39
+ depth = 0,
40
+ inListItem = false,
41
+ }) => {
42
+ const renderChildren = (
43
+ children?: MarkdownNode[],
44
+ childInListItem = false
45
+ ) => {
46
+ if (!children || children.length === 0) return null;
47
+
48
+ const elements: ReactNode[] = [];
49
+ let currentInlineGroup: MarkdownNode[] = [];
50
+
51
+ const flushInlineGroup = () => {
52
+ if (currentInlineGroup.length > 0) {
53
+ elements.push(
54
+ <Text key={`inline-group-${elements.length}`} style={styles.text}>
55
+ {currentInlineGroup.map((child, index) => (
56
+ <DefaultMarkdownRenderer
57
+ key={`${child.type}-${index}`}
58
+ node={child}
59
+ depth={depth + 1}
60
+ inListItem={childInListItem}
61
+ />
62
+ ))}
63
+ </Text>
64
+ );
65
+ currentInlineGroup = [];
66
+ }
67
+ };
68
+
69
+ children.forEach((child, index) => {
70
+ if (isInline(child.type)) {
71
+ currentInlineGroup.push(child);
72
+ } else {
73
+ flushInlineGroup();
74
+ elements.push(
75
+ <DefaultMarkdownRenderer
76
+ key={`${child.type}-${index}`}
77
+ node={child}
78
+ depth={depth + 1}
79
+ inListItem={childInListItem}
80
+ />
81
+ );
82
+ }
83
+ });
84
+
85
+ flushInlineGroup();
86
+ return elements;
87
+ };
88
+
89
+ switch (node.type) {
90
+ case "document":
91
+ return (
92
+ <View style={styles.document}>
93
+ {renderChildren(node.children, false)}
94
+ </View>
95
+ );
96
+
97
+ case "heading":
98
+ return (
99
+ <Heading level={node.level ?? 1}>
100
+ {renderChildren(node.children, inListItem)}
101
+ </Heading>
102
+ );
103
+
104
+ case "paragraph":
105
+ return (
106
+ <Paragraph inListItem={inListItem}>
107
+ {renderChildren(node.children, inListItem)}
108
+ </Paragraph>
109
+ );
110
+
111
+ case "text":
112
+ return <Text style={styles.text}>{node.content}</Text>;
113
+
114
+ case "bold":
115
+ return (
116
+ <Text style={styles.bold}>
117
+ {renderChildren(node.children, inListItem)}
118
+ </Text>
119
+ );
120
+
121
+ case "italic":
122
+ return (
123
+ <Text style={styles.italic}>
124
+ {renderChildren(node.children, inListItem)}
125
+ </Text>
126
+ );
127
+
128
+ case "strikethrough":
129
+ return (
130
+ <Text style={styles.strikethrough}>
131
+ {renderChildren(node.children, inListItem)}
132
+ </Text>
133
+ );
134
+
135
+ case "link":
136
+ return (
137
+ <Link href={node.href ?? ""}>
138
+ {renderChildren(node.children, inListItem)}
139
+ </Link>
140
+ );
141
+
142
+ case "image":
143
+ return (
144
+ <Image
145
+ url={node.href ?? ""}
146
+ title={node.title}
147
+ alt={node.alt}
148
+ Renderer={DefaultMarkdownRenderer}
149
+ />
150
+ );
151
+
152
+ case "code_inline":
153
+ return <InlineCode>{node.content}</InlineCode>;
154
+
155
+ case "code_block":
156
+ return (
157
+ <CodeBlock language={node.language} content={getTextContent(node)} />
158
+ );
159
+
160
+ case "blockquote":
161
+ return (
162
+ <Blockquote>{renderChildren(node.children, inListItem)}</Blockquote>
163
+ );
164
+
165
+ case "horizontal_rule":
166
+ return <HorizontalRule />;
167
+
168
+ case "line_break":
169
+ return <Text>{"\n"}</Text>;
170
+
171
+ case "soft_break":
172
+ return <Text> </Text>;
173
+
174
+ case "math_inline": {
175
+ let mathContent = getTextContent(node);
176
+ if (!mathContent) return null;
177
+ mathContent = mathContent.replace(/^\$+|\$+$/g, "").trim();
178
+ return <MathInline content={mathContent} />;
179
+ }
180
+
181
+ case "math_block": {
182
+ let mathContent = getTextContent(node);
183
+ if (!mathContent) return null;
184
+ mathContent = mathContent.replace(/^\$+|\$+$/g, "").trim();
185
+ return <MathBlock content={mathContent} />;
186
+ }
187
+
188
+ case "list":
189
+ return (
190
+ <List ordered={node.ordered ?? false} start={node.start} depth={depth}>
191
+ {node.children?.map((child, index) => {
192
+ if (child.type === "task_list_item") {
193
+ return (
194
+ <DefaultMarkdownRenderer
195
+ key={index}
196
+ node={child}
197
+ depth={depth + 1}
198
+ inListItem={true}
199
+ />
200
+ );
201
+ }
202
+ return (
203
+ <ListItem
204
+ key={index}
205
+ index={index}
206
+ ordered={node.ordered ?? false}
207
+ start={node.start ?? 1}
208
+ >
209
+ <DefaultMarkdownRenderer
210
+ node={child}
211
+ depth={depth + 1}
212
+ inListItem={true}
213
+ />
214
+ </ListItem>
215
+ );
216
+ })}
217
+ </List>
218
+ );
219
+
220
+ case "list_item":
221
+ return <>{renderChildren(node.children, true)}</>;
222
+
223
+ case "task_list_item":
224
+ return (
225
+ <TaskListItem checked={node.checked ?? false}>
226
+ {renderChildren(node.children, true)}
227
+ </TaskListItem>
228
+ );
229
+
230
+ case "table":
231
+ return <TableRenderer node={node} Renderer={DefaultMarkdownRenderer} />;
232
+
233
+ case "table_head":
234
+ case "table_body":
235
+ case "table_row":
236
+ case "table_cell":
237
+ // Handled by TableRenderer
238
+ return null;
239
+
240
+ default:
241
+ return null;
242
+ }
243
+ };
244
+
245
+ const styles = StyleSheet.create({
246
+ document: {
247
+ flex: 1,
248
+ },
249
+ text: {
250
+ color: defaultMarkdownTheme.colors.text,
251
+ },
252
+ bold: {
253
+ fontWeight: "700",
254
+ },
255
+ italic: {
256
+ fontStyle: "italic",
257
+ },
258
+ strikethrough: {
259
+ textDecorationLine: "line-through",
260
+ },
261
+ });
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Headless entry point for react-native-nitro-markdown.
3
+ * Use this when you want to build your own renderer and minimize bundle size.
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * import { parseMarkdown } from 'react-native-nitro-markdown/headless';
8
+ *
9
+ * const ast = parseMarkdown('# Hello World');
10
+ * // Build your own renderer using the AST
11
+ * ```
12
+ */
13
+ import { NitroModules } from "react-native-nitro-modules";
14
+ import type { MarkdownParser, ParserOptions } from "./Markdown.nitro";
15
+
16
+ export type { ParserOptions } from "./Markdown.nitro";
17
+
18
+ /**
19
+ * Represents a node in the Markdown AST (Abstract Syntax Tree).
20
+ * Each node has a type and optional properties depending on the node type.
21
+ */
22
+ export interface MarkdownNode {
23
+ /** The type of markdown element this node represents. Used to decide how to render the node. */
24
+ type:
25
+ | "document"
26
+ | "heading"
27
+ | "paragraph"
28
+ | "text"
29
+ | "bold"
30
+ | "italic"
31
+ | "strikethrough"
32
+ | "link"
33
+ | "image"
34
+ | "code_inline"
35
+ | "code_block"
36
+ | "blockquote"
37
+ | "horizontal_rule"
38
+ | "line_break"
39
+ | "soft_break"
40
+ | "table"
41
+ | "table_head"
42
+ | "table_body"
43
+ | "table_row"
44
+ | "table_cell"
45
+ | "list"
46
+ | "list_item"
47
+ | "task_list_item"
48
+ | "math_inline"
49
+ | "math_block"
50
+ | "html_block"
51
+ | "html_inline";
52
+ /** Text content for text, code, and similar nodes. */
53
+ content?: string;
54
+ /** Heading level (1-6) for heading nodes. */
55
+ level?: number;
56
+ /** URL for link and image nodes. */
57
+ href?: string;
58
+ /** Title attribute for link and image nodes. */
59
+ title?: string;
60
+ /** Alt text for image nodes. */
61
+ alt?: string;
62
+ /** Programming language for code blocks (e.g., 'typescript', 'javascript'). */
63
+ language?: string;
64
+ /** Whether a list is ordered (numbered) or unordered. */
65
+ ordered?: boolean;
66
+ /** The starting number for ordered lists. */
67
+ start?: number;
68
+ /** Whether a task list item is currently checked. */
69
+ checked?: boolean;
70
+ /** Whether a table cell is part of the header row. */
71
+ isHeader?: boolean;
72
+ /** Text alignment for table cells: 'left', 'center', or 'right'. */
73
+ align?: string;
74
+ /** Nested child nodes for hierarchical elements like paragraphs, lists, and tables. */
75
+ children?: MarkdownNode[];
76
+ }
77
+
78
+ export const MarkdownParserModule =
79
+ NitroModules.createHybridObject<MarkdownParser>("MarkdownParser");
80
+
81
+ /**
82
+ * Parse markdown text into an AST.
83
+ * @param text - The markdown text to parse
84
+ * @returns The root node of the parsed AST
85
+ */
86
+ export function parseMarkdown(text: string): MarkdownNode {
87
+ const jsonStr = MarkdownParserModule.parse(text);
88
+ return JSON.parse(jsonStr) as MarkdownNode;
89
+ }
90
+
91
+ /**
92
+ * Parse markdown text with custom options.
93
+ * @param text - The markdown text to parse
94
+ * @param options - Parser options (gfm, math)
95
+ * @returns The root node of the parsed AST
96
+ */
97
+ export function parseMarkdownWithOptions(
98
+ text: string,
99
+ options: ParserOptions
100
+ ): MarkdownNode {
101
+ const jsonStr = MarkdownParserModule.parseWithOptions(text, options);
102
+ return JSON.parse(jsonStr) as MarkdownNode;
103
+ }
104
+
105
+ export type { MarkdownParser };
106
+
107
+ /**
108
+ * Extract text content from a markdown node recursively.
109
+ * Useful for getting plain text from code blocks, headings, etc.
110
+ * @param node - The markdown node to extract text from
111
+ * @returns The concatenated text content
112
+ */
113
+ export const getTextContent = (node: MarkdownNode): string => {
114
+ if (node.content) return node.content;
115
+ return node.children?.map(getTextContent).join("") ?? "";
116
+ };