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
@@ -2,7 +2,9 @@ package com.swmansion.enriched.markdown.renderer
2
2
 
3
3
  import android.text.SpannableStringBuilder
4
4
  import com.swmansion.enriched.markdown.parser.MarkdownASTNode
5
+ import com.swmansion.enriched.markdown.spans.ListItemSpacingSpan
5
6
  import com.swmansion.enriched.markdown.spans.MarginBottomSpan
7
+ import com.swmansion.enriched.markdown.styles.ListStyle
6
8
  import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
7
9
  import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages
8
10
  import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop
@@ -22,8 +24,15 @@ class ListRenderer(
22
24
  val listStyle = config.style.listStyle
23
25
  val listType = if (isOrdered) BlockStyleContext.ListType.ORDERED else BlockStyleContext.ListType.UNORDERED
24
26
 
27
+ val startNumber =
28
+ if (isOrdered) {
29
+ node.getAttribute("start")?.toIntOrNull()?.coerceAtLeast(0) ?: 1
30
+ } else {
31
+ 1
32
+ }
33
+
25
34
  val contextManager = ListContextManager(factory.blockStyleContext)
26
- val entryState = contextManager.enterList(listType, listStyle)
35
+ val entryState = contextManager.enterList(listType, listStyle, startNumber)
27
36
 
28
37
  // For top-level lists, insert marginTop spacer before rendering content
29
38
  if (entryState.previousDepth == 0) {
@@ -45,7 +54,7 @@ class ListRenderer(
45
54
  }
46
55
 
47
56
  if (builder.length > contentStart) {
48
- applyListSpacing(builder, contentStart, entryState.previousDepth, listStyle)
57
+ applyListSpacing(builder, contentStart, entryState.previousDepth, listStyle, factory.blockStyleContext)
49
58
  }
50
59
  }
51
60
 
@@ -53,15 +62,18 @@ class ListRenderer(
53
62
  builder: SpannableStringBuilder,
54
63
  start: Int,
55
64
  depth: Int,
56
- style: com.swmansion.enriched.markdown.styles.BaseBlockStyle,
65
+ style: ListStyle,
66
+ styleContext: BlockStyleContext,
57
67
  ) {
58
68
  // TODO: LineHeightSpan may also clip superscript/subscript glyphs that extend
59
69
  // outside the normal line bounds. A similar "skip" strategy as for images may
60
70
  // be needed here once super/subscript usage in practice is better understood.
61
71
  applyLineHeightSkippingImages(builder, start, builder.length, style.lineHeight)
62
72
 
63
- // External bottom margin is only handled by the root-level list
73
+ // Item spacing and external bottom margin are only handled by the root-level list
64
74
  if (depth == 0) {
75
+ applyItemSpacing(builder, start, style.itemSpacing, styleContext)
76
+
65
77
  builder.append("\n")
66
78
  builder.setSpan(
67
79
  MarginBottomSpan(style.marginBottom),
@@ -71,4 +83,31 @@ class ListRenderer(
71
83
  )
72
84
  }
73
85
  }
86
+
87
+ // Inserts the vertical gap between consecutive items (including nested ones)
88
+ // by spanning the newline that precedes each item start. The first item of
89
+ // the root list gets no spacing above it.
90
+ private fun applyItemSpacing(
91
+ builder: SpannableStringBuilder,
92
+ start: Int,
93
+ itemSpacing: Float,
94
+ styleContext: BlockStyleContext,
95
+ ) {
96
+ if (itemSpacing <= 0f) return
97
+
98
+ val itemStarts =
99
+ styleContext.listItemStarts
100
+ .filter { it in start until builder.length }
101
+ .distinct()
102
+ .sorted()
103
+
104
+ for (itemStart in itemStarts.drop(1)) {
105
+ builder.setSpan(
106
+ ListItemSpacingSpan(itemSpacing),
107
+ itemStart - 1,
108
+ itemStart,
109
+ SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
110
+ )
111
+ }
112
+ }
74
113
  }
@@ -80,6 +80,7 @@ class RendererFactory(
80
80
 
81
81
  private val textRenderer = TextRenderer()
82
82
  private val lineBreakRenderer = LineBreakRenderer()
83
+ private val softBreakRenderer = SoftBreakRenderer()
83
84
 
84
85
  private val renderers: Map<MarkdownASTNode.NodeType, NodeRenderer> by lazy {
85
86
  buildMap {
@@ -103,13 +104,20 @@ class RendererFactory(
103
104
  put(MarkdownASTNode.NodeType.Code, CodeRenderer(config))
104
105
  put(MarkdownASTNode.NodeType.Image, ImageRenderer())
105
106
  put(MarkdownASTNode.NodeType.LineBreak, lineBreakRenderer)
107
+ put(MarkdownASTNode.NodeType.SoftBreak, softBreakRenderer)
106
108
  put(MarkdownASTNode.NodeType.ThematicBreak, ThematicBreakRenderer(config))
107
109
  put(MarkdownASTNode.NodeType.Spoiler, SpoilerRenderer())
108
110
  if (FeatureFlags.IS_MATH_ENABLED) {
109
111
  try {
110
112
  val mathInlineRendererClass = Class.forName("com.swmansion.enriched.markdown.renderer.MathInlineRenderer")
111
113
  val constructor = mathInlineRendererClass.getConstructor(RendererConfig::class.java, Context::class.java)
112
- put(MarkdownASTNode.NodeType.LatexMathInline, constructor.newInstance(config, context) as NodeRenderer)
114
+ val mathInlineRenderer = constructor.newInstance(config, context) as NodeRenderer
115
+ put(MarkdownASTNode.NodeType.LatexMathInline, mathInlineRenderer)
116
+ // Isolated display math is promoted to a block segment in the parser
117
+ // (see promoteDisplayMathFromParagraphs). What reaches the factory is
118
+ // genuinely mid-line display math (e.g. `a $$x$$ b`); render it inline
119
+ // rather than dropping it via the TextRenderer fallback.
120
+ put(MarkdownASTNode.NodeType.LatexMathDisplay, mathInlineRenderer)
113
121
  } catch (_: Exception) {
114
122
  // math not available
115
123
  }
@@ -0,0 +1,16 @@
1
+ package com.swmansion.enriched.markdown.renderer
2
+
3
+ import android.text.SpannableStringBuilder
4
+ import com.swmansion.enriched.markdown.parser.MarkdownASTNode
5
+
6
+ class SoftBreakRenderer : NodeRenderer {
7
+ override fun render(
8
+ node: MarkdownASTNode,
9
+ builder: SpannableStringBuilder,
10
+ onLinkPress: ((String) -> Unit)?,
11
+ onLinkLongPress: ((String) -> Unit)?,
12
+ factory: RendererFactory,
13
+ ) {
14
+ builder.append(" ")
15
+ }
16
+ }
@@ -1,6 +1,10 @@
1
1
  package com.swmansion.enriched.markdown.renderer
2
2
 
3
+ import android.content.res.AssetManager
3
4
  import android.graphics.Typeface
5
+ import com.facebook.react.common.ReactConstants
6
+ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
7
+ import com.swmansion.enriched.markdown.styles.LinkChipStyle
4
8
  import com.swmansion.enriched.markdown.styles.LinkVariantEntry
5
9
  import com.swmansion.enriched.markdown.styles.StyleConfig
6
10
 
@@ -8,6 +12,8 @@ import com.swmansion.enriched.markdown.styles.StyleConfig
8
12
  class SpanStyleCache(
9
13
  style: StyleConfig,
10
14
  ) {
15
+ private val assetManager: AssetManager = style.assetManager
16
+
11
17
  // Colors to preserve when applying inline styles (links, code, strong, emphasis)
12
18
  val colorsToPreserve: IntArray = buildColorsToPreserve(style)
13
19
 
@@ -21,7 +27,7 @@ class SpanStyleCache(
21
27
  val linkFontFamily: String = style.linkStyle.fontFamily
22
28
  val linkColor: Int = style.linkStyle.color
23
29
  val linkUnderline: Boolean = style.linkStyle.underline
24
- val linkBackgroundColor: Int = style.linkStyle.backgroundColor
30
+ val linkChip: LinkChipStyle = style.linkStyle.chip
25
31
  val linkVariants: List<LinkVariantEntry> = style.linkVariants
26
32
 
27
33
  private val compiledVariantPatterns: List<Pair<Regex, LinkVariantEntry>> =
@@ -95,36 +101,37 @@ class SpanStyleCache(
95
101
  return compiledVariantPatterns.firstOrNull { (regex, _) -> regex.containsMatchIn(url) }?.second
96
102
  }
97
103
 
98
- companion object {
99
- private val typefaceCache = mutableMapOf<String, Typeface>()
100
-
101
- /** Cached typeface for font family + style (BOLD, ITALIC, BOLD_ITALIC) */
102
- fun getTypeface(
103
- fontFamily: String,
104
- style: Int,
105
- ): Typeface =
106
- typefaceCache.getOrPut("$fontFamily|$style") {
107
- val base =
108
- fontFamily
109
- .takeIf { it.isNotEmpty() }
110
- ?.let { Typeface.create(it, Typeface.NORMAL) }
111
- ?: Typeface.DEFAULT
112
- Typeface.create(base, style)
113
- }
104
+ /** Chip style for [url]: the matching variant's own, else the base link's (never merged). */
105
+ fun linkChipForUrl(url: String): LinkChipStyle = resolvedVariantForUrl(url)?.chip ?: linkChip
114
106
 
115
- /** Cached typeface using weight string (e.g., "bold", "700") */
116
- fun getTypefaceWithWeight(
117
- fontFamily: String,
118
- fontWeight: String,
119
- ): Typeface {
120
- val style =
121
- when (fontWeight.lowercase()) {
122
- "bold", "700", "800", "900" -> Typeface.BOLD
123
- else -> Typeface.NORMAL
124
- }
125
- return getTypeface(fontFamily, style)
107
+ /**
108
+ * Cached typeface for font family + style (BOLD, ITALIC, BOLD_ITALIC).
109
+ *
110
+ * Loads the base custom font at its NORMAL weight (via applyStyles/ReactFontManager)
111
+ * so the bundled assets/fonts file resolves, then synthesizes bold/italic on that real
112
+ * typeface. Requesting bold/italic directly makes ReactFontManager look for `_bold`/
113
+ * `_italic` asset variants that single-file custom fonts don't have — and it then falls
114
+ * back to a default system face, dropping the custom font entirely.
115
+ */
116
+ fun getTypeface(
117
+ fontFamily: String,
118
+ style: Int,
119
+ ): Typeface =
120
+ typefaceCache.getOrPut("family|$fontFamily|$style") {
121
+ val base =
122
+ applyStyles(
123
+ null,
124
+ ReactConstants.UNSET,
125
+ ReactConstants.UNSET,
126
+ fontFamily.takeIf { it.isNotEmpty() },
127
+ assetManager,
128
+ )
129
+ if (style == Typeface.NORMAL) base else Typeface.create(base, style)
126
130
  }
127
131
 
132
+ companion object {
133
+ private val typefaceCache = mutableMapOf<String, Typeface>()
134
+
128
135
  /** Cached monospace typeface preserving bold/italic */
129
136
  fun getMonospaceTypeface(currentStyle: Int): Typeface =
130
137
  typefaceCache.getOrPut("monospace|$currentStyle") {
@@ -22,11 +22,20 @@ abstract class BaseListSpan(
22
22
  protected val blockStyle: BlockStyle,
23
23
  protected val marginLeft: Float,
24
24
  protected val gapWidth: Float,
25
+ internal val drawsMarker: Boolean = true,
25
26
  ) : MetricAffectingSpan(),
26
27
  LeadingMarginSpan {
27
28
  private var cachedText: CharSequence? = null
28
29
  private var cachedHasDeeperSpanByPosition = mutableMapOf<Int, Boolean>()
29
30
 
31
+ val markerFontMetrics: Paint.FontMetrics by lazy {
32
+ TextPaint()
33
+ .apply {
34
+ applyBlockStyleFont(blockStyle, context)
35
+ textSize = blockStyle.fontSize
36
+ }.fontMetrics
37
+ }
38
+
30
39
  protected abstract fun getMarkerWidth(): Float
31
40
 
32
41
  override fun updateMeasureState(textPaint: TextPaint) = applyTextStyle(textPaint)
@@ -55,6 +64,7 @@ abstract class BaseListSpan(
55
64
  first: Boolean,
56
65
  layout: Layout?,
57
66
  ) {
67
+ if (!drawsMarker) return
58
68
  if (!first || shouldSkipDrawing(text, start) || !hasContent(text, start, end)) return
59
69
 
60
70
  // Only draw the marker on the true first line of this span.
@@ -62,6 +72,20 @@ abstract class BaseListSpan(
62
72
  // but only the line at the span start should get a bullet/number.
63
73
  if (text is Spanned && text.getSpanStart(this) != start) return
64
74
 
75
+ drawMarkerAt(canvas, paint, x, dir, top, baseline, bottom, layout, start)
76
+ }
77
+
78
+ fun drawMarkerAt(
79
+ canvas: Canvas,
80
+ paint: Paint,
81
+ x: Int,
82
+ dir: Int,
83
+ top: Int,
84
+ baseline: Int,
85
+ bottom: Int,
86
+ layout: Layout?,
87
+ start: Int,
88
+ ) {
65
89
  val originalStyle = paint.style
66
90
  val originalColor = paint.color
67
91
  drawMarker(canvas, paint, x, dir, top, baseline, bottom, layout, start)
@@ -5,6 +5,8 @@ import android.content.Context
5
5
  import android.graphics.Canvas
6
6
  import android.graphics.Color
7
7
  import android.graphics.Paint
8
+ import android.graphics.Path
9
+ import android.graphics.RectF
8
10
  import android.graphics.Typeface
9
11
  import android.text.Layout
10
12
  import android.text.Spanned
@@ -12,6 +14,7 @@ import android.text.TextPaint
12
14
  import android.text.style.LeadingMarginSpan
13
15
  import android.text.style.LineBackgroundSpan
14
16
  import android.text.style.MetricAffectingSpan
17
+ import androidx.core.graphics.withSave
15
18
  import com.swmansion.enriched.markdown.renderer.BlockStyle
16
19
  import com.swmansion.enriched.markdown.renderer.SpanStyleCache
17
20
  import com.swmansion.enriched.markdown.styles.BlockquoteStyle
@@ -37,7 +40,13 @@ class BlockquoteSpan(
37
40
 
38
41
  // Cache for shouldSkipDrawing to avoid repeated getSpans() calls during draw passes
39
42
  private var cachedText: CharSequence? = null
40
- private var cachedMaxDepthByPosition = mutableMapOf<Int, Int>()
43
+ private var cachedSpansByPosition = mutableMapOf<Int, Array<BlockquoteSpan>>()
44
+ private var boxLeft = 0f
45
+ private var boxRight = 0f
46
+
47
+ private val path = Path()
48
+ private val rect = RectF()
49
+ private val radiiArray = FloatArray(8)
41
50
 
42
51
  override fun updateMeasureState(tp: TextPaint) = applyTextStyle(tp)
43
52
 
@@ -63,13 +72,56 @@ class BlockquoteSpan(
63
72
  if (shouldSkipDrawing(text, start)) return
64
73
 
65
74
  val borderPaint = configureBorderPaint()
66
- val borderTop = top.toFloat()
67
- val borderBottom = bottom.toFloat()
75
+ val radius = blockquoteStyle.borderRadius
76
+ val spanned = text as? Spanned
77
+
78
+ if (spanned == null) {
79
+ drawBorders(c, x, dir, top, bottom, borderPaint)
80
+ return
81
+ }
82
+
83
+ val rootSpan = spanAtMinDepth(spanned, start)
84
+ val clipToRoot =
85
+ radius > 0f && boxRight > boxLeft && rootSpan != null && isBoundaryLine(spanned, start, end, rootSpan)
86
+
87
+ val padding = blockquoteStyle.padding
88
+ var topInset = 0f
89
+ var bottomInset = 0f
68
90
 
69
91
  for (level in 0..depth) {
70
92
  val borderX = x + (levelSpacing * level * dir)
71
93
  val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
72
- c.drawRect(minOf(borderX, borderRight), borderTop, maxOf(borderX, borderRight), borderBottom, borderPaint)
94
+ val stripeLeft = minOf(borderX, borderRight)
95
+ val stripeRight = maxOf(borderX, borderRight)
96
+ val stripeTop = top.toFloat() + topInset
97
+ val stripeBottom = bottom.toFloat() - bottomInset
98
+
99
+ val levelSpan = if (level == 0) rootSpan else spanAtDepth(spanned, start, level)
100
+ val clipToOwn =
101
+ radius > 0f && level > 0 && levelSpan != null && isBoundaryLine(spanned, start, end, levelSpan)
102
+
103
+ if (!clipToRoot && !clipToOwn) {
104
+ c.drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
105
+ } else {
106
+ c.withSave {
107
+ if (clipToRoot) {
108
+ buildBoundaryPath(spanned, start, end, rootSpan!!, boxLeft, top.toFloat(), boxRight, bottom.toFloat())
109
+ clipPath(path)
110
+ }
111
+ if (clipToOwn) {
112
+ val clipLeft = if (dir >= 0) stripeLeft else boxLeft
113
+ val clipRight = if (dir >= 0) boxRight else stripeRight
114
+ buildBoundaryPath(spanned, start, end, levelSpan!!, clipLeft, stripeTop, clipRight, stripeBottom)
115
+ clipPath(path)
116
+ }
117
+ drawRect(stripeLeft, stripeTop, stripeRight, stripeBottom, borderPaint)
118
+ }
119
+ }
120
+
121
+ if (padding > 0 && levelSpan != null) {
122
+ if (start == spanned.getSpanStart(levelSpan)) topInset += padding
123
+ if (isLastLineOf(spanned, end, levelSpan)) bottomInset += padding
124
+ }
73
125
  }
74
126
  }
75
127
 
@@ -87,7 +139,40 @@ class BlockquoteSpan(
87
139
  lineNum: Int,
88
140
  ) {
89
141
  if (shouldSkipDrawing(text, start)) return
90
- drawBackground(canvas, left, top, bottom, right)
142
+
143
+ boxLeft = left.toFloat()
144
+ boxRight = right.toFloat()
145
+
146
+ val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
147
+ val backgroundPaint = configureBackgroundPaint(bgColor)
148
+ val radius = blockquoteStyle.borderRadius
149
+ val rootSpan = (text as? Spanned)?.let { spanAtMinDepth(it, start) }
150
+
151
+ if (radius <= 0f || rootSpan == null) {
152
+ canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
153
+ return
154
+ }
155
+
156
+ buildBoundaryPath(text as Spanned, start, end, rootSpan, left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
157
+ canvas.drawPath(path, backgroundPaint)
158
+ }
159
+
160
+ private fun drawBorders(
161
+ c: Canvas,
162
+ x: Int,
163
+ dir: Int,
164
+ top: Int,
165
+ bottom: Int,
166
+ borderPaint: Paint,
167
+ ) {
168
+ val borderTop = top.toFloat()
169
+ val borderBottom = bottom.toFloat()
170
+
171
+ for (level in 0..depth) {
172
+ val borderX = x + (levelSpacing * level * dir)
173
+ val borderRight = borderX + (blockquoteStyle.borderWidth * dir)
174
+ c.drawRect(minOf(borderX, borderRight), borderTop, maxOf(borderX, borderRight), borderBottom, borderPaint)
175
+ }
91
176
  }
92
177
 
93
178
  @SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
@@ -118,35 +203,100 @@ class BlockquoteSpan(
118
203
  color = bgColor
119
204
  }
120
205
 
206
+ private fun spansAt(
207
+ text: Spanned,
208
+ start: Int,
209
+ ): Array<BlockquoteSpan> {
210
+ if (cachedText !== text) {
211
+ cachedText = text
212
+ cachedSpansByPosition.clear()
213
+ }
214
+ return cachedSpansByPosition.getOrPut(start) {
215
+ text.getSpans(start, start + 1, BlockquoteSpan::class.java)
216
+ }
217
+ }
218
+
121
219
  private fun shouldSkipDrawing(
122
220
  text: CharSequence?,
123
221
  start: Int,
124
222
  ): Boolean {
125
223
  if (text !is Spanned) return false
224
+ val maxDepth = spansAt(text, start).maxOfOrNull { it.depth } ?: -1
225
+ return maxDepth > depth
226
+ }
126
227
 
127
- if (cachedText !== text) {
128
- cachedText = text
129
- cachedMaxDepthByPosition.clear()
130
- }
228
+ private fun spanAtMinDepth(
229
+ text: Spanned,
230
+ start: Int,
231
+ ): BlockquoteSpan? = spansAt(text, start).minByOrNull { it.depth }
131
232
 
132
- val maxDepth =
133
- cachedMaxDepthByPosition.getOrPut(start) {
134
- val spans = text.getSpans(start, start + 1, BlockquoteSpan::class.java)
135
- spans.maxOfOrNull { it.depth } ?: -1
136
- }
233
+ private fun spanAtDepth(
234
+ text: Spanned,
235
+ start: Int,
236
+ level: Int,
237
+ ): BlockquoteSpan? = spansAt(text, start).firstOrNull { it.depth == level }
137
238
 
138
- return maxDepth > depth
239
+ /**
240
+ * The span range can include trailing '\n'(s) that form no visible line (e.g. a
241
+ * paragraph break closing the quote), so the last drawn line ends before getSpanEnd;
242
+ * this compares against the end of visible content instead.
243
+ */
244
+ private fun isLastLineOf(
245
+ text: Spanned,
246
+ lineEnd: Int,
247
+ box: BlockquoteSpan,
248
+ ): Boolean {
249
+ var boxEnd = text.getSpanEnd(box)
250
+ while (boxEnd > 0 && text[boxEnd - 1] == '\n') {
251
+ boxEnd--
252
+ }
253
+ return lineEnd >= boxEnd
139
254
  }
140
255
 
141
- private fun drawBackground(
142
- c: Canvas,
143
- left: Int,
144
- top: Int,
145
- bottom: Int,
146
- right: Int,
256
+ private fun isBoundaryLine(
257
+ text: Spanned,
258
+ lineStart: Int,
259
+ lineEnd: Int,
260
+ box: BlockquoteSpan,
261
+ ): Boolean {
262
+ val boxStart = text.getSpanStart(box)
263
+ val boxEnd = text.getSpanEnd(box)
264
+ if (boxStart !in 0 until boxEnd) return false
265
+ return lineStart == boxStart || isLastLineOf(text, lineEnd, box)
266
+ }
267
+
268
+ private fun buildBoundaryPath(
269
+ text: Spanned,
270
+ lineStart: Int,
271
+ lineEnd: Int,
272
+ box: BlockquoteSpan,
273
+ left: Float,
274
+ top: Float,
275
+ right: Float,
276
+ bottom: Float,
147
277
  ) {
148
- val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
149
- val backgroundPaint = configureBackgroundPaint(bgColor)
150
- c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
278
+ val boxStart = text.getSpanStart(box)
279
+
280
+ val isFirstLine = lineStart == boxStart
281
+ val isLastLine = isLastLineOf(text, lineEnd, box)
282
+
283
+ val radius = blockquoteStyle.borderRadius
284
+ radiiArray.fill(0f)
285
+ if (isFirstLine) {
286
+ radiiArray[0] = radius
287
+ radiiArray[1] = radius // Top-Left
288
+ radiiArray[2] = radius
289
+ radiiArray[3] = radius // Top-Right
290
+ }
291
+ if (isLastLine) {
292
+ radiiArray[4] = radius
293
+ radiiArray[5] = radius // Bottom-Right
294
+ radiiArray[6] = radius
295
+ radiiArray[7] = radius // Bottom-Left
296
+ }
297
+
298
+ rect.set(left, top, right, bottom)
299
+ path.reset()
300
+ path.addRoundRect(rect, radiiArray, Path.Direction.CW)
151
301
  }
152
302
  }
@@ -5,8 +5,6 @@ import android.graphics.Paint
5
5
  import android.graphics.Path
6
6
  import android.graphics.RectF
7
7
  import android.text.Spanned
8
- import android.text.StaticLayout
9
- import android.text.TextPaint
10
8
  import android.text.style.LineBackgroundSpan
11
9
  import com.swmansion.enriched.markdown.styles.StyleConfig
12
10
  import kotlin.math.max
@@ -58,8 +56,9 @@ class CodeBackgroundSpan(
58
56
 
59
57
  // 2. Calculate coordinates
60
58
  val finalBottom = adjustBottomForMargin(text, end, bottom)
61
- val startX = if (isFirst) getHorizontalOffset(text, start, end, spanStart, p) + left else left.toFloat()
62
- val endX = if (isLast) getHorizontalOffset(text, start, end, spanEnd, p) + left else right.toFloat()
59
+ val leadingMargin = leadingMarginAt(text, start)
60
+ val startX = if (isFirst) getHorizontalOffset(text, start, end, spanStart, p, leadingMargin) + left else left.toFloat() + leadingMargin
61
+ val endX = if (isLast) getHorizontalOffset(text, start, end, spanEnd, p, leadingMargin) + left else right.toFloat()
63
62
 
64
63
  rect.set(min(startX, endX), top.toFloat(), max(startX, endX), finalBottom.toFloat())
65
64
 
@@ -77,92 +76,31 @@ class CodeBackgroundSpan(
77
76
  lineEnd: Int,
78
77
  index: Int,
79
78
  paint: Paint,
80
- ): Float {
81
- if (index <= lineStart) return 0f
82
- val lineText = text.subSequence(lineStart, lineEnd)
83
- val textPaint = paint as? TextPaint ?: TextPaint(paint)
84
- val layout = StaticLayout.Builder.obtain(lineText, 0, lineText.length, textPaint, 10000).build()
85
- return layout.getPrimaryHorizontal(index - lineStart)
86
- }
79
+ leadingMargin: Int,
80
+ ): Float = InlineChipPainter.horizontalOffset(text, lineStart, lineEnd, index, paint, leadingMargin)
87
81
 
88
82
  private fun drawShapes(
89
83
  canvas: Canvas,
90
84
  isFirst: Boolean,
91
85
  isLast: Boolean,
92
86
  ) {
93
- val radii = createRadii(isFirst, isLast)
94
-
95
- path.reset()
96
- path.addRoundRect(rect, radii, Path.Direction.CW)
97
- canvas.drawPath(path, sharedBackgroundPaint)
98
-
99
- if (isFirst && isLast) {
100
- canvas.drawPath(path, sharedBorderPaint)
101
- } else {
102
- drawOpenBorders(canvas, isFirst, isLast)
103
- }
104
- }
105
-
106
- private fun drawOpenBorders(
107
- canvas: Canvas,
108
- isFirst: Boolean,
109
- isLast: Boolean,
110
- ) {
111
- val r = CORNER_RADIUS
112
- path.reset()
113
-
114
- if (isFirst) {
115
- path.moveTo(rect.right, rect.top)
116
- path.lineTo(rect.left + r, rect.top)
117
- path.quadTo(rect.left, rect.top, rect.left, rect.top + r)
118
- path.lineTo(rect.left, rect.bottom - r)
119
- path.quadTo(rect.left, rect.bottom, rect.left + r, rect.bottom)
120
- path.lineTo(rect.right, rect.bottom)
121
- } else if (isLast) {
122
- path.moveTo(rect.left, rect.top)
123
- path.lineTo(rect.right - r, rect.top)
124
- path.quadTo(rect.right, rect.top, rect.right, rect.top + r)
125
- path.lineTo(rect.right, rect.bottom - r)
126
- path.quadTo(rect.right, rect.bottom, rect.right - r, rect.bottom)
127
- path.lineTo(rect.left, rect.bottom)
128
- } else {
129
- path.moveTo(rect.left, rect.top)
130
- path.lineTo(rect.right, rect.top)
131
- path.moveTo(rect.left, rect.bottom)
132
- path.lineTo(rect.right, rect.bottom)
133
- }
134
- canvas.drawPath(path, sharedBorderPaint)
87
+ InlineChipPainter.draw(
88
+ canvas,
89
+ rect,
90
+ path,
91
+ CORNER_RADIUS,
92
+ sharedBackgroundPaint,
93
+ sharedBorderPaint,
94
+ isFirst,
95
+ isLast,
96
+ strokeInset = false,
97
+ )
135
98
  }
136
99
 
137
- private fun createRadii(
138
- isFirst: Boolean,
139
- isLast: Boolean,
140
- ) = when {
141
- isFirst && isLast -> {
142
- floatArrayOf(
143
- CORNER_RADIUS,
144
- CORNER_RADIUS,
145
- CORNER_RADIUS,
146
- CORNER_RADIUS,
147
- CORNER_RADIUS,
148
- CORNER_RADIUS,
149
- CORNER_RADIUS,
150
- CORNER_RADIUS,
151
- )
152
- }
153
-
154
- isFirst -> {
155
- floatArrayOf(CORNER_RADIUS, CORNER_RADIUS, 0f, 0f, 0f, 0f, CORNER_RADIUS, CORNER_RADIUS)
156
- }
157
-
158
- isLast -> {
159
- floatArrayOf(0f, 0f, CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS, 0f, 0f)
160
- }
161
-
162
- else -> {
163
- floatArrayOf(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
164
- }
165
- }
100
+ private fun leadingMarginAt(
101
+ text: Spanned,
102
+ lineStart: Int,
103
+ ): Int = InlineChipPainter.leadingMarginAt(text, lineStart)
166
104
 
167
105
  private fun adjustBottomForMargin(
168
106
  text: Spanned,