react-native-nitro-markdown 0.4.2 → 0.5.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 (191) hide show
  1. package/README.md +605 -318
  2. package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +27 -8
  3. package/cpp/bindings/HybridMarkdownParser.cpp +216 -66
  4. package/cpp/bindings/HybridMarkdownParser.hpp +2 -0
  5. package/ios/HybridMarkdownSession.swift +33 -7
  6. package/lib/commonjs/MarkdownContext.js +2 -1
  7. package/lib/commonjs/MarkdownContext.js.map +1 -1
  8. package/lib/commonjs/headless.js +41 -5
  9. package/lib/commonjs/headless.js.map +1 -1
  10. package/lib/commonjs/index.js.map +1 -1
  11. package/lib/commonjs/markdown-stream.js +109 -13
  12. package/lib/commonjs/markdown-stream.js.map +1 -1
  13. package/lib/commonjs/markdown.js +215 -44
  14. package/lib/commonjs/markdown.js.map +1 -1
  15. package/lib/commonjs/renderers/code.js +4 -3
  16. package/lib/commonjs/renderers/code.js.map +1 -1
  17. package/lib/commonjs/renderers/heading.js +1 -1
  18. package/lib/commonjs/renderers/heading.js.map +1 -1
  19. package/lib/commonjs/renderers/image.js +7 -5
  20. package/lib/commonjs/renderers/image.js.map +1 -1
  21. package/lib/commonjs/renderers/link.js +15 -3
  22. package/lib/commonjs/renderers/link.js.map +1 -1
  23. package/lib/commonjs/renderers/list.js +2 -2
  24. package/lib/commonjs/renderers/list.js.map +1 -1
  25. package/lib/commonjs/renderers/table.js +126 -21
  26. package/lib/commonjs/renderers/table.js.map +1 -1
  27. package/lib/commonjs/use-markdown-stream.js +16 -14
  28. package/lib/commonjs/use-markdown-stream.js.map +1 -1
  29. package/lib/commonjs/utils/incremental-ast.js +153 -0
  30. package/lib/commonjs/utils/incremental-ast.js.map +1 -0
  31. package/lib/commonjs/utils/link-security.js +21 -0
  32. package/lib/commonjs/utils/link-security.js.map +1 -0
  33. package/lib/commonjs/utils/stream-timeline.js +62 -0
  34. package/lib/commonjs/utils/stream-timeline.js.map +1 -0
  35. package/lib/module/MarkdownContext.js +2 -1
  36. package/lib/module/MarkdownContext.js.map +1 -1
  37. package/lib/module/headless.js +37 -4
  38. package/lib/module/headless.js.map +1 -1
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/markdown-stream.js +110 -14
  41. package/lib/module/markdown-stream.js.map +1 -1
  42. package/lib/module/markdown.js +217 -46
  43. package/lib/module/markdown.js.map +1 -1
  44. package/lib/module/renderers/blockquote.js.map +1 -1
  45. package/lib/module/renderers/code.js +4 -3
  46. package/lib/module/renderers/code.js.map +1 -1
  47. package/lib/module/renderers/heading.js +1 -1
  48. package/lib/module/renderers/heading.js.map +1 -1
  49. package/lib/module/renderers/image.js +7 -5
  50. package/lib/module/renderers/image.js.map +1 -1
  51. package/lib/module/renderers/link.js +15 -3
  52. package/lib/module/renderers/link.js.map +1 -1
  53. package/lib/module/renderers/list.js +2 -2
  54. package/lib/module/renderers/list.js.map +1 -1
  55. package/lib/module/renderers/paragraph.js.map +1 -1
  56. package/lib/module/renderers/table.js +127 -22
  57. package/lib/module/renderers/table.js.map +1 -1
  58. package/lib/module/use-markdown-stream.js +16 -14
  59. package/lib/module/use-markdown-stream.js.map +1 -1
  60. package/lib/module/utils/incremental-ast.js +147 -0
  61. package/lib/module/utils/incremental-ast.js.map +1 -0
  62. package/lib/module/utils/link-security.js +15 -0
  63. package/lib/module/utils/link-security.js.map +1 -0
  64. package/lib/module/utils/stream-timeline.js +56 -0
  65. package/lib/module/utils/stream-timeline.js.map +1 -0
  66. package/lib/typescript/commonjs/Markdown.nitro.d.ts +5 -3
  67. package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/MarkdownContext.d.ts +26 -25
  69. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/headless.d.ts +15 -2
  71. package/lib/typescript/commonjs/headless.d.ts.map +1 -1
  72. package/lib/typescript/commonjs/index.d.ts +3 -1
  73. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  74. package/lib/typescript/commonjs/markdown-stream.d.ts +7 -2
  75. package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -1
  76. package/lib/typescript/commonjs/markdown.d.ts +62 -5
  77. package/lib/typescript/commonjs/markdown.d.ts.map +1 -1
  78. package/lib/typescript/commonjs/renderers/blockquote.d.ts +3 -3
  79. package/lib/typescript/commonjs/renderers/blockquote.d.ts.map +1 -1
  80. package/lib/typescript/commonjs/renderers/code.d.ts +5 -5
  81. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/renderers/heading.d.ts +3 -3
  83. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +2 -2
  85. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/renderers/image.d.ts +2 -2
  87. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/renderers/link.d.ts +3 -3
  89. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -1
  90. package/lib/typescript/commonjs/renderers/list.d.ts +7 -7
  91. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -1
  92. package/lib/typescript/commonjs/renderers/math.d.ts +4 -4
  93. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/renderers/paragraph.d.ts +3 -3
  95. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/renderers/table.d.ts +3 -3
  97. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +5 -2
  99. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/theme.d.ts +2 -2
  101. package/lib/typescript/commonjs/theme.d.ts.map +1 -1
  102. package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -1
  103. package/lib/typescript/commonjs/utils/incremental-ast.d.ts +12 -0
  104. package/lib/typescript/commonjs/utils/incremental-ast.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/utils/link-security.d.ts +3 -0
  106. package/lib/typescript/commonjs/utils/link-security.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/utils/stream-timeline.d.ts +11 -0
  108. package/lib/typescript/commonjs/utils/stream-timeline.d.ts.map +1 -0
  109. package/lib/typescript/module/Markdown.nitro.d.ts +5 -3
  110. package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -1
  111. package/lib/typescript/module/MarkdownContext.d.ts +26 -25
  112. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -1
  113. package/lib/typescript/module/headless.d.ts +15 -2
  114. package/lib/typescript/module/headless.d.ts.map +1 -1
  115. package/lib/typescript/module/index.d.ts +3 -1
  116. package/lib/typescript/module/index.d.ts.map +1 -1
  117. package/lib/typescript/module/markdown-stream.d.ts +7 -2
  118. package/lib/typescript/module/markdown-stream.d.ts.map +1 -1
  119. package/lib/typescript/module/markdown.d.ts +62 -5
  120. package/lib/typescript/module/markdown.d.ts.map +1 -1
  121. package/lib/typescript/module/renderers/blockquote.d.ts +3 -3
  122. package/lib/typescript/module/renderers/blockquote.d.ts.map +1 -1
  123. package/lib/typescript/module/renderers/code.d.ts +5 -5
  124. package/lib/typescript/module/renderers/code.d.ts.map +1 -1
  125. package/lib/typescript/module/renderers/heading.d.ts +3 -3
  126. package/lib/typescript/module/renderers/heading.d.ts.map +1 -1
  127. package/lib/typescript/module/renderers/horizontal-rule.d.ts +2 -2
  128. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -1
  129. package/lib/typescript/module/renderers/image.d.ts +2 -2
  130. package/lib/typescript/module/renderers/image.d.ts.map +1 -1
  131. package/lib/typescript/module/renderers/link.d.ts +3 -3
  132. package/lib/typescript/module/renderers/link.d.ts.map +1 -1
  133. package/lib/typescript/module/renderers/list.d.ts +7 -7
  134. package/lib/typescript/module/renderers/list.d.ts.map +1 -1
  135. package/lib/typescript/module/renderers/math.d.ts +4 -4
  136. package/lib/typescript/module/renderers/math.d.ts.map +1 -1
  137. package/lib/typescript/module/renderers/paragraph.d.ts +3 -3
  138. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -1
  139. package/lib/typescript/module/renderers/table.d.ts +3 -3
  140. package/lib/typescript/module/renderers/table.d.ts.map +1 -1
  141. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +5 -2
  142. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -1
  143. package/lib/typescript/module/theme.d.ts +2 -2
  144. package/lib/typescript/module/theme.d.ts.map +1 -1
  145. package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -1
  146. package/lib/typescript/module/utils/incremental-ast.d.ts +12 -0
  147. package/lib/typescript/module/utils/incremental-ast.d.ts.map +1 -0
  148. package/lib/typescript/module/utils/link-security.d.ts +3 -0
  149. package/lib/typescript/module/utils/link-security.d.ts.map +1 -0
  150. package/lib/typescript/module/utils/stream-timeline.d.ts +11 -0
  151. package/lib/typescript/module/utils/stream-timeline.d.ts.map +1 -0
  152. package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +2 -0
  153. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
  154. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +18 -6
  155. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +4 -2
  156. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void_double_double.kt +80 -0
  157. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +11 -3
  158. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +8 -0
  159. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +31 -0
  160. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +20 -2
  161. package/nitrogen/generated/ios/swift/Func_void.swift +0 -1
  162. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
  163. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +4 -3
  164. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +34 -10
  165. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +2 -0
  166. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +2 -0
  167. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +2 -0
  168. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +4 -2
  169. package/package.json +7 -5
  170. package/src/Markdown.nitro.ts +7 -3
  171. package/src/MarkdownContext.ts +31 -25
  172. package/src/headless.ts +44 -6
  173. package/src/index.ts +8 -0
  174. package/src/markdown-stream.tsx +159 -15
  175. package/src/markdown.tsx +406 -50
  176. package/src/renderers/blockquote.tsx +4 -4
  177. package/src/renderers/code.tsx +16 -10
  178. package/src/renderers/heading.tsx +4 -4
  179. package/src/renderers/horizontal-rule.tsx +3 -3
  180. package/src/renderers/image.tsx +11 -9
  181. package/src/renderers/link.tsx +25 -7
  182. package/src/renderers/list.tsx +9 -12
  183. package/src/renderers/math.tsx +4 -4
  184. package/src/renderers/paragraph.tsx +3 -3
  185. package/src/renderers/table.tsx +270 -98
  186. package/src/specs/MarkdownSession.nitro.ts +6 -2
  187. package/src/theme.ts +3 -3
  188. package/src/use-markdown-stream.ts +22 -16
  189. package/src/utils/incremental-ast.ts +224 -0
  190. package/src/utils/link-security.ts +22 -0
  191. package/src/utils/stream-timeline.ts +72 -0
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  useState,
3
- useEffect,
4
3
  useLayoutEffect,
5
4
  useMemo,
6
5
  type ReactNode,
@@ -15,10 +14,9 @@ import {
15
14
  Platform,
16
15
  type ViewStyle,
17
16
  } from "react-native";
18
-
19
17
  import { parseMarkdownWithOptions, type MarkdownNode } from "../headless";
20
- import type { NodeRendererProps } from "../MarkdownContext";
21
18
  import { useMarkdownContext } from "../MarkdownContext";
19
+ import type { NodeRendererProps } from "../MarkdownContext";
22
20
 
23
21
  const renderInlineContent = (
24
22
  node: MarkdownNode,
@@ -36,13 +34,13 @@ const renderInlineContent = (
36
34
  return null;
37
35
  };
38
36
 
39
- interface ImageProps {
37
+ type ImageProps = {
40
38
  url: string;
41
39
  title?: string;
42
40
  alt?: string;
43
41
  Renderer?: ComponentType<NodeRendererProps>;
44
42
  style?: ViewStyle;
45
- }
43
+ };
46
44
 
47
45
  export const Image: FC<ImageProps> = ({ url, title, alt, Renderer, style }) => {
48
46
  const [loading, setLoading] = useState(true);
@@ -187,22 +185,26 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer, style }) => {
187
185
 
188
186
  return (
189
187
  <View style={[styles.imageContainer, style]}>
190
- {loading && !aspectRatio && (
188
+ {loading && !aspectRatio ? (
191
189
  <View style={styles.imageLoading}>
192
190
  <Text style={styles.imageLoadingText}>Loading image...</Text>
193
191
  </View>
194
- )}
192
+ ) : null}
195
193
  <RNImage
196
194
  source={{ uri: url }}
197
195
  style={[styles.image, loading && !aspectRatio && styles.imageHidden]}
198
196
  resizeMode="contain"
199
- onLoad={() => setLoading(false)}
197
+ onLoad={() => {
198
+ setLoading(false);
199
+ }}
200
200
  onError={() => {
201
201
  setLoading(false);
202
202
  setError(true);
203
203
  }}
204
204
  />
205
- {title && !loading && <Text style={styles.imageCaption}>{title}</Text>}
205
+ {title && !loading ? (
206
+ <Text style={styles.imageCaption}>{title}</Text>
207
+ ) : null}
206
208
  </View>
207
209
  );
208
210
  };
@@ -1,4 +1,4 @@
1
- import { ReactNode, useMemo, type FC } from "react";
1
+ import { useMemo, type FC, type ReactNode } from "react";
2
2
  import {
3
3
  Text,
4
4
  StyleSheet,
@@ -7,15 +7,19 @@ import {
7
7
  type TextStyle,
8
8
  } from "react-native";
9
9
  import { useMarkdownContext } from "../MarkdownContext";
10
+ import {
11
+ getAllowedExternalHref,
12
+ normalizeLinkHref,
13
+ } from "../utils/link-security";
10
14
 
11
- interface LinkProps {
15
+ type LinkProps = {
12
16
  href: string;
13
17
  children: ReactNode;
14
18
  style?: TextStyle;
15
- }
19
+ };
16
20
 
17
21
  export const Link: FC<LinkProps> = ({ href, children, style }) => {
18
- const { theme } = useMarkdownContext();
22
+ const { theme, onLinkPress } = useMarkdownContext();
19
23
  const styles = useMemo(
20
24
  () =>
21
25
  StyleSheet.create({
@@ -27,11 +31,25 @@ export const Link: FC<LinkProps> = ({ href, children, style }) => {
27
31
  ...(Platform.OS === "android" && { includeFontPadding: false }),
28
32
  },
29
33
  }),
30
- [theme]
34
+ [theme],
31
35
  );
32
36
 
33
- const handlePress = () => {
34
- if (href) Linking.openURL(href);
37
+ const handlePress = async () => {
38
+ const normalizedHref = normalizeLinkHref(href);
39
+ if (!normalizedHref) return;
40
+
41
+ try {
42
+ const shouldOpen = (await onLinkPress?.(normalizedHref)) !== false;
43
+ if (!shouldOpen) return;
44
+
45
+ const allowedExternalHref = getAllowedExternalHref(normalizedHref);
46
+ if (!allowedExternalHref) return;
47
+
48
+ const canOpen = await Linking.canOpenURL(allowedExternalHref);
49
+ if (!canOpen) return;
50
+
51
+ await Linking.openURL(allowedExternalHref);
52
+ } catch {}
35
53
  };
36
54
 
37
55
  return (
@@ -1,14 +1,14 @@
1
- import { ReactNode, useMemo, type FC } from "react";
1
+ import { useMemo, type FC, type ReactNode } from "react";
2
2
  import { View, Text, StyleSheet, Platform, type ViewStyle } from "react-native";
3
3
  import { useMarkdownContext } from "../MarkdownContext";
4
4
 
5
- interface ListProps {
5
+ type ListProps = {
6
6
  ordered: boolean;
7
7
  start?: number;
8
8
  depth: number;
9
9
  children: ReactNode;
10
10
  style?: ViewStyle;
11
- }
11
+ };
12
12
 
13
13
  export const List: FC<ListProps> = ({ depth, children, style }) => {
14
14
  const { theme } = useMarkdownContext();
@@ -32,13 +32,13 @@ export const List: FC<ListProps> = ({ depth, children, style }) => {
32
32
  );
33
33
  };
34
34
 
35
- interface ListItemProps {
35
+ type ListItemProps = {
36
36
  children: ReactNode;
37
37
  index: number;
38
38
  ordered: boolean;
39
39
  start: number;
40
40
  style?: ViewStyle;
41
- }
41
+ };
42
42
 
43
43
  export const ListItem: FC<ListItemProps> = ({
44
44
  children,
@@ -82,11 +82,11 @@ export const ListItem: FC<ListItemProps> = ({
82
82
  );
83
83
  };
84
84
 
85
- interface TaskListItemProps {
85
+ type TaskListItemProps = {
86
86
  children: ReactNode;
87
87
  checked: boolean;
88
88
  style?: ViewStyle;
89
- }
89
+ };
90
90
 
91
91
  export const TaskListItem: FC<TaskListItemProps> = ({
92
92
  children,
@@ -134,12 +134,9 @@ export const TaskListItem: FC<TaskListItemProps> = ({
134
134
  return (
135
135
  <View style={[styles.taskListItem, style]}>
136
136
  <View
137
- style={[
138
- styles.taskCheckbox,
139
- checked && styles.taskCheckboxChecked,
140
- ]}
137
+ style={[styles.taskCheckbox, checked && styles.taskCheckboxChecked]}
141
138
  >
142
- {checked && <Text style={styles.taskCheckboxText}>✓</Text>}
139
+ {checked ? <Text style={styles.taskCheckboxText}>✓</Text> : null}
143
140
  </View>
144
141
  <View style={styles.taskContent}>{children}</View>
145
142
  </View>
@@ -26,10 +26,10 @@ try {
26
26
  // ignored
27
27
  }
28
28
 
29
- interface MathInlineProps {
29
+ type MathInlineProps = {
30
30
  content?: string;
31
31
  style?: ViewStyle;
32
- }
32
+ };
33
33
 
34
34
  const createMathStyles = (theme: MarkdownTheme) =>
35
35
  StyleSheet.create({
@@ -115,10 +115,10 @@ export const MathInline: FC<MathInlineProps> = ({ content, style }) => {
115
115
  );
116
116
  };
117
117
 
118
- interface MathBlockProps {
118
+ type MathBlockProps = {
119
119
  content?: string;
120
120
  style?: ViewStyle;
121
- }
121
+ };
122
122
 
123
123
  export const MathBlock: FC<MathBlockProps> = ({ content, style }) => {
124
124
  const { theme } = useMarkdownContext();
@@ -1,12 +1,12 @@
1
- import { ReactNode, useMemo, type FC } from "react";
1
+ import { useMemo, type FC, type ReactNode } from "react";
2
2
  import { View, StyleSheet, type StyleProp, type ViewStyle } from "react-native";
3
3
  import { useMarkdownContext } from "../MarkdownContext";
4
4
 
5
- interface ParagraphProps {
5
+ type ParagraphProps = {
6
6
  children: ReactNode;
7
7
  inListItem?: boolean;
8
8
  style?: StyleProp<ViewStyle>;
9
- }
9
+ };
10
10
 
11
11
  export const Paragraph: FC<ParagraphProps> = ({
12
12
  children,