react-native-enriched-markdown 0.2.0 → 0.3.0-nightly-20260221-b992065d9

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 (138) hide show
  1. package/README.md +117 -13
  2. package/android/build.gradle +1 -0
  3. package/android/consumer-rules.pro +8 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +54 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +26 -0
  6. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +1 -1
  7. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +1 -1
  8. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +40 -0
  9. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +31 -0
  10. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +64 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1813 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp +1 -1
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h +0 -9
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.h +1 -1
  15. package/android/src/main/baseline-prof.txt +32 -3
  16. package/android/src/main/cpp/jni-adapter.cpp +12 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +332 -0
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +70 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +189 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +21 -49
  21. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +31 -2
  22. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextPackage.kt +1 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +136 -1
  24. package/android/src/main/java/com/swmansion/enriched/markdown/events/TaskListItemPressEvent.kt +26 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +6 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +3 -8
  27. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +82 -14
  28. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +5 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +26 -35
  30. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +2 -3
  31. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  32. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +4 -5
  33. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +8 -1
  34. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +6 -8
  35. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -5
  36. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +130 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +6 -11
  38. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeStyle.kt +4 -1
  39. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +3 -1
  40. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +53 -1
  41. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +69 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TaskListStyle.kt +29 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/utils/CheckboxTouchHelper.kt +52 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/utils/ContextMenuPopup.kt +214 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/utils/HTMLGenerator.kt +198 -15
  46. package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownASTSerializer.kt +97 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownExtractor.kt +10 -3
  48. package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownTextViewUtils.kt +43 -0
  49. package/android/src/main/java/com/swmansion/enriched/markdown/utils/SelectionActionMode.kt +17 -2
  50. package/android/src/main/java/com/swmansion/enriched/markdown/utils/TaskListTapUtils.kt +82 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/utils/Utils.kt +8 -0
  52. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockSegmentView.kt +10 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +465 -0
  54. package/android/src/main/jni/EnrichedMarkdownTextSpec.h +1 -11
  55. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +48 -0
  56. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerComponentDescriptor.h +26 -0
  57. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.cpp +45 -0
  58. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.h +21 -0
  59. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +20 -0
  60. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +34 -0
  61. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +10 -1
  62. package/cpp/parser/MD4CParser.cpp +71 -2
  63. package/cpp/parser/MarkdownASTNode.hpp +7 -1
  64. package/ios/EnrichedMarkdown.h +18 -0
  65. package/ios/EnrichedMarkdown.mm +623 -0
  66. package/ios/EnrichedMarkdownText.mm +75 -944
  67. package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +1 -1
  68. package/ios/generated/EnrichedMarkdownTextSpec/ComponentDescriptors.h +1 -1
  69. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.cpp +40 -0
  70. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.h +31 -0
  71. package/ios/generated/EnrichedMarkdownTextSpec/Props.cpp +64 -0
  72. package/ios/generated/EnrichedMarkdownTextSpec/Props.h +1813 -0
  73. package/ios/generated/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +4 -0
  74. package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.cpp +1 -1
  75. package/ios/generated/EnrichedMarkdownTextSpec/ShadowNodes.h +0 -9
  76. package/ios/generated/EnrichedMarkdownTextSpec/States.h +1 -1
  77. package/ios/internals/EnrichedMarkdownComponentDescriptor.h +18 -0
  78. package/ios/internals/EnrichedMarkdownShadowNode.h +41 -0
  79. package/ios/internals/EnrichedMarkdownShadowNode.mm +84 -0
  80. package/ios/internals/EnrichedMarkdownState.h +23 -0
  81. package/ios/parser/{MarkdownParser.h → ENRMMarkdownParser.h} +4 -4
  82. package/ios/parser/{MarkdownParser.mm → ENRMMarkdownParser.mm} +9 -9
  83. package/ios/parser/MarkdownASTNode.h +7 -1
  84. package/ios/parser/MarkdownParserBridge.mm +20 -2
  85. package/ios/renderer/CodeBlockRenderer.m +5 -1
  86. package/ios/renderer/CodeRenderer.m +2 -1
  87. package/ios/renderer/LinkRenderer.m +18 -0
  88. package/ios/renderer/ListItemRenderer.h +4 -1
  89. package/ios/renderer/ListItemRenderer.m +71 -4
  90. package/ios/renderer/RenderContext.h +4 -0
  91. package/ios/renderer/RenderContext.m +14 -0
  92. package/ios/renderer/RendererFactory.m +7 -0
  93. package/ios/styles/StyleConfig.h +56 -0
  94. package/ios/styles/StyleConfig.mm +374 -0
  95. package/ios/utils/BlockquoteBorder.m +6 -1
  96. package/ios/utils/FontScaleObserver.h +10 -0
  97. package/ios/utils/FontScaleObserver.m +47 -0
  98. package/ios/utils/HTMLGenerator.h +3 -0
  99. package/ios/utils/HTMLGenerator.m +190 -21
  100. package/ios/utils/LinkTapUtils.h +21 -0
  101. package/ios/utils/LinkTapUtils.m +28 -0
  102. package/ios/utils/ListMarkerDrawer.m +81 -9
  103. package/ios/utils/MarkdownASTSerializer.h +24 -0
  104. package/ios/utils/MarkdownASTSerializer.m +96 -0
  105. package/ios/utils/MarkdownAccessibilityElementBuilder.h +7 -0
  106. package/ios/utils/MarkdownAccessibilityElementBuilder.m +22 -0
  107. package/ios/utils/MarkdownExtractor.m +18 -7
  108. package/ios/utils/ParagraphStyleUtils.h +1 -0
  109. package/ios/utils/ParagraphStyleUtils.m +16 -6
  110. package/ios/utils/StylePropsUtils.h +932 -0
  111. package/ios/utils/TaskListTapUtils.h +31 -0
  112. package/ios/utils/TaskListTapUtils.m +93 -0
  113. package/ios/views/EnrichedMarkdownInternalText.h +30 -0
  114. package/ios/views/EnrichedMarkdownInternalText.m +156 -0
  115. package/ios/views/TableContainerView.h +31 -0
  116. package/ios/views/TableContainerView.m +535 -0
  117. package/lib/module/EnrichedMarkdownNativeComponent.ts +250 -0
  118. package/lib/module/EnrichedMarkdownText.js +30 -6
  119. package/lib/module/EnrichedMarkdownText.js.map +1 -1
  120. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +41 -1
  121. package/lib/module/normalizeMarkdownStyle.js +70 -7
  122. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  123. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +220 -0
  124. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -0
  125. package/lib/typescript/src/EnrichedMarkdownText.d.ts +45 -3
  126. package/lib/typescript/src/EnrichedMarkdownText.d.ts.map +1 -1
  127. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +35 -0
  128. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  129. package/lib/typescript/src/index.d.ts +1 -1
  130. package/lib/typescript/src/index.d.ts.map +1 -1
  131. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  132. package/package.json +4 -1
  133. package/react-native.config.js +4 -1
  134. package/src/EnrichedMarkdownNativeComponent.ts +250 -0
  135. package/src/EnrichedMarkdownText.tsx +76 -15
  136. package/src/EnrichedMarkdownTextNativeComponent.ts +41 -1
  137. package/src/index.tsx +1 -0
  138. package/src/normalizeMarkdownStyle.ts +101 -7
package/README.md CHANGED
@@ -7,6 +7,7 @@
7
7
  - ⚡ Fully native text rendering (no WebView)
8
8
  - 🎯 High-performance Markdown parsing with [md4c](https://github.com/mity/md4c)
9
9
  - 📐 CommonMark standard compliant
10
+ - 📊 GitHub Flavored Markdown (GFM)
10
11
  - 🎨 Fully customizable styles for all elements
11
12
  - 📱 iOS and Android support
12
13
  - 🏛 Supports only the New Architecture (Fabric)
@@ -15,6 +16,7 @@
15
16
  - 🖼️ Native image interactions (iOS: Copy, Save to Camera Roll)
16
17
  - 🌐 Native platform features (Translate, Look Up, Search Web, Share)
17
18
  - 🗣️ Accessibility support (VoiceOver & TalkBack)
19
+ - 🔄 Full RTL (right-to-left) support including text, lists, blockquotes, tables, and task lists
18
20
 
19
21
  Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
20
22
  We can help you build your next dream product –
@@ -29,10 +31,12 @@ We can help you build your next dream product –
29
31
  - [Link Handling](#link-handling)
30
32
  - [Copy Options](#copy-options)
31
33
  - [Accessibility](#accessibility)
34
+ - [RTL Support](#rtl-support)
32
35
  - [Styling Architecture](#styling-architecture)
33
36
  - [Customizing Styles](#customizing-styles)
34
37
  - [API Reference](#api-reference)
35
38
  - [Contributing](#contributing)
39
+ - [Future Plans](#future-plans)
36
40
  - [License](#license)
37
41
 
38
42
  ## Prerequisites
@@ -88,7 +92,7 @@ npx expo prebuild
88
92
 
89
93
  ## Usage
90
94
 
91
- Here's a simple example of rendering Markdown content:
95
+ ### CommonMark (default)
92
96
 
93
97
  ```tsx
94
98
  import { EnrichedMarkdownText } from 'react-native-enriched-markdown';
@@ -102,27 +106,43 @@ This is a paragraph with **bold**, *italic*, and [links](https://reactnative.dev
102
106
  - List item one
103
107
  - List item two
104
108
  - Nested item
105
-
106
- \`\`\`javascript
107
- const greeting = 'Hello, World!';
108
- console.log(greeting);
109
- \`\`\`
110
109
  `;
111
110
 
112
111
  export default function App() {
113
- const handleLinkPress = (event: { nativeEvent: { url: string } }) => {
114
- Linking.openURL(event.nativeEvent.url);
115
- };
116
-
117
112
  return (
118
113
  <EnrichedMarkdownText
119
114
  markdown={markdown}
120
- onLinkPress={handleLinkPress}
115
+ onLinkPress={({ url }) => Linking.openURL(url)}
121
116
  />
122
117
  );
123
118
  }
124
119
  ```
125
120
 
121
+ ### GFM (tables)
122
+
123
+ Set `flavor="github"` to enable GitHub Flavored Markdown features like tables:
124
+
125
+ ```tsx
126
+ <EnrichedMarkdownText
127
+ flavor="github"
128
+ markdown={markdown}
129
+ onLinkPress={({ url }) => Linking.openURL(url)}
130
+ markdownStyle={{
131
+ table: {
132
+ fontSize: 14,
133
+ borderColor: '#E5E7EB',
134
+ borderRadius: 8,
135
+ headerBackgroundColor: '#F3F4F6',
136
+ headerFontFamily: 'System-Bold',
137
+ cellPaddingHorizontal: 12,
138
+ cellPaddingVertical: 8,
139
+ },
140
+ }}
141
+ />
142
+ ```
143
+
144
+ Tables support column alignment, rich text in cells (bold, italic, code, links), horizontal scrolling, header styling, alternating row colors, and a long-press context menu with "Copy" and "Copy as Markdown".
145
+
126
146
  ## Supported Markdown Elements
127
147
 
128
148
  `react-native-enriched-markdown` supports a comprehensive set of Markdown elements:
@@ -137,8 +157,10 @@ export default function App() {
137
157
  | Code Blocks | ` ``` code ``` ` | Multi-line code blocks |
138
158
  | Unordered Lists | `- Item`, `* Item`, or `+ Item` | Bullet lists with unlimited nesting |
139
159
  | Ordered Lists | `1. Item` | Numbered lists with unlimited nesting |
160
+ | Task Lists | `- [x] Done`, `- [ ] Todo` | Interactive checkboxes (requires `flavor="github"`) |
140
161
  | Thematic Break | `---`, `***`, or `___` | Visual separator line |
141
162
  | Images | `![alt](url)` | Block-level images |
163
+ | Tables | `| col | col |` | GFM tables with alignment support (requires `flavor="github"`) |
142
164
 
143
165
  ### Inline Elements
144
166
 
@@ -255,6 +277,36 @@ When selecting text that contains images, a **Copy Image URL** option appears to
255
277
  | **List items** | Position announced (e.g., "bullet point", "list item 1") | Position announced |
256
278
  | **Nested lists** | Proper depth handling | "Nested" prefix for deeper items |
257
279
 
280
+ ## RTL Support
281
+
282
+ `react-native-enriched-markdown` fully supports right-to-left (RTL) languages such as Arabic, Hebrew, and Persian.
283
+
284
+ ### Platform Behavior
285
+
286
+ - **Android** — RTL works automatically. Android's text system detects RTL characters (Arabic, Hebrew, etc.) and renders them right-to-left with no additional configuration.
287
+ - **iOS** — Requires `I18nManager.forceRTL(true)` to enable RTL layout direction. This must be called early in the app lifecycle (before the root component mounts) and requires an app restart to take effect.
288
+
289
+ ```tsx
290
+ import { I18nManager } from 'react-native';
291
+
292
+ // Required for iOS, Android handles RTL automatically
293
+ I18nManager.forceRTL(true);
294
+ ```
295
+
296
+ When RTL content is rendered, the following elements automatically mirror their layout:
297
+
298
+ | Element | RTL Behavior |
299
+ |---------|-------------|
300
+ | **Paragraphs & Headings** | Right-aligned with RTL writing direction |
301
+ | **Unordered lists** | Bullets on the right, text indented from the right |
302
+ | **Ordered lists** | Numbers on the right, text indented from the right |
303
+ | **Task lists** | Checkboxes on the right, tappable in RTL |
304
+ | **Blockquotes** | Border on the right side |
305
+ | **Tables** | Columns ordered right-to-left, scrolls to show first column |
306
+ | **Code blocks** | Always LTR (code is inherently left-to-right) |
307
+ | **Inline code** | Positioned correctly within RTL text flow |
308
+ | **Copy as HTML** | Exported HTML includes `dir="rtl"` for correct rendering in paste targets |
309
+
258
310
  ## Styling Architecture
259
311
 
260
312
  Understanding how `react-native-enriched-markdown` handles styling helps you create consistent, well-designed Markdown content.
@@ -274,6 +326,8 @@ Block elements are structural containers that define the layout. Each block has
274
326
  | `blockquote` | Quoted content with accent bar |
275
327
  | `list` | Ordered and unordered lists |
276
328
  | `codeBlock` | Multi-line code containers |
329
+ | `table` | GFM tables (requires `flavor="github"`) |
330
+ | `taskList` | Task list checkboxes |
277
331
 
278
332
  #### Inline Elements
279
333
 
@@ -285,8 +339,8 @@ Inline elements modify text within blocks. They inherit the parent block's base
285
339
  | `em` | Parent block | Italic style, optional color |
286
340
  | `strikethrough` | Parent block | Strike line with custom color (iOS only) |
287
341
  | `underline` | Parent block | Underline with custom color (iOS only) |
288
- | `code` | Parent block | Monospace font, background |
289
- | `link` | Parent block | Color, underline |
342
+ | `code` | Parent block | Monospace font, background, optional fontSize |
343
+ | `link` | Parent block | Optional font family, color, underline |
290
344
 
291
345
  ### Style Inheritance
292
346
 
@@ -365,10 +419,12 @@ The library provides sensible default styles for all Markdown elements out of th
365
419
  color: '#333',
366
420
  },
367
421
  link: {
422
+ fontFamily: 'System-Bold',
368
423
  color: '#007AFF',
369
424
  underline: true,
370
425
  },
371
426
  code: {
427
+ fontSize: 16,
372
428
  color: '#E91E63',
373
429
  backgroundColor: '#F5F5F5',
374
430
  borderColor: '#E0E0E0',
@@ -403,6 +459,12 @@ The library provides sensible default styles for all Markdown elements out of th
403
459
  inlineImage: {
404
460
  size: 20,
405
461
  },
462
+ taskList: {
463
+ checkedColor: '#2196F3',
464
+ borderColor: '#9E9E9E',
465
+ checkmarkColor: '#FFFFFF',
466
+ checkboxSize: 16,
467
+ },
406
468
  }}
407
469
  />
408
470
  ```
@@ -472,6 +534,7 @@ The library provides sensible default styles for all Markdown elements out of th
472
534
 
473
535
  | Property | Type | Description |
474
536
  |----------|------|-------------|
537
+ | `fontSize` | `number` | Font size in points. Defaults to the parent block's font size (1em). Set to customize the monospaced font size independently |
475
538
  | `color` | `string` | Text color |
476
539
  | `backgroundColor` | `string` | Background color |
477
540
  | `borderColor` | `string` | Border color |
@@ -480,6 +543,7 @@ The library provides sensible default styles for all Markdown elements out of th
480
543
 
481
544
  | Property | Type | Description |
482
545
  |----------|------|-------------|
546
+ | `fontFamily` | `string` | Font family for links. Overrides the parent block's font family when set |
483
547
  | `color` | `string` | Link text color |
484
548
  | `underline` | `boolean` | Show underline |
485
549
 
@@ -519,6 +583,35 @@ The library provides sensible default styles for all Markdown elements out of th
519
583
  | `marginTop` | `number` | Top margin |
520
584
  | `marginBottom` | `number` | Bottom margin |
521
585
 
586
+ #### Table-specific
587
+
588
+ Table styles only apply when `flavor="github"` is set. Tables inherit the base block styles (`fontSize`, `fontFamily`, `fontWeight`, `color`, `marginTop`, `marginBottom`, `lineHeight`) and add the following:
589
+
590
+ | Property | Type | Description |
591
+ |----------|------|-------------|
592
+ | `headerFontFamily` | `string` | Font family for header cells (falls back to `fontFamily` if not set) |
593
+ | `headerBackgroundColor` | `string` | Background color for the header row |
594
+ | `headerTextColor` | `string` | Text color for the header row |
595
+ | `rowEvenBackgroundColor` | `string` | Background color for even data rows |
596
+ | `rowOddBackgroundColor` | `string` | Background color for odd data rows |
597
+ | `borderColor` | `string` | Color of the table grid lines |
598
+ | `borderWidth` | `number` | Width of the table grid lines |
599
+ | `borderRadius` | `number` | Corner radius of the table container |
600
+ | `cellPaddingHorizontal` | `number` | Horizontal padding inside cells |
601
+ | `cellPaddingVertical` | `number` | Vertical padding inside cells |
602
+
603
+ #### Task List-specific
604
+
605
+ | Property | Type | Description |
606
+ |----------|------|-------------|
607
+ | `checkedColor` | `string` | Background color of checked checkbox |
608
+ | `borderColor` | `string` | Border color of unchecked checkbox |
609
+ | `checkmarkColor` | `string` | Color of the checkmark inside checked checkbox |
610
+ | `checkboxSize` | `number` | Size of the checkbox (defaults to 90% of list font size) |
611
+ | `checkboxBorderRadius` | `number` | Corner radius of the checkbox |
612
+ | `checkedTextColor` | `string` | Text color for checked items |
613
+ | `checkedStrikethrough` | `boolean` | Whether to apply strikethrough to checked items |
614
+
522
615
  ## API Reference
523
616
 
524
617
  ### Props
@@ -530,12 +623,23 @@ The library provides sensible default styles for all Markdown elements out of th
530
623
  | `containerStyle` | `ViewStyle` | - | Style for the container view |
531
624
  | `onLinkPress` | `(event: LinkPressEvent) => void` | - | Callback when a link is pressed. Access URL via `event.url` |
532
625
  | `onLinkLongPress` | `(event: LinkLongPressEvent) => void` | - | Callback when a link is long pressed. Access URL via `event.url`. On iOS, automatically disables the system link preview |
626
+ | `onTaskListItemPress` | `(event: TaskListItemPressEvent) => void` | - | Callback when a task list checkbox is tapped. Receives `index` (0-based), `checked` (previous state), and `text` (item text) |
533
627
  | `enableLinkPreview` | `boolean` | `true` | Controls the native link preview on long press (iOS only). Automatically set to `false` when `onLinkLongPress` is provided |
534
628
  | `selectable` | `boolean` | `true` | Whether text can be selected |
535
629
  | `md4cFlags` | `Md4cFlags` | `{ underline: false }` | Configuration for md4c parser extension flags |
536
630
  | `allowFontScaling` | `boolean` | `true` | Whether fonts should scale to respect Text Size accessibility settings |
537
631
  | `maxFontSizeMultiplier` | `number` | `undefined` | Maximum font scale multiplier when `allowFontScaling` is enabled |
538
632
  | `allowTrailingMargin` | `boolean` | `false` | Whether to preserve the bottom margin of the last block element |
633
+ | `flavor` | `'commonmark' \| 'github'` | `'commonmark'` | Markdown flavor. Set to `'github'` to enable GitHub Flavored Markdown table support |
634
+
635
+ ## Future Plans
636
+
637
+ We're actively working on expanding the capabilities of `react-native-enriched-markdown`. Here's what's on the roadmap:
638
+
639
+ - GFM (GitHub Flavored Markdown) Support
640
+ - LaTeX / Math Rendering
641
+ - `EnrichedMarkdownInput`
642
+ - Web Implementation via `react-native-web`
539
643
 
540
644
  ## Contributing
541
645
 
@@ -35,6 +35,7 @@ android {
35
35
  defaultConfig {
36
36
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
37
37
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
38
+ consumerProguardFiles "consumer-rules.pro"
38
39
  }
39
40
 
40
41
  buildFeatures {
@@ -0,0 +1,8 @@
1
+ # ProGuard/R8 consumer rules for react-native-enriched-markdown
2
+ #
3
+ # JNI: Classes accessed from C++ (jni-adapter.cpp) via FindClass/GetFieldID.
4
+ # R8 cannot trace hardcoded string lookups in native code.
5
+
6
+ -keep class com.swmansion.enriched.markdown.parser.MarkdownASTNode { *; }
7
+ -keep class com.swmansion.enriched.markdown.parser.MarkdownASTNode$NodeType { *; }
8
+ -keep class com.swmansion.enriched.markdown.parser.Md4cFlags { *; }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaDelegate.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+ import com.facebook.react.bridge.ReadableMap;
15
+ import com.facebook.react.uimanager.BaseViewManager;
16
+ import com.facebook.react.uimanager.BaseViewManagerDelegate;
17
+ import com.facebook.react.uimanager.LayoutShadowNode;
18
+
19
+ public class EnrichedMarkdownManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & EnrichedMarkdownManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
20
+ public EnrichedMarkdownManagerDelegate(U viewManager) {
21
+ super(viewManager);
22
+ }
23
+ @Override
24
+ public void setProperty(T view, String propName, @Nullable Object value) {
25
+ switch (propName) {
26
+ case "markdown":
27
+ mViewManager.setMarkdown(view, value == null ? null : (String) value);
28
+ break;
29
+ case "markdownStyle":
30
+ mViewManager.setMarkdownStyle(view, (ReadableMap) value);
31
+ break;
32
+ case "enableLinkPreview":
33
+ mViewManager.setEnableLinkPreview(view, value == null ? true : (boolean) value);
34
+ break;
35
+ case "selectable":
36
+ mViewManager.setSelectable(view, value == null ? false : (boolean) value);
37
+ break;
38
+ case "md4cFlags":
39
+ mViewManager.setMd4cFlags(view, (ReadableMap) value);
40
+ break;
41
+ case "allowFontScaling":
42
+ mViewManager.setAllowFontScaling(view, value == null ? true : (boolean) value);
43
+ break;
44
+ case "maxFontSizeMultiplier":
45
+ mViewManager.setMaxFontSizeMultiplier(view, value == null ? 0f : ((Double) value).floatValue());
46
+ break;
47
+ case "allowTrailingMargin":
48
+ mViewManager.setAllowTrailingMargin(view, value == null ? false : (boolean) value);
49
+ break;
50
+ default:
51
+ super.setProperty(view, propName, value);
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
+ *
4
+ * Do not edit this file as changes may cause incorrect behavior and will be lost
5
+ * once the code is regenerated.
6
+ *
7
+ * @generated by codegen project: GeneratePropsJavaInterface.js
8
+ */
9
+
10
+ package com.facebook.react.viewmanagers;
11
+
12
+ import android.view.View;
13
+ import androidx.annotation.Nullable;
14
+ import com.facebook.react.bridge.ReadableMap;
15
+ import com.facebook.react.uimanager.ViewManagerWithGeneratedInterface;
16
+
17
+ public interface EnrichedMarkdownManagerInterface<T extends View> extends ViewManagerWithGeneratedInterface {
18
+ void setMarkdown(T view, @Nullable String value);
19
+ void setMarkdownStyle(T view, @Nullable ReadableMap value);
20
+ void setEnableLinkPreview(T view, boolean value);
21
+ void setSelectable(T view, boolean value);
22
+ void setMd4cFlags(T view, @Nullable ReadableMap value);
23
+ void setAllowFontScaling(T view, boolean value);
24
+ void setMaxFontSizeMultiplier(T view, float value);
25
+ void setAllowTrailingMargin(T view, boolean value);
26
+ }
@@ -16,7 +16,7 @@ namespace facebook::react {
16
16
 
17
17
  void EnrichedMarkdownTextSpec_registerComponentDescriptorsFromCodegen(
18
18
  std::shared_ptr<const ComponentDescriptorProviderRegistry> registry) {
19
- registry->add(concreteComponentDescriptorProvider<EnrichedMarkdownTextComponentDescriptor>());
19
+
20
20
  }
21
21
 
22
22
  } // namespace facebook::react
@@ -16,7 +16,7 @@
16
16
 
17
17
  namespace facebook::react {
18
18
 
19
- using EnrichedMarkdownTextComponentDescriptor = ConcreteComponentDescriptor<EnrichedMarkdownTextShadowNode>;
19
+
20
20
 
21
21
  void EnrichedMarkdownTextSpec_registerComponentDescriptorsFromCodegen(
22
22
  std::shared_ptr<const ComponentDescriptorProviderRegistry> registry);
@@ -13,6 +13,35 @@
13
13
 
14
14
  namespace facebook::react {
15
15
 
16
+ void EnrichedMarkdownEventEmitter::onLinkPress(OnLinkPress event) const {
17
+ dispatchEvent("linkPress", [event=std::move(event)](jsi::Runtime &runtime) {
18
+ auto payload = jsi::Object(runtime);
19
+ payload.setProperty(runtime, "url", event.url);
20
+ return payload;
21
+ });
22
+ }
23
+
24
+
25
+ void EnrichedMarkdownEventEmitter::onLinkLongPress(OnLinkLongPress event) const {
26
+ dispatchEvent("linkLongPress", [event=std::move(event)](jsi::Runtime &runtime) {
27
+ auto payload = jsi::Object(runtime);
28
+ payload.setProperty(runtime, "url", event.url);
29
+ return payload;
30
+ });
31
+ }
32
+
33
+
34
+ void EnrichedMarkdownEventEmitter::onTaskListItemPress(OnTaskListItemPress event) const {
35
+ dispatchEvent("taskListItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
36
+ auto payload = jsi::Object(runtime);
37
+ payload.setProperty(runtime, "index", event.index);
38
+ payload.setProperty(runtime, "checked", event.checked);
39
+ payload.setProperty(runtime, "text", event.text);
40
+ return payload;
41
+ });
42
+ }
43
+
44
+
16
45
  void EnrichedMarkdownTextEventEmitter::onLinkPress(OnLinkPress event) const {
17
46
  dispatchEvent("linkPress", [event=std::move(event)](jsi::Runtime &runtime) {
18
47
  auto payload = jsi::Object(runtime);
@@ -30,4 +59,15 @@ void EnrichedMarkdownTextEventEmitter::onLinkLongPress(OnLinkLongPress event) co
30
59
  });
31
60
  }
32
61
 
62
+
63
+ void EnrichedMarkdownTextEventEmitter::onTaskListItemPress(OnTaskListItemPress event) const {
64
+ dispatchEvent("taskListItemPress", [event=std::move(event)](jsi::Runtime &runtime) {
65
+ auto payload = jsi::Object(runtime);
66
+ payload.setProperty(runtime, "index", event.index);
67
+ payload.setProperty(runtime, "checked", event.checked);
68
+ payload.setProperty(runtime, "text", event.text);
69
+ return payload;
70
+ });
71
+ }
72
+
33
73
  } // namespace facebook::react
@@ -13,6 +13,29 @@
13
13
 
14
14
 
15
15
  namespace facebook::react {
16
+ class EnrichedMarkdownEventEmitter : public ViewEventEmitter {
17
+ public:
18
+ using ViewEventEmitter::ViewEventEmitter;
19
+
20
+ struct OnLinkPress {
21
+ std::string url;
22
+ };
23
+
24
+ struct OnLinkLongPress {
25
+ std::string url;
26
+ };
27
+
28
+ struct OnTaskListItemPress {
29
+ int index;
30
+ bool checked;
31
+ std::string text;
32
+ };
33
+ void onLinkPress(OnLinkPress value) const;
34
+
35
+ void onLinkLongPress(OnLinkLongPress value) const;
36
+
37
+ void onTaskListItemPress(OnTaskListItemPress value) const;
38
+ };
16
39
  class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
17
40
  public:
18
41
  using ViewEventEmitter::ViewEventEmitter;
@@ -24,8 +47,16 @@ class EnrichedMarkdownTextEventEmitter : public ViewEventEmitter {
24
47
  struct OnLinkLongPress {
25
48
  std::string url;
26
49
  };
50
+
51
+ struct OnTaskListItemPress {
52
+ int index;
53
+ bool checked;
54
+ std::string text;
55
+ };
27
56
  void onLinkPress(OnLinkPress value) const;
28
57
 
29
58
  void onLinkLongPress(OnLinkLongPress value) const;
59
+
60
+ void onTaskListItemPress(OnTaskListItemPress value) const;
30
61
  };
31
62
  } // namespace facebook::react
@@ -14,6 +14,70 @@
14
14
 
15
15
  namespace facebook::react {
16
16
 
17
+ EnrichedMarkdownProps::EnrichedMarkdownProps(
18
+ const PropsParserContext &context,
19
+ const EnrichedMarkdownProps &sourceProps,
20
+ const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),
21
+
22
+ markdown(convertRawProp(context, rawProps, "markdown", sourceProps.markdown, {})),
23
+ markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
24
+ enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
25
+ selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
26
+ md4cFlags(convertRawProp(context, rawProps, "md4cFlags", sourceProps.md4cFlags, {})),
27
+ allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
28
+ maxFontSizeMultiplier(convertRawProp(context, rawProps, "maxFontSizeMultiplier", sourceProps.maxFontSizeMultiplier, {0.0})),
29
+ allowTrailingMargin(convertRawProp(context, rawProps, "allowTrailingMargin", sourceProps.allowTrailingMargin, {false})) {}
30
+
31
+ #ifdef RN_SERIALIZABLE_STATE
32
+ ComponentName EnrichedMarkdownProps::getDiffPropsImplementationTarget() const {
33
+ return "EnrichedMarkdown";
34
+ }
35
+
36
+ folly::dynamic EnrichedMarkdownProps::getDiffProps(
37
+ const Props* prevProps) const {
38
+ static const auto defaultProps = EnrichedMarkdownProps();
39
+ const EnrichedMarkdownProps* oldProps = prevProps == nullptr
40
+ ? &defaultProps
41
+ : static_cast<const EnrichedMarkdownProps*>(prevProps);
42
+ if (this == oldProps) {
43
+ return folly::dynamic::object();
44
+ }
45
+ folly::dynamic result = HostPlatformViewProps::getDiffProps(prevProps);
46
+
47
+ if (markdown != oldProps->markdown) {
48
+ result["markdown"] = markdown;
49
+ }
50
+
51
+ if (markdownStyle != oldProps->markdownStyle) {
52
+ result["markdownStyle"] = toDynamic(markdownStyle);
53
+ }
54
+
55
+ if (enableLinkPreview != oldProps->enableLinkPreview) {
56
+ result["enableLinkPreview"] = enableLinkPreview;
57
+ }
58
+
59
+ if (selectable != oldProps->selectable) {
60
+ result["selectable"] = selectable;
61
+ }
62
+
63
+ if (md4cFlags != oldProps->md4cFlags) {
64
+ result["md4cFlags"] = toDynamic(md4cFlags);
65
+ }
66
+
67
+ if (allowFontScaling != oldProps->allowFontScaling) {
68
+ result["allowFontScaling"] = allowFontScaling;
69
+ }
70
+
71
+ if ((maxFontSizeMultiplier != oldProps->maxFontSizeMultiplier) && !(std::isnan(maxFontSizeMultiplier) && std::isnan(oldProps->maxFontSizeMultiplier))) {
72
+ result["maxFontSizeMultiplier"] = maxFontSizeMultiplier;
73
+ }
74
+
75
+ if (allowTrailingMargin != oldProps->allowTrailingMargin) {
76
+ result["allowTrailingMargin"] = allowTrailingMargin;
77
+ }
78
+ return result;
79
+ }
80
+ #endif
17
81
  EnrichedMarkdownTextProps::EnrichedMarkdownTextProps(
18
82
  const PropsParserContext &context,
19
83
  const EnrichedMarkdownTextProps &sourceProps,