react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.10

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 (505) hide show
  1. package/README.md +54 -8
  2. package/ReactNativeEnrichedMarkdown.podspec +82 -73
  3. package/android/build.gradle +188 -1
  4. package/android/consumer-rules.pro +1 -1
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +27 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +7 -0
  7. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
  8. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
  9. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +27 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +7 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +65 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1086 -61
  15. package/android/src/main/baseline-prof.txt +1 -1
  16. package/android/src/main/cpp/jni-adapter.cpp +74 -0
  17. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +351 -13
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +62 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +85 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +160 -1
  21. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
  22. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +76 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +126 -10
  24. package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -0
  26. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
  27. package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +43 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +923 -462
  30. package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
  34. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
  36. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +108 -7
  37. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
  39. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  65. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  68. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  69. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  77. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  78. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  79. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  80. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +35 -28
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +20 -82
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
  90. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
  91. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  93. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  94. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  95. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  96. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  97. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  100. package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +16 -1
  101. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
  102. package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
  103. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  104. package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -0
  105. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  106. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +84 -7
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  117. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  118. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +52 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  120. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  121. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  122. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
  123. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
  124. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  125. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  126. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  127. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  128. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt +88 -0
  129. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
  130. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  131. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +72 -16
  132. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +232 -0
  133. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +64 -0
  134. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +414 -0
  135. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
  136. package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
  137. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +61 -11
  138. package/android/src/main/jni/CMakeLists.txt +53 -0
  139. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
  140. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
  141. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
  142. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
  143. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  144. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
  145. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
  146. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
  147. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +8 -2
  148. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  149. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +13 -6
  150. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
  151. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +26 -8
  152. package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
  153. package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
  154. package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
  155. package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
  156. package/cpp/highlight/HighlightGrammars.hpp +28 -0
  157. package/cpp/highlight/code_highlight_podspec.rb +211 -0
  158. package/cpp/highlight/gen-registry.mjs +155 -0
  159. package/cpp/highlight/grammar-versions.json +159 -0
  160. package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
  161. package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
  162. package/cpp/parser/MD4CParser.cpp +173 -61
  163. package/cpp/parser/MD4CParser.hpp +1 -0
  164. package/cpp/parser/MarkdownASTNode.hpp +2 -1
  165. package/cpp/wasm/ASTSerializer.cpp +2 -0
  166. package/cpp/wasm/build.sh +1 -0
  167. package/cpp/wasm/md4c_wasm.cpp +3 -1
  168. package/docs/ACCESSIBILITY.md +14 -2
  169. package/docs/API_REFERENCE.md +405 -12
  170. package/docs/BREAKING_CHANGES.md +129 -0
  171. package/docs/CODE_HIGHLIGHT.md +133 -0
  172. package/docs/COPY_OPTIONS.md +61 -3
  173. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  174. package/docs/IMAGE_CACHING.md +30 -0
  175. package/docs/INPUT.md +110 -11
  176. package/docs/LATEX_MATH.md +87 -45
  177. package/docs/MACOS.md +1 -1
  178. package/docs/MARKDOWN_STREAMING.md +27 -1
  179. package/docs/MENTIONS.md +8 -1
  180. package/docs/NATIVE_ASSETS.md +127 -0
  181. package/docs/RTL.md +1 -1
  182. package/docs/STYLES.md +73 -6
  183. package/docs/TESTING.md +112 -0
  184. package/docs/TEXT.md +18 -6
  185. package/docs/WEB.md +4 -1
  186. package/ios/EnrichedMarkdown.h +7 -0
  187. package/ios/EnrichedMarkdown.mm +583 -76
  188. package/ios/EnrichedMarkdownText.h +7 -0
  189. package/ios/EnrichedMarkdownText.mm +299 -73
  190. package/ios/attachments/ENRMImageAttachment.h +9 -0
  191. package/ios/attachments/ENRMImageAttachment.m +143 -40
  192. package/ios/attachments/ENRMMathInlineAttachment+macOS.m +2 -1
  193. package/ios/attachments/ENRMMathInlineAttachment.h +5 -0
  194. package/ios/attachments/ENRMMathInlineAttachment.m +50 -82
  195. package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
  196. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
  197. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
  198. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +65 -0
  199. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +1086 -61
  200. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +181 -2
  201. package/ios/input/ENRMAutoLinkDetector.h +2 -1
  202. package/ios/input/ENRMAutoLinkDetector.mm +79 -41
  203. package/ios/input/ENRMBlockEditCoordinator.h +71 -0
  204. package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
  205. package/ios/input/ENRMBlockRange.h +28 -0
  206. package/ios/input/ENRMBlockRange.mm +30 -0
  207. package/ios/input/ENRMBlockStore.h +56 -0
  208. package/ios/input/ENRMBlockStore.mm +275 -0
  209. package/ios/input/ENRMClipboardCoordinator.h +45 -0
  210. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  211. package/ios/input/ENRMDetectorPipeline.h +2 -1
  212. package/ios/input/ENRMEditPipeline.h +76 -0
  213. package/ios/input/ENRMEditPipeline.mm +228 -0
  214. package/ios/input/ENRMEditSession.h +36 -0
  215. package/ios/input/ENRMEditSession.mm +63 -0
  216. package/ios/input/ENRMFormattingStore.h +17 -0
  217. package/ios/input/ENRMFormattingStore.mm +95 -105
  218. package/ios/input/ENRMInputBlockType.h +91 -0
  219. package/ios/input/ENRMInputBlockType.mm +5 -0
  220. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  221. package/ios/input/ENRMInputEventEmitter.h +56 -0
  222. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  223. package/ios/input/ENRMInputFormatter.h +29 -69
  224. package/ios/input/ENRMInputFormatter.mm +216 -124
  225. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  226. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  227. package/ios/input/ENRMInputLayoutManager.h +9 -0
  228. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  229. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  230. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  231. package/ios/input/ENRMInputParser.h +5 -6
  232. package/ios/input/ENRMInputParser.mm +461 -178
  233. package/ios/input/ENRMInputRemend.mm +2 -2
  234. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  235. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  236. package/ios/input/ENRMInputTextView.mm +103 -8
  237. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  238. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  239. package/ios/input/ENRMLinkCoordinator.h +41 -0
  240. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  241. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  242. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  243. package/ios/input/ENRMMathAtom.h +26 -0
  244. package/ios/input/ENRMMathAtom.mm +12 -0
  245. package/ios/input/ENRMMentionCoordinator.h +45 -0
  246. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  247. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  248. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  249. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  250. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  251. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  252. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  253. package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
  254. package/ios/input/InputStylePropsUtils.h +109 -68
  255. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  256. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  257. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  258. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  259. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  260. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  261. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  262. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  263. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  264. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  265. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  266. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  267. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  268. package/ios/internals/MeasurementCache.h +41 -9
  269. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  270. package/ios/math/ENRMMathChipController.h +74 -0
  271. package/ios/math/ENRMMathChipController.mm +476 -0
  272. package/ios/math/ENRMRaTeXBridge.swift +27 -6
  273. package/ios/parser/ENRMMarkdownParser.h +1 -8
  274. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  275. package/ios/parser/MarkdownASTNode.h +2 -1
  276. package/ios/parser/MarkdownParserBridge.mm +4 -0
  277. package/ios/renderer/AttributedRenderer.m +20 -2
  278. package/ios/renderer/BaseRenderer.h +17 -2
  279. package/ios/renderer/BaseRenderer.m +30 -0
  280. package/ios/renderer/BlockquoteRenderer.h +1 -1
  281. package/ios/renderer/BlockquoteRenderer.m +144 -35
  282. package/ios/renderer/CodeBlockRenderer.h +1 -1
  283. package/ios/renderer/CodeBlockRenderer.m +27 -23
  284. package/ios/renderer/CodeRenderer.h +1 -1
  285. package/ios/renderer/CodeRenderer.m +3 -1
  286. package/ios/renderer/ENRMImageRenderer.h +1 -1
  287. package/ios/renderer/ENRMImageRenderer.m +5 -1
  288. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  289. package/ios/renderer/ENRMMathInlineRenderer.m +6 -1
  290. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  291. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  292. package/ios/renderer/EmphasisRenderer.h +1 -1
  293. package/ios/renderer/EmphasisRenderer.m +3 -1
  294. package/ios/renderer/HeadingRenderer.h +1 -1
  295. package/ios/renderer/HeadingRenderer.m +13 -6
  296. package/ios/renderer/HighlightRenderer.h +1 -1
  297. package/ios/renderer/HighlightRenderer.m +3 -1
  298. package/ios/renderer/LinkRenderer.h +1 -1
  299. package/ios/renderer/LinkRenderer.m +50 -16
  300. package/ios/renderer/ListItemRenderer.h +13 -1
  301. package/ios/renderer/ListItemRenderer.m +102 -44
  302. package/ios/renderer/ListRenderer.h +2 -2
  303. package/ios/renderer/ListRenderer.m +63 -25
  304. package/ios/renderer/ParagraphRenderer.h +1 -1
  305. package/ios/renderer/ParagraphRenderer.m +16 -8
  306. package/ios/renderer/RenderContext.h +10 -0
  307. package/ios/renderer/RenderContext.m +44 -0
  308. package/ios/renderer/RendererFactory.m +14 -0
  309. package/ios/renderer/StrikethroughRenderer.h +1 -1
  310. package/ios/renderer/StrikethroughRenderer.m +3 -1
  311. package/ios/renderer/StrongRenderer.h +1 -1
  312. package/ios/renderer/StrongRenderer.m +3 -1
  313. package/ios/renderer/SubscriptRenderer.h +1 -1
  314. package/ios/renderer/SubscriptRenderer.m +3 -1
  315. package/ios/renderer/SuperscriptRenderer.h +1 -1
  316. package/ios/renderer/SuperscriptRenderer.m +3 -1
  317. package/ios/renderer/TextRenderer.h +2 -2
  318. package/ios/renderer/TextRenderer.m +3 -1
  319. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  320. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  321. package/ios/renderer/UnderlineRenderer.h +1 -1
  322. package/ios/renderer/UnderlineRenderer.m +3 -1
  323. package/ios/styles/StyleConfig.h +42 -0
  324. package/ios/styles/StyleConfig.mm +216 -0
  325. package/ios/utils/BlockquoteBorder.h +6 -0
  326. package/ios/utils/BlockquoteBorder.m +249 -52
  327. package/ios/utils/CodeBackground.m +3 -65
  328. package/ios/utils/CodeBlockBackground.m +16 -2
  329. package/ios/utils/ENRMAtomicSize.h +65 -0
  330. package/ios/utils/ENRMBlockMenu.h +66 -0
  331. package/ios/utils/ENRMChipDrawing.h +24 -0
  332. package/ios/utils/ENRMChipDrawing.m +83 -0
  333. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  334. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  335. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  336. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  337. package/ios/utils/ENRMFeatureFlags.h +7 -0
  338. package/ios/utils/ENRMImageDownloader.h +11 -1
  339. package/ios/utils/ENRMImageDownloader.m +60 -16
  340. package/ios/utils/ENRMLinkChip.h +70 -0
  341. package/ios/utils/ENRMLinkChip.m +213 -0
  342. package/ios/utils/ENRMLinkLayout.h +50 -0
  343. package/ios/utils/ENRMLinkLayout.m +45 -0
  344. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  345. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  346. package/ios/utils/ENRMMathFallback.h +26 -0
  347. package/ios/utils/ENRMMathFallback.m +18 -0
  348. package/ios/utils/ENRMSelectionChange.h +120 -0
  349. package/ios/utils/ENRMSelectionChange.m +282 -0
  350. package/ios/utils/ENRMTextViewSetup.h +35 -17
  351. package/ios/utils/EditMenuUtils+macOS.m +4 -1
  352. package/ios/utils/EditMenuUtils.h +35 -6
  353. package/ios/utils/EditMenuUtils.m +188 -11
  354. package/ios/utils/HTMLGenerator.m +2 -1
  355. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  356. package/ios/utils/LastElementUtils.h +1 -0
  357. package/ios/utils/ListMarkerDrawer.m +29 -42
  358. package/ios/utils/MarkdownASTSerializer.m +4 -0
  359. package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
  360. package/ios/utils/MarkdownExtractor.m +2 -1
  361. package/ios/utils/ParagraphStyleUtils.h +5 -0
  362. package/ios/utils/ParagraphStyleUtils.m +77 -17
  363. package/ios/utils/RTFExportUtils.m +2 -0
  364. package/ios/utils/RenderedMarkdownSegment.h +13 -1
  365. package/ios/utils/RenderedMarkdownSegment.m +20 -0
  366. package/ios/utils/SegmentRenderer.m +17 -4
  367. package/ios/utils/StreamingMarkdownFilter.h +11 -1
  368. package/ios/utils/StreamingMarkdownFilter.m +98 -2
  369. package/ios/utils/StylePropsUtils.h +110 -1
  370. package/ios/utils/TaskListTapUtils.m +24 -0
  371. package/ios/utils/TextViewLayoutManager.mm +3 -0
  372. package/ios/views/ENRMCodeBlockContainerView.h +60 -0
  373. package/ios/views/ENRMCodeBlockContainerView.m +569 -0
  374. package/ios/views/ENRMMathContainerView.h +23 -0
  375. package/ios/views/ENRMMathContainerView.m +87 -20
  376. package/ios/views/TableContainerView.h +32 -0
  377. package/ios/views/TableContainerView.m +291 -175
  378. package/jest.d.ts +1 -0
  379. package/jest.js +5 -0
  380. package/lib/module/EnrichedMarkdownNativeComponent.ts +203 -1
  381. package/lib/module/EnrichedMarkdownTextInput.js +84 -5
  382. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  383. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  384. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +204 -1
  385. package/lib/module/headingDefaults.js +34 -0
  386. package/lib/module/headingDefaults.js.map +1 -0
  387. package/lib/module/index.js.map +1 -1
  388. package/lib/module/jest/index.js +205 -0
  389. package/lib/module/jest/index.js.map +1 -0
  390. package/lib/module/native/EnrichedMarkdownText.js +199 -15
  391. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  392. package/lib/module/normalizeMarkdownStyle.js +98 -23
  393. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  394. package/lib/module/normalizeMarkdownStyle.web.js +73 -22
  395. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  396. package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
  397. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  398. package/lib/module/normalizeMenuItem.js +1 -1
  399. package/lib/module/utils/textInputState.js +26 -0
  400. package/lib/module/utils/textInputState.js.map +1 -0
  401. package/lib/module/web/EnrichedMarkdownText.js +15 -8
  402. package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
  403. package/lib/module/web/parseMarkdown.js +4 -3
  404. package/lib/module/web/parseMarkdown.js.map +1 -1
  405. package/lib/module/web/renderers/InlineRenderers.js +102 -3
  406. package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
  407. package/lib/module/web/renderers/ListRenderers.js +7 -2
  408. package/lib/module/web/renderers/ListRenderers.js.map +1 -1
  409. package/lib/module/web/renderers/index.js +7 -4
  410. package/lib/module/web/renderers/index.js.map +1 -1
  411. package/lib/module/web/styles.js +101 -6
  412. package/lib/module/web/styles.js.map +1 -1
  413. package/lib/module/web/utils.js +14 -0
  414. package/lib/module/web/utils.js.map +1 -1
  415. package/lib/module/web/wasm/md4c.js +0 -0
  416. package/lib/module/web/wasm/md4c.js.map +1 -1
  417. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +185 -2
  418. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  419. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
  420. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  421. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
  422. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  423. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +185 -2
  424. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  425. package/lib/typescript/src/headingDefaults.d.ts +9 -0
  426. package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
  427. package/lib/typescript/src/index.d.ts +3 -3
  428. package/lib/typescript/src/index.d.ts.map +1 -1
  429. package/lib/typescript/src/index.web.d.ts +2 -2
  430. package/lib/typescript/src/index.web.d.ts.map +1 -1
  431. package/lib/typescript/src/jest/index.d.ts +6 -0
  432. package/lib/typescript/src/jest/index.d.ts.map +1 -0
  433. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
  434. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  435. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  436. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  437. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
  438. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  439. package/lib/typescript/src/types/MarkdownStyle.d.ts +122 -5
  440. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  441. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +39 -0
  442. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  443. package/lib/typescript/src/types/MarkdownTextProps.d.ts +207 -10
  444. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  445. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +60 -1
  446. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
  447. package/lib/typescript/src/types/events.d.ts +85 -0
  448. package/lib/typescript/src/types/events.d.ts.map +1 -1
  449. package/lib/typescript/src/utils/textInputState.d.ts +24 -0
  450. package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
  451. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
  452. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
  453. package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
  454. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
  455. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
  456. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
  457. package/lib/typescript/src/web/renderers/index.d.ts +2 -1
  458. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
  459. package/lib/typescript/src/web/styles.d.ts +2 -1
  460. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  461. package/lib/typescript/src/web/types.d.ts +10 -2
  462. package/lib/typescript/src/web/types.d.ts.map +1 -1
  463. package/lib/typescript/src/web/utils.d.ts +4 -0
  464. package/lib/typescript/src/web/utils.d.ts.map +1 -1
  465. package/package.json +36 -9
  466. package/postinstall.mjs +131 -0
  467. package/ratex-version.json +21 -0
  468. package/src/EnrichedMarkdownNativeComponent.ts +203 -1
  469. package/src/EnrichedMarkdownTextInput.tsx +159 -8
  470. package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  471. package/src/EnrichedMarkdownTextNativeComponent.ts +204 -1
  472. package/src/headingDefaults.ts +21 -0
  473. package/src/index.tsx +15 -0
  474. package/src/index.web.tsx +6 -1
  475. package/src/jest/index.tsx +236 -0
  476. package/src/native/EnrichedMarkdownText.tsx +260 -11
  477. package/src/normalizeMarkdownStyle.ts +117 -16
  478. package/src/normalizeMarkdownStyle.web.ts +76 -15
  479. package/src/normalizeMarkdownTextInputStyle.ts +110 -35
  480. package/src/normalizeMenuItem.ts +1 -1
  481. package/src/types/MarkdownStyle.ts +125 -5
  482. package/src/types/MarkdownStyleInternal.ts +51 -0
  483. package/src/types/MarkdownTextProps.ts +215 -10
  484. package/src/types/MarkdownTextProps.web.ts +62 -1
  485. package/src/types/events.ts +90 -0
  486. package/src/utils/textInputState.ts +35 -0
  487. package/src/web/EnrichedMarkdownText.tsx +26 -5
  488. package/src/web/parseMarkdown.ts +6 -2
  489. package/src/web/renderers/InlineRenderers.tsx +116 -3
  490. package/src/web/renderers/ListRenderers.tsx +14 -2
  491. package/src/web/renderers/index.tsx +6 -2
  492. package/src/web/styles.ts +114 -5
  493. package/src/web/types.ts +10 -1
  494. package/src/web/utils.ts +9 -0
  495. package/src/web/wasm/md4c.js +0 -0
  496. package/vendor-grammars.mjs +511 -0
  497. package/vendor-ratex.mjs +173 -0
  498. package/app.plugin.js +0 -2
  499. package/plugin/build/withAndroidMath.js +0 -19
  500. package/plugin/build/withIosMath.js +0 -28
  501. package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
  502. package/plugin/src/withAndroidMath.ts +0 -24
  503. package/plugin/src/withIosMath.ts +0 -35
  504. package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
  505. package/plugin/tsconfig.build.json +0 -16
@@ -9,7 +9,7 @@ import {
9
9
  import { parseMarkdown } from './parseMarkdown';
10
10
  import { RenderNode } from './renderers';
11
11
  import type { ASTNode, RendererCallbacks, RenderCapabilities } from './types';
12
- import { indexTaskItems, markInlineImages } from './utils';
12
+ import { indexLinks, indexTaskItems, markInlineImages } from './utils';
13
13
  import { loadKaTeX } from './katex';
14
14
  import type { KaTeXInstance } from './katex';
15
15
  import { ENRM_TEXT_CLASS, ENRM_SELECTION_BG_VAR } from './globalStyles';
@@ -21,11 +21,13 @@ export const EnrichedMarkdownText = ({
21
21
  onLinkPress,
22
22
  onLinkLongPress,
23
23
  onTaskListItemPress,
24
+ enableTaskListItemToggle = true,
24
25
  allowTrailingMargin = false,
25
26
  containerStyle,
26
27
  selectable = true,
27
28
  dir,
28
29
  selectionColor,
30
+ renderLinkDecoration,
29
31
  ...rest
30
32
  }: EnrichedMarkdownTextProps) => {
31
33
  const normalizedStyle = useMemo(
@@ -43,6 +45,7 @@ export const EnrichedMarkdownText = ({
43
45
  superscript = false,
44
46
  subscript = false,
45
47
  highlight = false,
48
+ hardSoftBreaks = false,
46
49
  } = md4cFlags;
47
50
 
48
51
  useEffect(() => {
@@ -57,12 +60,14 @@ export const EnrichedMarkdownText = ({
57
60
  superscript,
58
61
  subscript,
59
62
  highlight,
63
+ hardSoftBreaks,
60
64
  }),
61
65
  katexPromise,
62
66
  ])
63
67
  .then(([result, katexInstance]) => {
64
68
  if (!cancelled) {
65
69
  indexTaskItems(result);
70
+ indexLinks(result);
66
71
  markInlineImages(result);
67
72
 
68
73
  setParseError(false);
@@ -85,14 +90,30 @@ export const EnrichedMarkdownText = ({
85
90
  return () => {
86
91
  cancelled = true;
87
92
  };
88
- }, [markdown, underline, latexMath, superscript, subscript, highlight]);
93
+ }, [
94
+ markdown,
95
+ underline,
96
+ latexMath,
97
+ superscript,
98
+ subscript,
99
+ highlight,
100
+ hardSoftBreaks,
101
+ ]);
89
102
 
90
103
  const callbacks = useMemo<RendererCallbacks>(
91
- () => ({ onLinkPress, onLinkLongPress, onTaskListItemPress }),
92
- [onLinkPress, onLinkLongPress, onTaskListItemPress]
104
+ () => ({
105
+ onLinkPress,
106
+ onLinkLongPress,
107
+ onTaskListItemPress,
108
+ renderLinkDecoration,
109
+ }),
110
+ [onLinkPress, onLinkLongPress, onTaskListItemPress, renderLinkDecoration]
93
111
  );
94
112
 
95
- const capabilities = useMemo<RenderCapabilities>(() => ({ katex }), [katex]);
113
+ const capabilities = useMemo<RenderCapabilities>(
114
+ () => ({ katex, enableTaskListItemToggle }),
115
+ [katex, enableTaskListItemToggle]
116
+ );
96
117
 
97
118
  const lastChildStyle = useMemo(
98
119
  () =>
@@ -7,7 +7,8 @@ type ParseFn = (
7
7
  latexMath: number,
8
8
  superscript: number,
9
9
  subscript: number,
10
- highlight: number
10
+ highlight: number,
11
+ hardSoftBreaks: number
11
12
  ) => string;
12
13
 
13
14
  // Caching the Promise (not the resolved value) means concurrent callers share
@@ -28,6 +29,7 @@ function initializeParser(): Promise<ParseFn> {
28
29
  'number',
29
30
  'number',
30
31
  'number',
32
+ 'number',
31
33
  ])
32
34
  )
33
35
  .catch((error) => {
@@ -55,6 +57,7 @@ export async function parseMarkdown(
55
57
  superscript = false,
56
58
  subscript = false,
57
59
  highlight = false,
60
+ hardSoftBreaks = false,
58
61
  }: Md4cFlags = {}
59
62
  ): Promise<ASTNode> {
60
63
  const parse = await initializeParser();
@@ -66,7 +69,8 @@ export async function parseMarkdown(
66
69
  latexMath ? 1 : 0,
67
70
  superscript ? 1 : 0,
68
71
  subscript ? 1 : 0,
69
- highlight ? 1 : 0
72
+ highlight ? 1 : 0,
73
+ hardSoftBreaks ? 1 : 0
70
74
  )
71
75
  );
72
76
 
@@ -1,8 +1,16 @@
1
- import type { MouseEvent } from 'react';
1
+ import {
2
+ useLayoutEffect,
3
+ useRef,
4
+ useState,
5
+ type MouseEvent,
6
+ type ReactNode,
7
+ } from 'react';
8
+ import type { LinkRect } from '../../types/MarkdownTextProps.web';
2
9
  import type { RendererProps, RendererMap } from '../types';
3
10
  import { extractNodeText } from '../utils';
4
11
  import { KaTeXRenderer } from './KaTeXRenderer';
5
12
  import { linkStyleForUrl } from '../styles';
13
+ import type { CSSProperties } from 'react';
6
14
 
7
15
  function TextRenderer({ node }: RendererProps) {
8
16
  return <>{node.content ?? ''}</>;
@@ -12,6 +20,10 @@ function LineBreakRenderer(_props: RendererProps) {
12
20
  return <br />;
13
21
  }
14
22
 
23
+ function SoftBreakRenderer(_props: RendererProps) {
24
+ return <> </>;
25
+ }
26
+
15
27
  function StrongRenderer({ node, styles, renderChildren }: RendererProps) {
16
28
  return <strong style={styles.strong}>{renderChildren(node)}</strong>;
17
29
  }
@@ -74,16 +86,116 @@ function LinkRenderer({
74
86
  }
75
87
  };
76
88
 
89
+ const linkStyle = linkStyleForUrl(style, url);
90
+ const children = renderChildren(node);
91
+
92
+ if (callbacks.renderLinkDecoration) {
93
+ return (
94
+ <DecoratedLink
95
+ url={url}
96
+ index={node.attributes?.linkIndex ?? 0}
97
+ text={extractNodeText(node)}
98
+ linkStyle={linkStyle}
99
+ renderLinkDecoration={callbacks.renderLinkDecoration}
100
+ onClick={handleClick}
101
+ onContextMenu={handleContextMenu}
102
+ >
103
+ {children}
104
+ </DecoratedLink>
105
+ );
106
+ }
107
+
77
108
  return (
78
109
  <a
79
110
  href={url}
80
- style={linkStyleForUrl(style, url)}
111
+ style={linkStyle}
81
112
  target="_blank"
82
113
  rel="noopener noreferrer"
83
114
  onClick={handleClick}
84
115
  onContextMenu={handleContextMenu}
85
116
  >
86
- {renderChildren(node)}
117
+ {children}
118
+ </a>
119
+ );
120
+ }
121
+
122
+ const EMPTY_RECT: LinkRect = { x: 0, y: 0, width: 0, height: 0 };
123
+
124
+ const decorationLayerStyle: CSSProperties = {
125
+ position: 'absolute',
126
+ inset: 0,
127
+ pointerEvents: 'none',
128
+ };
129
+
130
+ const decorationContentStyle: CSSProperties = { pointerEvents: 'auto' };
131
+
132
+ /**
133
+ * A link with a `renderLinkDecoration` overlay. Unlike native, the overlay
134
+ * anchors to the link's whole inline box (not the last line fragment of a
135
+ * wrapping link), and `rect` is that box relative to itself.
136
+ */
137
+ function DecoratedLink({
138
+ url,
139
+ index,
140
+ text,
141
+ linkStyle,
142
+ renderLinkDecoration,
143
+ onClick,
144
+ onContextMenu,
145
+ children,
146
+ }: {
147
+ url: string;
148
+ index: number;
149
+ text: string;
150
+ linkStyle: ReturnType<typeof linkStyleForUrl>;
151
+ renderLinkDecoration: NonNullable<
152
+ RendererProps['callbacks']['renderLinkDecoration']
153
+ >;
154
+ onClick: (event: MouseEvent) => void;
155
+ onContextMenu: (event: MouseEvent) => void;
156
+ children: ReactNode;
157
+ }) {
158
+ const anchorRef = useRef<HTMLAnchorElement>(null);
159
+ const [rect, setRect] = useState<LinkRect>(EMPTY_RECT);
160
+
161
+ // The overlay itself is sized by CSS (inset: 0); `rect` is informational, so
162
+ // re-measuring when the content or chip style changes is enough.
163
+ useLayoutEffect(() => {
164
+ const anchor = anchorRef.current;
165
+ if (!anchor) return;
166
+ const { width, height } = anchor.getBoundingClientRect();
167
+ setRect((prev) =>
168
+ prev.width === width && prev.height === height
169
+ ? prev
170
+ : { x: 0, y: 0, width, height }
171
+ );
172
+ }, [text, linkStyle]);
173
+
174
+ const decoration = renderLinkDecoration({
175
+ index,
176
+ url,
177
+ text,
178
+ rect,
179
+ rects: [rect],
180
+ });
181
+
182
+ return (
183
+ <a
184
+ ref={anchorRef}
185
+ href={url}
186
+ style={{ ...linkStyle, position: 'relative' }} // eslint-disable-line react-native/no-inline-styles
187
+ target="_blank"
188
+ rel="noopener noreferrer"
189
+ onClick={onClick}
190
+ onContextMenu={onContextMenu}
191
+ >
192
+ {children}
193
+ {decoration != null && (
194
+ <span aria-hidden style={decorationLayerStyle}>
195
+ {/* Mirrors native pointerEvents="box-none": only the decoration itself is hit-testable. */}
196
+ <span style={decorationContentStyle}>{decoration}</span>
197
+ </span>
198
+ )}
87
199
  </a>
88
200
  );
89
201
  }
@@ -108,6 +220,7 @@ function LatexMathInlineRenderer({
108
220
  export const inlineRenderers: RendererMap = {
109
221
  Text: TextRenderer,
110
222
  LineBreak: LineBreakRenderer,
223
+ SoftBreak: SoftBreakRenderer,
111
224
  Strong: StrongRenderer,
112
225
  Emphasis: EmphasisRenderer,
113
226
  Strikethrough: StrikethroughRenderer,
@@ -44,7 +44,9 @@ function ListItemRenderer({
44
44
  node,
45
45
  style,
46
46
  styles,
47
+ index,
47
48
  callbacks,
49
+ capabilities,
48
50
  renderChildren,
49
51
  }: RendererProps) {
50
52
  const isTask = node.attributes?.isTask === 'true';
@@ -57,6 +59,8 @@ function ListItemRenderer({
57
59
  }, [initialChecked]);
58
60
 
59
61
  const handleChange = () => {
62
+ if (!capabilities.enableTaskListItemToggle) return;
63
+
60
64
  const taskIndex = node.attributes?.taskIndex;
61
65
  if (taskIndex === undefined) return;
62
66
 
@@ -85,14 +89,22 @@ function ListItemRenderer({
85
89
  : null;
86
90
 
87
91
  return (
88
- <li style={listItemStyle(isTask)}>
92
+ <li style={listItemStyle(style, isTask, (index ?? 0) === 0)}>
89
93
  <span style={checkedStyle}>
90
94
  {isTask && (
91
95
  <input
92
96
  type="checkbox"
93
97
  checked={isChecked}
94
98
  onChange={handleChange}
95
- style={styles.taskCheckbox}
99
+ readOnly={!capabilities.enableTaskListItemToggle}
100
+ aria-disabled={
101
+ capabilities.enableTaskListItemToggle ? undefined : true
102
+ }
103
+ style={
104
+ capabilities.enableTaskListItemToggle
105
+ ? styles.taskCheckbox
106
+ : styles.taskCheckboxDisabled
107
+ }
96
108
  aria-label={`Task: ${taskText}`}
97
109
  />
98
110
  )}
@@ -35,6 +35,7 @@ export interface RenderNodeProps {
35
35
  callbacks: RendererCallbacks;
36
36
  capabilities: RenderCapabilities;
37
37
  parentType?: NodeType;
38
+ index?: number;
38
39
  }
39
40
 
40
41
  export function RenderNode({
@@ -44,20 +45,22 @@ export function RenderNode({
44
45
  callbacks,
45
46
  capabilities,
46
47
  parentType,
48
+ index,
47
49
  }: RenderNodeProps): ReactNode {
48
50
  const Renderer = RENDERERS[node.type];
49
51
  if (!Renderer) return null;
50
52
 
51
53
  const renderChildren = (childNode: ASTNode): ReactNode =>
52
- childNode.children?.map((child, index) => (
54
+ childNode.children?.map((child, childIndex) => (
53
55
  <RenderNode
54
- key={nodeKey(child, index)}
56
+ key={nodeKey(child, childIndex)}
55
57
  node={child}
56
58
  style={style}
57
59
  styles={styles}
58
60
  callbacks={callbacks}
59
61
  capabilities={capabilities}
60
62
  parentType={childNode.type}
63
+ index={childIndex}
61
64
  />
62
65
  )) ?? null;
63
66
 
@@ -67,6 +70,7 @@ export function RenderNode({
67
70
  style={style}
68
71
  styles={styles}
69
72
  parentType={parentType}
73
+ index={index}
70
74
  callbacks={callbacks}
71
75
  capabilities={capabilities}
72
76
  renderChildren={renderChildren}
package/src/web/styles.ts CHANGED
@@ -126,7 +126,11 @@ function blockquoteStyle(style: MarkdownStyleInternal): CSSProperties {
126
126
  marginInlineStart: 0, // reset UA default (40px in LTR, auto in RTL)
127
127
  marginInlineEnd: 0,
128
128
  paddingInlineStart: blockquote.gapWidth,
129
+ paddingInlineEnd: blockquote.padding,
130
+ paddingTop: blockquote.padding,
131
+ paddingBottom: blockquote.padding,
129
132
  borderInlineStart: `${blockquote.borderWidth}px solid ${blockquote.borderColor}`,
133
+ borderRadius: blockquote.borderRadius,
130
134
  backgroundColor: blockquote.backgroundColor,
131
135
  };
132
136
  }
@@ -180,16 +184,55 @@ function thematicBreakStyle(style: MarkdownStyleInternal): CSSProperties {
180
184
  };
181
185
  }
182
186
 
187
+ const RESIZE_MODE_TO_OBJECT_FIT: Record<
188
+ Exclude<MarkdownStyleInternal['image']['resizeMode'], ''>,
189
+ NonNullable<CSSProperties['objectFit']>
190
+ > = {
191
+ contain: 'contain',
192
+ cover: 'cover',
193
+ stretch: 'fill',
194
+ center: 'scale-down',
195
+ none: 'none',
196
+ };
197
+
183
198
  function imageStyle(style: MarkdownStyleInternal): CSSProperties {
184
199
  const image = style.image;
185
- return {
186
- height: image.height,
200
+ const base: CSSProperties = {
187
201
  borderRadius: image.borderRadius,
188
202
  marginTop: image.marginTop,
189
203
  marginBottom: image.marginBottom,
190
204
  maxWidth: '100%',
191
205
  display: 'block',
192
206
  };
207
+
208
+ // Sizing precedence: aspectRatio > maxHeight > height. resizeMode '' means
209
+ // legacy sizing — emit today's exact CSS for backward compatibility.
210
+ if (image.resizeMode === '') {
211
+ return { ...base, height: image.height };
212
+ }
213
+
214
+ const objectFit = RESIZE_MODE_TO_OBJECT_FIT[image.resizeMode] ?? 'cover';
215
+
216
+ if (image.aspectRatio > 0) {
217
+ return {
218
+ ...base,
219
+ width: '100%',
220
+ aspectRatio: image.aspectRatio,
221
+ objectFit,
222
+ };
223
+ }
224
+
225
+ if (image.maxHeight > 0) {
226
+ return {
227
+ ...base,
228
+ width: '100%',
229
+ height: 'auto',
230
+ maxHeight: image.maxHeight,
231
+ objectFit,
232
+ };
233
+ }
234
+
235
+ return { ...base, width: '100%', height: image.height, objectFit };
193
236
  }
194
237
 
195
238
  function inlineImageStyle(style: MarkdownStyleInternal): CSSProperties {
@@ -280,6 +323,12 @@ export function linkStyleForUrl(
280
323
  variantIndex !== -1 ? style.linkVariants[variantIndex]! : base;
281
324
 
282
325
  const backgroundColor = resolved.backgroundColor;
326
+ const hasBorder =
327
+ resolved.borderWidth > 0 &&
328
+ !!resolved.borderColor &&
329
+ resolved.borderColor !== 'transparent';
330
+ const hasPadding =
331
+ resolved.paddingHorizontal > 0 || resolved.paddingVertical > 0;
283
332
  return {
284
333
  color: resolved.color,
285
334
  fontFamily: normalizeFontFamily(base.fontFamily),
@@ -287,6 +336,25 @@ export function linkStyleForUrl(
287
336
  ...(backgroundColor && backgroundColor !== 'transparent'
288
337
  ? { backgroundColor }
289
338
  : undefined),
339
+ // Chip: inline padding reserves horizontal space like native; vertical
340
+ // padding only paints (inline boxes don't grow the line box). `clone`
341
+ // rounds and pads each fragment of a wrapping link.
342
+ ...(hasPadding
343
+ ? {
344
+ padding: `${resolved.paddingVertical}px ${resolved.paddingHorizontal}px`,
345
+ }
346
+ : undefined),
347
+ ...(resolved.borderRadius > 0
348
+ ? { borderRadius: resolved.borderRadius }
349
+ : undefined),
350
+ ...(hasBorder
351
+ ? {
352
+ border: `${resolved.borderWidth}px solid ${resolved.borderColor}`,
353
+ }
354
+ : undefined),
355
+ ...(hasPadding || hasBorder || resolved.borderRadius > 0
356
+ ? { boxDecorationBreak: 'clone', WebkitBoxDecorationBreak: 'clone' }
357
+ : undefined),
290
358
  };
291
359
  }
292
360
 
@@ -368,8 +436,17 @@ function tableStyle(style: MarkdownStyleInternal): CSSProperties {
368
436
  };
369
437
  }
370
438
 
371
- export function listItemStyle(isTask: boolean): CSSProperties | undefined {
372
- return isTask ? { listStyle: 'none' } : undefined;
439
+ export function listItemStyle(
440
+ style: MarkdownStyleInternal,
441
+ isTask: boolean,
442
+ isFirstChild: boolean
443
+ ): CSSProperties | undefined {
444
+ const { itemSpacing } = style.list;
445
+ const marginTop = !isFirstChild && itemSpacing > 0 ? itemSpacing : undefined;
446
+ if (isTask) {
447
+ return { listStyle: 'none', marginTop };
448
+ }
449
+ return marginTop !== undefined ? { marginTop } : undefined;
373
450
  }
374
451
 
375
452
  export function checkedTaskTextStyle(
@@ -384,6 +461,21 @@ export function checkedTaskTextStyle(
384
461
  };
385
462
  }
386
463
 
464
+ /**
465
+ * Checkbox style used when `enableTaskListItemToggle` is `false`. Pointer-inert
466
+ * so the browser paints no hover/active state on a checkbox that cannot be
467
+ * toggled; appearance is otherwise identical to the enabled checkbox.
468
+ */
469
+ function taskCheckboxDisabledStyle(
470
+ style: MarkdownStyleInternal
471
+ ): CSSProperties {
472
+ return {
473
+ ...taskCheckboxStyle(style),
474
+ pointerEvents: 'none',
475
+ cursor: 'default',
476
+ };
477
+ }
478
+
387
479
  function taskCheckboxStyle(style: MarkdownStyleInternal): CSSProperties {
388
480
  const taskList = style.taskList;
389
481
  return {
@@ -411,11 +503,20 @@ export function tableBodyRowStyle(
411
503
 
412
504
  function tableWrapperStyle(style: MarkdownStyleInternal): CSSProperties {
413
505
  const table = style.table;
506
+ const alignment: CSSProperties = table.align
507
+ ? {
508
+ width: 'fit-content',
509
+ maxWidth: '100%',
510
+ marginLeft: table.align === 'left' ? 0 : 'auto',
511
+ marginRight: table.align === 'right' ? 0 : 'auto',
512
+ }
513
+ : {};
414
514
  return {
415
515
  overflowX: 'auto',
416
516
  overflowY: 'hidden',
417
517
  marginTop: table.marginTop,
418
518
  marginBottom: table.marginBottom,
519
+ ...alignment,
419
520
  // borderRadius must live on the wrapper, not the <table> — border-collapse:
420
521
  // collapse causes browsers to ignore border-radius on the table element itself.
421
522
  borderRadius: table.borderRadius,
@@ -491,6 +592,7 @@ export interface Styles {
491
592
  tableHeaderCell: Record<ColumnAlign, CSSProperties>;
492
593
  tableCell: Record<ColumnAlign, CSSProperties>;
493
594
  taskCheckbox: CSSProperties;
595
+ taskCheckboxDisabled: CSSProperties;
494
596
  }
495
597
 
496
598
  type ColumnAlign = 'left' | 'center' | 'right' | 'default';
@@ -513,7 +615,13 @@ export function buildStyles(style: MarkdownStyleInternal): Styles {
513
615
  h6: headingStyle(style, '6'),
514
616
  blockquote: blockquoteStyle(style),
515
617
  list: listStyle(style),
516
- listNested: { ...listStyle(style), marginBottom: 0 },
618
+ listNested: {
619
+ ...listStyle(style),
620
+ // A nested list sits directly under its parent item's text; itemSpacing
621
+ // (not the list's outer margins) controls that gap, like on native.
622
+ marginTop: Math.max(0, style.list.itemSpacing),
623
+ marginBottom: 0,
624
+ },
517
625
  listTask: listStyle(style, true),
518
626
  codeBlock,
519
627
  codeBlockFont: { fontFamily: codeBlock.fontFamily },
@@ -546,6 +654,7 @@ export function buildStyles(style: MarkdownStyleInternal): Styles {
546
654
  default: tableCellStyle(style, 'default'),
547
655
  },
548
656
  taskCheckbox: taskCheckboxStyle(style),
657
+ taskCheckboxDisabled: taskCheckboxDisabledStyle(style),
549
658
  };
550
659
 
551
660
  stylesStore.set(style, result);
package/src/web/types.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  LinkLongPressEvent,
7
7
  TaskListItemPressEvent,
8
8
  } from '../types/events';
9
+ import type { LinkDecorationInfo } from '../types/MarkdownTextProps.web';
9
10
  import type { KaTeXInstance } from './katex';
10
11
 
11
12
  export type NodeType =
@@ -15,6 +16,7 @@ export type NodeType =
15
16
  | 'Link'
16
17
  | 'Heading'
17
18
  | 'LineBreak'
19
+ | 'SoftBreak'
18
20
  | 'Strong'
19
21
  | 'Emphasis'
20
22
  | 'Strikethrough'
@@ -51,6 +53,8 @@ export interface NodeAttributes {
51
53
  taskIndex?: number;
52
54
  /** Stamped by markInlineImages() — not present in the raw WASM output. */
53
55
  isInline?: boolean;
56
+ /** Stamped by indexLinks() — document-order link index, not in the raw WASM output. */
57
+ linkIndex?: number;
54
58
  colCount?: string;
55
59
  headRowCount?: string;
56
60
  bodyRowCount?: string;
@@ -63,7 +67,7 @@ export interface ASTNode {
63
67
  content?: string;
64
68
  /** Present on nodes that carry structural metadata (Heading, Link, etc.). */
65
69
  attributes?: NodeAttributes;
66
- /** Child nodes; absent on leaf nodes (Text, LineBreak, ThematicBreak). */
70
+ /** Child nodes; absent on leaf nodes (Text, LineBreak, SoftBreak, ThematicBreak). */
67
71
  children?: ASTNode[];
68
72
  }
69
73
 
@@ -71,10 +75,13 @@ export interface RendererCallbacks {
71
75
  onLinkPress?: (event: LinkPressEvent) => void;
72
76
  onLinkLongPress?: (event: LinkLongPressEvent) => void;
73
77
  onTaskListItemPress?: (event: TaskListItemPressEvent) => void;
78
+ renderLinkDecoration?: (info: LinkDecorationInfo) => ReactNode | null;
74
79
  }
75
80
 
76
81
  export interface RenderCapabilities {
77
82
  katex: KaTeXInstance | null;
83
+ /** When false, task list checkboxes render read-only and ignore clicks. */
84
+ enableTaskListItemToggle: boolean;
78
85
  }
79
86
 
80
87
  export interface RendererProps {
@@ -82,6 +89,8 @@ export interface RendererProps {
82
89
  style: MarkdownStyleInternal;
83
90
  styles: Styles;
84
91
  parentType?: NodeType;
92
+ /** Position among the parent node's children. */
93
+ index?: number;
85
94
  callbacks: RendererCallbacks;
86
95
  capabilities: RenderCapabilities;
87
96
  renderChildren: (node: ASTNode) => ReactNode;
package/src/web/utils.ts CHANGED
@@ -2,6 +2,7 @@ import type { ASTNode } from './types';
2
2
 
3
3
  /** Recursively collects plain text content from an AST node's subtree. */
4
4
  export function extractNodeText(node: ASTNode): string {
5
+ if (node.type === 'SoftBreak' || node.type === 'LineBreak') return ' ';
5
6
  if (node.content !== undefined) return node.content;
6
7
  return node.children?.map(extractNodeText).join('') ?? '';
7
8
  }
@@ -29,6 +30,14 @@ export function indexTaskItems(node: ASTNode, counter = { value: 0 }): void {
29
30
  node.children?.forEach((child) => indexTaskItems(child, counter));
30
31
  }
31
32
 
33
+ /** Stamps Link nodes with their document-order index (the `renderLinkDecoration` key). */
34
+ export function indexLinks(node: ASTNode, counter = { value: 0 }): void {
35
+ if (node.type === 'Link') {
36
+ node.attributes = { ...node.attributes, linkIndex: counter.value++ };
37
+ }
38
+ node.children?.forEach((child) => indexLinks(child, counter));
39
+ }
40
+
32
41
  /**
33
42
  * Stamps Image nodes with `isInline` when they appear inside a paragraph
34
43
  * that also contains other content (text, links, etc.).
Binary file