react-native-enriched 0.2.1 → 0.3.0

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 (156) hide show
  1. package/README.md +15 -12
  2. package/android/build.gradle +77 -72
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +18 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +6 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +146 -0
  6. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +140 -0
  7. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  8. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +194 -0
  9. package/android/lint.gradle +70 -0
  10. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputConnectionWrapper.kt +140 -0
  11. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +245 -116
  12. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
  13. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +162 -53
  14. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +1 -3
  15. package/android/src/main/java/com/swmansion/enriched/MeasurementStore.kt +70 -21
  16. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +20 -10
  17. package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +8 -9
  18. package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +10 -9
  19. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +21 -0
  20. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +9 -12
  21. package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +10 -10
  22. package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +7 -9
  23. package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +7 -9
  24. package/android/src/main/java/com/swmansion/enriched/events/OnInputKeyPressEvent.kt +27 -0
  25. package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +13 -11
  26. package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +10 -9
  27. package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +9 -8
  28. package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +1 -2
  29. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +21 -8
  30. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +5 -4
  31. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +7 -5
  32. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +5 -4
  33. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +5 -4
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +5 -4
  35. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +24 -0
  36. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +24 -0
  37. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +24 -0
  38. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +29 -17
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +5 -4
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +5 -4
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +7 -7
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +11 -14
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +15 -14
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +167 -71
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +5 -4
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +5 -4
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +8 -8
  48. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +3 -2
  49. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +1 -2
  50. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +1 -2
  51. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +3 -2
  52. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +1 -0
  53. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -2
  54. package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +2 -1
  55. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +78 -21
  56. package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +25 -8
  57. package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +60 -20
  58. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +86 -26
  59. package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +128 -52
  60. package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +10 -7
  61. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedConstants.kt +11 -0
  62. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedEditableFactory.kt +17 -0
  63. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +128 -87
  64. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +71 -42
  65. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +183 -48
  66. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannable.kt +82 -0
  67. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannableStringBuilder.kt +15 -0
  68. package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -70
  69. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +46 -14
  70. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +34 -11
  71. package/android/src/main/new_arch/CMakeLists.txt +6 -0
  72. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +21 -1
  73. package/ios/EnrichedTextInputView.h +1 -1
  74. package/ios/EnrichedTextInputView.mm +381 -49
  75. package/ios/config/InputConfig.h +18 -0
  76. package/ios/config/InputConfig.mm +118 -8
  77. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +146 -0
  78. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +140 -0
  79. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  80. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
  81. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +74 -0
  82. package/ios/inputParser/InputParser.mm +83 -10
  83. package/ios/{attachments → interfaces}/ImageAttachment.mm +3 -1
  84. package/ios/interfaces/LinkRegexConfig.h +19 -0
  85. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  86. package/ios/{utils → interfaces}/MentionStyleProps.mm +2 -2
  87. package/ios/{utils → interfaces}/StyleHeaders.h +10 -0
  88. package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
  89. package/ios/styles/BlockQuoteStyle.mm +5 -5
  90. package/ios/styles/BoldStyle.mm +21 -6
  91. package/ios/styles/CodeBlockStyle.mm +5 -5
  92. package/ios/styles/H4Style.mm +17 -0
  93. package/ios/styles/H5Style.mm +17 -0
  94. package/ios/styles/H6Style.mm +17 -0
  95. package/ios/styles/HeadingStyleBase.mm +27 -10
  96. package/ios/styles/ImageStyle.mm +5 -5
  97. package/ios/styles/InlineCodeStyle.mm +30 -19
  98. package/ios/styles/ItalicStyle.mm +5 -5
  99. package/ios/styles/LinkStyle.mm +98 -40
  100. package/ios/styles/MentionStyle.mm +4 -4
  101. package/ios/styles/OrderedListStyle.mm +5 -5
  102. package/ios/styles/StrikethroughStyle.mm +5 -5
  103. package/ios/styles/UnderlineStyle.mm +5 -5
  104. package/ios/styles/UnorderedListStyle.mm +5 -5
  105. package/ios/utils/ParagraphAttributesUtils.h +4 -0
  106. package/ios/utils/ParagraphAttributesUtils.mm +67 -0
  107. package/ios/utils/ParagraphsUtils.mm +4 -4
  108. package/lib/module/EnrichedTextInput.js +22 -1
  109. package/lib/module/EnrichedTextInput.js.map +1 -1
  110. package/lib/module/EnrichedTextInputNativeComponent.ts +138 -12
  111. package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
  112. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  113. package/lib/module/utils/regexParser.js +46 -0
  114. package/lib/module/utils/regexParser.js.map +1 -0
  115. package/lib/typescript/src/EnrichedTextInput.d.ts +23 -14
  116. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  117. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +123 -12
  118. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  119. package/lib/typescript/src/index.d.ts +1 -1
  120. package/lib/typescript/src/index.d.ts.map +1 -1
  121. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  122. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  123. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  124. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  125. package/package.json +10 -6
  126. package/src/EnrichedTextInput.tsx +51 -13
  127. package/src/EnrichedTextInputNativeComponent.ts +138 -12
  128. package/src/index.tsx +2 -0
  129. package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
  130. package/src/utils/regexParser.ts +56 -0
  131. package/lib/module/normalizeHtmlStyle.js.map +0 -1
  132. package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
  133. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
  134. /package/ios/{utils → extensions}/ColorExtension.h +0 -0
  135. /package/ios/{utils → extensions}/ColorExtension.mm +0 -0
  136. /package/ios/{utils → extensions}/FontExtension.h +0 -0
  137. /package/ios/{utils → extensions}/FontExtension.mm +0 -0
  138. /package/ios/{utils → extensions}/LayoutManagerExtension.h +0 -0
  139. /package/ios/{utils → extensions}/LayoutManagerExtension.mm +0 -0
  140. /package/ios/{utils → extensions}/StringExtension.h +0 -0
  141. /package/ios/{utils → extensions}/StringExtension.mm +0 -0
  142. /package/ios/{utils → interfaces}/BaseStyleProtocol.h +0 -0
  143. /package/ios/{attachments → interfaces}/ImageAttachment.h +0 -0
  144. /package/ios/{utils → interfaces}/ImageData.h +0 -0
  145. /package/ios/{utils → interfaces}/ImageData.mm +0 -0
  146. /package/ios/{utils → interfaces}/LinkData.h +0 -0
  147. /package/ios/{utils → interfaces}/LinkData.mm +0 -0
  148. /package/ios/{attachments → interfaces}/MediaAttachment.h +0 -0
  149. /package/ios/{attachments → interfaces}/MediaAttachment.mm +0 -0
  150. /package/ios/{utils → interfaces}/MentionParams.h +0 -0
  151. /package/ios/{utils → interfaces}/MentionParams.mm +0 -0
  152. /package/ios/{utils → interfaces}/MentionStyleProps.h +0 -0
  153. /package/ios/{utils → interfaces}/StylePair.h +0 -0
  154. /package/ios/{utils → interfaces}/StylePair.mm +0 -0
  155. /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
  156. /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
@@ -9,13 +9,15 @@ import android.text.Spanned;
9
9
  import android.text.TextUtils;
10
10
  import android.text.style.AlignmentSpan;
11
11
  import android.text.style.ParagraphStyle;
12
-
13
12
  import com.swmansion.enriched.spans.EnrichedBlockQuoteSpan;
14
13
  import com.swmansion.enriched.spans.EnrichedBoldSpan;
15
14
  import com.swmansion.enriched.spans.EnrichedCodeBlockSpan;
16
15
  import com.swmansion.enriched.spans.EnrichedH1Span;
17
16
  import com.swmansion.enriched.spans.EnrichedH2Span;
18
17
  import com.swmansion.enriched.spans.EnrichedH3Span;
18
+ import com.swmansion.enriched.spans.EnrichedH4Span;
19
+ import com.swmansion.enriched.spans.EnrichedH5Span;
20
+ import com.swmansion.enriched.spans.EnrichedH6Span;
19
21
  import com.swmansion.enriched.spans.EnrichedImageSpan;
20
22
  import com.swmansion.enriched.spans.EnrichedInlineCodeSpan;
21
23
  import com.swmansion.enriched.spans.EnrichedItalicSpan;
@@ -26,11 +28,14 @@ import com.swmansion.enriched.spans.EnrichedStrikeThroughSpan;
26
28
  import com.swmansion.enriched.spans.EnrichedUnderlineSpan;
27
29
  import com.swmansion.enriched.spans.EnrichedUnorderedListSpan;
28
30
  import com.swmansion.enriched.spans.interfaces.EnrichedBlockSpan;
29
- import com.swmansion.enriched.spans.interfaces.EnrichedParagraphSpan;
30
31
  import com.swmansion.enriched.spans.interfaces.EnrichedInlineSpan;
32
+ import com.swmansion.enriched.spans.interfaces.EnrichedParagraphSpan;
31
33
  import com.swmansion.enriched.spans.interfaces.EnrichedZeroWidthSpaceSpan;
32
34
  import com.swmansion.enriched.styles.HtmlStyle;
33
-
35
+ import java.io.IOException;
36
+ import java.io.StringReader;
37
+ import java.util.HashMap;
38
+ import java.util.Map;
34
39
  import org.ccil.cowan.tagsoup.HTMLSchema;
35
40
  import org.ccil.cowan.tagsoup.Parser;
36
41
  import org.xml.sax.Attributes;
@@ -42,46 +47,38 @@ import org.xml.sax.SAXNotRecognizedException;
42
47
  import org.xml.sax.SAXNotSupportedException;
43
48
  import org.xml.sax.XMLReader;
44
49
 
45
- import java.io.IOException;
46
- import java.io.StringReader;
47
- import java.util.HashMap;
48
- import java.util.Map;
49
-
50
50
  /**
51
51
  * Most of the code in this file is copied from the Android source code and adjusted to our needs.
52
- * For the reference see <a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/text/Html.java">docs</a>
52
+ * For the reference see <a
53
+ * href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/text/Html.java">docs</a>
53
54
  */
54
55
  public class EnrichedParser {
55
- /**
56
- * Retrieves images for HTML &lt;img&gt; tags.
57
- */
56
+ /** Retrieves images for HTML &lt;img&gt; tags. */
58
57
  public interface ImageGetter {
59
58
  /**
60
- * This method is called when the HTML parser encounters an
61
- * &lt;img&gt; tag. The <code>source</code> argument is the
62
- * string from the "src" attribute; the return value should be
63
- * a Drawable representation of the image or <code>null</code>
64
- * for a generic replacement image. Make sure you call
65
- * setBounds() on your Drawable if it doesn't already have
66
- * its bounds set.
59
+ * This method is called when the HTML parser encounters an &lt;img&gt; tag. The <code>source
60
+ * </code> argument is the string from the "src" attribute; the return value should be a
61
+ * Drawable representation of the image or <code>null</code> for a generic replacement image.
62
+ * Make sure you call setBounds() on your Drawable if it doesn't already have its bounds set.
67
63
  */
68
64
  Drawable getDrawable(String source);
69
65
  }
70
66
 
71
- private EnrichedParser() { }
67
+ private EnrichedParser() {}
68
+
72
69
  /**
73
- * Lazy initialization holder for HTML parser. This class will
74
- * a) be preloaded by the zygote, or b) not loaded until absolutely
75
- * necessary.
70
+ * Lazy initialization holder for HTML parser. This class will a) be preloaded by the zygote, or
71
+ * b) not loaded until absolutely necessary.
76
72
  */
77
73
  private static class HtmlParser {
78
74
  private static final HTMLSchema schema = new HTMLSchema();
79
75
  }
76
+
80
77
  /**
81
- * Returns displayable styled text from the provided HTML string. Any &lt;img&gt; tags in the
82
- * HTML will use the specified ImageGetter to request a representation of the image (use null
83
- * if you don't want this) and the specified TagHandler to handle unknown tags (specify null if
84
- * you don't want this).
78
+ * Returns displayable styled text from the provided HTML string. Any &lt;img&gt; tags in the HTML
79
+ * will use the specified ImageGetter to request a representation of the image (use null if you
80
+ * don't want this) and the specified TagHandler to handle unknown tags (specify null if you don't
81
+ * want this).
85
82
  *
86
83
  * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
87
84
  */
@@ -93,16 +90,19 @@ public class EnrichedParser {
93
90
  // Should not happen.
94
91
  throw new RuntimeException(e);
95
92
  }
96
- HtmlToSpannedConverter converter = new HtmlToSpannedConverter(source, style, imageGetter, parser);
93
+ HtmlToSpannedConverter converter =
94
+ new HtmlToSpannedConverter(source, style, imageGetter, parser);
97
95
  return converter.convert();
98
96
  }
97
+
99
98
  public static String toHtml(Spanned text) {
100
99
  StringBuilder out = new StringBuilder();
101
100
  withinHtml(out, text);
102
101
  String outString = out.toString();
103
102
  // Codeblocks and blockquotes appends a newline character by default, so we have to remove it
104
103
  String normalizedCodeBlock = outString.replaceAll("</codeblock>\\n<br>", "</codeblock>");
105
- String normalizedBlockQuote = normalizedCodeBlock.replaceAll("</blockquote>\\n<br>", "</blockquote>");
104
+ String normalizedBlockQuote =
105
+ normalizedCodeBlock.replaceAll("</blockquote>\\n<br>", "</blockquote>");
106
106
  return "<html>\n" + normalizedBlockQuote + "</html>";
107
107
  }
108
108
 
@@ -113,24 +113,24 @@ public class EnrichedParser {
113
113
  return "<html>\n<p></p>\n</html>";
114
114
  }
115
115
 
116
- /**
117
- * Returns an HTML escaped representation of the given plain text.
118
- */
116
+ /** Returns an HTML escaped representation of the given plain text. */
119
117
  public static String escapeHtml(CharSequence text) {
120
118
  StringBuilder out = new StringBuilder();
121
119
  withinStyle(out, text, 0, text.length());
122
120
  return out.toString();
123
121
  }
122
+
124
123
  private static void withinHtml(StringBuilder out, Spanned text) {
125
124
  withinDiv(out, text, 0, text.length());
126
125
  }
126
+
127
127
  private static void withinDiv(StringBuilder out, Spanned text, int start, int end) {
128
128
  int next;
129
129
  for (int i = start; i < end; i = next) {
130
130
  next = text.nextSpanTransition(i, end, EnrichedBlockSpan.class);
131
131
  EnrichedBlockSpan[] blocks = text.getSpans(i, next, EnrichedBlockSpan.class);
132
132
  String tag = "unknown";
133
- if (blocks.length > 0){
133
+ if (blocks.length > 0) {
134
134
  tag = blocks[0] instanceof EnrichedCodeBlockSpan ? "codeblock" : "blockquote";
135
135
  }
136
136
 
@@ -149,6 +149,7 @@ public class EnrichedParser {
149
149
  }
150
150
  }
151
151
  }
152
+
152
153
  private static String getBlockTag(EnrichedParagraphSpan[] spans) {
153
154
  for (EnrichedParagraphSpan span : spans) {
154
155
  if (span instanceof EnrichedUnorderedListSpan) {
@@ -161,11 +162,18 @@ public class EnrichedParser {
161
162
  return "h2";
162
163
  } else if (span instanceof EnrichedH3Span) {
163
164
  return "h3";
165
+ } else if (span instanceof EnrichedH4Span) {
166
+ return "h4";
167
+ } else if (span instanceof EnrichedH5Span) {
168
+ return "h5";
169
+ } else if (span instanceof EnrichedH6Span) {
170
+ return "h6";
164
171
  }
165
172
  }
166
173
 
167
174
  return "p";
168
175
  }
176
+
169
177
  private static void withinBlock(StringBuilder out, Spanned text, int start, int end) {
170
178
  boolean isInUlList = false;
171
179
  boolean isInOlList = false;
@@ -187,7 +195,8 @@ public class EnrichedParser {
187
195
  }
188
196
  out.append("<br>\n");
189
197
  } else {
190
- EnrichedParagraphSpan[] paragraphStyles = text.getSpans(i, next, EnrichedParagraphSpan.class);
198
+ EnrichedParagraphSpan[] paragraphStyles =
199
+ text.getSpans(i, next, EnrichedParagraphSpan.class);
191
200
  String tag = getBlockTag(paragraphStyles);
192
201
  boolean isUlListItem = tag.equals("ul");
193
202
  boolean isOlListItem = tag.equals("ol");
@@ -234,6 +243,7 @@ public class EnrichedParser {
234
243
  next++;
235
244
  }
236
245
  }
246
+
237
247
  private static void withinParagraph(StringBuilder out, Spanned text, int start, int end) {
238
248
  int next;
239
249
  for (int i = start; i < end; i = next) {
@@ -323,11 +333,11 @@ public class EnrichedParser {
323
333
  }
324
334
  }
325
335
  }
326
- private static void withinStyle(StringBuilder out, CharSequence text,
327
- int start, int end) {
336
+
337
+ private static void withinStyle(StringBuilder out, CharSequence text, int start, int end) {
328
338
  for (int i = start; i < end; i++) {
329
339
  char c = text.charAt(i);
330
- if (c == '\u200B') {
340
+ if (c == EnrichedConstants.ZWS) {
331
341
  // Do not output zero-width space characters.
332
342
  continue;
333
343
  } else if (c == '<') {
@@ -359,6 +369,7 @@ public class EnrichedParser {
359
369
  }
360
370
  }
361
371
  }
372
+
362
373
  class HtmlToSpannedConverter implements ContentHandler {
363
374
  private final HtmlStyle mStyle;
364
375
  private final String mSource;
@@ -369,7 +380,8 @@ class HtmlToSpannedConverter implements ContentHandler {
369
380
  private static Boolean isInOrderedList = false;
370
381
  private static Boolean isEmptyTag = false;
371
382
 
372
- public HtmlToSpannedConverter(String source, HtmlStyle style, EnrichedParser.ImageGetter imageGetter, Parser parser) {
383
+ public HtmlToSpannedConverter(
384
+ String source, HtmlStyle style, EnrichedParser.ImageGetter imageGetter, Parser parser) {
373
385
  mStyle = style;
374
386
  mSource = source;
375
387
  mSpannableStringBuilder = new SpannableStringBuilder();
@@ -389,14 +401,15 @@ class HtmlToSpannedConverter implements ContentHandler {
389
401
  throw new RuntimeException(e);
390
402
  }
391
403
  // Fix flags and range for paragraph-type markup.
392
- Object[] obj = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class);
404
+ Object[] obj =
405
+ mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class);
393
406
  for (int i = 0; i < obj.length; i++) {
394
407
  int start = mSpannableStringBuilder.getSpanStart(obj[i]);
395
408
  int end = mSpannableStringBuilder.getSpanEnd(obj[i]);
396
409
  // If the last line of the range is blank, back off by one.
397
410
  if (end - 2 >= 0) {
398
- if (mSpannableStringBuilder.charAt(end - 1) == '\n' &&
399
- mSpannableStringBuilder.charAt(end - 2) == '\n') {
411
+ if (mSpannableStringBuilder.charAt(end - 1) == '\n'
412
+ && mSpannableStringBuilder.charAt(end - 2) == '\n') {
400
413
  end--;
401
414
  }
402
415
  }
@@ -404,25 +417,29 @@ class HtmlToSpannedConverter implements ContentHandler {
404
417
  mSpannableStringBuilder.removeSpan(obj[i]);
405
418
  } else {
406
419
  // TODO: verify if Spannable.SPAN_EXCLUSIVE_EXCLUSIVE does not break anything.
407
- // Previously it was SPAN_PARAGRAPH. I've changed that in order to fix ranges for list items.
420
+ // Previously it was SPAN_PARAGRAPH. I've changed that in order to fix ranges for list
421
+ // items.
408
422
  mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
409
423
  }
410
424
  }
411
425
 
412
426
  // Assign zero-width space character to the proper spans.
413
- EnrichedZeroWidthSpaceSpan[] zeroWidthSpaceSpans = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), EnrichedZeroWidthSpaceSpan.class);
427
+ EnrichedZeroWidthSpaceSpan[] zeroWidthSpaceSpans =
428
+ mSpannableStringBuilder.getSpans(
429
+ 0, mSpannableStringBuilder.length(), EnrichedZeroWidthSpaceSpan.class);
414
430
  for (EnrichedZeroWidthSpaceSpan zeroWidthSpaceSpan : zeroWidthSpaceSpans) {
415
431
  int start = mSpannableStringBuilder.getSpanStart(zeroWidthSpaceSpan);
416
432
  int end = mSpannableStringBuilder.getSpanEnd(zeroWidthSpaceSpan);
417
433
 
418
- if (mSpannableStringBuilder.charAt(start) != '\u200B') {
434
+ if (mSpannableStringBuilder.charAt(start) != EnrichedConstants.ZWS) {
419
435
  // Insert zero-width space character at the start if it's not already present.
420
- mSpannableStringBuilder.insert(start, "\u200B");
436
+ mSpannableStringBuilder.insert(start, EnrichedConstants.ZWS_STRING);
421
437
  end++; // Adjust end position due to insertion.
422
438
  }
423
439
 
424
440
  mSpannableStringBuilder.removeSpan(zeroWidthSpaceSpan);
425
- mSpannableStringBuilder.setSpan(zeroWidthSpaceSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
441
+ mSpannableStringBuilder.setSpan(
442
+ zeroWidthSpaceSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
426
443
  }
427
444
 
428
445
  return mSpannableStringBuilder;
@@ -469,6 +486,12 @@ class HtmlToSpannedConverter implements ContentHandler {
469
486
  startHeading(mSpannableStringBuilder, 2);
470
487
  } else if (tag.equalsIgnoreCase("h3")) {
471
488
  startHeading(mSpannableStringBuilder, 3);
489
+ } else if (tag.equalsIgnoreCase("h4")) {
490
+ startHeading(mSpannableStringBuilder, 4);
491
+ } else if (tag.equalsIgnoreCase("h5")) {
492
+ startHeading(mSpannableStringBuilder, 5);
493
+ } else if (tag.equalsIgnoreCase("h6")) {
494
+ startHeading(mSpannableStringBuilder, 6);
472
495
  } else if (tag.equalsIgnoreCase("img")) {
473
496
  startImg(mSpannableStringBuilder, attributes, mImageGetter);
474
497
  } else if (tag.equalsIgnoreCase("code")) {
@@ -507,6 +530,12 @@ class HtmlToSpannedConverter implements ContentHandler {
507
530
  endHeading(mSpannableStringBuilder, mStyle, 2);
508
531
  } else if (tag.equalsIgnoreCase("h3")) {
509
532
  endHeading(mSpannableStringBuilder, mStyle, 3);
533
+ } else if (tag.equalsIgnoreCase("h4")) {
534
+ endHeading(mSpannableStringBuilder, mStyle, 4);
535
+ } else if (tag.equalsIgnoreCase("h5")) {
536
+ endHeading(mSpannableStringBuilder, mStyle, 5);
537
+ } else if (tag.equalsIgnoreCase("h6")) {
538
+ endHeading(mSpannableStringBuilder, mStyle, 6);
510
539
  } else if (tag.equalsIgnoreCase("code")) {
511
540
  end(mSpannableStringBuilder, Code.class, new EnrichedInlineCodeSpan(mStyle));
512
541
  } else if (tag.equalsIgnoreCase("mention")) {
@@ -529,8 +558,8 @@ class HtmlToSpannedConverter implements ContentHandler {
529
558
  }
530
559
 
531
560
  private static void startBlockElement(Editable text) {
532
- appendNewlines(text, 1);
533
- start(text, new Newline(1));
561
+ appendNewlines(text, 1);
562
+ start(text, new Newline(1));
534
563
  }
535
564
 
536
565
  private static void endBlockElement(Editable text) {
@@ -610,6 +639,15 @@ class HtmlToSpannedConverter implements ContentHandler {
610
639
  case 3:
611
640
  start(text, new H3());
612
641
  break;
642
+ case 4:
643
+ start(text, new H4());
644
+ break;
645
+ case 5:
646
+ start(text, new H5());
647
+ break;
648
+ case 6:
649
+ start(text, new H6());
650
+ break;
613
651
  default:
614
652
  throw new IllegalArgumentException("Unsupported heading level: " + level);
615
653
  }
@@ -631,6 +669,18 @@ class HtmlToSpannedConverter implements ContentHandler {
631
669
  H3 lastH3 = getLast(text, H3.class);
632
670
  setParagraphSpanFromMark(text, lastH3, new EnrichedH3Span(style));
633
671
  break;
672
+ case 4:
673
+ H4 lastH4 = getLast(text, H4.class);
674
+ setParagraphSpanFromMark(text, lastH4, new EnrichedH4Span(style));
675
+ break;
676
+ case 5:
677
+ H5 lastH5 = getLast(text, H5.class);
678
+ setParagraphSpanFromMark(text, lastH5, new EnrichedH5Span(style));
679
+ break;
680
+ case 6:
681
+ H6 lastH6 = getLast(text, H6.class);
682
+ setParagraphSpanFromMark(text, lastH6, new EnrichedH6Span(style));
683
+ break;
634
684
  default:
635
685
  throw new IllegalArgumentException("Unsupported heading level: " + level);
636
686
  }
@@ -667,7 +717,7 @@ class HtmlToSpannedConverter implements ContentHandler {
667
717
 
668
718
  // Block spans require at least one character to be applied.
669
719
  if (isEmptyTag) {
670
- text.append("\u200B");
720
+ text.append(EnrichedConstants.ZWS);
671
721
  len++;
672
722
  }
673
723
 
@@ -695,13 +745,16 @@ class HtmlToSpannedConverter implements ContentHandler {
695
745
  }
696
746
  }
697
747
 
698
- private static void startImg(Editable text, Attributes attributes, EnrichedParser.ImageGetter img) {
748
+ private static void startImg(
749
+ Editable text, Attributes attributes, EnrichedParser.ImageGetter img) {
699
750
  String src = attributes.getValue("", "src");
700
751
  String width = attributes.getValue("", "width");
701
752
  String height = attributes.getValue("", "height");
702
753
 
703
754
  int len = text.length();
704
- EnrichedImageSpan span = EnrichedImageSpan.Companion.createEnrichedImageSpan(src, Integer.parseInt(width), Integer.parseInt(height));
755
+ EnrichedImageSpan span =
756
+ EnrichedImageSpan.Companion.createEnrichedImageSpan(
757
+ src, Integer.parseInt(width), Integer.parseInt(height));
705
758
  text.append("");
706
759
  text.setSpan(span, len, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
707
760
  }
@@ -745,20 +798,15 @@ class HtmlToSpannedConverter implements ContentHandler {
745
798
  setSpanFromMark(text, m, new EnrichedMentionSpan(m.mText, m.mIndicator, m.mAttributes, style));
746
799
  }
747
800
 
748
- public void setDocumentLocator(Locator locator) {
749
- }
801
+ public void setDocumentLocator(Locator locator) {}
750
802
 
751
- public void startDocument() {
752
- }
803
+ public void startDocument() {}
753
804
 
754
- public void endDocument() {
755
- }
805
+ public void endDocument() {}
756
806
 
757
- public void startPrefixMapping(String prefix, String uri) {
758
- }
807
+ public void startPrefixMapping(String prefix, String uri) {}
759
808
 
760
- public void endPrefixMapping(String prefix) {
761
- }
809
+ public void endPrefixMapping(String prefix) {}
762
810
 
763
811
  public void startElement(String uri, String localName, String qName, Attributes attributes) {
764
812
  handleStartTag(localName, attributes);
@@ -801,44 +849,37 @@ class HtmlToSpannedConverter implements ContentHandler {
801
849
  mSpannableStringBuilder.append(sb);
802
850
  }
803
851
 
804
- public void ignorableWhitespace(char[] ch, int start, int length) {
805
- }
852
+ public void ignorableWhitespace(char[] ch, int start, int length) {}
806
853
 
807
- public void processingInstruction(String target, String data) {
808
- }
854
+ public void processingInstruction(String target, String data) {}
809
855
 
810
- public void skippedEntity(String name) {
811
- }
856
+ public void skippedEntity(String name) {}
812
857
 
813
- private static class H1 {
814
- }
858
+ private static class H1 {}
815
859
 
816
- private static class H2 {
817
- }
860
+ private static class H2 {}
818
861
 
819
- private static class H3 {
820
- }
862
+ private static class H3 {}
821
863
 
822
- private static class Bold {
823
- }
864
+ private static class H4 {}
824
865
 
825
- private static class Italic {
826
- }
866
+ private static class H5 {}
827
867
 
828
- private static class Underline {
829
- }
868
+ private static class H6 {}
830
869
 
831
- private static class Code {
832
- }
870
+ private static class Bold {}
833
871
 
834
- private static class CodeBlock {
835
- }
872
+ private static class Italic {}
836
873
 
837
- private static class Strikethrough {
838
- }
874
+ private static class Underline {}
839
875
 
840
- private static class Blockquote {
841
- }
876
+ private static class Code {}
877
+
878
+ private static class CodeBlock {}
879
+
880
+ private static class Strikethrough {}
881
+
882
+ private static class Blockquote {}
842
883
 
843
884
  private static class List {
844
885
  public int mIndex;
@@ -13,14 +13,19 @@ import com.swmansion.enriched.spans.EnrichedMentionSpan
13
13
  import com.swmansion.enriched.spans.EnrichedSpans
14
14
  import org.json.JSONObject
15
15
 
16
- class EnrichedSelection(private val view: EnrichedTextInputView) {
16
+ class EnrichedSelection(
17
+ private val view: EnrichedTextInputView,
18
+ ) {
17
19
  var start: Int = 0
18
20
  var end: Int = 0
19
21
 
20
22
  private var previousLinkDetectedEvent: MutableMap<String, String> = mutableMapOf("text" to "", "url" to "")
21
23
  private var previousMentionDetectedEvent: MutableMap<String, String> = mutableMapOf("text" to "", "payload" to "")
22
24
 
23
- fun onSelection(selStart: Int, selEnd: Int) {
25
+ fun onSelection(
26
+ selStart: Int,
27
+ selEnd: Int,
28
+ ) {
24
29
  var shouldValidateStyles = false
25
30
  var newStart = start
26
31
  var newEnd = end
@@ -52,19 +57,23 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
52
57
  emitSelectionChangeEvent(view.text, finalStart, finalEnd)
53
58
  }
54
59
 
55
- private fun isZeroWidthSelection(start: Int, end: Int): Boolean {
60
+ private fun isZeroWidthSelection(
61
+ start: Int,
62
+ end: Int,
63
+ ): Boolean {
56
64
  val text = view.text ?: return false
57
65
 
58
66
  if (start != end) {
59
- return text.substring(start, end) == "\u200B"
67
+ return text.substring(start, end) == EnrichedConstants.ZWS_STRING
60
68
  }
61
69
 
62
- val isNewLine = if (start > 0 ) text.substring(start - 1, start) == "\n" else true
63
- val isNextCharacterZeroWidth = if (start < text.length) {
64
- text.substring(start, start + 1) == "\u200B"
65
- } else {
66
- false
67
- }
70
+ val isNewLine = if (start > 0) text.substring(start - 1, start) == "\n" else true
71
+ val isNextCharacterZeroWidth =
72
+ if (start < text.length) {
73
+ text.substring(start, start + 1) == EnrichedConstants.ZWS_STRING
74
+ } else {
75
+ false
76
+ }
68
77
 
69
78
  return isNewLine && isNextCharacterZeroWidth
70
79
  }
@@ -103,7 +112,7 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
103
112
  return Pair(finalStart, finalEnd)
104
113
  }
105
114
 
106
- private fun <T>getInlineStyleStart(type: Class<T>): Int? {
115
+ private fun <T> getInlineStyleStart(type: Class<T>): Int? {
107
116
  val (start, end) = getInlineSelection()
108
117
  val spannable = view.text as Spannable
109
118
  val spans = spannable.getSpans(start, end, type)
@@ -129,7 +138,7 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
129
138
  return spannable.getParagraphBounds(currentStart, currentEnd)
130
139
  }
131
140
 
132
- private fun <T>getParagraphStyleStart(type: Class<T>): Int? {
141
+ private fun <T> getParagraphStyleStart(type: Class<T>): Int? {
133
142
  val (start, end) = getParagraphSelection()
134
143
  val spannable = view.text as Spannable
135
144
  val spans = spannable.getSpans(start, end, type)
@@ -148,7 +157,7 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
148
157
  return styleStart
149
158
  }
150
159
 
151
- private fun <T>getListStyleStart(type: Class<T>): Int? {
160
+ private fun <T> getListStyleStart(type: Class<T>): Int? {
152
161
  val (start, end) = getParagraphSelection()
153
162
  val spannable = view.text as Spannable
154
163
  var styleStart: Int? = null
@@ -177,7 +186,7 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
177
186
  return styleStart
178
187
  }
179
188
 
180
- private fun <T>getParametrizedStyleStart(type: Class<T>): Int? {
189
+ private fun <T> getParametrizedStyleStart(type: Class<T>): Int? {
181
190
  val (start, end) = getInlineSelection()
182
191
  val spannable = view.text as Spannable
183
192
  val spans = spannable.getSpans(start, end, type)
@@ -212,7 +221,11 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
212
221
  return null
213
222
  }
214
223
 
215
- private fun emitSelectionChangeEvent(editable: Editable?, start: Int, end: Int) {
224
+ private fun emitSelectionChangeEvent(
225
+ editable: Editable?,
226
+ start: Int,
227
+ end: Int,
228
+ ) {
216
229
  if (editable == null) return
217
230
 
218
231
  val context = view.context as ReactContext
@@ -220,17 +233,24 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
220
233
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
221
234
 
222
235
  val text = editable.substring(start, end)
223
- dispatcher?.dispatchEvent(OnChangeSelectionEvent(
224
- surfaceId,
225
- view.id,
226
- text,
227
- start ,
228
- end,
229
- view.experimentalSynchronousEvents,
230
- ))
236
+ dispatcher?.dispatchEvent(
237
+ OnChangeSelectionEvent(
238
+ surfaceId,
239
+ view.id,
240
+ text,
241
+ start,
242
+ end,
243
+ view.experimentalSynchronousEvents,
244
+ ),
245
+ )
231
246
  }
232
247
 
233
- private fun emitLinkDetectedEvent(spannable: Spannable, span: EnrichedLinkSpan?, start: Int, end: Int) {
248
+ private fun emitLinkDetectedEvent(
249
+ spannable: Spannable,
250
+ span: EnrichedLinkSpan?,
251
+ start: Int,
252
+ end: Int,
253
+ ) {
234
254
  val text = spannable.substring(start, end)
235
255
  val url = span?.getUrl() ?: ""
236
256
 
@@ -243,18 +263,25 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
243
263
  val context = view.context as ReactContext
244
264
  val surfaceId = UIManagerHelper.getSurfaceId(context)
245
265
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
246
- dispatcher?.dispatchEvent(OnLinkDetectedEvent(
247
- surfaceId,
248
- view.id,
249
- text,
250
- url,
251
- start,
252
- end,
253
- view.experimentalSynchronousEvents,
254
- ))
266
+ dispatcher?.dispatchEvent(
267
+ OnLinkDetectedEvent(
268
+ surfaceId,
269
+ view.id,
270
+ text,
271
+ url,
272
+ start,
273
+ end,
274
+ view.experimentalSynchronousEvents,
275
+ ),
276
+ )
255
277
  }
256
278
 
257
- private fun emitMentionDetectedEvent(spannable: Spannable, span: EnrichedMentionSpan?, start: Int, end: Int) {
279
+ private fun emitMentionDetectedEvent(
280
+ spannable: Spannable,
281
+ span: EnrichedMentionSpan?,
282
+ start: Int,
283
+ end: Int,
284
+ ) {
258
285
  val text = spannable.substring(start, end)
259
286
  val attributes = span?.getAttributes() ?: emptyMap()
260
287
  val indicator = span?.getIndicator() ?: ""
@@ -273,13 +300,15 @@ class EnrichedSelection(private val view: EnrichedTextInputView) {
273
300
  val context = view.context as ReactContext
274
301
  val surfaceId = UIManagerHelper.getSurfaceId(context)
275
302
  val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, view.id)
276
- dispatcher?.dispatchEvent(OnMentionDetectedEvent(
277
- surfaceId,
278
- view.id,
279
- text,
280
- indicator,
281
- payload,
282
- view.experimentalSynchronousEvents,
283
- ))
303
+ dispatcher?.dispatchEvent(
304
+ OnMentionDetectedEvent(
305
+ surfaceId,
306
+ view.id,
307
+ text,
308
+ indicator,
309
+ payload,
310
+ view.experimentalSynchronousEvents,
311
+ ),
312
+ )
284
313
  }
285
314
  }