react-native-nitro-markdown 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -84
  3. package/android/src/main/cpp/cpp-adapter.cpp +1 -1
  4. package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +61 -0
  5. package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +5 -1
  6. package/cpp/bindings/HybridMarkdownParser.cpp +2 -2
  7. package/cpp/bindings/HybridMarkdownParser.hpp +2 -2
  8. package/cpp/bindings/HybridMarkdownSession.cpp +0 -0
  9. package/cpp/core/MarkdownSessionCore.cpp +0 -0
  10. package/ios/HybridMarkdownSession.swift +64 -0
  11. package/lib/commonjs/MarkdownContext.js +21 -0
  12. package/lib/commonjs/MarkdownContext.js.map +1 -0
  13. package/lib/commonjs/MarkdownSession.js +11 -0
  14. package/lib/commonjs/MarkdownSession.js.map +1 -0
  15. package/lib/commonjs/default-markdown-renderer.js +220 -0
  16. package/lib/commonjs/default-markdown-renderer.js.map +1 -0
  17. package/lib/commonjs/headless.js +50 -0
  18. package/lib/commonjs/headless.js.map +1 -0
  19. package/lib/commonjs/index.js +185 -13
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/markdown-stream.js +32 -0
  22. package/lib/commonjs/markdown-stream.js.map +1 -0
  23. package/lib/commonjs/markdown.js +326 -0
  24. package/lib/commonjs/markdown.js.map +1 -0
  25. package/lib/commonjs/package.json +1 -0
  26. package/lib/commonjs/renderers/blockquote.js +36 -0
  27. package/lib/commonjs/renderers/blockquote.js.map +1 -0
  28. package/lib/commonjs/renderers/code.js +92 -0
  29. package/lib/commonjs/renderers/code.js.map +1 -0
  30. package/lib/commonjs/renderers/heading.js +62 -0
  31. package/lib/commonjs/renderers/heading.js.map +1 -0
  32. package/lib/commonjs/renderers/horizontal-rule.js +27 -0
  33. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -0
  34. package/lib/commonjs/renderers/image.js +159 -0
  35. package/lib/commonjs/renderers/image.js.map +1 -0
  36. package/lib/commonjs/renderers/link.js +37 -0
  37. package/lib/commonjs/renderers/link.js.map +1 -0
  38. package/lib/commonjs/renderers/list.js +114 -0
  39. package/lib/commonjs/renderers/list.js.map +1 -0
  40. package/lib/commonjs/renderers/math.js +151 -0
  41. package/lib/commonjs/renderers/math.js.map +1 -0
  42. package/lib/commonjs/renderers/paragraph.js +44 -0
  43. package/lib/commonjs/renderers/paragraph.js.map +1 -0
  44. package/lib/commonjs/renderers/table.js +283 -0
  45. package/lib/commonjs/renderers/table.js.map +1 -0
  46. package/lib/commonjs/specs/MarkdownSession.nitro.js +6 -0
  47. package/lib/commonjs/specs/MarkdownSession.nitro.js.map +1 -0
  48. package/lib/commonjs/theme.js +58 -0
  49. package/lib/commonjs/theme.js.map +1 -0
  50. package/lib/commonjs/use-markdown-stream.js +71 -0
  51. package/lib/commonjs/use-markdown-stream.js.map +1 -0
  52. package/lib/module/MarkdownContext.js +17 -0
  53. package/lib/module/MarkdownContext.js.map +1 -0
  54. package/lib/module/MarkdownSession.js +7 -0
  55. package/lib/module/MarkdownSession.js.map +1 -0
  56. package/lib/module/default-markdown-renderer.js +215 -0
  57. package/lib/module/default-markdown-renderer.js.map +1 -0
  58. package/lib/module/headless.js +44 -0
  59. package/lib/module/headless.js.map +1 -0
  60. package/lib/module/index.js +36 -10
  61. package/lib/module/index.js.map +1 -1
  62. package/lib/module/markdown-stream.js +27 -0
  63. package/lib/module/markdown-stream.js.map +1 -0
  64. package/lib/module/markdown.js +321 -0
  65. package/lib/module/markdown.js.map +1 -0
  66. package/lib/module/package.json +1 -0
  67. package/lib/module/renderers/blockquote.js +31 -0
  68. package/lib/module/renderers/blockquote.js.map +1 -0
  69. package/lib/module/renderers/code.js +86 -0
  70. package/lib/module/renderers/code.js.map +1 -0
  71. package/lib/module/renderers/heading.js +57 -0
  72. package/lib/module/renderers/heading.js.map +1 -0
  73. package/lib/module/renderers/horizontal-rule.js +22 -0
  74. package/lib/module/renderers/horizontal-rule.js.map +1 -0
  75. package/lib/module/renderers/image.js +154 -0
  76. package/lib/module/renderers/image.js.map +1 -0
  77. package/lib/module/renderers/link.js +32 -0
  78. package/lib/module/renderers/link.js.map +1 -0
  79. package/lib/module/renderers/list.js +107 -0
  80. package/lib/module/renderers/list.js.map +1 -0
  81. package/lib/module/renderers/math.js +145 -0
  82. package/lib/module/renderers/math.js.map +1 -0
  83. package/lib/module/renderers/paragraph.js +39 -0
  84. package/lib/module/renderers/paragraph.js.map +1 -0
  85. package/lib/module/renderers/table.js +278 -0
  86. package/lib/module/renderers/table.js.map +1 -0
  87. package/lib/module/specs/MarkdownSession.nitro.js +4 -0
  88. package/lib/module/specs/MarkdownSession.nitro.js.map +1 -0
  89. package/lib/module/theme.js +54 -0
  90. package/lib/module/theme.js.map +1 -0
  91. package/lib/module/use-markdown-stream.js +66 -0
  92. package/lib/module/use-markdown-stream.js.map +1 -0
  93. package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -0
  94. package/lib/typescript/commonjs/MarkdownContext.d.ts +26 -0
  95. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/MarkdownSession.d.ts +4 -0
  97. package/lib/typescript/commonjs/MarkdownSession.d.ts.map +1 -0
  98. package/lib/typescript/commonjs/default-markdown-renderer.d.ts +10 -0
  99. package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -0
  100. package/lib/typescript/commonjs/headless.d.ts +50 -0
  101. package/lib/typescript/commonjs/headless.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/index.d.ts +34 -0
  103. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  104. package/lib/typescript/commonjs/markdown-stream.d.ts +15 -0
  105. package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -0
  106. package/lib/typescript/commonjs/markdown.d.ts +29 -0
  107. package/lib/typescript/commonjs/markdown.d.ts.map +1 -0
  108. package/lib/typescript/commonjs/package.json +1 -0
  109. package/lib/typescript/commonjs/renderers/blockquote.d.ts +9 -0
  110. package/lib/typescript/commonjs/renderers/blockquote.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/renderers/code.d.ts +15 -0
  112. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/renderers/heading.d.ts +10 -0
  114. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +3 -0
  116. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/renderers/image.d.ts +11 -0
  118. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/renderers/link.d.ts +10 -0
  120. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/renderers/list.d.ts +22 -0
  122. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/renderers/math.d.ts +15 -0
  124. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/renderers/paragraph.d.ts +15 -0
  126. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/renderers/table.d.ts +10 -0
  128. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +12 -0
  130. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/theme.d.ts +52 -0
  132. package/lib/typescript/commonjs/theme.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/use-markdown-stream.d.ts +22 -0
  134. package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -0
  135. package/lib/typescript/module/Markdown.nitro.d.ts +13 -0
  136. package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -0
  137. package/lib/typescript/module/MarkdownContext.d.ts +26 -0
  138. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -0
  139. package/lib/typescript/module/MarkdownSession.d.ts +4 -0
  140. package/lib/typescript/module/MarkdownSession.d.ts.map +1 -0
  141. package/lib/typescript/module/default-markdown-renderer.d.ts +10 -0
  142. package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -0
  143. package/lib/typescript/module/headless.d.ts +50 -0
  144. package/lib/typescript/module/headless.d.ts.map +1 -0
  145. package/lib/typescript/module/index.d.ts +34 -0
  146. package/lib/typescript/module/index.d.ts.map +1 -0
  147. package/lib/typescript/module/markdown-stream.d.ts +15 -0
  148. package/lib/typescript/module/markdown-stream.d.ts.map +1 -0
  149. package/lib/typescript/module/markdown.d.ts +29 -0
  150. package/lib/typescript/module/markdown.d.ts.map +1 -0
  151. package/lib/typescript/module/package.json +1 -0
  152. package/lib/typescript/module/renderers/blockquote.d.ts +9 -0
  153. package/lib/typescript/module/renderers/blockquote.d.ts.map +1 -0
  154. package/lib/typescript/module/renderers/code.d.ts +15 -0
  155. package/lib/typescript/module/renderers/code.d.ts.map +1 -0
  156. package/lib/typescript/module/renderers/heading.d.ts +10 -0
  157. package/lib/typescript/module/renderers/heading.d.ts.map +1 -0
  158. package/lib/typescript/module/renderers/horizontal-rule.d.ts +3 -0
  159. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -0
  160. package/lib/typescript/module/renderers/image.d.ts +11 -0
  161. package/lib/typescript/module/renderers/image.d.ts.map +1 -0
  162. package/lib/typescript/module/renderers/link.d.ts +10 -0
  163. package/lib/typescript/module/renderers/link.d.ts.map +1 -0
  164. package/lib/typescript/module/renderers/list.d.ts +22 -0
  165. package/lib/typescript/module/renderers/list.d.ts.map +1 -0
  166. package/lib/typescript/module/renderers/math.d.ts +15 -0
  167. package/lib/typescript/module/renderers/math.d.ts.map +1 -0
  168. package/lib/typescript/module/renderers/paragraph.d.ts +15 -0
  169. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -0
  170. package/lib/typescript/module/renderers/table.d.ts +10 -0
  171. package/lib/typescript/module/renderers/table.d.ts.map +1 -0
  172. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +12 -0
  173. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -0
  174. package/lib/typescript/module/theme.d.ts +52 -0
  175. package/lib/typescript/module/theme.d.ts.map +1 -0
  176. package/lib/typescript/module/use-markdown-stream.d.ts +22 -0
  177. package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -0
  178. package/nitro.json +5 -2
  179. package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +3 -2
  180. package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +1 -1
  181. package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +17 -5
  182. package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +4 -4
  183. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  184. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +91 -0
  185. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +70 -0
  186. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void.kt +80 -0
  187. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +78 -0
  188. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/NitroMarkdownOnLoad.kt +1 -1
  189. package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +2 -2
  190. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +28 -4
  191. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +72 -6
  192. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +11 -4
  193. package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +11 -3
  194. package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +16 -3
  195. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.cpp +11 -0
  196. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +108 -0
  197. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  198. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +59 -0
  199. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +190 -0
  200. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +3 -3
  201. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +4 -4
  202. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +26 -0
  203. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +67 -0
  204. package/nitrogen/generated/shared/c++/ParserOptions.hpp +22 -14
  205. package/package.json +45 -15
  206. package/react-native-nitro-markdown.podspec +5 -5
  207. package/src/MarkdownContext.ts +41 -0
  208. package/src/MarkdownSession.ts +8 -0
  209. package/src/default-markdown-renderer.tsx +266 -0
  210. package/src/headless.ts +106 -0
  211. package/src/index.ts +41 -59
  212. package/src/markdown-stream.tsx +32 -0
  213. package/src/markdown.tsx +415 -0
  214. package/src/renderers/blockquote.tsx +31 -0
  215. package/src/renderers/code.tsx +88 -0
  216. package/src/renderers/heading.tsx +66 -0
  217. package/src/renderers/horizontal-rule.tsx +20 -0
  218. package/src/renderers/image.tsx +160 -0
  219. package/src/renderers/link.tsx +38 -0
  220. package/src/renderers/list.tsx +125 -0
  221. package/src/renderers/math.tsx +164 -0
  222. package/src/renderers/paragraph.tsx +53 -0
  223. package/src/renderers/table.tsx +345 -0
  224. package/src/specs/MarkdownSession.nitro.ts +16 -0
  225. package/src/theme.ts +52 -0
  226. package/src/use-markdown-stream.ts +83 -0
  227. package/ios/NitroMarkdown-Bridging-Header.h +0 -14
  228. package/lib/commonjs/MarkdownJS.reference.js +0 -114
  229. package/lib/commonjs/MarkdownJS.reference.js.map +0 -1
  230. package/lib/module/MarkdownJS.reference.js +0 -107
  231. package/lib/module/MarkdownJS.reference.js.map +0 -1
  232. package/lib/typescript/Markdown.nitro.d.ts.map +0 -1
  233. package/lib/typescript/MarkdownJS.reference.d.ts +0 -33
  234. package/lib/typescript/MarkdownJS.reference.d.ts.map +0 -1
  235. package/lib/typescript/index.d.ts +0 -22
  236. package/lib/typescript/index.d.ts.map +0 -1
  237. package/src/MarkdownJS.reference.ts +0 -122
  238. /package/lib/typescript/{Markdown.nitro.d.ts → commonjs/Markdown.nitro.d.ts} +0 -0
@@ -0,0 +1,345 @@
1
+ import {
2
+ useMemo,
3
+ useRef,
4
+ useState,
5
+ useCallback,
6
+ useEffect,
7
+ type FC,
8
+ type ComponentType,
9
+ } from "react";
10
+ import {
11
+ View,
12
+ Text,
13
+ StyleSheet,
14
+ ScrollView,
15
+ type StyleProp,
16
+ type TextStyle,
17
+ } from "react-native";
18
+
19
+ import type { MarkdownNode } from "../headless";
20
+ import { useMarkdownContext, type NodeRendererProps } from "../MarkdownContext";
21
+ import { MarkdownTheme } from "../theme";
22
+
23
+ type TableData = {
24
+ headers: MarkdownNode[];
25
+ rows: MarkdownNode[][];
26
+ alignments: (string | undefined)[];
27
+ };
28
+
29
+ const extractTableData = (node: MarkdownNode): TableData => {
30
+ const headers: MarkdownNode[] = [];
31
+ const rows: MarkdownNode[][] = [];
32
+ const alignments: (string | undefined)[] = [];
33
+
34
+ const head = node.children?.find((c) => c.type === "table_head");
35
+ const body = node.children?.find((c) => c.type === "table_body");
36
+
37
+ // Extract Headers
38
+ head?.children?.forEach((row) => {
39
+ if (row.type === "table_row") {
40
+ row.children?.forEach((cell) => {
41
+ if (cell.type === "table_cell") {
42
+ headers.push(cell);
43
+ alignments.push(cell.align);
44
+ }
45
+ });
46
+ }
47
+ });
48
+
49
+ // Extract Body Rows
50
+ body?.children?.forEach((row) => {
51
+ if (row.type === "table_row") {
52
+ const rowCells: MarkdownNode[] = [];
53
+ row.children?.forEach((cell) => {
54
+ if (cell.type === "table_cell") {
55
+ rowCells.push(cell);
56
+ }
57
+ });
58
+ if (rowCells.length > 0) rows.push(rowCells);
59
+ }
60
+ });
61
+
62
+ return { headers, rows, alignments };
63
+ };
64
+
65
+ interface TableRendererProps {
66
+ node: MarkdownNode;
67
+ Renderer: ComponentType<NodeRendererProps>;
68
+ }
69
+
70
+ export const TableRenderer: FC<TableRendererProps> = ({
71
+ node,
72
+ Renderer,
73
+ }) => {
74
+ const { theme } = useMarkdownContext();
75
+ const { headers, rows, alignments } = useMemo(
76
+ () => extractTableData(node),
77
+ [node]
78
+ );
79
+
80
+ const columnCount = headers.length;
81
+ const styles = useMemo(() => createTableStyles(theme), [theme]);
82
+
83
+ const [columnWidths, setColumnWidths] = useState<number[]>([]);
84
+ const measuredWidths = useRef<Map<string, number>>(new Map());
85
+ const hasAppliedWidths = useRef(false);
86
+
87
+ const calculateAndApplyWidths = useCallback(() => {
88
+ if (columnCount === 0) return;
89
+
90
+ const finalWidths = new Array(columnCount).fill(0);
91
+ for (let col = 0; col < columnCount; col++) {
92
+ let maxWidth = measuredWidths.current.get(`h-${col}`) || 0;
93
+ for (let row = 0; row < rows.length; row++) {
94
+ const cellWidth = measuredWidths.current.get(`c-${row}-${col}`) || 0;
95
+ if (cellWidth > maxWidth) maxWidth = cellWidth;
96
+ }
97
+ // Apply padding and min-width
98
+ finalWidths[col] = Math.max(maxWidth + 32, 100);
99
+ }
100
+
101
+ setColumnWidths(finalWidths);
102
+ hasAppliedWidths.current = true;
103
+ }, [columnCount, rows.length]);
104
+
105
+ useEffect(() => {
106
+ if (columnCount === 0) return;
107
+
108
+ const timer = setTimeout(() => {
109
+ if (!hasAppliedWidths.current) {
110
+ calculateAndApplyWidths();
111
+ }
112
+ }, 400);
113
+
114
+ return () => clearTimeout(timer);
115
+ }, [columnCount, rows.length, calculateAndApplyWidths]);
116
+
117
+ const onLayout = (key: string, width: number) => {
118
+ if (hasAppliedWidths.current) return;
119
+ measuredWidths.current.set(key, width);
120
+
121
+ const expectedCount = columnCount + rows.length * columnCount;
122
+ if (measuredWidths.current.size >= expectedCount) {
123
+ calculateAndApplyWidths();
124
+ }
125
+ };
126
+
127
+ const getAlignStyle = (index: number) => {
128
+ const align = alignments[index];
129
+ if (align === "center")
130
+ return { alignItems: "center", textAlign: "center" } as const;
131
+ if (align === "right")
132
+ return { alignItems: "flex-end", textAlign: "right" } as const;
133
+ return { alignItems: "flex-start", textAlign: "left" } as const;
134
+ };
135
+
136
+ if (columnCount === 0) return null;
137
+
138
+ return (
139
+ <View style={styles.container}>
140
+ {!hasAppliedWidths.current && (
141
+ <View style={styles.measurementWrapper} pointerEvents="none">
142
+ <View style={styles.row}>
143
+ {headers.map((cell, i) => (
144
+ <View
145
+ key={`m-h-${i}`}
146
+ onLayout={(e) => onLayout(`h-${i}`, e.nativeEvent.layout.width)}
147
+ style={styles.measuringCell}
148
+ >
149
+ <CellContent node={cell} Renderer={Renderer} styles={styles} />
150
+ </View>
151
+ ))}
152
+ </View>
153
+ {rows.map((row, ri) => (
154
+ <View key={`m-r-${ri}`} style={styles.row}>
155
+ {row.map((cell, ci) => (
156
+ <View
157
+ key={`m-c-${ri}-${ci}`}
158
+ onLayout={(e) =>
159
+ onLayout(`c-${ri}-${ci}`, e.nativeEvent.layout.width)
160
+ }
161
+ style={styles.measuringCell}
162
+ >
163
+ <CellContent
164
+ node={cell}
165
+ Renderer={Renderer}
166
+ styles={styles}
167
+ />
168
+ </View>
169
+ ))}
170
+ </View>
171
+ ))}
172
+ </View>
173
+ )}
174
+
175
+ <ScrollView
176
+ horizontal
177
+ showsHorizontalScrollIndicator={true}
178
+ bounces={false}
179
+ style={styles.tableScroll}
180
+ >
181
+ <View style={styles.table}>
182
+ {/* Header */}
183
+ <View style={styles.headerRow}>
184
+ {headers.map((cell, i) => (
185
+ <View
186
+ key={`h-${i}`}
187
+ style={[
188
+ styles.headerCell,
189
+ { width: columnWidths[i] || 120 },
190
+ getAlignStyle(i),
191
+ i === columnCount - 1 && styles.lastCell,
192
+ ]}
193
+ >
194
+ <CellContent
195
+ node={cell}
196
+ Renderer={Renderer}
197
+ styles={styles}
198
+ textStyle={styles.headerText}
199
+ />
200
+ </View>
201
+ ))}
202
+ </View>
203
+
204
+ {/* Body */}
205
+ {rows.map((row, ri) => (
206
+ <View
207
+ key={`r-${ri}`}
208
+ style={[
209
+ styles.bodyRow,
210
+ ri === rows.length - 1 && styles.lastRow,
211
+ ri % 2 === 1 && styles.oddRow,
212
+ ]}
213
+ >
214
+ {row.map((cell, ci) => (
215
+ <View
216
+ key={`c-${ri}-${ci}`}
217
+ style={[
218
+ styles.bodyCell,
219
+ { width: columnWidths[ci] || 120 },
220
+ getAlignStyle(ci),
221
+ ci === columnCount - 1 && styles.lastCell,
222
+ ]}
223
+ >
224
+ <CellContent
225
+ node={cell}
226
+ Renderer={Renderer}
227
+ styles={styles}
228
+ textStyle={styles.cellText}
229
+ />
230
+ </View>
231
+ ))}
232
+ </View>
233
+ ))}
234
+ </View>
235
+ </ScrollView>
236
+ </View>
237
+ );
238
+ };
239
+
240
+ const CellContent: FC<{
241
+ node: MarkdownNode;
242
+ Renderer: ComponentType<NodeRendererProps>;
243
+ styles: ReturnType<typeof createTableStyles>;
244
+ textStyle?: StyleProp<TextStyle>;
245
+ }> = ({ node, Renderer, styles, textStyle }) => {
246
+ if (!node.children || node.children.length === 0) {
247
+ return <Text style={textStyle}>{node.content ?? ""}</Text>;
248
+ }
249
+
250
+ return (
251
+ <View style={styles.cellContentWrapper}>
252
+ {node.children.map((child, idx) => (
253
+ <Renderer
254
+ key={idx}
255
+ node={child}
256
+ depth={0}
257
+ inListItem={false}
258
+ parentIsText={false}
259
+ />
260
+ ))}
261
+ </View>
262
+ );
263
+ };
264
+
265
+ const createTableStyles = (theme: MarkdownTheme) => {
266
+ const colors = theme?.colors || {};
267
+ return StyleSheet.create({
268
+ container: {
269
+ marginVertical: 12,
270
+ },
271
+ measurementWrapper: {
272
+ position: "absolute",
273
+ top: 0,
274
+ left: 0,
275
+ opacity: 0,
276
+ zIndex: -1,
277
+ },
278
+ measuringCell: {
279
+ paddingHorizontal: 16,
280
+ paddingVertical: 12,
281
+ alignSelf: "flex-start",
282
+ },
283
+ tableScroll: {
284
+ borderRadius: 12,
285
+ borderWidth: 1,
286
+ borderColor: colors.tableBorder || "#374151",
287
+ },
288
+ table: {
289
+ backgroundColor: colors.surface || "#111827",
290
+ },
291
+ row: {
292
+ flexDirection: "row",
293
+ },
294
+ headerRow: {
295
+ flexDirection: "row",
296
+ backgroundColor: colors.tableHeader || "#1f2937",
297
+ borderBottomWidth: 2,
298
+ borderBottomColor: colors.tableBorder || "#374151",
299
+ },
300
+ bodyRow: {
301
+ flexDirection: "row",
302
+ borderBottomWidth: 1,
303
+ borderBottomColor: colors.tableBorder || "#374151",
304
+ },
305
+ oddRow: {
306
+ backgroundColor: colors.tableRowOdd || "rgba(255,255,255,0.02)",
307
+ },
308
+ lastRow: {
309
+ borderBottomWidth: 0,
310
+ },
311
+ headerCell: {
312
+ paddingVertical: 14,
313
+ paddingHorizontal: 16,
314
+ borderRightWidth: 1,
315
+ borderRightColor: colors.tableBorder || "#374151",
316
+ },
317
+ bodyCell: {
318
+ paddingVertical: 12,
319
+ paddingHorizontal: 16,
320
+ borderRightWidth: 1,
321
+ borderRightColor: colors.tableBorder || "#374151",
322
+ justifyContent: "center",
323
+ },
324
+ lastCell: {
325
+ borderRightWidth: 0,
326
+ },
327
+ headerText: {
328
+ color: colors.tableHeaderText || "#9ca3af",
329
+ fontSize: 12,
330
+ fontWeight: "700",
331
+ textTransform: "uppercase",
332
+ letterSpacing: 1,
333
+ },
334
+ cellText: {
335
+ color: colors.text || "#e5e7eb",
336
+ fontSize: 14,
337
+ lineHeight: 20,
338
+ },
339
+ cellContentWrapper: {
340
+ flexDirection: "row",
341
+ flexWrap: "wrap",
342
+ alignItems: "center",
343
+ },
344
+ });
345
+ };
@@ -0,0 +1,16 @@
1
+ import type { HybridObject } from "react-native-nitro-modules";
2
+
3
+ export interface MarkdownSession
4
+ extends HybridObject<{ ios: "swift"; android: "kotlin" }> {
5
+ // Buffer operations
6
+ append(chunk: string): void;
7
+ clear(): void;
8
+ getAllText(): string;
9
+
10
+ // Karaoke highlighting (native rendering)
11
+ // Nitro generates getter/setter for properties automatically
12
+ highlightPosition: number;
13
+
14
+ // Listener for view updates
15
+ addListener(listener: () => void): () => void;
16
+ }
package/src/theme.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Default theme configuration for the Markdown components.
3
+ * Optimized for a modern dark mode aesthetic.
4
+ */
5
+ export const defaultMarkdownTheme = {
6
+ /** Colors used throughout the markdown renderer */
7
+ colors: {
8
+ text: "#e0e0e0",
9
+ textMuted: "#888",
10
+ heading: "#f0f0f0",
11
+ link: "#60a5fa",
12
+ code: "#fbbf24",
13
+ codeBackground: "#1a1a2e",
14
+ blockquote: "#3b82f6",
15
+ border: "#252525",
16
+ surface: "#151515",
17
+ surfaceLight: "#1a1a1a",
18
+ accent: "#4ade80",
19
+ tableBorder: "#334155",
20
+ tableHeader: "#0f172a",
21
+ tableHeaderText: "#94a3b8",
22
+ tableRowEven: "#0f172a",
23
+ tableRowOdd: "#1e293b",
24
+ },
25
+ /** Standard spacing increments */
26
+ spacing: {
27
+ xs: 4,
28
+ s: 8,
29
+ m: 12,
30
+ l: 16,
31
+ xl: 24,
32
+ },
33
+ /** Font sizes for different text elements */
34
+ fontSizes: {
35
+ xs: 12,
36
+ s: 14,
37
+ m: 16,
38
+ l: 18,
39
+ xl: 22,
40
+ h1: 32,
41
+ h2: 26,
42
+ h3: 22,
43
+ h4: 18,
44
+ h5: 16,
45
+ h6: 14,
46
+ },
47
+ };
48
+
49
+ /**
50
+ * Type definition for the Markdown theme.
51
+ */
52
+ export type MarkdownTheme = typeof defaultMarkdownTheme;
@@ -0,0 +1,83 @@
1
+ import { useRef, useCallback, useState, useEffect } from "react";
2
+ import { createMarkdownSession } from "./MarkdownSession";
3
+
4
+ export type MarkdownSession = ReturnType<typeof createMarkdownSession>;
5
+
6
+ export function useMarkdownSession() {
7
+ const sessionRef = useRef<MarkdownSession | null>(null);
8
+ if (sessionRef.current === null) {
9
+ sessionRef.current = createMarkdownSession();
10
+ }
11
+
12
+ const [isStreaming, setIsStreaming] = useState(false);
13
+
14
+ useEffect(() => {
15
+ const session = sessionRef.current!;
16
+ return () => {
17
+ session.clear();
18
+ };
19
+ }, []);
20
+
21
+ const stop = useCallback(() => {
22
+ setIsStreaming(false);
23
+ }, []);
24
+
25
+ const clear = useCallback(() => {
26
+ stop();
27
+ sessionRef.current!.clear();
28
+ sessionRef.current!.highlightPosition = 0;
29
+ }, [stop]);
30
+
31
+ const setHighlight = useCallback((position: number) => {
32
+ sessionRef.current!.highlightPosition = position;
33
+ }, []);
34
+
35
+ const getSession = useCallback(() => sessionRef.current!, []);
36
+
37
+ return {
38
+ getSession,
39
+ isStreaming,
40
+ setIsStreaming,
41
+ stop,
42
+ clear,
43
+ setHighlight,
44
+ };
45
+ }
46
+
47
+ export function useStream(timestamps?: Record<number, number>) {
48
+ const engine = useMarkdownSession();
49
+ const [isPlaying, setIsPlaying] = useState(false);
50
+
51
+ const sortedKeys = useRef<number[]>([]);
52
+ useEffect(() => {
53
+ if (timestamps) {
54
+ sortedKeys.current = Object.keys(timestamps)
55
+ .map(Number)
56
+ .sort((a, b) => a - b);
57
+ }
58
+ }, [timestamps]);
59
+
60
+ const sync = useCallback(
61
+ (currentTimeMs: number) => {
62
+ if (!timestamps) return;
63
+
64
+ let wordIdx = 0;
65
+ for (const idx of sortedKeys.current) {
66
+ if (currentTimeMs >= timestamps[idx]) {
67
+ wordIdx = idx + 1;
68
+ } else {
69
+ break;
70
+ }
71
+ }
72
+ engine.setHighlight(wordIdx);
73
+ },
74
+ [timestamps, engine]
75
+ );
76
+
77
+ return {
78
+ ...engine,
79
+ isPlaying,
80
+ setIsPlaying,
81
+ sync,
82
+ };
83
+ }
@@ -1,14 +0,0 @@
1
- //
2
- // NitroMarkdown-Bridging-Header.h
3
- // react-native-nitro-markdown
4
- //
5
- // Bridging header for Swift/ObjC interop (if needed)
6
- //
7
-
8
- #ifndef NitroMarkdown_Bridging_Header_h
9
- #define NitroMarkdown_Bridging_Header_h
10
-
11
- // Add any headers you want to expose to Swift here
12
-
13
- #endif /* NitroMarkdown_Bridging_Header_h */
14
-
@@ -1,114 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.JSMarkdownParser = exports.JSINitroMarkdownParser = exports.HybridMarkdownParser = void 0;
7
- // Pure JavaScript implementation using JSI
8
- class JSMarkdownParser {
9
- parseImpl(text, options) {
10
- // Simple regex-based parser for comparison
11
- // This is much slower than the C++ version but demonstrates JSI usage
12
- const root = {
13
- type: "document",
14
- children: []
15
- };
16
- const lines = text.split("\n");
17
- let i = 0;
18
- while (i < lines.length) {
19
- const line = lines[i].trim();
20
- if (!line) {
21
- i++;
22
- continue;
23
- }
24
-
25
- // Headers
26
- const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
27
- if (headerMatch) {
28
- root.children.push({
29
- type: "heading",
30
- level: headerMatch[1].length,
31
- children: [{
32
- type: "text",
33
- content: headerMatch[2]
34
- }]
35
- });
36
- i++;
37
- continue;
38
- }
39
-
40
- // Bold
41
- const boldMatch = line.match(/\*\*(.+?)\*\*/);
42
- if (boldMatch) {
43
- root.children.push({
44
- type: "paragraph",
45
- children: [{
46
- type: "bold",
47
- children: [{
48
- type: "text",
49
- content: boldMatch[1]
50
- }]
51
- }]
52
- });
53
- i++;
54
- continue;
55
- }
56
-
57
- // Default paragraph
58
- root.children.push({
59
- type: "paragraph",
60
- children: [{
61
- type: "text",
62
- content: line
63
- }]
64
- });
65
- i++;
66
- }
67
- return root;
68
- }
69
- parse(text, options = {
70
- gfm: true,
71
- math: true
72
- }) {
73
- return this.parseImpl(text, options);
74
- }
75
- }
76
-
77
- // JSI-enabled version using Nitro but with JS implementation
78
- exports.JSMarkdownParser = JSMarkdownParser;
79
- class JSINitroMarkdownParser {
80
- parse(text, options = {
81
- gfm: true,
82
- math: true
83
- }) {
84
- // This would use JSI to call into JavaScriptCore
85
- // For now, we'll simulate it
86
- const parser = new JSMarkdownParser();
87
- return parser.parse(text, options);
88
- }
89
- }
90
-
91
- // Hybrid approach: C++ for complex parsing, JS for simple cases
92
- exports.JSINitroMarkdownParser = JSINitroMarkdownParser;
93
- class HybridMarkdownParser {
94
- constructor() {
95
- // In real implementation, this would be the Nitro C++ parser
96
- this.cppParser = null;
97
- this.jsParser = new JSMarkdownParser();
98
- }
99
- parse(text, options = {
100
- gfm: true,
101
- math: true
102
- }) {
103
- // Use C++ parser for complex cases, JS for simple
104
- if (text.length > 1000 || options.gfm || options.math) {
105
- // Would call C++ parser via Nitro
106
- return this.jsParser.parse(text, options);
107
- } else {
108
- // Use JS parser for simple cases
109
- return this.jsParser.parse(text, options);
110
- }
111
- }
112
- }
113
- exports.HybridMarkdownParser = HybridMarkdownParser;
114
- //# sourceMappingURL=MarkdownJS.reference.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["JSMarkdownParser","parseImpl","text","options","root","type","children","lines","split","i","length","line","trim","headerMatch","match","push","level","content","boldMatch","parse","gfm","math","exports","JSINitroMarkdownParser","parser","HybridMarkdownParser","constructor","cppParser","jsParser"],"sourceRoot":"../../src","sources":["MarkdownJS.reference.ts"],"mappings":"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","ignoreList":[]}