react-native-enriched 0.2.0 → 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 (186) hide show
  1. package/README.md +16 -17
  2. package/android/build.gradle +77 -72
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  6. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -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 +304 -83
  12. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
  13. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +166 -51
  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 +21 -11
  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 +32 -0
  29. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +24 -5
  30. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +8 -1
  31. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +10 -2
  32. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +8 -1
  33. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +8 -1
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +8 -1
  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 +34 -17
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +8 -1
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +7 -1
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +10 -4
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +14 -11
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +18 -11
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +174 -72
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +7 -1
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +7 -1
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -5
  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 +5 -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 +155 -20
  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 +161 -25
  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 +136 -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/RNEnrichedTextInputViewSpec.cpp +6 -6
  73. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
  74. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
  75. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
  76. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
  77. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
  78. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
  79. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
  80. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
  81. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +33 -14
  82. package/ios/EnrichedTextInputView.h +26 -14
  83. package/ios/EnrichedTextInputView.mm +1209 -586
  84. package/ios/config/InputConfig.h +24 -6
  85. package/ios/config/InputConfig.mm +154 -38
  86. package/ios/{utils → extensions}/ColorExtension.mm +7 -5
  87. package/ios/extensions/FontExtension.mm +106 -0
  88. package/ios/{utils → extensions}/LayoutManagerExtension.h +1 -1
  89. package/ios/extensions/LayoutManagerExtension.mm +396 -0
  90. package/ios/{utils → extensions}/StringExtension.mm +19 -16
  91. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  92. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
  93. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  94. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
  95. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +95 -0
  96. package/ios/inputParser/InputParser.h +5 -5
  97. package/ios/inputParser/InputParser.mm +864 -380
  98. package/ios/inputTextView/InputTextView.h +1 -1
  99. package/ios/inputTextView/InputTextView.mm +100 -59
  100. package/ios/{utils → interfaces}/BaseStyleProtocol.h +2 -2
  101. package/ios/interfaces/ImageAttachment.h +10 -0
  102. package/ios/interfaces/ImageAttachment.mm +36 -0
  103. package/ios/interfaces/LinkRegexConfig.h +19 -0
  104. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  105. package/ios/interfaces/MediaAttachment.h +23 -0
  106. package/ios/interfaces/MediaAttachment.mm +31 -0
  107. package/ios/{utils → interfaces}/MentionParams.h +0 -1
  108. package/ios/{utils → interfaces}/MentionStyleProps.mm +27 -20
  109. package/ios/{utils → interfaces}/StyleHeaders.h +37 -15
  110. package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
  111. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
  112. package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
  113. package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
  114. package/ios/internals/EnrichedTextInputViewState.h +3 -1
  115. package/ios/styles/BlockQuoteStyle.mm +189 -118
  116. package/ios/styles/BoldStyle.mm +110 -63
  117. package/ios/styles/CodeBlockStyle.mm +204 -128
  118. package/ios/styles/H1Style.mm +10 -4
  119. package/ios/styles/H2Style.mm +10 -4
  120. package/ios/styles/H3Style.mm +10 -4
  121. package/ios/styles/H4Style.mm +17 -0
  122. package/ios/styles/H5Style.mm +17 -0
  123. package/ios/styles/H6Style.mm +17 -0
  124. package/ios/styles/HeadingStyleBase.mm +148 -86
  125. package/ios/styles/ImageStyle.mm +75 -73
  126. package/ios/styles/InlineCodeStyle.mm +162 -88
  127. package/ios/styles/ItalicStyle.mm +76 -52
  128. package/ios/styles/LinkStyle.mm +411 -232
  129. package/ios/styles/MentionStyle.mm +363 -246
  130. package/ios/styles/OrderedListStyle.mm +171 -106
  131. package/ios/styles/StrikethroughStyle.mm +52 -35
  132. package/ios/styles/UnderlineStyle.mm +68 -46
  133. package/ios/styles/UnorderedListStyle.mm +169 -106
  134. package/ios/utils/OccurenceUtils.h +42 -42
  135. package/ios/utils/OccurenceUtils.mm +142 -119
  136. package/ios/utils/ParagraphAttributesUtils.h +10 -2
  137. package/ios/utils/ParagraphAttributesUtils.mm +182 -71
  138. package/ios/utils/ParagraphsUtils.h +2 -1
  139. package/ios/utils/ParagraphsUtils.mm +41 -27
  140. package/ios/utils/TextInsertionUtils.h +13 -2
  141. package/ios/utils/TextInsertionUtils.mm +38 -20
  142. package/ios/utils/WordsUtils.h +2 -1
  143. package/ios/utils/WordsUtils.mm +32 -22
  144. package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
  145. package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
  146. package/lib/module/EnrichedTextInput.js +61 -2
  147. package/lib/module/EnrichedTextInput.js.map +1 -1
  148. package/lib/module/EnrichedTextInputNativeComponent.ts +149 -12
  149. package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
  150. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  151. package/lib/module/utils/regexParser.js +46 -0
  152. package/lib/module/utils/regexParser.js.map +1 -0
  153. package/lib/typescript/src/EnrichedTextInput.d.ts +24 -14
  154. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  155. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +129 -12
  156. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  157. package/lib/typescript/src/index.d.ts +1 -1
  158. package/lib/typescript/src/index.d.ts.map +1 -1
  159. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  160. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  161. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  162. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  163. package/package.json +17 -6
  164. package/src/EnrichedTextInput.tsx +96 -13
  165. package/src/EnrichedTextInputNativeComponent.ts +149 -12
  166. package/src/index.tsx +2 -0
  167. package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
  168. package/src/utils/regexParser.ts +56 -0
  169. package/ios/utils/FontExtension.mm +0 -91
  170. package/ios/utils/LayoutManagerExtension.mm +0 -286
  171. package/lib/module/normalizeHtmlStyle.js.map +0 -1
  172. package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
  173. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
  174. package/ios/{utils → extensions}/ColorExtension.h +0 -0
  175. package/ios/{utils → extensions}/FontExtension.h +0 -0
  176. package/ios/{utils → extensions}/StringExtension.h +1 -1
  177. package/ios/{utils → interfaces}/ImageData.h +0 -0
  178. package/ios/{utils → interfaces}/ImageData.mm +0 -0
  179. package/ios/{utils → interfaces}/LinkData.h +0 -0
  180. package/ios/{utils → interfaces}/LinkData.mm +0 -0
  181. package/ios/{utils → interfaces}/MentionParams.mm +0 -0
  182. package/ios/{utils → interfaces}/MentionStyleProps.h +1 -1
  183. /package/ios/{utils → interfaces}/StylePair.h +0 -0
  184. /package/ios/{utils → interfaces}/StylePair.mm +0 -0
  185. /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
  186. /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
@@ -0,0 +1,396 @@
1
+ #import "LayoutManagerExtension.h"
2
+ #import "ColorExtension.h"
3
+ #import "EnrichedTextInputView.h"
4
+ #import "ParagraphsUtils.h"
5
+ #import "StyleHeaders.h"
6
+ #import <objc/runtime.h>
7
+
8
+ @implementation NSLayoutManager (LayoutManagerExtension)
9
+
10
+ static void const *kInputKey = &kInputKey;
11
+
12
+ - (id)input {
13
+ return objc_getAssociatedObject(self, kInputKey);
14
+ }
15
+
16
+ - (void)setInput:(id)value {
17
+ objc_setAssociatedObject(self, kInputKey, value,
18
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
19
+ }
20
+
21
+ + (void)load {
22
+ static dispatch_once_t onceToken;
23
+ dispatch_once(&onceToken, ^{
24
+ Class myClass = [NSLayoutManager class];
25
+ SEL originalSelector = @selector(drawBackgroundForGlyphRange:atPoint:);
26
+ SEL swizzledSelector = @selector(my_drawBackgroundForGlyphRange:atPoint:);
27
+ Method originalMethod = class_getInstanceMethod(myClass, originalSelector);
28
+ Method swizzledMethod = class_getInstanceMethod(myClass, swizzledSelector);
29
+
30
+ BOOL didAddMethod = class_addMethod(
31
+ myClass, originalSelector, method_getImplementation(swizzledMethod),
32
+ method_getTypeEncoding(swizzledMethod));
33
+
34
+ if (didAddMethod) {
35
+ class_replaceMethod(myClass, swizzledSelector,
36
+ method_getImplementation(originalMethod),
37
+ method_getTypeEncoding(originalMethod));
38
+ } else {
39
+ method_exchangeImplementations(originalMethod, swizzledMethod);
40
+ }
41
+ });
42
+ }
43
+
44
+ - (void)my_drawBackgroundForGlyphRange:(NSRange)glyphRange
45
+ atPoint:(CGPoint)origin {
46
+ [self my_drawBackgroundForGlyphRange:glyphRange atPoint:origin];
47
+
48
+ EnrichedTextInputView *typedInput = (EnrichedTextInputView *)self.input;
49
+ if (typedInput == nullptr) {
50
+ return;
51
+ }
52
+
53
+ NSRange visibleCharRange = [self characterRangeForGlyphRange:glyphRange
54
+ actualGlyphRange:NULL];
55
+
56
+ [self drawBlockQuotes:typedInput
57
+ origin:origin
58
+ visibleCharRange:visibleCharRange];
59
+ [self drawLists:typedInput origin:origin visibleCharRange:visibleCharRange];
60
+ [self drawCodeBlocks:typedInput
61
+ origin:origin
62
+ visibleCharRange:visibleCharRange];
63
+ }
64
+
65
+ - (void)drawCodeBlocks:(EnrichedTextInputView *)typedInput
66
+ origin:(CGPoint)origin
67
+ visibleCharRange:(NSRange)visibleCharRange {
68
+ CodeBlockStyle *codeBlockStyle =
69
+ typedInput->stylesDict[@([CodeBlockStyle getStyleType])];
70
+ if (codeBlockStyle == nullptr) {
71
+ return;
72
+ }
73
+
74
+ NSArray<StylePair *> *allCodeBlocks =
75
+ [codeBlockStyle findAllOccurences:visibleCharRange];
76
+ NSArray<StylePair *> *mergedCodeBlocks =
77
+ [self mergeContiguousStylePairs:allCodeBlocks];
78
+ UIColor *bgColor = [[typedInput->config codeBlockBgColor]
79
+ colorWithAlphaIfNotTransparent:0.4];
80
+ CGFloat radius = [typedInput->config codeBlockBorderRadius];
81
+ [bgColor setFill];
82
+
83
+ for (StylePair *pair in mergedCodeBlocks) {
84
+ NSRange blockCharacterRange = [pair.rangeValue rangeValue];
85
+ if (blockCharacterRange.length == 0)
86
+ continue;
87
+
88
+ NSArray *paragraphs =
89
+ [ParagraphsUtils getSeparateParagraphsRangesIn:typedInput->textView
90
+ range:blockCharacterRange];
91
+ if (paragraphs.count == 0)
92
+ continue;
93
+
94
+ NSRange firstParagraphRange =
95
+ [((NSValue *)[paragraphs firstObject]) rangeValue];
96
+ NSRange lastParagraphRange =
97
+ [((NSValue *)[paragraphs lastObject]) rangeValue];
98
+
99
+ for (NSValue *paragraphValue in paragraphs) {
100
+ NSRange paragraphCharacterRange = [paragraphValue rangeValue];
101
+
102
+ BOOL isFirstParagraph =
103
+ NSEqualRanges(paragraphCharacterRange, firstParagraphRange);
104
+ BOOL isLastParagraph =
105
+ NSEqualRanges(paragraphCharacterRange, lastParagraphRange);
106
+
107
+ NSRange paragraphGlyphRange =
108
+ [self glyphRangeForCharacterRange:paragraphCharacterRange
109
+ actualCharacterRange:NULL];
110
+
111
+ __block BOOL isFirstLineOfParagraph = YES;
112
+
113
+ [self
114
+ enumerateLineFragmentsForGlyphRange:paragraphGlyphRange
115
+ usingBlock:^(
116
+ CGRect rect, CGRect usedRect,
117
+ NSTextContainer *_Nonnull textContainer,
118
+ NSRange glyphRange,
119
+ BOOL *_Nonnull stop) {
120
+ CGRect lineBgRect = rect;
121
+ lineBgRect.origin.x = origin.x;
122
+ lineBgRect.origin.y += origin.y;
123
+ lineBgRect.size.width =
124
+ textContainer.size.width;
125
+
126
+ UIRectCorner cornersForThisLine = 0;
127
+
128
+ if (isFirstParagraph &&
129
+ isFirstLineOfParagraph) {
130
+ cornersForThisLine =
131
+ UIRectCornerTopLeft |
132
+ UIRectCornerTopRight;
133
+ }
134
+
135
+ BOOL isLastLineOfParagraph =
136
+ (NSMaxRange(glyphRange) >=
137
+ NSMaxRange(paragraphGlyphRange));
138
+
139
+ if (isLastParagraph &&
140
+ isLastLineOfParagraph) {
141
+ cornersForThisLine =
142
+ cornersForThisLine |
143
+ UIRectCornerBottomLeft |
144
+ UIRectCornerBottomRight;
145
+ }
146
+
147
+ UIBezierPath *path = [UIBezierPath
148
+ bezierPathWithRoundedRect:lineBgRect
149
+ byRoundingCorners:
150
+ cornersForThisLine
151
+ cornerRadii:CGSizeMake(
152
+ radius,
153
+ radius)];
154
+ [path fill];
155
+
156
+ isFirstLineOfParagraph = NO;
157
+ }];
158
+ }
159
+ }
160
+ }
161
+
162
+ - (NSArray<StylePair *> *)mergeContiguousStylePairs:
163
+ (NSArray<StylePair *> *)pairs {
164
+ if (pairs.count == 0) {
165
+ return @[];
166
+ }
167
+
168
+ NSMutableArray<StylePair *> *mergedPairs = [[NSMutableArray alloc] init];
169
+ StylePair *currentPair = pairs[0];
170
+ NSRange currentRange = [currentPair.rangeValue rangeValue];
171
+ for (NSUInteger i = 1; i < pairs.count; i++) {
172
+ StylePair *nextPair = pairs[i];
173
+ NSRange nextRange = [nextPair.rangeValue rangeValue];
174
+
175
+ // The Gap Check:
176
+ // NSMaxRange(currentRange) is where the current block ends.
177
+ // nextRange.location is where the next block starts.
178
+ if (NSMaxRange(currentRange) == nextRange.location) {
179
+ // They touch perfectly (no gap). Merge them.
180
+ currentRange.length += nextRange.length;
181
+ } else {
182
+ // There is a gap (indices don't match).
183
+ // 1. Save the finished block.
184
+ StylePair *mergedPair = [[StylePair alloc] init];
185
+ mergedPair.rangeValue = [NSValue valueWithRange:currentRange];
186
+ mergedPair.styleValue = currentPair.styleValue;
187
+ [mergedPairs addObject:mergedPair];
188
+
189
+ // 2. Start a brand new block.
190
+ currentPair = nextPair;
191
+ currentRange = nextRange;
192
+ }
193
+ }
194
+
195
+ // Add the final block
196
+ StylePair *lastPair = [[StylePair alloc] init];
197
+ lastPair.rangeValue = [NSValue valueWithRange:currentRange];
198
+ lastPair.styleValue = currentPair.styleValue;
199
+ [mergedPairs addObject:lastPair];
200
+
201
+ return mergedPairs;
202
+ }
203
+
204
+ - (void)drawBlockQuotes:(EnrichedTextInputView *)typedInput
205
+ origin:(CGPoint)origin
206
+ visibleCharRange:(NSRange)visibleCharRange {
207
+ BlockQuoteStyle *bqStyle =
208
+ typedInput->stylesDict[@([BlockQuoteStyle getStyleType])];
209
+ if (bqStyle == nullptr) {
210
+ return;
211
+ }
212
+
213
+ NSArray *allBlockquotes = [bqStyle findAllOccurences:visibleCharRange];
214
+
215
+ for (StylePair *pair in allBlockquotes) {
216
+ NSRange paragraphRange = [typedInput->textView.textStorage.string
217
+ paragraphRangeForRange:[pair.rangeValue rangeValue]];
218
+ NSRange paragraphGlyphRange =
219
+ [self glyphRangeForCharacterRange:paragraphRange
220
+ actualCharacterRange:nullptr];
221
+ [self
222
+ enumerateLineFragmentsForGlyphRange:paragraphGlyphRange
223
+ usingBlock:^(
224
+ CGRect rect, CGRect usedRect,
225
+ NSTextContainer *_Nonnull textContainer,
226
+ NSRange glyphRange, BOOL *_Nonnull stop) {
227
+ CGFloat paddingLeft = origin.x;
228
+ CGFloat paddingTop = origin.y;
229
+ CGFloat x = paddingLeft;
230
+ CGFloat y = paddingTop + rect.origin.y;
231
+ CGFloat width =
232
+ [typedInput
233
+ ->config blockquoteBorderWidth];
234
+ CGFloat height = rect.size.height;
235
+
236
+ CGRect lineRect =
237
+ CGRectMake(x, y, width, height);
238
+ [[typedInput->config blockquoteBorderColor]
239
+ setFill];
240
+ UIRectFill(lineRect);
241
+ }];
242
+ }
243
+ }
244
+
245
+ - (void)drawLists:(EnrichedTextInputView *)typedInput
246
+ origin:(CGPoint)origin
247
+ visibleCharRange:(NSRange)visibleCharRange {
248
+ UnorderedListStyle *ulStyle =
249
+ typedInput->stylesDict[@([UnorderedListStyle getStyleType])];
250
+ OrderedListStyle *olStyle =
251
+ typedInput->stylesDict[@([OrderedListStyle getStyleType])];
252
+ if (ulStyle == nullptr || olStyle == nullptr) {
253
+ return;
254
+ }
255
+
256
+ NSMutableArray *allLists = [[NSMutableArray alloc] init];
257
+ [allLists addObjectsFromArray:[ulStyle findAllOccurences:visibleCharRange]];
258
+ [allLists addObjectsFromArray:[olStyle findAllOccurences:visibleCharRange]];
259
+
260
+ for (StylePair *pair in allLists) {
261
+ NSParagraphStyle *pStyle = (NSParagraphStyle *)pair.styleValue;
262
+ NSDictionary *markerAttributes = @{
263
+ NSFontAttributeName : [typedInput->config orderedListMarkerFont],
264
+ NSForegroundColorAttributeName :
265
+ [typedInput->config orderedListMarkerColor]
266
+ };
267
+
268
+ NSArray *paragraphs = [ParagraphsUtils
269
+ getSeparateParagraphsRangesIn:typedInput->textView
270
+ range:[pair.rangeValue rangeValue]];
271
+
272
+ for (NSValue *paragraph in paragraphs) {
273
+ NSRange paragraphGlyphRange =
274
+ [self glyphRangeForCharacterRange:[paragraph rangeValue]
275
+ actualCharacterRange:nullptr];
276
+
277
+ [self
278
+ enumerateLineFragmentsForGlyphRange:paragraphGlyphRange
279
+ usingBlock:^(CGRect rect, CGRect usedRect,
280
+ NSTextContainer *container,
281
+ NSRange lineGlyphRange,
282
+ BOOL *stop) {
283
+ NSString *marker = [self
284
+ markerForList:pStyle.textLists
285
+ .firstObject
286
+ charIndex:
287
+ [self
288
+ characterIndexForGlyphAtIndex:
289
+ lineGlyphRange
290
+ .location]
291
+ input:typedInput];
292
+
293
+ if (pStyle.textLists.firstObject
294
+ .markerFormat ==
295
+ NSTextListMarkerDecimal) {
296
+ CGFloat gapWidth =
297
+ [typedInput->config
298
+ orderedListGapWidth];
299
+ CGFloat markerWidth =
300
+ [marker sizeWithAttributes:
301
+ markerAttributes]
302
+ .width;
303
+ CGFloat markerX = usedRect.origin.x -
304
+ gapWidth -
305
+ markerWidth / 2;
306
+
307
+ [marker drawAtPoint:CGPointMake(
308
+ markerX,
309
+ usedRect.origin
310
+ .y +
311
+ origin.y)
312
+ withAttributes:markerAttributes];
313
+ } else {
314
+ CGFloat gapWidth =
315
+ [typedInput->config
316
+ unorderedListGapWidth];
317
+ CGFloat bulletSize =
318
+ [typedInput->config
319
+ unorderedListBulletSize];
320
+ CGFloat bulletX = usedRect.origin.x -
321
+ gapWidth -
322
+ bulletSize / 2;
323
+ CGFloat centerY =
324
+ CGRectGetMidY(usedRect);
325
+
326
+ CGContextRef context =
327
+ UIGraphicsGetCurrentContext();
328
+ CGContextSaveGState(context);
329
+ {
330
+ [[typedInput->config
331
+ unorderedListBulletColor]
332
+ setFill];
333
+ CGContextAddArc(
334
+ context, bulletX, centerY,
335
+ bulletSize / 2, 0, 2 * M_PI, YES);
336
+ CGContextFillPath(context);
337
+ }
338
+ CGContextRestoreGState(context);
339
+ }
340
+ // only first line of a list gets its
341
+ // marker drawn
342
+ *stop = YES;
343
+ }];
344
+ }
345
+ }
346
+ }
347
+
348
+ - (NSString *)markerForList:(NSTextList *)list
349
+ charIndex:(NSUInteger)index
350
+ input:(EnrichedTextInputView *)input {
351
+ if (list.markerFormat == NSTextListMarkerDecimal) {
352
+ NSString *fullText = input->textView.textStorage.string;
353
+ NSInteger itemNumber = 1;
354
+
355
+ NSRange currentParagraph =
356
+ [fullText paragraphRangeForRange:NSMakeRange(index, 0)];
357
+ if (currentParagraph.location > 0) {
358
+ OrderedListStyle *olStyle =
359
+ input->stylesDict[@([OrderedListStyle getStyleType])];
360
+
361
+ NSInteger prevParagraphsCount = 0;
362
+ NSInteger recentParagraphLocation =
363
+ [fullText
364
+ paragraphRangeForRange:NSMakeRange(currentParagraph.location - 1,
365
+ 0)]
366
+ .location;
367
+
368
+ // seek for previous lists
369
+ while (true) {
370
+ if ([olStyle detectStyle:NSMakeRange(recentParagraphLocation, 0)]) {
371
+ prevParagraphsCount += 1;
372
+
373
+ if (recentParagraphLocation > 0) {
374
+ recentParagraphLocation =
375
+ [fullText
376
+ paragraphRangeForRange:NSMakeRange(
377
+ recentParagraphLocation - 1, 0)]
378
+ .location;
379
+ } else {
380
+ break;
381
+ }
382
+ } else {
383
+ break;
384
+ }
385
+ }
386
+
387
+ itemNumber = prevParagraphsCount + 1;
388
+ }
389
+
390
+ return [NSString stringWithFormat:@"%ld.", (long)(itemNumber)];
391
+ } else {
392
+ return @"•";
393
+ }
394
+ }
395
+
396
+ @end
@@ -13,41 +13,44 @@
13
13
  + (NSString *)stringByEscapingHtml:(NSString *)html {
14
14
  NSMutableString *escaped = [html mutableCopy];
15
15
  NSDictionary *escapeMap = @{
16
- @"&": @"&amp;",
17
- @"<": @"&lt;",
18
- @">": @"&gt;",
16
+ @"&" : @"&amp;",
17
+ @"<" : @"&lt;",
18
+ @">" : @"&gt;",
19
19
  };
20
-
21
- for(NSString *key in escapeMap) {
22
- [escaped replaceOccurrencesOfString:key withString:escapeMap[key] options:NSLiteralSearch range:NSMakeRange(0, escaped.length)];
20
+
21
+ for (NSString *key in escapeMap) {
22
+ [escaped replaceOccurrencesOfString:key
23
+ withString:escapeMap[key]
24
+ options:NSLiteralSearch
25
+ range:NSMakeRange(0, escaped.length)];
23
26
  }
24
27
  return escaped;
25
28
  }
26
29
 
27
30
  + (NSDictionary *)getEscapedCharactersInfoFrom:(NSString *)text {
28
31
  NSDictionary *unescapeMap = @{
29
- @"&amp;": @"&",
30
- @"&lt;": @"<",
31
- @"&gt;": @">",
32
+ @"&amp;" : @"&",
33
+ @"&lt;" : @"<",
34
+ @"&gt;" : @">",
32
35
  };
33
-
36
+
34
37
  NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
35
-
36
- for(NSString *key in unescapeMap) {
38
+
39
+ for (NSString *key in unescapeMap) {
37
40
  NSRange searchRange = NSMakeRange(0, text.length);
38
41
  NSRange foundRange;
39
42
 
40
- while(searchRange.location < text.length) {
43
+ while (searchRange.location < text.length) {
41
44
  foundRange = [text rangeOfString:key options:0 range:searchRange];
42
- if(foundRange.location == NSNotFound) {
45
+ if (foundRange.location == NSNotFound) {
43
46
  break;
44
47
  }
45
- results[@(foundRange.location)] = @[key, unescapeMap[key]];
48
+ results[@(foundRange.location)] = @[ key, unescapeMap[key] ];
46
49
  searchRange.location = foundRange.location + foundRange.length;
47
50
  searchRange.length = text.length - searchRange.location;
48
51
  }
49
52
  }
50
-
53
+
51
54
  return results;
52
55
  }
53
56
 
@@ -51,6 +51,140 @@ void EnrichedTextInputViewEventEmitter::onChangeHtml(OnChangeHtml event) const {
51
51
 
52
52
  void EnrichedTextInputViewEventEmitter::onChangeState(OnChangeState event) const {
53
53
  dispatchEvent("changeState", [event=std::move(event)](jsi::Runtime &runtime) {
54
+ auto payload = jsi::Object(runtime);
55
+ {
56
+ auto bold = jsi::Object(runtime);
57
+ bold.setProperty(runtime, "isActive", event.bold.isActive);
58
+ bold.setProperty(runtime, "isConflicting", event.bold.isConflicting);
59
+ bold.setProperty(runtime, "isBlocking", event.bold.isBlocking);
60
+ payload.setProperty(runtime, "bold", bold);
61
+ }
62
+ {
63
+ auto italic = jsi::Object(runtime);
64
+ italic.setProperty(runtime, "isActive", event.italic.isActive);
65
+ italic.setProperty(runtime, "isConflicting", event.italic.isConflicting);
66
+ italic.setProperty(runtime, "isBlocking", event.italic.isBlocking);
67
+ payload.setProperty(runtime, "italic", italic);
68
+ }
69
+ {
70
+ auto underline = jsi::Object(runtime);
71
+ underline.setProperty(runtime, "isActive", event.underline.isActive);
72
+ underline.setProperty(runtime, "isConflicting", event.underline.isConflicting);
73
+ underline.setProperty(runtime, "isBlocking", event.underline.isBlocking);
74
+ payload.setProperty(runtime, "underline", underline);
75
+ }
76
+ {
77
+ auto strikeThrough = jsi::Object(runtime);
78
+ strikeThrough.setProperty(runtime, "isActive", event.strikeThrough.isActive);
79
+ strikeThrough.setProperty(runtime, "isConflicting", event.strikeThrough.isConflicting);
80
+ strikeThrough.setProperty(runtime, "isBlocking", event.strikeThrough.isBlocking);
81
+ payload.setProperty(runtime, "strikeThrough", strikeThrough);
82
+ }
83
+ {
84
+ auto inlineCode = jsi::Object(runtime);
85
+ inlineCode.setProperty(runtime, "isActive", event.inlineCode.isActive);
86
+ inlineCode.setProperty(runtime, "isConflicting", event.inlineCode.isConflicting);
87
+ inlineCode.setProperty(runtime, "isBlocking", event.inlineCode.isBlocking);
88
+ payload.setProperty(runtime, "inlineCode", inlineCode);
89
+ }
90
+ {
91
+ auto h1 = jsi::Object(runtime);
92
+ h1.setProperty(runtime, "isActive", event.h1.isActive);
93
+ h1.setProperty(runtime, "isConflicting", event.h1.isConflicting);
94
+ h1.setProperty(runtime, "isBlocking", event.h1.isBlocking);
95
+ payload.setProperty(runtime, "h1", h1);
96
+ }
97
+ {
98
+ auto h2 = jsi::Object(runtime);
99
+ h2.setProperty(runtime, "isActive", event.h2.isActive);
100
+ h2.setProperty(runtime, "isConflicting", event.h2.isConflicting);
101
+ h2.setProperty(runtime, "isBlocking", event.h2.isBlocking);
102
+ payload.setProperty(runtime, "h2", h2);
103
+ }
104
+ {
105
+ auto h3 = jsi::Object(runtime);
106
+ h3.setProperty(runtime, "isActive", event.h3.isActive);
107
+ h3.setProperty(runtime, "isConflicting", event.h3.isConflicting);
108
+ h3.setProperty(runtime, "isBlocking", event.h3.isBlocking);
109
+ payload.setProperty(runtime, "h3", h3);
110
+ }
111
+ {
112
+ auto h4 = jsi::Object(runtime);
113
+ h4.setProperty(runtime, "isActive", event.h4.isActive);
114
+ h4.setProperty(runtime, "isConflicting", event.h4.isConflicting);
115
+ h4.setProperty(runtime, "isBlocking", event.h4.isBlocking);
116
+ payload.setProperty(runtime, "h4", h4);
117
+ }
118
+ {
119
+ auto h5 = jsi::Object(runtime);
120
+ h5.setProperty(runtime, "isActive", event.h5.isActive);
121
+ h5.setProperty(runtime, "isConflicting", event.h5.isConflicting);
122
+ h5.setProperty(runtime, "isBlocking", event.h5.isBlocking);
123
+ payload.setProperty(runtime, "h5", h5);
124
+ }
125
+ {
126
+ auto h6 = jsi::Object(runtime);
127
+ h6.setProperty(runtime, "isActive", event.h6.isActive);
128
+ h6.setProperty(runtime, "isConflicting", event.h6.isConflicting);
129
+ h6.setProperty(runtime, "isBlocking", event.h6.isBlocking);
130
+ payload.setProperty(runtime, "h6", h6);
131
+ }
132
+ {
133
+ auto codeBlock = jsi::Object(runtime);
134
+ codeBlock.setProperty(runtime, "isActive", event.codeBlock.isActive);
135
+ codeBlock.setProperty(runtime, "isConflicting", event.codeBlock.isConflicting);
136
+ codeBlock.setProperty(runtime, "isBlocking", event.codeBlock.isBlocking);
137
+ payload.setProperty(runtime, "codeBlock", codeBlock);
138
+ }
139
+ {
140
+ auto blockQuote = jsi::Object(runtime);
141
+ blockQuote.setProperty(runtime, "isActive", event.blockQuote.isActive);
142
+ blockQuote.setProperty(runtime, "isConflicting", event.blockQuote.isConflicting);
143
+ blockQuote.setProperty(runtime, "isBlocking", event.blockQuote.isBlocking);
144
+ payload.setProperty(runtime, "blockQuote", blockQuote);
145
+ }
146
+ {
147
+ auto orderedList = jsi::Object(runtime);
148
+ orderedList.setProperty(runtime, "isActive", event.orderedList.isActive);
149
+ orderedList.setProperty(runtime, "isConflicting", event.orderedList.isConflicting);
150
+ orderedList.setProperty(runtime, "isBlocking", event.orderedList.isBlocking);
151
+ payload.setProperty(runtime, "orderedList", orderedList);
152
+ }
153
+ {
154
+ auto unorderedList = jsi::Object(runtime);
155
+ unorderedList.setProperty(runtime, "isActive", event.unorderedList.isActive);
156
+ unorderedList.setProperty(runtime, "isConflicting", event.unorderedList.isConflicting);
157
+ unorderedList.setProperty(runtime, "isBlocking", event.unorderedList.isBlocking);
158
+ payload.setProperty(runtime, "unorderedList", unorderedList);
159
+ }
160
+ {
161
+ auto link = jsi::Object(runtime);
162
+ link.setProperty(runtime, "isActive", event.link.isActive);
163
+ link.setProperty(runtime, "isConflicting", event.link.isConflicting);
164
+ link.setProperty(runtime, "isBlocking", event.link.isBlocking);
165
+ payload.setProperty(runtime, "link", link);
166
+ }
167
+ {
168
+ auto image = jsi::Object(runtime);
169
+ image.setProperty(runtime, "isActive", event.image.isActive);
170
+ image.setProperty(runtime, "isConflicting", event.image.isConflicting);
171
+ image.setProperty(runtime, "isBlocking", event.image.isBlocking);
172
+ payload.setProperty(runtime, "image", image);
173
+ }
174
+ {
175
+ auto mention = jsi::Object(runtime);
176
+ mention.setProperty(runtime, "isActive", event.mention.isActive);
177
+ mention.setProperty(runtime, "isConflicting", event.mention.isConflicting);
178
+ mention.setProperty(runtime, "isBlocking", event.mention.isBlocking);
179
+ payload.setProperty(runtime, "mention", mention);
180
+ }
181
+ return payload;
182
+ });
183
+ }
184
+
185
+
186
+ void EnrichedTextInputViewEventEmitter::onChangeStateDeprecated(OnChangeStateDeprecated event) const {
187
+ dispatchEvent("changeStateDeprecated", [event=std::move(event)](jsi::Runtime &runtime) {
54
188
  auto payload = jsi::Object(runtime);
55
189
  payload.setProperty(runtime, "isBold", event.isBold);
56
190
  payload.setProperty(runtime, "isItalic", event.isItalic);
@@ -60,6 +194,9 @@ payload.setProperty(runtime, "isInlineCode", event.isInlineCode);
60
194
  payload.setProperty(runtime, "isH1", event.isH1);
61
195
  payload.setProperty(runtime, "isH2", event.isH2);
62
196
  payload.setProperty(runtime, "isH3", event.isH3);
197
+ payload.setProperty(runtime, "isH4", event.isH4);
198
+ payload.setProperty(runtime, "isH5", event.isH5);
199
+ payload.setProperty(runtime, "isH6", event.isH6);
63
200
  payload.setProperty(runtime, "isCodeBlock", event.isCodeBlock);
64
201
  payload.setProperty(runtime, "isBlockQuote", event.isBlockQuote);
65
202
  payload.setProperty(runtime, "isOrderedList", event.isOrderedList);
@@ -115,4 +252,23 @@ payload.setProperty(runtime, "text", event.text);
115
252
  });
116
253
  }
117
254
 
255
+
256
+ void EnrichedTextInputViewEventEmitter::onRequestHtmlResult(OnRequestHtmlResult event) const {
257
+ dispatchEvent("requestHtmlResult", [event=std::move(event)](jsi::Runtime &runtime) {
258
+ auto payload = jsi::Object(runtime);
259
+ payload.setProperty(runtime, "requestId", event.requestId);
260
+ payload.setProperty(runtime, "html", jsi::valueFromDynamic(runtime, event.html));
261
+ return payload;
262
+ });
263
+ }
264
+
265
+
266
+ void EnrichedTextInputViewEventEmitter::onInputKeyPress(OnInputKeyPress event) const {
267
+ dispatchEvent("inputKeyPress", [event=std::move(event)](jsi::Runtime &runtime) {
268
+ auto payload = jsi::Object(runtime);
269
+ payload.setProperty(runtime, "key", event.key);
270
+ return payload;
271
+ });
272
+ }
273
+
118
274
  } // namespace facebook::react