react-native-nitro-markdown 0.2.1 → 0.3.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 (148) hide show
  1. package/README.md +237 -103
  2. package/cpp/bindings/HybridMarkdownParser.cpp +2 -0
  3. package/cpp/core/MD4CParser.cpp +73 -39
  4. package/cpp/core/MarkdownTypes.hpp +6 -1
  5. package/cpp/md4c/md4c.c +79 -56
  6. package/cpp/md4c/md4c.h +7 -4
  7. package/lib/commonjs/MarkdownContext.js +3 -7
  8. package/lib/commonjs/MarkdownContext.js.map +1 -1
  9. package/lib/commonjs/default-markdown-renderer.js +4 -7
  10. package/lib/commonjs/default-markdown-renderer.js.map +1 -1
  11. package/lib/commonjs/headless.js +49 -1
  12. package/lib/commonjs/headless.js.map +1 -1
  13. package/lib/commonjs/index.js +35 -0
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/markdown.js +100 -41
  16. package/lib/commonjs/markdown.js.map +1 -1
  17. package/lib/commonjs/renderers/blockquote.js +1 -1
  18. package/lib/commonjs/renderers/blockquote.js.map +1 -1
  19. package/lib/commonjs/renderers/code.js +15 -8
  20. package/lib/commonjs/renderers/code.js.map +1 -1
  21. package/lib/commonjs/renderers/heading.js +2 -1
  22. package/lib/commonjs/renderers/heading.js.map +1 -1
  23. package/lib/commonjs/renderers/horizontal-rule.js +4 -2
  24. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -1
  25. package/lib/commonjs/renderers/image.js +39 -14
  26. package/lib/commonjs/renderers/image.js.map +1 -1
  27. package/lib/commonjs/renderers/link.js +1 -3
  28. package/lib/commonjs/renderers/link.js.map +1 -1
  29. package/lib/commonjs/renderers/list.js +12 -10
  30. package/lib/commonjs/renderers/list.js.map +1 -1
  31. package/lib/commonjs/renderers/math.js +33 -47
  32. package/lib/commonjs/renderers/math.js.map +1 -1
  33. package/lib/commonjs/renderers/paragraph.js +0 -6
  34. package/lib/commonjs/renderers/paragraph.js.map +1 -1
  35. package/lib/commonjs/renderers/table.js +127 -120
  36. package/lib/commonjs/renderers/table.js.map +1 -1
  37. package/lib/commonjs/theme.js +146 -13
  38. package/lib/commonjs/theme.js.map +1 -1
  39. package/lib/module/MarkdownContext.js +3 -8
  40. package/lib/module/MarkdownContext.js.map +1 -1
  41. package/lib/module/default-markdown-renderer.js +1 -4
  42. package/lib/module/default-markdown-renderer.js.map +1 -1
  43. package/lib/module/headless.js +46 -0
  44. package/lib/module/headless.js.map +1 -1
  45. package/lib/module/index.js +2 -20
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/markdown.js +101 -42
  48. package/lib/module/markdown.js.map +1 -1
  49. package/lib/module/renderers/blockquote.js +1 -1
  50. package/lib/module/renderers/blockquote.js.map +1 -1
  51. package/lib/module/renderers/code.js +15 -8
  52. package/lib/module/renderers/code.js.map +1 -1
  53. package/lib/module/renderers/heading.js +2 -1
  54. package/lib/module/renderers/heading.js.map +1 -1
  55. package/lib/module/renderers/horizontal-rule.js +4 -2
  56. package/lib/module/renderers/horizontal-rule.js.map +1 -1
  57. package/lib/module/renderers/image.js +40 -15
  58. package/lib/module/renderers/image.js.map +1 -1
  59. package/lib/module/renderers/link.js +1 -3
  60. package/lib/module/renderers/link.js.map +1 -1
  61. package/lib/module/renderers/list.js +12 -10
  62. package/lib/module/renderers/list.js.map +1 -1
  63. package/lib/module/renderers/math.js +34 -48
  64. package/lib/module/renderers/math.js.map +1 -1
  65. package/lib/module/renderers/paragraph.js +0 -6
  66. package/lib/module/renderers/paragraph.js.map +1 -1
  67. package/lib/module/renderers/table.js +128 -121
  68. package/lib/module/renderers/table.js.map +1 -1
  69. package/lib/module/theme.js +144 -12
  70. package/lib/module/theme.js.map +1 -1
  71. package/lib/typescript/commonjs/MarkdownContext.d.ts +45 -6
  72. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/default-markdown-renderer.d.ts +1 -1
  74. package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/headless.d.ts +12 -1
  76. package/lib/typescript/commonjs/headless.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/index.d.ts +4 -16
  78. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/markdown.d.ts +33 -2
  80. package/lib/typescript/commonjs/markdown.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/renderers/code.d.ts +6 -2
  82. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -1
  83. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +6 -1
  85. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/renderers/image.d.ts +2 -0
  87. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -1
  89. package/lib/typescript/commonjs/renderers/list.d.ts +4 -0
  90. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/renderers/math.d.ts +3 -4
  92. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/renderers/paragraph.d.ts +0 -5
  94. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -1
  95. package/lib/typescript/commonjs/renderers/table.d.ts +2 -0
  96. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/theme.d.ts +41 -28
  99. package/lib/typescript/commonjs/theme.d.ts.map +1 -1
  100. package/lib/typescript/module/MarkdownContext.d.ts +45 -6
  101. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -1
  102. package/lib/typescript/module/default-markdown-renderer.d.ts +1 -1
  103. package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -1
  104. package/lib/typescript/module/headless.d.ts +12 -1
  105. package/lib/typescript/module/headless.d.ts.map +1 -1
  106. package/lib/typescript/module/index.d.ts +4 -16
  107. package/lib/typescript/module/index.d.ts.map +1 -1
  108. package/lib/typescript/module/markdown.d.ts +33 -2
  109. package/lib/typescript/module/markdown.d.ts.map +1 -1
  110. package/lib/typescript/module/renderers/code.d.ts +6 -2
  111. package/lib/typescript/module/renderers/code.d.ts.map +1 -1
  112. package/lib/typescript/module/renderers/heading.d.ts.map +1 -1
  113. package/lib/typescript/module/renderers/horizontal-rule.d.ts +6 -1
  114. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -1
  115. package/lib/typescript/module/renderers/image.d.ts +2 -0
  116. package/lib/typescript/module/renderers/image.d.ts.map +1 -1
  117. package/lib/typescript/module/renderers/link.d.ts.map +1 -1
  118. package/lib/typescript/module/renderers/list.d.ts +4 -0
  119. package/lib/typescript/module/renderers/list.d.ts.map +1 -1
  120. package/lib/typescript/module/renderers/math.d.ts +3 -4
  121. package/lib/typescript/module/renderers/math.d.ts.map +1 -1
  122. package/lib/typescript/module/renderers/paragraph.d.ts +0 -5
  123. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -1
  124. package/lib/typescript/module/renderers/table.d.ts +2 -0
  125. package/lib/typescript/module/renderers/table.d.ts.map +1 -1
  126. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -1
  127. package/lib/typescript/module/theme.d.ts +41 -28
  128. package/lib/typescript/module/theme.d.ts.map +1 -1
  129. package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +8 -7
  130. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +2 -2
  131. package/package.json +1 -1
  132. package/src/MarkdownContext.ts +66 -9
  133. package/src/default-markdown-renderer.tsx +1 -6
  134. package/src/headless.ts +67 -2
  135. package/src/index.ts +24 -19
  136. package/src/markdown.tsx +158 -52
  137. package/src/renderers/blockquote.tsx +1 -2
  138. package/src/renderers/code.tsx +36 -12
  139. package/src/renderers/heading.tsx +1 -1
  140. package/src/renderers/horizontal-rule.tsx +7 -4
  141. package/src/renderers/image.tsx +59 -15
  142. package/src/renderers/link.tsx +1 -6
  143. package/src/renderers/list.tsx +15 -15
  144. package/src/renderers/math.tsx +28 -45
  145. package/src/renderers/paragraph.tsx +1 -8
  146. package/src/renderers/table.tsx +185 -160
  147. package/src/specs/MarkdownSession.nitro.ts +4 -6
  148. package/src/theme.ts +203 -12
@@ -1,5 +1,19 @@
1
- import { useState, useMemo, type ReactNode, type FC, type ComponentType } from "react";
2
- import { View, Text, Image as RNImage, StyleSheet } from "react-native";
1
+ import {
2
+ useState,
3
+ useEffect,
4
+ useLayoutEffect,
5
+ useMemo,
6
+ type ReactNode,
7
+ type FC,
8
+ type ComponentType,
9
+ } from "react";
10
+ import {
11
+ View,
12
+ Text,
13
+ Image as RNImage,
14
+ StyleSheet,
15
+ type ViewStyle,
16
+ } from "react-native";
3
17
 
4
18
  import { parseMarkdownWithOptions, type MarkdownNode } from "../headless";
5
19
  import type { NodeRendererProps } from "../MarkdownContext";
@@ -7,7 +21,7 @@ import { useMarkdownContext } from "../MarkdownContext";
7
21
 
8
22
  const renderInlineContent = (
9
23
  node: MarkdownNode,
10
- Renderer: ComponentType<NodeRendererProps>
24
+ Renderer: ComponentType<NodeRendererProps>,
11
25
  ): ReactNode => {
12
26
  if (node.type === "paragraph" && node.children) {
13
27
  return (
@@ -25,13 +39,14 @@ interface ImageProps {
25
39
  url: string;
26
40
  title?: string;
27
41
  alt?: string;
28
-
29
42
  Renderer?: ComponentType<NodeRendererProps>;
43
+ style?: ViewStyle;
30
44
  }
31
45
 
32
- export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
46
+ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer, style }) => {
33
47
  const [loading, setLoading] = useState(true);
34
48
  const [error, setError] = useState(false);
49
+ const [aspectRatio, setAspectRatio] = useState<number | undefined>(undefined);
35
50
  const { theme } = useMarkdownContext();
36
51
 
37
52
  const styles = useMemo(
@@ -43,8 +58,10 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
43
58
  },
44
59
  image: {
45
60
  width: "100%",
46
- height: 200,
47
- borderRadius: 8,
61
+ // If we have an aspect ratio, use it. Otherwise, use minHeight as fallback.
62
+ aspectRatio: aspectRatio,
63
+ minHeight: aspectRatio ? undefined : 200,
64
+ borderRadius: theme.borderRadius.m,
48
65
  backgroundColor: theme.colors.surface,
49
66
  },
50
67
  imageHidden: {
@@ -53,8 +70,10 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
53
70
  },
54
71
  imageLoading: {
55
72
  width: "100%",
56
- height: 200,
57
- borderRadius: 8,
73
+ // Match the image size if possible
74
+ aspectRatio: aspectRatio,
75
+ height: aspectRatio ? undefined : 200,
76
+ borderRadius: theme.borderRadius.m,
58
77
  backgroundColor: theme.colors.surface,
59
78
  justifyContent: "center",
60
79
  alignItems: "center",
@@ -62,11 +81,12 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
62
81
  imageLoadingText: {
63
82
  color: theme.colors.textMuted,
64
83
  fontSize: theme.fontSizes.s,
84
+ fontFamily: theme.fontFamilies.regular,
65
85
  },
66
86
  imageError: {
67
87
  width: "100%",
68
88
  padding: theme.spacing.l,
69
- borderRadius: 8,
89
+ borderRadius: theme.borderRadius.m,
70
90
  backgroundColor: theme.colors.surface,
71
91
  alignItems: "center",
72
92
  marginVertical: theme.spacing.m,
@@ -74,6 +94,7 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
74
94
  imageErrorText: {
75
95
  color: theme.colors.textMuted,
76
96
  fontSize: theme.fontSizes.s,
97
+ fontFamily: theme.fontFamilies.regular,
77
98
  },
78
99
  imageCaption: {
79
100
  color: theme.colors.textMuted,
@@ -81,11 +102,34 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
81
102
  marginTop: theme.spacing.s,
82
103
  fontStyle: "italic",
83
104
  textAlign: "center",
105
+ fontFamily: theme.fontFamilies.regular,
84
106
  },
85
107
  }),
86
- [theme]
108
+ [theme, aspectRatio],
87
109
  );
88
110
 
111
+ useLayoutEffect(() => {
112
+ // Fast path for consistent aspect ratios if checking picsum
113
+ const picsumMatch = url.match(/picsum\.photos\/.*\/(\d+)\/(\d+)/);
114
+ if (picsumMatch) {
115
+ const w = parseInt(picsumMatch[1], 10);
116
+ const h = parseInt(picsumMatch[2], 10);
117
+ if (!isNaN(w) && !isNaN(h) && h !== 0) {
118
+ setAspectRatio(w / h);
119
+ }
120
+ }
121
+
122
+ RNImage.getSize(
123
+ url,
124
+ (width, height) => {
125
+ if (width > 0 && height > 0) {
126
+ setAspectRatio(width / height);
127
+ }
128
+ },
129
+ () => {},
130
+ );
131
+ }, [url]);
132
+
89
133
  const altContent = useMemo(() => {
90
134
  if (!alt || !Renderer) return null;
91
135
  if (
@@ -117,7 +161,7 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
117
161
 
118
162
  if (error) {
119
163
  return (
120
- <View style={styles.imageError}>
164
+ <View style={[styles.imageError, style]}>
121
165
  <View
122
166
  style={{
123
167
  flexDirection: "row",
@@ -138,15 +182,15 @@ export const Image: FC<ImageProps> = ({ url, title, alt, Renderer }) => {
138
182
  }
139
183
 
140
184
  return (
141
- <View style={styles.imageContainer}>
142
- {loading && (
185
+ <View style={[styles.imageContainer, style]}>
186
+ {loading && !aspectRatio && (
143
187
  <View style={styles.imageLoading}>
144
188
  <Text style={styles.imageLoadingText}>Loading image...</Text>
145
189
  </View>
146
190
  )}
147
191
  <RNImage
148
192
  source={{ uri: url }}
149
- style={[styles.image, loading && styles.imageHidden]}
193
+ style={[styles.image, loading && !aspectRatio && styles.imageHidden]}
150
194
  resizeMode="contain"
151
195
  onLoad={() => setLoading(false)}
152
196
  onError={() => {
@@ -22,11 +22,7 @@ export const Link: FC<LinkProps> = ({ href, children, style }) => {
22
22
  );
23
23
 
24
24
  const handlePress = () => {
25
- if (href) {
26
- Linking.openURL(href).catch((err) =>
27
- console.error("Failed to open URL:", err)
28
- );
29
- }
25
+ if (href) Linking.openURL(href);
30
26
  };
31
27
 
32
28
  return (
@@ -35,4 +31,3 @@ export const Link: FC<LinkProps> = ({ href, children, style }) => {
35
31
  </Text>
36
32
  );
37
33
  };
38
-
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, useMemo, type FC } from "react";
2
- import { View, Text, StyleSheet } from "react-native";
2
+ import { View, Text, StyleSheet, type ViewStyle } from "react-native";
3
3
  import { useMarkdownContext } from "../MarkdownContext";
4
4
 
5
5
  interface ListProps {
@@ -7,14 +7,10 @@ interface ListProps {
7
7
  start?: number;
8
8
  depth: number;
9
9
  children: ReactNode;
10
+ style?: ViewStyle;
10
11
  }
11
12
 
12
- export const List: FC<ListProps> = ({
13
- ordered,
14
- start = 1,
15
- depth,
16
- children,
17
- }) => {
13
+ export const List: FC<ListProps> = ({ depth, children, style }) => {
18
14
  const { theme } = useMarkdownContext();
19
15
  const styles = useMemo(
20
16
  () =>
@@ -23,14 +19,14 @@ export const List: FC<ListProps> = ({
23
19
  marginBottom: theme.spacing.m,
24
20
  },
25
21
  listNested: {
26
- marginLeft: theme.spacing.l,
22
+ marginLeft: theme.spacing.s,
27
23
  marginBottom: 0,
28
24
  },
29
25
  }),
30
- [theme]
26
+ [theme],
31
27
  );
32
28
  return (
33
- <View style={[styles.list, depth > 0 && styles.listNested]}>
29
+ <View style={[styles.list, depth > 0 && styles.listNested, style]}>
34
30
  {children}
35
31
  </View>
36
32
  );
@@ -41,6 +37,7 @@ interface ListItemProps {
41
37
  index: number;
42
38
  ordered: boolean;
43
39
  start: number;
40
+ style?: ViewStyle;
44
41
  }
45
42
 
46
43
  export const ListItem: FC<ListItemProps> = ({
@@ -48,6 +45,7 @@ export const ListItem: FC<ListItemProps> = ({
48
45
  index,
49
46
  ordered,
50
47
  start,
48
+ style,
51
49
  }) => {
52
50
  const { theme } = useMarkdownContext();
53
51
  const styles = useMemo(
@@ -65,6 +63,7 @@ export const ListItem: FC<ListItemProps> = ({
65
63
  marginRight: theme.spacing.s,
66
64
  minWidth: 20,
67
65
  textAlign: "center",
66
+ fontFamily: theme.fontFamilies.regular,
68
67
  },
69
68
  listItemContent: {
70
69
  flex: 1,
@@ -72,11 +71,11 @@ export const ListItem: FC<ListItemProps> = ({
72
71
  minWidth: 0,
73
72
  },
74
73
  }),
75
- [theme]
74
+ [theme],
76
75
  );
77
76
  const bullet = ordered ? `${start + index}.` : "•";
78
77
  return (
79
- <View style={styles.listItem}>
78
+ <View style={[styles.listItem, style]}>
80
79
  <Text style={styles.listBullet}>{bullet}</Text>
81
80
  <View style={styles.listItemContent}>{children}</View>
82
81
  </View>
@@ -86,11 +85,13 @@ export const ListItem: FC<ListItemProps> = ({
86
85
  interface TaskListItemProps {
87
86
  children: ReactNode;
88
87
  checked: boolean;
88
+ style?: ViewStyle;
89
89
  }
90
90
 
91
91
  export const TaskListItem: FC<TaskListItemProps> = ({
92
92
  children,
93
93
  checked,
94
+ style,
94
95
  }) => {
95
96
  const { theme } = useMarkdownContext();
96
97
  const styles = useMemo(
@@ -113,13 +114,12 @@ export const TaskListItem: FC<TaskListItemProps> = ({
113
114
  minWidth: 0,
114
115
  },
115
116
  }),
116
- [theme]
117
+ [theme],
117
118
  );
118
119
  return (
119
- <View style={styles.taskListItem}>
120
+ <View style={[styles.taskListItem, style]}>
120
121
  <Text style={styles.taskCheckbox}>{checked ? "☑" : "☐"}</Text>
121
122
  <View style={styles.taskContent}>{children}</View>
122
123
  </View>
123
124
  );
124
125
  };
125
-
@@ -3,6 +3,7 @@ import {
3
3
  View,
4
4
  Text,
5
5
  StyleSheet,
6
+ Platform,
6
7
  type StyleProp,
7
8
  type ViewStyle,
8
9
  } from "react-native";
@@ -27,41 +28,27 @@ try {
27
28
 
28
29
  interface MathInlineProps {
29
30
  content?: string;
31
+ style?: ViewStyle;
30
32
  }
31
33
 
32
- /**
33
- * Inline math renderer.
34
- * Uses react-native-mathjax-svg if installed, otherwise shows raw LaTeX.
35
- * Note: Renders as a View since SVG can't be nested in Text.
36
- */
37
-
38
34
  const createMathStyles = (theme: MarkdownTheme) =>
39
35
  StyleSheet.create({
40
36
  mathInlineContainer: {
41
- flexDirection: "row",
42
- alignItems: "baseline",
43
- alignSelf: "baseline",
44
- justifyContent: "flex-start",
45
- flexShrink: 1,
46
37
  marginHorizontal: 2,
47
- top: -theme.fontSizes.m,
48
- marginBottom: 0,
49
- paddingVertical: 0,
50
- },
51
- mathJaxInline: {
52
- marginTop: 0,
53
- marginBottom: 0,
38
+ // Ensure the inline view has layout alignment
39
+ justifyContent: "center",
54
40
  },
55
41
  mathInlineFallbackContainer: {
56
42
  backgroundColor: theme.colors.codeBackground,
57
- paddingHorizontal: 4,
43
+ paddingHorizontal: theme.spacing.xs,
58
44
  paddingVertical: 2,
59
- borderRadius: 4,
60
- alignSelf: "baseline",
45
+ borderRadius: theme.borderRadius.s,
61
46
  marginHorizontal: 2,
62
47
  },
63
48
  mathInlineFallback: {
64
- fontFamily: "monospace",
49
+ fontFamily:
50
+ theme.fontFamilies.mono ??
51
+ Platform.select({ ios: "Courier", android: "monospace" }),
65
52
  fontSize: theme.fontSizes.s,
66
53
  color: theme.colors.code,
67
54
  },
@@ -70,49 +57,48 @@ const createMathStyles = (theme: MarkdownTheme) =>
70
57
  paddingVertical: theme.spacing.l,
71
58
  paddingHorizontal: theme.spacing.l,
72
59
  backgroundColor: theme.colors.surface,
73
- borderRadius: 12,
60
+ borderRadius: theme.borderRadius.l,
74
61
  alignItems: "center",
75
62
  borderWidth: 1,
76
63
  borderColor: theme.colors.border,
77
- shadowColor: "#000",
78
- shadowOffset: { width: 0, height: 1 },
79
- shadowOpacity: 0.05,
80
- shadowRadius: 2,
81
- elevation: 1,
64
+ // Ensure we don't collapse if MathJax fails to report size immediately
65
+ minHeight: 48,
82
66
  },
83
67
  mathBlockFallbackContainer: {
84
68
  marginVertical: theme.spacing.m,
85
69
  paddingVertical: theme.spacing.m,
86
70
  paddingHorizontal: theme.spacing.l,
87
71
  backgroundColor: theme.colors.codeBackground,
88
- borderRadius: 8,
72
+ borderRadius: theme.borderRadius.m,
89
73
  alignItems: "center",
90
74
  borderWidth: 1,
91
75
  borderColor: theme.colors.border,
92
76
  },
93
77
  mathBlockFallback: {
94
- fontFamily: "monospace",
78
+ fontFamily:
79
+ theme.fontFamilies.mono ??
80
+ Platform.select({ ios: "Courier", android: "monospace" }),
95
81
  fontSize: theme.fontSizes.m,
96
82
  color: theme.colors.code,
97
83
  textAlign: "center",
98
84
  },
99
85
  });
100
86
 
101
- export const MathInline: FC<MathInlineProps> = ({ content }) => {
87
+ export const MathInline: FC<MathInlineProps> = ({ content, style }) => {
102
88
  const { theme } = useMarkdownContext();
103
89
  const styles = useMemo(() => createMathStyles(theme), [theme]);
104
90
 
105
91
  if (!content) return null;
106
92
 
107
93
  if (MathJaxComponent) {
108
- const fontSize = theme.fontSizes.m;
94
+ const fontSize = theme.fontSizes.s;
109
95
  return (
110
- <View style={styles.mathInlineContainer}>
96
+ <View style={[styles.mathInlineContainer, style]}>
111
97
  <MathJaxComponent
112
98
  fontSize={fontSize}
113
99
  color={theme.colors.text}
114
- fontCache={true}
115
- style={styles.mathJaxInline}
100
+ fontCache={false}
101
+ style={{ backgroundColor: "transparent" }}
116
102
  >
117
103
  {content}
118
104
  </MathJaxComponent>
@@ -121,7 +107,7 @@ export const MathInline: FC<MathInlineProps> = ({ content }) => {
121
107
  }
122
108
 
123
109
  return (
124
- <View style={styles.mathInlineFallbackContainer}>
110
+ <View style={[styles.mathInlineFallbackContainer, style]}>
125
111
  <Text style={styles.mathInlineFallback}>{content}</Text>
126
112
  </View>
127
113
  );
@@ -129,13 +115,10 @@ export const MathInline: FC<MathInlineProps> = ({ content }) => {
129
115
 
130
116
  interface MathBlockProps {
131
117
  content?: string;
118
+ style?: ViewStyle;
132
119
  }
133
120
 
134
- /**
135
- * Block math renderer.
136
- * Uses react-native-mathjax-svg if installed, otherwise shows raw LaTeX.
137
- */
138
- export const MathBlock: FC<MathBlockProps> = ({ content }) => {
121
+ export const MathBlock: FC<MathBlockProps> = ({ content, style }) => {
139
122
  const { theme } = useMarkdownContext();
140
123
  const styles = useMemo(() => createMathStyles(theme), [theme]);
141
124
 
@@ -143,11 +126,12 @@ export const MathBlock: FC<MathBlockProps> = ({ content }) => {
143
126
 
144
127
  if (MathJaxComponent) {
145
128
  return (
146
- <View style={styles.mathBlockContainer}>
129
+ <View style={[styles.mathBlockContainer, style]}>
147
130
  <MathJaxComponent
148
131
  fontSize={theme.fontSizes.l}
149
132
  color={theme.colors.text}
150
- fontCache={true}
133
+ fontCache={false}
134
+ style={{ backgroundColor: "transparent" }}
151
135
  >
152
136
  {`\\displaystyle ${content}`}
153
137
  </MathJaxComponent>
@@ -156,9 +140,8 @@ export const MathBlock: FC<MathBlockProps> = ({ content }) => {
156
140
  }
157
141
 
158
142
  return (
159
- <View style={styles.mathBlockFallbackContainer}>
143
+ <View style={[styles.mathBlockFallbackContainer, style]}>
160
144
  <Text style={styles.mathBlockFallback}>{content}</Text>
161
145
  </View>
162
146
  );
163
147
  };
164
-
@@ -8,11 +8,6 @@ interface ParagraphProps {
8
8
  style?: StyleProp<ViewStyle>;
9
9
  }
10
10
 
11
- /**
12
- * Paragraph component that supports mixed content (Text and View elements).
13
- * Uses View with flexDirection: 'row' and flexWrap: 'wrap' to allow inline flow
14
- * of both text and non-text elements (like inline math).
15
- */
16
11
  export const Paragraph: FC<ParagraphProps> = ({
17
12
  children,
18
13
  inListItem,
@@ -25,7 +20,6 @@ export const Paragraph: FC<ParagraphProps> = ({
25
20
  paragraph: {
26
21
  flexDirection: "row",
27
22
  flexWrap: "wrap",
28
- alignItems: "baseline",
29
23
  marginBottom: theme.spacing.l,
30
24
  gap: 0,
31
25
  },
@@ -35,7 +29,7 @@ export const Paragraph: FC<ParagraphProps> = ({
35
29
  flexShrink: 1,
36
30
  },
37
31
  }),
38
- [theme]
32
+ [theme],
39
33
  );
40
34
 
41
35
  return (
@@ -50,4 +44,3 @@ export const Paragraph: FC<ParagraphProps> = ({
50
44
  </View>
51
45
  );
52
46
  };
53
-