@fendent/react-native-enriched 0.5.2-fork.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +343 -0
  3. package/ReactNativeEnriched.podspec +31 -0
  4. package/android/build.gradle +106 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +197 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +72 -0
  7. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  8. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  9. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
  10. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
  11. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.cpp +173 -0
  12. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/Props.h +833 -0
  13. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  14. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  15. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.cpp +16 -0
  16. package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/States.h +20 -0
  17. package/android/gradle.properties +5 -0
  18. package/android/lint.gradle +70 -0
  19. package/android/src/main/AndroidManifest.xml +3 -0
  20. package/android/src/main/AndroidManifestNew.xml +2 -0
  21. package/android/src/main/java/com/swmansion/enriched/ReactNativeEnrichedPackage.kt +20 -0
  22. package/android/src/main/java/com/swmansion/enriched/common/AsyncDrawable.kt +126 -0
  23. package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
  24. package/android/src/main/java/com/swmansion/enriched/common/EnrichedConstants.kt +11 -0
  25. package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
  26. package/android/src/main/java/com/swmansion/enriched/common/ForceRedrawSpan.kt +14 -0
  27. package/android/src/main/java/com/swmansion/enriched/common/GumboNormalizer.kt +5 -0
  28. package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
  29. package/android/src/main/java/com/swmansion/enriched/common/ResourceManager.kt +26 -0
  30. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java +956 -0
  31. package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
  32. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBlockQuoteSpan.kt +53 -0
  33. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
  34. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +92 -0
  35. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCodeBlockSpan.kt +81 -0
  36. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
  37. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
  38. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
  39. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
  40. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
  41. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
  42. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedImageSpan.kt +184 -0
  43. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedInlineCodeSpan.kt +24 -0
  44. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
  45. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedLinkSpan.kt +29 -0
  46. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedMentionSpan.kt +35 -0
  47. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedOrderedListSpan.kt +79 -0
  48. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
  49. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
  50. package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnorderedListSpan.kt +62 -0
  51. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedBlockSpan.kt +5 -0
  52. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedHeadingSpan.kt +3 -0
  53. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
  54. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedParagraphSpan.kt +5 -0
  55. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
  56. package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +4 -0
  57. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputConnectionWrapper.kt +140 -0
  58. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
  59. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt +1120 -0
  60. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewLayoutManager.kt +27 -0
  61. package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt +478 -0
  62. package/android/src/main/java/com/swmansion/enriched/textinput/MeasurementStore.kt +225 -0
  63. package/android/src/main/java/com/swmansion/enriched/textinput/events/MentionHandler.kt +55 -0
  64. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeHtmlEvent.kt +27 -0
  65. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeSelectionEvent.kt +30 -0
  66. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeStateEvent.kt +21 -0
  67. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeTextEvent.kt +30 -0
  68. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnContextMenuItemPressEvent.kt +35 -0
  69. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputBlurEvent.kt +25 -0
  70. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputFocusEvent.kt +25 -0
  71. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputKeyPressEvent.kt +27 -0
  72. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnLinkDetectedEvent.kt +32 -0
  73. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionDetectedEvent.kt +30 -0
  74. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnMentionEvent.kt +34 -0
  75. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
  76. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnRequestHtmlResultEvent.kt +32 -0
  77. package/android/src/main/java/com/swmansion/enriched/textinput/events/OnSubmitEditingEvent.kt +29 -0
  78. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
  79. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
  80. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
  81. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
  82. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
  83. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
  84. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
  85. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
  86. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
  87. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
  88. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
  89. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
  90. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
  91. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +16 -0
  92. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
  93. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
  94. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
  95. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
  96. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
  97. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedLineHeightSpan.kt +44 -0
  98. package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedSpans.kt +241 -0
  99. package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
  100. package/android/src/main/java/com/swmansion/enriched/textinput/styles/HtmlStyle.kt +372 -0
  101. package/android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt +164 -0
  102. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +263 -0
  103. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt +434 -0
  104. package/android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt +394 -0
  105. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedEditableFactory.kt +17 -0
  106. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSelection.kt +320 -0
  107. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +310 -0
  108. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt +106 -0
  109. package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannableStringBuilder.kt +24 -0
  110. package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
  111. package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +106 -0
  112. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedSpanWatcher.kt +107 -0
  113. package/android/src/main/java/com/swmansion/enriched/textinput/watchers/EnrichedTextWatcher.kt +74 -0
  114. package/android/src/main/new_arch/CMakeLists.txt +62 -0
  115. package/android/src/main/new_arch/GumboNormalizerJni.cpp +14 -0
  116. package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
  117. package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +15 -0
  118. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputComponentDescriptor.h +35 -0
  119. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.cpp +53 -0
  120. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputMeasurementManager.h +25 -0
  121. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.cpp +35 -0
  122. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputShadowNode.h +53 -0
  123. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.cpp +9 -0
  124. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/EnrichedTextInputState.h +24 -0
  125. package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +27 -0
  126. package/android/src/main/res/drawable/broken_image.xml +10 -0
  127. package/cpp/CMakeLists.txt +50 -0
  128. package/cpp/GumboParser/GumboParser.h +34043 -0
  129. package/cpp/README.md +59 -0
  130. package/cpp/parser/GumboNormalizer.c +915 -0
  131. package/cpp/parser/GumboParser.cpp +16 -0
  132. package/cpp/parser/GumboParser.hpp +23 -0
  133. package/cpp/tests/GumboParserTest.cpp +457 -0
  134. package/ios/EnrichedTextInputView.h +53 -0
  135. package/ios/EnrichedTextInputView.mm +2360 -0
  136. package/ios/EnrichedTextInputViewManager.mm +13 -0
  137. package/ios/attributesManager/AttributesManager.h +17 -0
  138. package/ios/attributesManager/AttributesManager.mm +195 -0
  139. package/ios/config/InputConfig.h +104 -0
  140. package/ios/config/InputConfig.mm +664 -0
  141. package/ios/extensions/ColorExtension.h +7 -0
  142. package/ios/extensions/ColorExtension.mm +38 -0
  143. package/ios/extensions/FontExtension.h +11 -0
  144. package/ios/extensions/FontExtension.mm +72 -0
  145. package/ios/extensions/ImageExtension.h +34 -0
  146. package/ios/extensions/ImageExtension.mm +165 -0
  147. package/ios/extensions/LayoutManagerExtension.h +6 -0
  148. package/ios/extensions/LayoutManagerExtension.mm +443 -0
  149. package/ios/extensions/StringExtension.h +15 -0
  150. package/ios/extensions/StringExtension.mm +69 -0
  151. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.cpp +22 -0
  152. package/ios/generated/ReactNativeEnrichedSpec/ComponentDescriptors.h +24 -0
  153. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +434 -0
  154. package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +391 -0
  155. package/ios/generated/ReactNativeEnrichedSpec/Props.cpp +173 -0
  156. package/ios/generated/ReactNativeEnrichedSpec/Props.h +833 -0
  157. package/ios/generated/ReactNativeEnrichedSpec/RCTComponentViewHelpers.h +582 -0
  158. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.cpp +17 -0
  159. package/ios/generated/ReactNativeEnrichedSpec/ShadowNodes.h +23 -0
  160. package/ios/generated/ReactNativeEnrichedSpec/States.cpp +16 -0
  161. package/ios/generated/ReactNativeEnrichedSpec/States.h +20 -0
  162. package/ios/inputParser/InputParser.h +11 -0
  163. package/ios/inputParser/InputParser.mm +1463 -0
  164. package/ios/inputTextView/InputTextView.h +6 -0
  165. package/ios/inputTextView/InputTextView.mm +285 -0
  166. package/ios/interfaces/AttributeEntry.h +9 -0
  167. package/ios/interfaces/AttributeEntry.mm +4 -0
  168. package/ios/interfaces/BaseStyleProtocol.h +17 -0
  169. package/ios/interfaces/ImageAttachment.h +11 -0
  170. package/ios/interfaces/ImageAttachment.mm +107 -0
  171. package/ios/interfaces/ImageData.h +10 -0
  172. package/ios/interfaces/ImageData.mm +4 -0
  173. package/ios/interfaces/LinkData.h +11 -0
  174. package/ios/interfaces/LinkData.mm +29 -0
  175. package/ios/interfaces/LinkRegexConfig.h +19 -0
  176. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  177. package/ios/interfaces/MediaAttachment.h +23 -0
  178. package/ios/interfaces/MediaAttachment.mm +31 -0
  179. package/ios/interfaces/MentionParams.h +8 -0
  180. package/ios/interfaces/MentionParams.mm +4 -0
  181. package/ios/interfaces/MentionStyleProps.h +13 -0
  182. package/ios/interfaces/MentionStyleProps.mm +63 -0
  183. package/ios/interfaces/StyleBase.h +36 -0
  184. package/ios/interfaces/StyleBase.mm +256 -0
  185. package/ios/interfaces/StyleHeaders.h +102 -0
  186. package/ios/interfaces/StylePair.h +9 -0
  187. package/ios/interfaces/StylePair.mm +4 -0
  188. package/ios/interfaces/StyleTypeEnum.h +26 -0
  189. package/ios/interfaces/TextDecorationLineEnum.h +6 -0
  190. package/ios/interfaces/TextDecorationLineEnum.mm +4 -0
  191. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +19 -0
  192. package/ios/internals/EnrichedTextInputViewShadowNode.h +44 -0
  193. package/ios/internals/EnrichedTextInputViewShadowNode.mm +103 -0
  194. package/ios/internals/EnrichedTextInputViewState.cpp +10 -0
  195. package/ios/internals/EnrichedTextInputViewState.h +22 -0
  196. package/ios/styles/BlockQuoteStyle.mm +55 -0
  197. package/ios/styles/BoldStyle.mm +37 -0
  198. package/ios/styles/CheckboxListStyle.mm +153 -0
  199. package/ios/styles/CodeBlockStyle.mm +49 -0
  200. package/ios/styles/H1Style.mm +20 -0
  201. package/ios/styles/H2Style.mm +20 -0
  202. package/ios/styles/H3Style.mm +20 -0
  203. package/ios/styles/H4Style.mm +20 -0
  204. package/ios/styles/H5Style.mm +20 -0
  205. package/ios/styles/H6Style.mm +20 -0
  206. package/ios/styles/HeadingStyleBase.mm +65 -0
  207. package/ios/styles/ImageStyle.mm +146 -0
  208. package/ios/styles/InlineCodeStyle.mm +65 -0
  209. package/ios/styles/ItalicStyle.mm +37 -0
  210. package/ios/styles/LinkStyle.mm +532 -0
  211. package/ios/styles/MentionStyle.mm +538 -0
  212. package/ios/styles/OrderedListStyle.mm +86 -0
  213. package/ios/styles/StrikethroughStyle.mm +25 -0
  214. package/ios/styles/UnderlineStyle.mm +24 -0
  215. package/ios/styles/UnorderedListStyle.mm +86 -0
  216. package/ios/utils/CheckboxHitTestUtils.h +10 -0
  217. package/ios/utils/CheckboxHitTestUtils.mm +122 -0
  218. package/ios/utils/DotReplacementUtils.h +10 -0
  219. package/ios/utils/DotReplacementUtils.mm +68 -0
  220. package/ios/utils/KeyboardUtils.h +7 -0
  221. package/ios/utils/KeyboardUtils.mm +31 -0
  222. package/ios/utils/OccurenceUtils.h +44 -0
  223. package/ios/utils/OccurenceUtils.mm +179 -0
  224. package/ios/utils/ParagraphAttributesUtils.h +15 -0
  225. package/ios/utils/ParagraphAttributesUtils.mm +257 -0
  226. package/ios/utils/RangeUtils.h +12 -0
  227. package/ios/utils/RangeUtils.mm +183 -0
  228. package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
  229. package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
  230. package/ios/utils/TextInsertionUtils.h +17 -0
  231. package/ios/utils/TextInsertionUtils.mm +64 -0
  232. package/ios/utils/WordsUtils.h +7 -0
  233. package/ios/utils/WordsUtils.mm +98 -0
  234. package/ios/utils/ZeroWidthSpaceUtils.h +9 -0
  235. package/ios/utils/ZeroWidthSpaceUtils.mm +270 -0
  236. package/lib/module/index.js +4 -0
  237. package/lib/module/index.js.map +1 -0
  238. package/lib/module/native/EnrichedTextInput.js +304 -0
  239. package/lib/module/native/EnrichedTextInput.js.map +1 -0
  240. package/lib/module/package.json +1 -0
  241. package/lib/module/spec/EnrichedTextInputNativeComponent.ts +517 -0
  242. package/lib/module/types.js +4 -0
  243. package/lib/module/types.js.map +1 -0
  244. package/lib/module/utils/EnrichedTextInputDefaultProps.js +12 -0
  245. package/lib/module/utils/EnrichedTextInputDefaultProps.js.map +1 -0
  246. package/lib/module/utils/normalizeHtmlStyle.js +155 -0
  247. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  248. package/lib/module/utils/nullthrows.js +9 -0
  249. package/lib/module/utils/nullthrows.js.map +1 -0
  250. package/lib/module/utils/regexParser.js +46 -0
  251. package/lib/module/utils/regexParser.js.map +1 -0
  252. package/lib/typescript/package.json +1 -0
  253. package/lib/typescript/src/index.d.ts +3 -0
  254. package/lib/typescript/src/index.d.ts.map +1 -0
  255. package/lib/typescript/src/native/EnrichedTextInput.d.ts +3 -0
  256. package/lib/typescript/src/native/EnrichedTextInput.d.ts.map +1 -0
  257. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts +397 -0
  258. package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
  259. package/lib/typescript/src/types.d.ts +447 -0
  260. package/lib/typescript/src/types.d.ts.map +1 -0
  261. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts +10 -0
  262. package/lib/typescript/src/utils/EnrichedTextInputDefaultProps.d.ts.map +1 -0
  263. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  264. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  265. package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
  266. package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
  267. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  268. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  269. package/package.json +226 -0
  270. package/react-native.config.js +13 -0
  271. package/src/index.tsx +20 -0
  272. package/src/native/EnrichedTextInput.tsx +370 -0
  273. package/src/spec/EnrichedTextInputNativeComponent.ts +517 -0
  274. package/src/types.ts +499 -0
  275. package/src/utils/EnrichedTextInputDefaultProps.ts +9 -0
  276. package/src/utils/normalizeHtmlStyle.ts +199 -0
  277. package/src/utils/nullthrows.ts +7 -0
  278. package/src/utils/regexParser.ts +56 -0
package/src/types.ts ADDED
@@ -0,0 +1,499 @@
1
+ import type { RefObject } from 'react';
2
+ import type {
3
+ ColorValue,
4
+ DimensionValue,
5
+ NativeMethods,
6
+ NativeSyntheticEvent,
7
+ ReturnKeyTypeOptions,
8
+ TargetedEvent,
9
+ TextStyle,
10
+ ViewProps,
11
+ ViewStyle,
12
+ } from 'react-native';
13
+
14
+ export interface EnrichedInputStyle {
15
+ // Layout / FlexStyle
16
+ alignSelf?: TextStyle['alignSelf'];
17
+ aspectRatio?: number | string;
18
+ borderBottomWidth?: number;
19
+ borderEndWidth?: number;
20
+ borderLeftWidth?: number;
21
+ borderRightWidth?: number;
22
+ borderStartWidth?: number;
23
+ borderTopWidth?: number;
24
+ borderWidth?: number;
25
+ bottom?: DimensionValue;
26
+ boxSizing?: TextStyle['boxSizing'];
27
+ display?: TextStyle['display'];
28
+ end?: DimensionValue;
29
+ flex?: number;
30
+ flexBasis?: DimensionValue;
31
+ flexGrow?: number;
32
+ flexShrink?: number;
33
+ height?: DimensionValue;
34
+ inset?: DimensionValue;
35
+ insetBlock?: DimensionValue;
36
+ insetBlockEnd?: DimensionValue;
37
+ insetBlockStart?: DimensionValue;
38
+ insetInline?: DimensionValue;
39
+ insetInlineEnd?: DimensionValue;
40
+ insetInlineStart?: DimensionValue;
41
+ left?: DimensionValue;
42
+ margin?: DimensionValue;
43
+ marginBlock?: DimensionValue;
44
+ marginBlockEnd?: DimensionValue;
45
+ marginBlockStart?: DimensionValue;
46
+ marginBottom?: DimensionValue;
47
+ marginEnd?: DimensionValue;
48
+ marginHorizontal?: DimensionValue;
49
+ marginInline?: DimensionValue;
50
+ marginInlineEnd?: DimensionValue;
51
+ marginInlineStart?: DimensionValue;
52
+ marginLeft?: DimensionValue;
53
+ marginRight?: DimensionValue;
54
+ marginStart?: DimensionValue;
55
+ marginTop?: DimensionValue;
56
+ marginVertical?: DimensionValue;
57
+ maxHeight?: DimensionValue;
58
+ maxWidth?: DimensionValue;
59
+ minHeight?: DimensionValue;
60
+ minWidth?: DimensionValue;
61
+ padding?: DimensionValue;
62
+ paddingBlock?: DimensionValue;
63
+ paddingBlockEnd?: DimensionValue;
64
+ paddingBlockStart?: DimensionValue;
65
+ paddingBottom?: DimensionValue;
66
+ paddingEnd?: DimensionValue;
67
+ paddingHorizontal?: DimensionValue;
68
+ paddingInline?: DimensionValue;
69
+ paddingInlineEnd?: DimensionValue;
70
+ paddingInlineStart?: DimensionValue;
71
+ paddingLeft?: DimensionValue;
72
+ paddingRight?: DimensionValue;
73
+ paddingStart?: DimensionValue;
74
+ paddingTop?: DimensionValue;
75
+ paddingVertical?: DimensionValue;
76
+ position?: TextStyle['position'];
77
+ right?: DimensionValue;
78
+ start?: DimensionValue;
79
+ top?: DimensionValue;
80
+ width?: DimensionValue;
81
+ zIndex?: number;
82
+
83
+ // Shadows
84
+ /** @platform ios */
85
+ shadowColor?: ColorValue;
86
+ /** @platform ios */
87
+ shadowOffset?: TextStyle['shadowOffset'];
88
+ /** @platform ios */
89
+ shadowOpacity?: TextStyle['shadowOpacity'];
90
+ /** @platform ios */
91
+ shadowRadius?: number;
92
+
93
+ // Transforms
94
+ transform?: TextStyle['transform'];
95
+ transformOrigin?: TextStyle['transformOrigin'];
96
+
97
+ // View appearance
98
+ /** @platform ios web */
99
+ backfaceVisibility?: TextStyle['backfaceVisibility'];
100
+ backgroundColor?: ColorValue;
101
+ /** @platform ios web */
102
+ borderBlockColor?: ColorValue;
103
+ /** @platform ios web */
104
+ borderBlockEndColor?: ColorValue;
105
+ /** @platform ios web */
106
+ borderBlockStartColor?: ColorValue;
107
+ /** @platform ios web */
108
+ borderBottomColor?: ColorValue;
109
+ /** @platform ios web */
110
+ borderBottomEndRadius?: TextStyle['borderBottomEndRadius'];
111
+ /** @platform ios web */
112
+ borderBottomLeftRadius?: TextStyle['borderBottomLeftRadius'];
113
+ /** @platform ios web */
114
+ borderBottomRightRadius?: TextStyle['borderBottomRightRadius'];
115
+ /** @platform ios web */
116
+ borderBottomStartRadius?: TextStyle['borderBottomStartRadius'];
117
+ /** @platform ios web */
118
+ borderColor?: ColorValue;
119
+ /** @platform ios web */
120
+ borderEndColor?: ColorValue;
121
+ /** @platform ios web */
122
+ borderEndEndRadius?: TextStyle['borderEndEndRadius'];
123
+ /** @platform ios web */
124
+ borderEndStartRadius?: TextStyle['borderEndStartRadius'];
125
+ /** @platform ios web */
126
+ borderLeftColor?: ColorValue;
127
+ /** @platform ios web */
128
+ borderRadius?: TextStyle['borderRadius'];
129
+ /** @platform ios web */
130
+ borderRightColor?: ColorValue;
131
+ /** @platform ios web */
132
+ borderStartColor?: ColorValue;
133
+ /** @platform ios web */
134
+ borderStartEndRadius?: TextStyle['borderStartEndRadius'];
135
+ /** @platform ios web */
136
+ borderStartStartRadius?: TextStyle['borderStartStartRadius'];
137
+ /** @platform ios web */
138
+ borderStyle?: TextStyle['borderStyle'];
139
+ /** @platform ios web */
140
+ borderTopColor?: ColorValue;
141
+ /** @platform ios web */
142
+ borderTopEndRadius?: TextStyle['borderTopEndRadius'];
143
+ /** @platform ios web */
144
+ borderTopLeftRadius?: TextStyle['borderTopLeftRadius'];
145
+ /** @platform ios web */
146
+ borderTopRightRadius?: TextStyle['borderTopRightRadius'];
147
+ /** @platform ios web */
148
+ borderTopStartRadius?: TextStyle['borderTopStartRadius'];
149
+ boxShadow?: TextStyle['boxShadow'];
150
+ /** @platform web */
151
+ cursor?: TextStyle['cursor'];
152
+ /** @platform android */
153
+ elevation?: number;
154
+ /** @platform android web */
155
+ filter?: TextStyle['filter'];
156
+ /** @platform android web */
157
+ mixBlendMode?: TextStyle['mixBlendMode'];
158
+ opacity?: TextStyle['opacity'];
159
+ /** @platform ios web */
160
+ outlineColor?: ColorValue;
161
+ outlineOffset?: TextStyle['outlineOffset'];
162
+ /** @platform android web */
163
+ outlineStyle?: TextStyle['outlineStyle'];
164
+ outlineWidth?: TextStyle['outlineWidth'];
165
+ /** @platform ios web */
166
+ pointerEvents?: TextStyle['pointerEvents'];
167
+
168
+ // Typography
169
+ color?: ColorValue;
170
+ fontFamily?: string;
171
+ fontSize?: number;
172
+ fontStyle?: TextStyle['fontStyle'];
173
+ fontWeight?: TextStyle['fontWeight'];
174
+ lineHeight?: number;
175
+ /** @platform web */
176
+ letterSpacing?: number;
177
+ }
178
+
179
+ interface HeadingStyle {
180
+ fontSize?: number;
181
+ bold?: boolean;
182
+ }
183
+
184
+ export interface MentionStyleProperties {
185
+ color?: ColorValue;
186
+ backgroundColor?: ColorValue;
187
+ textDecorationLine?: 'underline' | 'none';
188
+ }
189
+
190
+ export interface HtmlStyle {
191
+ h1?: HeadingStyle;
192
+ h2?: HeadingStyle;
193
+ h3?: HeadingStyle;
194
+ h4?: HeadingStyle;
195
+ h5?: HeadingStyle;
196
+ h6?: HeadingStyle;
197
+ blockquote?: {
198
+ borderColor?: ColorValue;
199
+ borderWidth?: number;
200
+ gapWidth?: number;
201
+ color?: ColorValue;
202
+ };
203
+ codeblock?: {
204
+ color?: ColorValue;
205
+ borderRadius?: number;
206
+ backgroundColor?: ColorValue;
207
+ };
208
+ code?: {
209
+ color?: ColorValue;
210
+ backgroundColor?: ColorValue;
211
+ };
212
+ a?: {
213
+ color?: ColorValue;
214
+ textDecorationLine?: 'underline' | 'none';
215
+ };
216
+ mention?: Record<string, MentionStyleProperties> | MentionStyleProperties;
217
+ ol?: {
218
+ gapWidth?: number;
219
+ marginLeft?: number;
220
+ markerFontWeight?: TextStyle['fontWeight'];
221
+ markerColor?: ColorValue;
222
+ };
223
+ ul?: {
224
+ bulletColor?: ColorValue;
225
+ bulletSize?: number;
226
+ marginLeft?: number;
227
+ gapWidth?: number;
228
+ };
229
+ ulCheckbox?: {
230
+ boxSize?: number;
231
+ gapWidth?: number;
232
+ marginLeft?: number;
233
+ boxColor?: ColorValue;
234
+ };
235
+ }
236
+
237
+ // Event types
238
+
239
+ export interface OnChangeTextEvent {
240
+ value: string;
241
+ }
242
+
243
+ export interface OnChangeHtmlEvent {
244
+ value: string;
245
+ }
246
+
247
+ export interface OnChangeStateEvent {
248
+ bold: {
249
+ isActive: boolean;
250
+ isConflicting: boolean;
251
+ isBlocking: boolean;
252
+ };
253
+ italic: {
254
+ isActive: boolean;
255
+ isConflicting: boolean;
256
+ isBlocking: boolean;
257
+ };
258
+ underline: {
259
+ isActive: boolean;
260
+ isConflicting: boolean;
261
+ isBlocking: boolean;
262
+ };
263
+ strikeThrough: {
264
+ isActive: boolean;
265
+ isConflicting: boolean;
266
+ isBlocking: boolean;
267
+ };
268
+ inlineCode: {
269
+ isActive: boolean;
270
+ isConflicting: boolean;
271
+ isBlocking: boolean;
272
+ };
273
+ h1: {
274
+ isActive: boolean;
275
+ isConflicting: boolean;
276
+ isBlocking: boolean;
277
+ };
278
+ h2: {
279
+ isActive: boolean;
280
+ isConflicting: boolean;
281
+ isBlocking: boolean;
282
+ };
283
+ h3: {
284
+ isActive: boolean;
285
+ isConflicting: boolean;
286
+ isBlocking: boolean;
287
+ };
288
+ h4: {
289
+ isActive: boolean;
290
+ isConflicting: boolean;
291
+ isBlocking: boolean;
292
+ };
293
+ h5: {
294
+ isActive: boolean;
295
+ isConflicting: boolean;
296
+ isBlocking: boolean;
297
+ };
298
+ h6: {
299
+ isActive: boolean;
300
+ isConflicting: boolean;
301
+ isBlocking: boolean;
302
+ };
303
+ codeBlock: {
304
+ isActive: boolean;
305
+ isConflicting: boolean;
306
+ isBlocking: boolean;
307
+ };
308
+ blockQuote: {
309
+ isActive: boolean;
310
+ isConflicting: boolean;
311
+ isBlocking: boolean;
312
+ };
313
+ orderedList: {
314
+ isActive: boolean;
315
+ isConflicting: boolean;
316
+ isBlocking: boolean;
317
+ };
318
+ unorderedList: {
319
+ isActive: boolean;
320
+ isConflicting: boolean;
321
+ isBlocking: boolean;
322
+ };
323
+ link: {
324
+ isActive: boolean;
325
+ isConflicting: boolean;
326
+ isBlocking: boolean;
327
+ };
328
+ image: {
329
+ isActive: boolean;
330
+ isConflicting: boolean;
331
+ isBlocking: boolean;
332
+ };
333
+ mention: {
334
+ isActive: boolean;
335
+ isConflicting: boolean;
336
+ isBlocking: boolean;
337
+ };
338
+ checkboxList: {
339
+ isActive: boolean;
340
+ isConflicting: boolean;
341
+ isBlocking: boolean;
342
+ };
343
+ }
344
+
345
+ export interface OnLinkDetected {
346
+ text: string;
347
+ url: string;
348
+ start: number;
349
+ end: number;
350
+ }
351
+
352
+ export interface OnMentionDetected {
353
+ text: string;
354
+ indicator: string;
355
+ attributes: Record<string, string>;
356
+ }
357
+
358
+ export interface OnChangeSelectionEvent {
359
+ start: number;
360
+ end: number;
361
+ text: string;
362
+ }
363
+
364
+ export interface OnKeyPressEvent {
365
+ key: string;
366
+ }
367
+
368
+ export interface OnPasteImagesEvent {
369
+ images: {
370
+ uri: string;
371
+ type: string;
372
+ width: number;
373
+ height: number;
374
+ }[];
375
+ }
376
+
377
+ export interface OnSubmitEditing {
378
+ text: string;
379
+ }
380
+
381
+ // Component types
382
+
383
+ export type FocusEvent = NativeSyntheticEvent<TargetedEvent>;
384
+ export type BlurEvent = NativeSyntheticEvent<TargetedEvent>;
385
+
386
+ export interface EnrichedTextInputInstance extends NativeMethods {
387
+ // General commands
388
+ focus: () => void;
389
+ blur: () => void;
390
+ setValue: (value: string) => void;
391
+ insertText: (text: string, start?: number, end?: number) => void;
392
+ setSelection: (start: number, end: number) => void;
393
+ getHTML: () => Promise<string>;
394
+
395
+ // Text formatting commands
396
+ toggleBold: () => void;
397
+ toggleItalic: () => void;
398
+ toggleUnderline: () => void;
399
+ toggleStrikeThrough: () => void;
400
+ toggleInlineCode: () => void;
401
+ toggleH1: () => void;
402
+ toggleH2: () => void;
403
+ toggleH3: () => void;
404
+ toggleH4: () => void;
405
+ toggleH5: () => void;
406
+ toggleH6: () => void;
407
+ toggleCodeBlock: () => void;
408
+ toggleBlockQuote: () => void;
409
+ toggleOrderedList: () => void;
410
+ toggleUnorderedList: () => void;
411
+ toggleCheckboxList: (checked: boolean) => void;
412
+ setLink: (start: number, end: number, text: string, url: string) => void;
413
+ removeLink: (start: number, end: number) => void;
414
+ setImage: (src: string, width: number, height: number) => void;
415
+ startMention: (indicator: string) => void;
416
+ setMention: (
417
+ indicator: string,
418
+ text: string,
419
+ attributes?: Record<string, string>
420
+ ) => void;
421
+ }
422
+
423
+ export interface ContextMenuItem {
424
+ text: string;
425
+ onPress: ({
426
+ text,
427
+ selection,
428
+ styleState,
429
+ }: {
430
+ text: string;
431
+ selection: { start: number; end: number };
432
+ styleState: OnChangeStateEvent;
433
+ }) => void;
434
+ visible?: boolean;
435
+ }
436
+
437
+ export interface OnChangeMentionEvent {
438
+ indicator: string;
439
+ text: string;
440
+ }
441
+
442
+ export interface EnrichedTextInputProps extends Omit<ViewProps, 'children'> {
443
+ ref?: RefObject<EnrichedTextInputInstance | null>;
444
+ autoFocus?: boolean;
445
+ editable?: boolean;
446
+ mentionIndicators?: string[];
447
+ defaultValue?: string;
448
+ placeholder?: string;
449
+ placeholderTextColor?: ColorValue;
450
+ cursorColor?: ColorValue;
451
+ selectionColor?: ColorValue;
452
+ autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
453
+ htmlStyle?: HtmlStyle;
454
+ style?: ViewStyle | TextStyle;
455
+ scrollEnabled?: boolean;
456
+ linkRegex?: RegExp | null;
457
+ returnKeyType?: ReturnKeyTypeOptions;
458
+ returnKeyLabel?: string;
459
+ submitBehavior?: 'submit' | 'blurAndSubmit' | 'newline';
460
+ onFocus?: (e: FocusEvent) => void;
461
+ onBlur?: (e: BlurEvent) => void;
462
+ onChangeText?: (e: NativeSyntheticEvent<OnChangeTextEvent>) => void;
463
+ onChangeHtml?: (e: NativeSyntheticEvent<OnChangeHtmlEvent>) => void;
464
+ onChangeState?: (e: NativeSyntheticEvent<OnChangeStateEvent>) => void;
465
+ onLinkDetected?: (e: OnLinkDetected) => void;
466
+ onMentionDetected?: (e: OnMentionDetected) => void;
467
+ onStartMention?: (indicator: string) => void;
468
+ onChangeMention?: (e: OnChangeMentionEvent) => void;
469
+ onEndMention?: (indicator: string) => void;
470
+ onChangeSelection?: (e: NativeSyntheticEvent<OnChangeSelectionEvent>) => void;
471
+ onKeyPress?: (e: NativeSyntheticEvent<OnKeyPressEvent>) => void;
472
+ onSubmitEditing?: (e: NativeSyntheticEvent<OnSubmitEditing>) => void;
473
+ onPasteImages?: (e: NativeSyntheticEvent<OnPasteImagesEvent>) => void;
474
+ contextMenuItems?: ContextMenuItem[];
475
+ /**
476
+ * If true, Android will use experimental synchronous events.
477
+ * This will prevent from input flickering when updating component size.
478
+ * However, this is an experimental feature, which has not been thoroughly tested.
479
+ * We may decide to enable it by default in a future release.
480
+ * Disabled by default.
481
+ */
482
+ androidExperimentalSynchronousEvents?: boolean;
483
+ /**
484
+ * If true, external HTML (e.g. from Google Docs, Word, web pages) will be
485
+ * normalized through the HTML normalizer before being applied.
486
+ * This converts arbitrary HTML into the canonical tag subset that the enriched
487
+ * parser understands.
488
+ * Disabled by default.
489
+ */
490
+ useHtmlNormalizer?: boolean;
491
+ }
492
+
493
+ // Web-only for now. Native will eventually migrate to EnrichedInputStyle too,
494
+ // at which point this interface will be removed and EnrichedTextInputProps
495
+ // will use EnrichedInputStyle directly.
496
+ export interface EnrichedTextInputWebProps
497
+ extends Omit<EnrichedTextInputProps, 'style'> {
498
+ style?: EnrichedInputStyle;
499
+ }
@@ -0,0 +1,9 @@
1
+ export const ENRICHED_TEXT_INPUT_DEFAULT_PROPS = {
2
+ mentionIndicators: ['@'],
3
+ editable: true,
4
+ htmlStyle: {},
5
+ autoCapitalize: 'sentences',
6
+ scrollEnabled: true,
7
+ androidExperimentalSynchronousEvents: false,
8
+ useHtmlNormalizer: false,
9
+ } as const;
@@ -0,0 +1,199 @@
1
+ import { type ColorValue, processColor } from 'react-native';
2
+ import type { HtmlStyleInternal } from '../spec/EnrichedTextInputNativeComponent';
3
+ import type { HtmlStyle, MentionStyleProperties } from '../types';
4
+
5
+ const defaultStyle: Required<HtmlStyle> = {
6
+ h1: {
7
+ fontSize: 32,
8
+ bold: false,
9
+ },
10
+ h2: {
11
+ fontSize: 24,
12
+ bold: false,
13
+ },
14
+ h3: {
15
+ fontSize: 20,
16
+ bold: false,
17
+ },
18
+ h4: {
19
+ fontSize: 16,
20
+ bold: false,
21
+ },
22
+ h5: {
23
+ fontSize: 14,
24
+ bold: false,
25
+ },
26
+ h6: {
27
+ fontSize: 12,
28
+ bold: false,
29
+ },
30
+ blockquote: {
31
+ borderColor: 'darkgray',
32
+ borderWidth: 4,
33
+ gapWidth: 16,
34
+ color: undefined,
35
+ },
36
+ codeblock: {
37
+ color: 'black',
38
+ borderRadius: 8,
39
+ backgroundColor: 'darkgray',
40
+ },
41
+ code: {
42
+ color: 'red',
43
+ backgroundColor: 'darkgray',
44
+ },
45
+ a: {
46
+ color: 'blue',
47
+ textDecorationLine: 'underline',
48
+ },
49
+ mention: {
50
+ color: 'blue',
51
+ backgroundColor: 'yellow',
52
+ textDecorationLine: 'underline',
53
+ },
54
+ ol: {
55
+ gapWidth: 16,
56
+ marginLeft: 16,
57
+ markerFontWeight: undefined,
58
+ markerColor: undefined,
59
+ },
60
+ ul: {
61
+ bulletColor: 'black',
62
+ bulletSize: 8,
63
+ marginLeft: 16,
64
+ gapWidth: 16,
65
+ },
66
+ ulCheckbox: {
67
+ boxSize: 24,
68
+ gapWidth: 16,
69
+ marginLeft: 16,
70
+ boxColor: 'blue',
71
+ },
72
+ };
73
+
74
+ const isMentionStyleRecord = (
75
+ mentionStyle: HtmlStyle['mention']
76
+ ): mentionStyle is Record<string, MentionStyleProperties> => {
77
+ if (
78
+ mentionStyle &&
79
+ typeof mentionStyle === 'object' &&
80
+ !Array.isArray(mentionStyle)
81
+ ) {
82
+ const keys = Object.keys(mentionStyle);
83
+
84
+ return (
85
+ keys.length > 0 &&
86
+ keys.every(
87
+ (key) =>
88
+ typeof (mentionStyle as Record<string, unknown>)[key] === 'object' &&
89
+ (mentionStyle as Record<string, unknown>)[key] !== null
90
+ )
91
+ );
92
+ }
93
+ return false;
94
+ };
95
+
96
+ const convertToHtmlStyleInternal = (
97
+ style: HtmlStyle,
98
+ mentionIndicators: string[]
99
+ ): HtmlStyleInternal => {
100
+ const mentionStyles: Record<string, MentionStyleProperties> = {};
101
+
102
+ mentionIndicators.forEach((indicator) => {
103
+ mentionStyles[indicator] = {
104
+ ...defaultStyle.mention,
105
+ ...(isMentionStyleRecord(style.mention)
106
+ ? (style.mention[indicator] ?? style.mention.default ?? {})
107
+ : style.mention),
108
+ };
109
+ });
110
+
111
+ let markerFontWeight: string | undefined;
112
+ if (style.ol?.markerFontWeight) {
113
+ if (typeof style.ol?.markerFontWeight === 'number') {
114
+ markerFontWeight = String(style.ol?.markerFontWeight);
115
+ } else if (typeof style.ol?.markerFontWeight === 'string') {
116
+ markerFontWeight = style.ol?.markerFontWeight;
117
+ }
118
+ }
119
+
120
+ const olStyles = {
121
+ ...style.ol,
122
+ markerFontWeight: markerFontWeight,
123
+ };
124
+
125
+ return {
126
+ ...style,
127
+ mention: mentionStyles,
128
+ ol: olStyles,
129
+ };
130
+ };
131
+
132
+ const assignDefaultValues = (style: HtmlStyleInternal): HtmlStyleInternal => {
133
+ const merged: Record<string, any> = { ...defaultStyle };
134
+
135
+ for (const key in style) {
136
+ if (key === 'mention') {
137
+ merged[key] = {
138
+ ...(style.mention as object),
139
+ };
140
+
141
+ continue;
142
+ }
143
+
144
+ merged[key] = {
145
+ ...defaultStyle[key as keyof HtmlStyle],
146
+ ...(style[key as keyof HtmlStyle] as object),
147
+ };
148
+ }
149
+
150
+ return merged;
151
+ };
152
+
153
+ const parseStyle = (name: string, value: unknown) => {
154
+ if (name !== 'color' && !name.endsWith('Color')) {
155
+ return value;
156
+ }
157
+
158
+ return processColor(value as ColorValue);
159
+ };
160
+
161
+ const parseColors = (style: HtmlStyleInternal): HtmlStyleInternal => {
162
+ const finalStyle: Record<string, any> = {};
163
+
164
+ for (const [tagName, tagStyle] of Object.entries(style)) {
165
+ const tagStyles: Record<string, any> = {};
166
+
167
+ if (tagName === 'mention') {
168
+ for (const [indicator, mentionStyle] of Object.entries(tagStyle)) {
169
+ tagStyles[indicator] = {};
170
+
171
+ for (const [styleName, styleValue] of Object.entries(
172
+ mentionStyle as MentionStyleProperties
173
+ )) {
174
+ tagStyles[indicator][styleName] = parseStyle(styleName, styleValue);
175
+ }
176
+ }
177
+
178
+ finalStyle[tagName] = tagStyles;
179
+ continue;
180
+ }
181
+
182
+ for (const [styleName, styleValue] of Object.entries(tagStyle)) {
183
+ tagStyles[styleName] = parseStyle(styleName, styleValue);
184
+ }
185
+
186
+ finalStyle[tagName] = tagStyles;
187
+ }
188
+
189
+ return finalStyle;
190
+ };
191
+
192
+ export const normalizeHtmlStyle = (
193
+ style: HtmlStyle,
194
+ mentionIndicators: string[]
195
+ ): HtmlStyleInternal => {
196
+ const converted = convertToHtmlStyleInternal(style, mentionIndicators);
197
+ const withDefaults = assignDefaultValues(converted);
198
+ return parseColors(withDefaults);
199
+ };
@@ -0,0 +1,7 @@
1
+ export const nullthrows = <T>(value: T | null | undefined): T => {
2
+ if (value == null) {
3
+ throw new Error('Unexpected null or undefined value');
4
+ }
5
+
6
+ return value;
7
+ };