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

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 (469) hide show
  1. package/README.md +54 -8
  2. package/ReactNativeEnrichedMarkdown.podspec +82 -73
  3. package/android/build.gradle +186 -1
  4. package/android/consumer-rules.pro +1 -1
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -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 +9 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
  11. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  12. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  13. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +35 -0
  14. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -23
  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 +189 -13
  18. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
  19. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -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 +42 -0
  23. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
  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/input/EnrichedMarkdownTextInputManager.kt +54 -4
  26. package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +901 -462
  27. package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
  28. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
  29. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
  30. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
  31. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
  34. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
  36. package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
  39. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
  40. package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
  41. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
  43. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
  44. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
  45. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
  46. package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
  47. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
  48. package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
  49. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
  51. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
  52. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
  53. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
  55. package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
  58. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
  59. package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
  60. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
  61. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
  62. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
  63. package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
  64. package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
  65. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
  66. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
  67. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
  68. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
  69. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
  70. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
  71. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
  72. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
  73. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
  74. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
  75. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
  76. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
  77. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
  78. package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
  79. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
  80. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
  81. package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
  82. package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
  83. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
  84. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
  85. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
  86. package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
  87. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
  88. package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
  89. package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
  90. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
  91. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
  92. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
  93. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
  94. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
  95. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
  96. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
  97. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
  98. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
  99. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
  100. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
  101. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
  102. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
  103. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
  104. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
  105. package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
  106. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
  107. package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
  108. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
  109. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
  110. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
  111. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
  112. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
  113. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
  114. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
  115. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
  116. package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
  117. package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
  118. package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -0
  119. package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
  120. package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
  121. package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +36 -9
  122. package/android/src/main/jni/CMakeLists.txt +53 -0
  123. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
  124. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
  125. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
  126. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
  127. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
  128. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
  129. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
  130. package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
  131. package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
  132. package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
  133. package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +6 -4
  134. package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
  135. package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
  136. package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
  137. package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
  138. package/cpp/highlight/HighlightGrammars.hpp +28 -0
  139. package/cpp/highlight/code_highlight_podspec.rb +211 -0
  140. package/cpp/highlight/gen-registry.mjs +155 -0
  141. package/cpp/highlight/grammar-versions.json +159 -0
  142. package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
  143. package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
  144. package/cpp/parser/MD4CParser.cpp +173 -61
  145. package/cpp/parser/MD4CParser.hpp +1 -0
  146. package/cpp/parser/MarkdownASTNode.hpp +2 -1
  147. package/cpp/wasm/ASTSerializer.cpp +2 -0
  148. package/cpp/wasm/build.sh +1 -0
  149. package/cpp/wasm/md4c_wasm.cpp +3 -1
  150. package/docs/ACCESSIBILITY.md +14 -2
  151. package/docs/API_REFERENCE.md +234 -12
  152. package/docs/BREAKING_CHANGES.md +129 -0
  153. package/docs/CODE_HIGHLIGHT.md +133 -0
  154. package/docs/COPY_OPTIONS.md +47 -3
  155. package/docs/ELEMENTS_STRUCTURE.md +52 -4
  156. package/docs/IMAGE_CACHING.md +30 -0
  157. package/docs/INPUT.md +108 -11
  158. package/docs/LATEX_MATH.md +87 -45
  159. package/docs/MACOS.md +1 -1
  160. package/docs/MARKDOWN_STREAMING.md +27 -1
  161. package/docs/NATIVE_ASSETS.md +127 -0
  162. package/docs/RTL.md +1 -1
  163. package/docs/STYLES.md +46 -6
  164. package/docs/TESTING.md +112 -0
  165. package/docs/TEXT.md +16 -6
  166. package/docs/WEB.md +3 -1
  167. package/ios/EnrichedMarkdown.h +7 -0
  168. package/ios/EnrichedMarkdown.mm +284 -75
  169. package/ios/EnrichedMarkdownText.h +7 -0
  170. package/ios/EnrichedMarkdownText.mm +101 -73
  171. package/ios/attachments/ENRMImageAttachment.h +9 -0
  172. package/ios/attachments/ENRMImageAttachment.m +143 -40
  173. package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
  174. package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
  175. package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
  176. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
  177. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
  178. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +35 -0
  179. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -23
  180. package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
  181. package/ios/input/ENRMAutoLinkDetector.h +2 -1
  182. package/ios/input/ENRMAutoLinkDetector.mm +79 -41
  183. package/ios/input/ENRMBlockEditCoordinator.h +71 -0
  184. package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
  185. package/ios/input/ENRMBlockRange.h +28 -0
  186. package/ios/input/ENRMBlockRange.mm +30 -0
  187. package/ios/input/ENRMBlockStore.h +56 -0
  188. package/ios/input/ENRMBlockStore.mm +275 -0
  189. package/ios/input/ENRMClipboardCoordinator.h +45 -0
  190. package/ios/input/ENRMClipboardCoordinator.mm +120 -0
  191. package/ios/input/ENRMDetectorPipeline.h +2 -1
  192. package/ios/input/ENRMEditPipeline.h +76 -0
  193. package/ios/input/ENRMEditPipeline.mm +228 -0
  194. package/ios/input/ENRMEditSession.h +36 -0
  195. package/ios/input/ENRMEditSession.mm +63 -0
  196. package/ios/input/ENRMFormattingStore.h +17 -0
  197. package/ios/input/ENRMFormattingStore.mm +95 -105
  198. package/ios/input/ENRMInputBlockType.h +91 -0
  199. package/ios/input/ENRMInputBlockType.mm +5 -0
  200. package/ios/input/ENRMInputDecorationDrawer.h +18 -0
  201. package/ios/input/ENRMInputEventEmitter.h +56 -0
  202. package/ios/input/ENRMInputEventEmitter.mm +308 -0
  203. package/ios/input/ENRMInputFormatter.h +29 -69
  204. package/ios/input/ENRMInputFormatter.mm +216 -124
  205. package/ios/input/ENRMInputFormatterStyle.h +99 -0
  206. package/ios/input/ENRMInputFormatterStyle.mm +188 -0
  207. package/ios/input/ENRMInputLayoutManager.h +9 -0
  208. package/ios/input/ENRMInputLayoutManager.mm +30 -0
  209. package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
  210. package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
  211. package/ios/input/ENRMInputParser.h +5 -6
  212. package/ios/input/ENRMInputParser.mm +461 -178
  213. package/ios/input/ENRMInputRemend.mm +2 -2
  214. package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
  215. package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
  216. package/ios/input/ENRMInputTextView.mm +103 -8
  217. package/ios/input/ENRMInputTypingAttributesController.h +42 -0
  218. package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
  219. package/ios/input/ENRMLinkCoordinator.h +41 -0
  220. package/ios/input/ENRMLinkCoordinator.mm +89 -0
  221. package/ios/input/ENRMMarkdownSerializer.h +29 -5
  222. package/ios/input/ENRMMarkdownSerializer.mm +170 -48
  223. package/ios/input/ENRMMathAtom.h +26 -0
  224. package/ios/input/ENRMMathAtom.mm +12 -0
  225. package/ios/input/ENRMMentionCoordinator.h +45 -0
  226. package/ios/input/ENRMMentionCoordinator.mm +167 -0
  227. package/ios/input/ENRMRangeEditAdjustment.h +38 -0
  228. package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
  229. package/ios/input/ENRMRangeStoreUtils.h +39 -0
  230. package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
  231. package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
  232. package/ios/input/EnrichedMarkdownTextInput.h +7 -1
  233. package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
  234. package/ios/input/InputStylePropsUtils.h +109 -68
  235. package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
  236. package/ios/input/styles/ENRMBlockHandler.h +46 -0
  237. package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
  238. package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
  239. package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
  240. package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
  241. package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
  242. package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
  243. package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
  244. package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
  245. package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
  246. package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
  247. package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
  248. package/ios/internals/MeasurementCache.h +33 -7
  249. package/ios/internals/ShadowMeasurementUtils.h +63 -58
  250. package/ios/math/ENRMMathChipController.h +74 -0
  251. package/ios/math/ENRMMathChipController.mm +476 -0
  252. package/ios/math/ENRMRaTeXBridge.swift +4 -1
  253. package/ios/parser/ENRMMarkdownParser.h +1 -8
  254. package/ios/parser/ENRMMarkdownParser.mm +2 -11
  255. package/ios/parser/MarkdownASTNode.h +2 -1
  256. package/ios/parser/MarkdownParserBridge.mm +4 -0
  257. package/ios/renderer/AttributedRenderer.m +20 -2
  258. package/ios/renderer/BaseRenderer.h +17 -2
  259. package/ios/renderer/BaseRenderer.m +30 -0
  260. package/ios/renderer/BlockquoteRenderer.h +1 -1
  261. package/ios/renderer/BlockquoteRenderer.m +144 -35
  262. package/ios/renderer/CodeBlockRenderer.h +1 -1
  263. package/ios/renderer/CodeBlockRenderer.m +27 -23
  264. package/ios/renderer/CodeRenderer.h +1 -1
  265. package/ios/renderer/CodeRenderer.m +3 -1
  266. package/ios/renderer/ENRMImageRenderer.h +1 -1
  267. package/ios/renderer/ENRMImageRenderer.m +5 -1
  268. package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
  269. package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
  270. package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
  271. package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
  272. package/ios/renderer/EmphasisRenderer.h +1 -1
  273. package/ios/renderer/EmphasisRenderer.m +3 -1
  274. package/ios/renderer/HeadingRenderer.h +1 -1
  275. package/ios/renderer/HeadingRenderer.m +13 -6
  276. package/ios/renderer/HighlightRenderer.h +1 -1
  277. package/ios/renderer/HighlightRenderer.m +3 -1
  278. package/ios/renderer/LinkRenderer.h +1 -1
  279. package/ios/renderer/LinkRenderer.m +3 -1
  280. package/ios/renderer/ListItemRenderer.h +13 -1
  281. package/ios/renderer/ListItemRenderer.m +102 -44
  282. package/ios/renderer/ListRenderer.h +2 -2
  283. package/ios/renderer/ListRenderer.m +63 -25
  284. package/ios/renderer/ParagraphRenderer.h +1 -1
  285. package/ios/renderer/ParagraphRenderer.m +16 -8
  286. package/ios/renderer/RenderContext.h +10 -0
  287. package/ios/renderer/RenderContext.m +44 -0
  288. package/ios/renderer/RendererFactory.m +14 -0
  289. package/ios/renderer/StrikethroughRenderer.h +1 -1
  290. package/ios/renderer/StrikethroughRenderer.m +3 -1
  291. package/ios/renderer/StrongRenderer.h +1 -1
  292. package/ios/renderer/StrongRenderer.m +3 -1
  293. package/ios/renderer/SubscriptRenderer.h +1 -1
  294. package/ios/renderer/SubscriptRenderer.m +3 -1
  295. package/ios/renderer/SuperscriptRenderer.h +1 -1
  296. package/ios/renderer/SuperscriptRenderer.m +3 -1
  297. package/ios/renderer/TextRenderer.h +2 -2
  298. package/ios/renderer/TextRenderer.m +3 -1
  299. package/ios/renderer/ThematicBreakRenderer.h +1 -1
  300. package/ios/renderer/ThematicBreakRenderer.m +3 -1
  301. package/ios/renderer/UnderlineRenderer.h +1 -1
  302. package/ios/renderer/UnderlineRenderer.m +3 -1
  303. package/ios/styles/StyleConfig.h +22 -0
  304. package/ios/styles/StyleConfig.mm +132 -0
  305. package/ios/utils/BlockquoteBorder.h +6 -0
  306. package/ios/utils/BlockquoteBorder.m +249 -52
  307. package/ios/utils/CodeBlockBackground.m +16 -2
  308. package/ios/utils/ENRMAtomicSize.h +65 -0
  309. package/ios/utils/ENRMBlockMenu.h +57 -0
  310. package/ios/utils/ENRMCodeBlockContent.h +37 -0
  311. package/ios/utils/ENRMCodeBlockContent.mm +79 -0
  312. package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
  313. package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
  314. package/ios/utils/ENRMFeatureFlags.h +7 -0
  315. package/ios/utils/ENRMImageDownloader.h +11 -1
  316. package/ios/utils/ENRMImageDownloader.m +60 -16
  317. package/ios/utils/ENRMLocalImageLoader.h +31 -0
  318. package/ios/utils/ENRMLocalImageLoader.m +68 -0
  319. package/ios/utils/ENRMMathFallback.h +26 -0
  320. package/ios/utils/ENRMMathFallback.m +18 -0
  321. package/ios/utils/ENRMTextViewSetup.h +35 -17
  322. package/ios/utils/EditMenuUtils.h +22 -5
  323. package/ios/utils/EditMenuUtils.m +53 -9
  324. package/ios/utils/ImageRequestHeaderUtils.h +35 -0
  325. package/ios/utils/LastElementUtils.h +1 -0
  326. package/ios/utils/ListMarkerDrawer.m +29 -42
  327. package/ios/utils/MarkdownASTSerializer.m +4 -0
  328. package/ios/utils/ParagraphStyleUtils.h +5 -0
  329. package/ios/utils/ParagraphStyleUtils.m +77 -17
  330. package/ios/utils/RenderedMarkdownSegment.h +13 -1
  331. package/ios/utils/RenderedMarkdownSegment.m +20 -0
  332. package/ios/utils/SegmentRenderer.m +17 -4
  333. package/ios/utils/StreamingMarkdownFilter.h +11 -1
  334. package/ios/utils/StreamingMarkdownFilter.m +98 -2
  335. package/ios/utils/StylePropsUtils.h +63 -0
  336. package/ios/utils/TaskListTapUtils.m +24 -0
  337. package/ios/views/ENRMCodeBlockContainerView.h +53 -0
  338. package/ios/views/ENRMCodeBlockContainerView.m +559 -0
  339. package/ios/views/ENRMMathContainerView.h +16 -0
  340. package/ios/views/ENRMMathContainerView.m +74 -19
  341. package/ios/views/TableContainerView.h +22 -0
  342. package/ios/views/TableContainerView.m +261 -175
  343. package/jest.d.ts +1 -0
  344. package/jest.js +5 -0
  345. package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
  346. package/lib/module/EnrichedMarkdownTextInput.js +84 -5
  347. package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
  348. package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  349. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +74 -0
  350. package/lib/module/headingDefaults.js +34 -0
  351. package/lib/module/headingDefaults.js.map +1 -0
  352. package/lib/module/index.js.map +1 -1
  353. package/lib/module/jest/index.js +191 -0
  354. package/lib/module/jest/index.js.map +1 -0
  355. package/lib/module/native/EnrichedMarkdownText.js +37 -5
  356. package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
  357. package/lib/module/normalizeMarkdownStyle.js +81 -19
  358. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  359. package/lib/module/normalizeMarkdownStyle.web.js +56 -18
  360. package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
  361. package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
  362. package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
  363. package/lib/module/normalizeMenuItem.js +1 -1
  364. package/lib/module/utils/textInputState.js +26 -0
  365. package/lib/module/utils/textInputState.js.map +1 -0
  366. package/lib/module/web/EnrichedMarkdownText.js +9 -5
  367. package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
  368. package/lib/module/web/parseMarkdown.js +4 -3
  369. package/lib/module/web/parseMarkdown.js.map +1 -1
  370. package/lib/module/web/renderers/InlineRenderers.js +6 -0
  371. package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
  372. package/lib/module/web/renderers/ListRenderers.js +7 -2
  373. package/lib/module/web/renderers/ListRenderers.js.map +1 -1
  374. package/lib/module/web/renderers/index.js +7 -4
  375. package/lib/module/web/renderers/index.js.map +1 -1
  376. package/lib/module/web/styles.js +83 -6
  377. package/lib/module/web/styles.js.map +1 -1
  378. package/lib/module/web/utils.js +1 -0
  379. package/lib/module/web/utils.js.map +1 -1
  380. package/lib/module/web/wasm/md4c.js +0 -0
  381. package/lib/module/web/wasm/md4c.js.map +1 -1
  382. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +66 -0
  383. package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
  384. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
  385. package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
  386. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
  387. package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
  388. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +66 -0
  389. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  390. package/lib/typescript/src/headingDefaults.d.ts +9 -0
  391. package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
  392. package/lib/typescript/src/index.d.ts +2 -2
  393. package/lib/typescript/src/index.d.ts.map +1 -1
  394. package/lib/typescript/src/index.web.d.ts +1 -1
  395. package/lib/typescript/src/index.web.d.ts.map +1 -1
  396. package/lib/typescript/src/jest/index.d.ts +6 -0
  397. package/lib/typescript/src/jest/index.d.ts.map +1 -0
  398. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
  399. package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
  400. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  401. package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
  402. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
  403. package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
  404. package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
  405. package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
  406. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
  407. package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
  408. package/lib/typescript/src/types/MarkdownTextProps.d.ts +104 -9
  409. package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
  410. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
  411. package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
  412. package/lib/typescript/src/types/events.d.ts +19 -0
  413. package/lib/typescript/src/types/events.d.ts.map +1 -1
  414. package/lib/typescript/src/utils/textInputState.d.ts +24 -0
  415. package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
  416. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
  417. package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
  418. package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
  419. package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
  420. package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
  421. package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
  422. package/lib/typescript/src/web/renderers/index.d.ts +2 -1
  423. package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
  424. package/lib/typescript/src/web/styles.d.ts +2 -1
  425. package/lib/typescript/src/web/styles.d.ts.map +1 -1
  426. package/lib/typescript/src/web/types.d.ts +6 -2
  427. package/lib/typescript/src/web/types.d.ts.map +1 -1
  428. package/lib/typescript/src/web/utils.d.ts.map +1 -1
  429. package/package.json +36 -9
  430. package/postinstall.mjs +131 -0
  431. package/ratex-version.json +21 -0
  432. package/src/EnrichedMarkdownNativeComponent.ts +73 -0
  433. package/src/EnrichedMarkdownTextInput.tsx +159 -8
  434. package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
  435. package/src/EnrichedMarkdownTextNativeComponent.ts +74 -0
  436. package/src/headingDefaults.ts +21 -0
  437. package/src/index.tsx +9 -0
  438. package/src/index.web.tsx +1 -0
  439. package/src/jest/index.tsx +215 -0
  440. package/src/native/EnrichedMarkdownText.tsx +53 -2
  441. package/src/normalizeMarkdownStyle.ts +102 -16
  442. package/src/normalizeMarkdownStyle.web.ts +63 -15
  443. package/src/normalizeMarkdownTextInputStyle.ts +110 -35
  444. package/src/normalizeMenuItem.ts +1 -1
  445. package/src/types/MarkdownStyle.ts +74 -0
  446. package/src/types/MarkdownStyleInternal.ts +39 -0
  447. package/src/types/MarkdownTextProps.ts +101 -9
  448. package/src/types/MarkdownTextProps.web.ts +19 -0
  449. package/src/types/events.ts +21 -0
  450. package/src/utils/textInputState.ts +35 -0
  451. package/src/web/EnrichedMarkdownText.tsx +16 -2
  452. package/src/web/parseMarkdown.ts +6 -2
  453. package/src/web/renderers/InlineRenderers.tsx +5 -0
  454. package/src/web/renderers/ListRenderers.tsx +14 -2
  455. package/src/web/renderers/index.tsx +6 -2
  456. package/src/web/styles.ts +89 -5
  457. package/src/web/types.ts +6 -1
  458. package/src/web/utils.ts +1 -0
  459. package/src/web/wasm/md4c.js +0 -0
  460. package/vendor-grammars.mjs +511 -0
  461. package/vendor-ratex.mjs +173 -0
  462. package/app.plugin.js +0 -2
  463. package/plugin/build/withAndroidMath.js +0 -19
  464. package/plugin/build/withIosMath.js +0 -28
  465. package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
  466. package/plugin/src/withAndroidMath.ts +0 -24
  467. package/plugin/src/withIosMath.ts +0 -35
  468. package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
  469. package/plugin/tsconfig.build.json +0 -16
@@ -3,6 +3,11 @@
3
3
  #import "LastElementUtils.h"
4
4
  #import "StyleConfig.h"
5
5
 
6
+ // Draws the commonmark-flavor code block box behind the text view's glyph
7
+ // runs. The visual conventions (half-stroke border inset, corner radius
8
+ // handling) must stay in sync with the whole-rect box the github flavor
9
+ // draws in ENRMCodeBlockContainerView's drawRect:.
10
+
6
11
  @implementation CodeBlockBackground {
7
12
  StyleConfig *_config;
8
13
  }
@@ -53,9 +58,18 @@
53
58
  if (CGRectIsEmpty(blockRect))
54
59
  return;
55
60
 
56
- blockRect.origin.x = origin.x;
61
+ NSNumber *indentAttr = [layoutManager.textStorage attribute:CodeBlockIndentAttributeName
62
+ atIndex:range.location
63
+ effectiveRange:NULL];
64
+ CGFloat indent = [indentAttr doubleValue];
65
+
66
+ CGFloat availableWidth = textContainer.size.width - indent;
67
+ if (availableWidth <= 0)
68
+ return;
69
+
70
+ blockRect.origin.x = origin.x + indent;
57
71
  blockRect.origin.y += origin.y;
58
- blockRect.size.width = textContainer.size.width;
72
+ blockRect.size.width = availableWidth;
59
73
 
60
74
  // We extend the background specifically to cover the bottom padding spacer,
61
75
  // excluding any additional marginBottom applied via measurement.
@@ -0,0 +1,65 @@
1
+ #pragma once
2
+
3
+ #include <CoreGraphics/CGGeometry.h>
4
+ #include <atomic>
5
+ #include <cstdint>
6
+ #include <cstring>
7
+
8
+ /**
9
+ * Lock-free size mailbox (issue #550).
10
+ *
11
+ * `measureContent` may run on the JS/layout thread while React Native holds
12
+ * the ShadowTree revision mutex (`preventShadowTreeCommitExhaustion` re-runs
13
+ * the entire commit — layout included — under `revisionMutexRecursive_` after
14
+ * three failed optimistic commits). A main-thread committer (e.g. Reanimated)
15
+ * can already be blocked on that same mutex, so any `dispatch_sync` to main
16
+ * from the measure path can deadlock: JS waits for main, main waits for the
17
+ * mutex JS holds. iOS kills the frozen app ~60s later (watchdog 0x8BADF00D).
18
+ *
19
+ * Reading `view.bounds` from a background thread is not safe either, so the
20
+ * component view *publishes* its last committed size here (from
21
+ * `updateLayoutMetrics:`, always on main) and the measure path *loads* it
22
+ * wait-free from any thread.
23
+ *
24
+ * Both dimensions are packed as IEEE-754 floats into one `uint64_t` so a
25
+ * single lock-free atomic covers the pair — a reader can never observe a new
26
+ * width with an old height (no torn reads). Relaxed memory ordering suffices:
27
+ * the value is self-contained and no other memory is published through it.
28
+ */
29
+ class ENRMAtomicSize {
30
+ public:
31
+ void store(CGSize size)
32
+ {
33
+ bits_.store(pack(size), std::memory_order_relaxed);
34
+ }
35
+
36
+ CGSize load() const
37
+ {
38
+ return unpack(bits_.load(std::memory_order_relaxed));
39
+ }
40
+
41
+ private:
42
+ static uint64_t pack(CGSize size)
43
+ {
44
+ float width = (float)size.width;
45
+ float height = (float)size.height;
46
+ uint32_t widthBits;
47
+ uint32_t heightBits;
48
+ memcpy(&widthBits, &width, sizeof(widthBits));
49
+ memcpy(&heightBits, &height, sizeof(heightBits));
50
+ return ((uint64_t)widthBits << 32) | heightBits;
51
+ }
52
+
53
+ static CGSize unpack(uint64_t bits)
54
+ {
55
+ uint32_t widthBits = (uint32_t)(bits >> 32);
56
+ uint32_t heightBits = (uint32_t)bits;
57
+ float width;
58
+ float height;
59
+ memcpy(&width, &widthBits, sizeof(width));
60
+ memcpy(&height, &heightBits, sizeof(height));
61
+ return CGSizeMake(width, height);
62
+ }
63
+
64
+ std::atomic<uint64_t> bits_{0};
65
+ };
@@ -0,0 +1,57 @@
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+ #include <TargetConditionals.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ /// Selection-menu options that table, math and code block views need for their
8
+ /// own long-press menus. Every field is phrased so that the zero value keeps the
9
+ /// legacy behavior, so a block view that has not received options yet behaves
10
+ /// exactly as before.
11
+ typedef struct {
12
+ // `selectionMenuConfig.copy.enabled == false`.
13
+ BOOL copyHidden;
14
+ // `selectionMenuConfig.copy.format == 'markdown'`: the Copy item writes the
15
+ // block's Markdown instead of its raw content.
16
+ BOOL copyWritesMarkdown;
17
+ // `selectionMenuConfig.copyAsMarkdown.enabled == false`.
18
+ BOOL copyAsMarkdownHidden;
19
+ // `selectionMenuConfig.codeBlockCopyButton.enabled == false`.
20
+ BOOL copyButtonHidden;
21
+ } ENRMBlockMenuOptions;
22
+
23
+ #if !TARGET_OS_OSX
24
+ /// Builds the long-press menu shared by the table, math and code block views.
25
+ /// Returns nil when no item is left — nil is how UIKit suppresses a context
26
+ /// menu, whereas an empty menu would still lift the view.
27
+ static inline UIContextMenuConfiguration *_Nullable ENRMBlockContextMenuConfiguration(
28
+ ENRMBlockMenuOptions options, NSString *_Nullable copyLabel, NSString *_Nullable copyAsMarkdownLabel,
29
+ void (^copyRaw)(void), void (^copyMarkdown)(void))
30
+ {
31
+ if (options.copyHidden && options.copyAsMarkdownHidden) {
32
+ return nil;
33
+ }
34
+ void (^copyHandler)(void) = options.copyWritesMarkdown ? copyMarkdown : copyRaw;
35
+ return [UIContextMenuConfiguration
36
+ configurationWithIdentifier:nil
37
+ previewProvider:nil
38
+ actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) {
39
+ NSMutableArray<UIMenuElement *> *children = [NSMutableArray arrayWithCapacity:2];
40
+ if (!options.copyHidden) {
41
+ [children addObject:[UIAction actionWithTitle:copyLabel ?: @""
42
+ image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
43
+ identifier:nil
44
+ handler:^(__kindof UIAction *action) { copyHandler(); }]];
45
+ }
46
+ if (!options.copyAsMarkdownHidden) {
47
+ [children addObject:[UIAction actionWithTitle:copyAsMarkdownLabel ?: @""
48
+ image:[RCTUIImage systemImageNamed:@"doc.text"]
49
+ identifier:nil
50
+ handler:^(__kindof UIAction *action) { copyMarkdown(); }]];
51
+ }
52
+ return [UIMenu menuWithTitle:@"" children:children];
53
+ }];
54
+ }
55
+ #endif
56
+
57
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,37 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ @class MarkdownASTNode;
6
+ @class StyleConfig;
7
+
8
+ NS_ASSUME_NONNULL_BEGIN
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ /// Shared code block node semantics, used by both markdown flavors so the
15
+ /// meaning of a CodeBlock AST node (its text, language, fence) is defined in
16
+ /// one place. Language display names come from the shared C++ core
17
+ /// (cpp/highlight/CodeBlockLanguages.hpp) so all platforms label fences
18
+ /// identically.
19
+
20
+ NSString *ENRMCodeBlockExtractCode(MarkdownASTNode *node);
21
+ NSString *_Nullable ENRMCodeBlockLanguage(MarkdownASTNode *node);
22
+ NSString *ENRMCodeBlockFenceChar(MarkdownASTNode *node);
23
+ NSString *ENRMCodeBlockFencedMarkdown(NSString *code, NSString *_Nullable language, NSString *fenceChar);
24
+ NSString *ENRMCodeBlockDisplayLanguageName(NSString *_Nullable language);
25
+
26
+ /// Applies the flavor-independent code block text attributes (code font,
27
+ /// color, line height, forced-LTR left-aligned paragraph) to the range.
28
+ /// Callers layer their container-specific paragraph adjustments on top (the
29
+ /// commonmark span flavor adds padding indents; the github block view has
30
+ /// none).
31
+ void ENRMApplyCodeBlockTextAttributes(NSMutableAttributedString *string, NSRange range, StyleConfig *config);
32
+
33
+ #ifdef __cplusplus
34
+ }
35
+ #endif
36
+
37
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,79 @@
1
+ #import "ENRMCodeBlockContent.h"
2
+ #include "CodeBlockLanguages.hpp"
3
+ #import "ENRMUIKit.h"
4
+ #import "MarkdownASTNode.h"
5
+ #import "ParagraphStyleUtils.h"
6
+ #import "StyleConfig.h"
7
+
8
+ static void ENRMAppendNodeContent(MarkdownASTNode *node, NSMutableString *output)
9
+ {
10
+ if (node.content.length > 0) {
11
+ [output appendString:node.content];
12
+ }
13
+ for (MarkdownASTNode *child in node.children) {
14
+ ENRMAppendNodeContent(child, output);
15
+ }
16
+ }
17
+
18
+ NSString *ENRMCodeBlockExtractCode(MarkdownASTNode *node)
19
+ {
20
+ NSMutableString *code = [NSMutableString string];
21
+ ENRMAppendNodeContent(node, code);
22
+ NSUInteger end = code.length;
23
+ while (end > 0 && [code characterAtIndex:end - 1] == '\n') {
24
+ end--;
25
+ }
26
+ return [code substringToIndex:end];
27
+ }
28
+
29
+ NSString *ENRMCodeBlockLanguage(MarkdownASTNode *node)
30
+ {
31
+ NSString *language = node.attributes[@"language"];
32
+ return language.length > 0 ? language : nil;
33
+ }
34
+
35
+ NSString *ENRMCodeBlockFenceChar(MarkdownASTNode *node)
36
+ {
37
+ NSString *fenceChar = node.attributes[@"fenceChar"];
38
+ return fenceChar.length > 0 ? fenceChar : @"`";
39
+ }
40
+
41
+ NSString *ENRMCodeBlockFencedMarkdown(NSString *code, NSString *language, NSString *fenceChar)
42
+ {
43
+ NSString *fence = [@"" stringByPaddingToLength:3 withString:fenceChar startingAtIndex:0];
44
+ return [NSString stringWithFormat:@"%@%@\n%@\n%@", fence, language ?: @"", code, fence];
45
+ }
46
+
47
+ NSString *ENRMCodeBlockDisplayLanguageName(NSString *language)
48
+ {
49
+ if (language.length == 0) {
50
+ return @"";
51
+ }
52
+ std::string display = Markdown::displayNameForLanguage(language.UTF8String ?: "");
53
+ return [NSString stringWithUTF8String:display.c_str()] ?: language;
54
+ }
55
+
56
+ void ENRMApplyCodeBlockTextAttributes(NSMutableAttributedString *string, NSRange range, StyleConfig *config)
57
+ {
58
+ if (range.length == 0) {
59
+ return;
60
+ }
61
+
62
+ UIFont *font = [config codeBlockFont];
63
+ RCTUIColor *color = [config codeBlockColor];
64
+ if (color) {
65
+ [string addAttributes:@{NSFontAttributeName : font, NSForegroundColorAttributeName : color} range:range];
66
+ } else {
67
+ [string addAttribute:NSFontAttributeName value:font range:range];
68
+ }
69
+
70
+ CGFloat lineHeight = [config codeBlockLineHeight];
71
+ if (lineHeight > 0) {
72
+ applyLineHeight(string, range, lineHeight);
73
+ }
74
+
75
+ NSMutableParagraphStyle *paragraphStyle = [getOrCreateParagraphStyle(string, range.location) mutableCopy];
76
+ paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
77
+ paragraphStyle.alignment = NSTextAlignmentLeft;
78
+ [string addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
79
+ }
@@ -0,0 +1,37 @@
1
+ #pragma once
2
+
3
+ #import <Foundation/Foundation.h>
4
+
5
+ @class StyleConfig;
6
+
7
+ NS_ASSUME_NONNULL_BEGIN
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif
12
+
13
+ /// Platform adapter over the shared C++ syntax highlighting seam
14
+ /// (cpp/highlight/CodeBlockHighlighter.hpp).
15
+ ///
16
+ /// Applies token colors as foreground-color attributes onto a mutable copy of
17
+ /// the plain styled code, so highlighting can never change text metrics and
18
+ /// the block height measured from the plain string stays valid. Token colors
19
+ /// come from the config's resolved per-token palette. Returns nil when
20
+ /// highlighting is unavailable (module compiled out, unknown language, parse
21
+ /// failure); callers keep the plain attributed code.
22
+ NSAttributedString *_Nullable ENRMHighlightedAttributedCode(NSAttributedString *plainCode, NSString *code,
23
+ NSString *_Nullable language, StyleConfig *config);
24
+
25
+ /// Applies token foreground colors from the config's palette onto `output`
26
+ /// within `range` (range.location is where the code begins in output). Used by
27
+ /// the commonmark flavor, which renders code inline instead of as a container.
28
+ /// Returns whether any color was applied. No-op when highlighting is
29
+ /// unavailable, so callers keep the plain rendering.
30
+ BOOL ENRMApplyHighlightTokens(NSMutableAttributedString *output, NSRange range, NSString *code,
31
+ NSString *_Nullable language, StyleConfig *config);
32
+
33
+ #ifdef __cplusplus
34
+ }
35
+ #endif
36
+
37
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,51 @@
1
+ #import "ENRMCodeBlockHighlighter.h"
2
+ #include "CodeBlockHighlighter.hpp"
3
+ #import "ENRMUIKit.h"
4
+ #import "StyleConfig.h"
5
+
6
+ BOOL ENRMApplyHighlightTokens(NSMutableAttributedString *output, NSRange range, NSString *code,
7
+ NSString *_Nullable language, StyleConfig *config)
8
+ {
9
+ if (code.length == 0) {
10
+ return NO;
11
+ }
12
+
13
+ std::vector<Markdown::HighlightToken> tokens;
14
+ try {
15
+ tokens = Markdown::highlightCode(code.UTF8String ?: "", language.UTF8String ?: "");
16
+ } catch (...) {
17
+ return NO;
18
+ }
19
+ if (tokens.empty()) {
20
+ return NO;
21
+ }
22
+
23
+ NSUInteger cap = MIN(NSMaxRange(range), output.length);
24
+ BOOL applied = NO;
25
+ for (const auto &token : tokens) {
26
+ RCTUIColor *color = [config codeBlockSyntaxColorForToken:(NSInteger)token.type];
27
+ if (!color || token.end <= token.start) {
28
+ continue;
29
+ }
30
+ NSUInteger start = range.location + token.start;
31
+ NSUInteger end = range.location + token.end;
32
+ if (end > cap) {
33
+ continue;
34
+ }
35
+ [output addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(start, end - start)];
36
+ applied = YES;
37
+ }
38
+ return applied;
39
+ }
40
+
41
+ NSAttributedString *ENRMHighlightedAttributedCode(NSAttributedString *plainCode, NSString *code,
42
+ NSString *_Nullable language, StyleConfig *config)
43
+ {
44
+ if (code.length == 0) {
45
+ return nil;
46
+ }
47
+
48
+ NSMutableAttributedString *highlighted = [plainCode mutableCopy];
49
+ BOOL applied = ENRMApplyHighlightTokens(highlighted, NSMakeRange(0, highlighted.length), code, language, config);
50
+ return applied ? highlighted : nil;
51
+ }
@@ -10,3 +10,10 @@
10
10
  #if !defined(ENRICHED_MARKDOWN_MATH)
11
11
  #define ENRICHED_MARKDOWN_MATH 0
12
12
  #endif
13
+
14
+ // Code-block syntax highlighting is defined purely by the podspec (no external
15
+ // framework to auto-detect, unlike RaTeX). Default off when the podspec did not
16
+ // enable it; the C++ seam then degrades to no tokens.
17
+ #if !defined(ENRICHED_MARKDOWN_CODE_HIGHLIGHT)
18
+ #define ENRICHED_MARKDOWN_CODE_HIGHLIGHT 0
19
+ #endif
@@ -5,11 +5,21 @@ NS_ASSUME_NONNULL_BEGIN
5
5
 
6
6
  typedef void (^ENRMImageDownloadCompletion)(RCTUIImage *_Nullable image);
7
7
 
8
+ /**
9
+ * Cache identity for a remote image request. Returns the URL itself when no
10
+ * headers are set; otherwise appends a SHA-256 digest of the sorted header
11
+ * pairs, so the same URL fetched with different headers is cached and
12
+ * deduplicated separately without embedding header values in the key.
13
+ */
14
+ NSString *ENRMImageCacheKey(NSString *url, NSDictionary<NSString *, NSString *> *_Nullable headers);
15
+
8
16
  @interface ENRMImageDownloader : NSObject
9
17
 
10
18
  + (instancetype)shared;
11
19
 
12
- - (void)downloadURL:(NSString *)url completion:(ENRMImageDownloadCompletion)completion;
20
+ - (void)downloadURL:(NSString *)url
21
+ headers:(nullable NSDictionary<NSString *, NSString *> *)headers
22
+ completion:(ENRMImageDownloadCompletion)completion;
13
23
 
14
24
  @end
15
25
 
@@ -1,5 +1,7 @@
1
1
  #import "ENRMImageDownloader.h"
2
2
  #import "ENRMImageAttachment.h"
3
+ #import "ENRMLocalImageLoader.h"
4
+ #import <CommonCrypto/CommonDigest.h>
3
5
  #include <TargetConditionals.h>
4
6
 
5
7
  static const NSUInteger kDiskCacheMemoryCapacity = 10 * 1024 * 1024;
@@ -13,6 +15,27 @@ static inline NSUInteger ENRMImageByteCost(RCTUIImage *image)
13
15
  return CGImageGetBytesPerRow(cgImage) * CGImageGetHeight(cgImage);
14
16
  }
15
17
 
18
+ NSString *ENRMImageCacheKey(NSString *url, NSDictionary<NSString *, NSString *> *headers)
19
+ {
20
+ if (headers.count == 0) {
21
+ return url;
22
+ }
23
+ NSArray<NSString *> *names = [headers.allKeys sortedArrayUsingSelector:@selector(compare:)];
24
+ NSMutableArray<NSString *> *pairs = [NSMutableArray arrayWithCapacity:names.count];
25
+ for (NSString *name in names) {
26
+ [pairs addObject:[NSString stringWithFormat:@"%@:%@", name, headers[name]]];
27
+ }
28
+ NSString *joined = [pairs componentsJoinedByString:@"\n"];
29
+ NSData *data = [joined dataUsingEncoding:NSUTF8StringEncoding];
30
+ unsigned char digest[CC_SHA256_DIGEST_LENGTH];
31
+ CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
32
+ NSMutableString *hash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
33
+ for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
34
+ [hash appendFormat:@"%02x", digest[i]];
35
+ }
36
+ return [NSString stringWithFormat:@"%@|%@", url, hash];
37
+ }
38
+
16
39
  @implementation ENRMImageDownloader {
17
40
  NSURLSession *_session;
18
41
  NSMutableDictionary<NSString *, NSMutableArray<ENRMImageDownloadCompletion> *> *_inFlightRequests;
@@ -43,56 +66,77 @@ static inline NSUInteger ENRMImageByteCost(RCTUIImage *image)
43
66
  return self;
44
67
  }
45
68
 
46
- - (void)downloadURL:(NSString *)url completion:(ENRMImageDownloadCompletion)completion
69
+ - (void)downloadURL:(NSString *)url
70
+ headers:(NSDictionary<NSString *, NSString *> *)headers
71
+ completion:(ENRMImageDownloadCompletion)completion
47
72
  {
48
73
  if (url.length == 0) {
49
74
  completion(nil);
50
75
  return;
51
76
  }
52
77
 
53
- RCTUIImage *cached = [[ENRMImageAttachment originalImageCache] objectForKey:url];
78
+ BOOL isLocal = ENRMIsLocalImageURL(url);
79
+ NSString *cacheKey = isLocal ? url : ENRMImageCacheKey(url, headers);
80
+
81
+ RCTUIImage *cached = [[ENRMImageAttachment originalImageCache] objectForKey:cacheKey];
54
82
  if (cached) {
55
83
  completion(cached);
56
84
  return;
57
85
  }
58
86
 
87
+ if (isLocal) {
88
+ RCTUIImage *local = ENRMLoadLocalImage(url);
89
+ if (local) {
90
+ [[ENRMImageAttachment originalImageCache] setObject:local forKey:cacheKey cost:ENRMImageByteCost(local)];
91
+ }
92
+ completion(local);
93
+ return;
94
+ }
95
+
59
96
  @synchronized(_inFlightRequests) {
60
- NSMutableArray *existing = _inFlightRequests[url];
97
+ NSMutableArray *existing = _inFlightRequests[cacheKey];
61
98
  if (existing) {
62
99
  [existing addObject:completion];
63
100
  return;
64
101
  }
65
- _inFlightRequests[url] = [NSMutableArray arrayWithObject:completion];
102
+ _inFlightRequests[cacheKey] = [NSMutableArray arrayWithObject:completion];
66
103
  }
67
104
 
68
105
  NSURL *nsURL = [NSURL URLWithString:url];
69
106
  if (!nsURL) {
70
- [self dispatchCallbacksForURL:url image:nil];
107
+ [self dispatchCallbacksForKey:cacheKey image:nil];
71
108
  return;
72
109
  }
73
110
 
74
- [[_session dataTaskWithURL:nsURL
75
- completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
111
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsURL];
112
+ [headers enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *stop) {
113
+ [request setValue:value forHTTPHeaderField:name];
114
+ }];
115
+
116
+ [[_session dataTaskWithRequest:request
117
+ completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
76
118
  #if !TARGET_OS_OSX
77
- RCTUIImage *image = (data && !error) ? [RCTUIImage imageWithData:data] : nil;
119
+ RCTUIImage *image = (data && !error) ? [RCTUIImage imageWithData:data] : nil;
78
120
  #else
79
121
  RCTUIImage *image = (data && !error) ? [[RCTUIImage alloc] initWithData:data] : nil;
80
122
  #endif
81
123
 
82
- if (image) {
83
- [[ENRMImageAttachment originalImageCache] setObject:image forKey:url cost:ENRMImageByteCost(image)];
84
- }
124
+ if (image) {
125
+ [[ENRMImageAttachment originalImageCache] setObject:image
126
+ forKey:cacheKey
127
+ cost:ENRMImageByteCost(image)];
128
+ }
85
129
 
86
- [self dispatchCallbacksForURL:url image:image];
87
- }] resume];
130
+ [self dispatchCallbacksForKey:cacheKey image:image];
131
+ }] resume];
88
132
  }
89
133
 
90
- - (void)dispatchCallbacksForURL:(NSString *)url image:(RCTUIImage *_Nullable)image
134
+ - (void)dispatchCallbacksForKey:(NSString *)cacheKey image:(RCTUIImage *_Nullable)image
91
135
  {
92
136
  NSArray<ENRMImageDownloadCompletion> *callbacks;
93
137
  @synchronized(_inFlightRequests) {
94
- callbacks = [_inFlightRequests[url] copy];
95
- [_inFlightRequests removeObjectForKey:url];
138
+ callbacks = [_inFlightRequests[cacheKey] copy];
139
+ [_inFlightRequests removeObjectForKey:cacheKey];
96
140
  }
97
141
 
98
142
  if (!callbacks)
@@ -0,0 +1,31 @@
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ /**
7
+ * Local (non-network) image loading for markdown sources (issue #377).
8
+ *
9
+ * React Native's asset system resolves `require('./img.png')` to a Metro http
10
+ * URL in dev, but to a `file://` URL near the app bundle in release builds
11
+ * (`AssetSourceResolver.scaledAssetURLNearBundle`), and libraries like
12
+ * expo-asset also hand out percent-encoded `file://` paths in the caches
13
+ * directory. These should not go through NSURLSession + NSURLCache: they gain
14
+ * nothing from HTTP caching or timeouts, and bundle assets lose `@2x`/`@3x`
15
+ * scale selection and asset-catalog resolution.
16
+ *
17
+ * Resolution mirrors RN's RCTImageFromLocalAssetURL: bundle-relative names are
18
+ * tried with `imageNamed:` first (scale suffixes, asset catalogs, and system
19
+ * caching for free), then the loader falls back to loading the file directly,
20
+ * appending `.png` when the path has no extension.
21
+ */
22
+
23
+ /// YES when the URL refers to a non-network source: any `file://` URL, or a
24
+ /// scheme-less string (bare bundle-relative asset name or absolute path).
25
+ BOOL ENRMIsLocalImageURL(NSString *url);
26
+
27
+ /// Synchronously loads a local image; returns nil when the source cannot be
28
+ /// resolved. Safe to call off the main thread.
29
+ RCTUIImage *_Nullable ENRMLoadLocalImage(NSString *url);
30
+
31
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,68 @@
1
+ #import "ENRMLocalImageLoader.h"
2
+
3
+ static NSString *_Nullable ENRMBundleRelativePath(NSString *path)
4
+ {
5
+ NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
6
+ if (bundlePath == nil || ![path hasPrefix:bundlePath]) {
7
+ return nil;
8
+ }
9
+ NSString *relative = [path substringFromIndex:bundlePath.length];
10
+ return [relative hasPrefix:@"/"] ? [relative substringFromIndex:1] : relative;
11
+ }
12
+
13
+ static RCTUIImage *_Nullable ENRMImageNamed(NSString *name)
14
+ {
15
+ return [RCTUIImage imageNamed:name];
16
+ }
17
+
18
+ static RCTUIImage *_Nullable ENRMImageAtPath(NSString *path)
19
+ {
20
+ if (path.pathExtension.length == 0) {
21
+ path = [path stringByAppendingPathExtension:@"png"];
22
+ }
23
+ #if !TARGET_OS_OSX
24
+ return [RCTUIImage imageWithContentsOfFile:path];
25
+ #else
26
+ return [[RCTUIImage alloc] initWithContentsOfFile:path];
27
+ #endif
28
+ }
29
+
30
+ BOOL ENRMIsLocalImageURL(NSString *url)
31
+ {
32
+ if ([url hasPrefix:@"file://"]) {
33
+ return YES;
34
+ }
35
+ NSURL *parsed = [NSURL URLWithString:url];
36
+ return parsed == nil || parsed.scheme.length == 0;
37
+ }
38
+
39
+ RCTUIImage *_Nullable ENRMLoadLocalImage(NSString *url)
40
+ {
41
+ NSString *filePath = nil;
42
+ NSString *imageName = nil;
43
+
44
+ if ([url hasPrefix:@"file://"]) {
45
+ NSURL *fileURL = [NSURL URLWithString:url];
46
+ if (fileURL.fileURL) {
47
+ filePath = @(fileURL.fileSystemRepresentation);
48
+ } else {
49
+ NSString *stripped = [url substringFromIndex:@"file://".length];
50
+ filePath = [stripped stringByRemovingPercentEncoding] ?: stripped;
51
+ }
52
+ imageName = ENRMBundleRelativePath(filePath);
53
+ } else {
54
+ NSString *decoded = [url stringByRemovingPercentEncoding] ?: url;
55
+ if (decoded.absolutePath) {
56
+ filePath = decoded;
57
+ } else {
58
+ imageName = decoded;
59
+ filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:decoded];
60
+ }
61
+ }
62
+
63
+ RCTUIImage *image = imageName.length > 0 ? ENRMImageNamed(imageName) : nil;
64
+ if (image == nil && filePath.length > 0) {
65
+ image = ENRMImageAtPath(filePath);
66
+ }
67
+ return image;
68
+ }
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+ #import "ENRMUIKit.h"
3
+ #import <Foundation/Foundation.h>
4
+
5
+ static const CGFloat kENRMMathFallbackDefaultFontSize = 16.0;
6
+
7
+ NS_ASSUME_NONNULL_BEGIN
8
+
9
+ #ifdef __cplusplus
10
+ extern "C" {
11
+ #endif
12
+
13
+ /**
14
+ * Builds the visible-source fallback for a RaTeX parse failure: the original
15
+ * LaTeX source wrapped in its delimiters ($ inline, $$ block), typeset in body
16
+ * style. A parse failure must never render as an invisible zero-size box —
17
+ * the formula stays visible and copyable instead.
18
+ */
19
+ NSAttributedString *ENRMMathFallbackString(NSString *_Nullable latex, NSString *delimiter, CGFloat fontSize,
20
+ RCTUIColor *_Nullable color);
21
+
22
+ #ifdef __cplusplus
23
+ }
24
+ #endif
25
+
26
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,18 @@
1
+ #import "ENRMMathFallback.h"
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ NSAttributedString *ENRMMathFallbackString(NSString *_Nullable latex, NSString *delimiter, CGFloat fontSize,
6
+ RCTUIColor *_Nullable color)
7
+ {
8
+ CGFloat size = fontSize > 0 ? fontSize : kENRMMathFallbackDefaultFontSize;
9
+ UIFont *font = [UIFont systemFontOfSize:size];
10
+ NSString *source = [NSString stringWithFormat:@"%@%@%@", delimiter, latex ?: @"", delimiter];
11
+ return [[NSAttributedString alloc] initWithString:source
12
+ attributes:@{
13
+ NSFontAttributeName : font,
14
+ NSForegroundColorAttributeName : color ?: [RCTUIColor blackColor],
15
+ }];
16
+ }
17
+
18
+ NS_ASSUME_NONNULL_END