react-native-enriched 0.1.6 → 0.2.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.
- package/README.md +4 -14
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +4 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +2 -1
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +0 -45
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +111 -2
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +9 -3
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +42 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +135 -9
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +13 -3
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +13 -0
- package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +80 -9
- package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +188 -5
- package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +57 -30
- package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +91 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +24 -13
- package/android/src/main/java/com/swmansion/enriched/utils/ResourceManager.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +3 -0
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +12 -13
- package/android/src/main/res/drawable/broken_image.xml +10 -0
- package/ios/EnrichedTextInputView.h +27 -12
- package/ios/EnrichedTextInputView.mm +906 -547
- package/ios/attachments/ImageAttachment.h +10 -0
- package/ios/attachments/ImageAttachment.mm +34 -0
- package/ios/attachments/MediaAttachment.h +23 -0
- package/ios/attachments/MediaAttachment.mm +31 -0
- package/ios/config/InputConfig.h +12 -6
- package/ios/config/InputConfig.mm +71 -33
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +0 -45
- package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +41 -4
- package/ios/inputParser/InputParser.h +5 -5
- package/ios/inputParser/InputParser.mm +867 -333
- package/ios/inputTextView/InputTextView.h +1 -1
- package/ios/inputTextView/InputTextView.mm +100 -59
- package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
- package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -24
- package/ios/internals/EnrichedTextInputViewShadowNode.mm +64 -47
- package/ios/internals/EnrichedTextInputViewState.h +3 -1
- package/ios/styles/BlockQuoteStyle.mm +192 -142
- package/ios/styles/BoldStyle.mm +96 -62
- package/ios/styles/CodeBlockStyle.mm +304 -0
- package/ios/styles/H1Style.mm +10 -3
- package/ios/styles/H2Style.mm +10 -3
- package/ios/styles/H3Style.mm +10 -3
- package/ios/styles/HeadingStyleBase.mm +129 -84
- package/ios/styles/ImageStyle.mm +160 -0
- package/ios/styles/InlineCodeStyle.mm +149 -84
- package/ios/styles/ItalicStyle.mm +77 -51
- package/ios/styles/LinkStyle.mm +353 -224
- package/ios/styles/MentionStyle.mm +434 -220
- package/ios/styles/OrderedListStyle.mm +172 -105
- package/ios/styles/StrikethroughStyle.mm +53 -34
- package/ios/styles/UnderlineStyle.mm +69 -45
- package/ios/styles/UnorderedListStyle.mm +170 -105
- package/ios/utils/BaseStyleProtocol.h +3 -2
- package/ios/utils/ColorExtension.mm +7 -5
- package/ios/utils/FontExtension.mm +42 -27
- package/ios/utils/ImageData.h +10 -0
- package/ios/utils/ImageData.mm +4 -0
- package/ios/utils/LayoutManagerExtension.h +1 -1
- package/ios/utils/LayoutManagerExtension.mm +334 -109
- package/ios/utils/MentionParams.h +0 -1
- package/ios/utils/MentionStyleProps.h +1 -1
- package/ios/utils/MentionStyleProps.mm +27 -20
- package/ios/utils/OccurenceUtils.h +42 -38
- package/ios/utils/OccurenceUtils.mm +177 -107
- package/ios/utils/ParagraphAttributesUtils.h +6 -1
- package/ios/utils/ParagraphAttributesUtils.mm +152 -41
- package/ios/utils/ParagraphsUtils.h +2 -1
- package/ios/utils/ParagraphsUtils.mm +40 -26
- package/ios/utils/StringExtension.h +1 -1
- package/ios/utils/StringExtension.mm +19 -16
- package/ios/utils/StyleHeaders.h +35 -11
- package/ios/utils/TextInsertionUtils.h +13 -2
- package/ios/utils/TextInsertionUtils.mm +38 -20
- package/ios/utils/WordsUtils.h +2 -1
- package/ios/utils/WordsUtils.mm +32 -22
- package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
- package/ios/utils/ZeroWidthSpaceUtils.mm +153 -75
- package/lib/module/EnrichedTextInput.js +41 -3
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/EnrichedTextInputNativeComponent.ts +17 -5
- package/lib/module/normalizeHtmlStyle.js +0 -4
- package/lib/module/normalizeHtmlStyle.js.map +1 -1
- package/lib/typescript/src/EnrichedTextInput.d.ts +2 -5
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +7 -5
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +1 -1
- package/package.json +8 -1
- package/src/EnrichedTextInput.tsx +48 -7
- package/src/EnrichedTextInputNativeComponent.ts +17 -5
- package/src/normalizeHtmlStyle.ts +0 -4
|
@@ -1,63 +1,174 @@
|
|
|
1
1
|
#import "ParagraphAttributesUtils.h"
|
|
2
2
|
#import "EnrichedTextInputView.h"
|
|
3
|
-
#import "StyleHeaders.h"
|
|
4
3
|
#import "ParagraphsUtils.h"
|
|
4
|
+
#import "StyleHeaders.h"
|
|
5
5
|
#import "TextInsertionUtils.h"
|
|
6
6
|
|
|
7
7
|
@implementation ParagraphAttributesUtils
|
|
8
8
|
|
|
9
|
-
// if the user backspaces the last character in a line, the iOS applies typing
|
|
10
|
-
// in the case of some paragraph styles it
|
|
11
|
-
//
|
|
12
|
-
|
|
9
|
+
// if the user backspaces the last character in a line, the iOS applies typing
|
|
10
|
+
// attributes from the previous line in the case of some paragraph styles it
|
|
11
|
+
// works especially bad when a list point just appears this method handles that
|
|
12
|
+
// case differently with or without present paragraph styles
|
|
13
|
+
+ (BOOL)handleBackspaceInRange:(NSRange)range
|
|
14
|
+
replacementText:(NSString *)text
|
|
15
|
+
input:(id)input {
|
|
13
16
|
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
|
|
14
|
-
UnorderedListStyle *ulStyle =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
UnorderedListStyle *ulStyle =
|
|
18
|
+
typedInput->stylesDict[@([UnorderedListStyle getStyleType])];
|
|
19
|
+
OrderedListStyle *olStyle =
|
|
20
|
+
typedInput->stylesDict[@([OrderedListStyle getStyleType])];
|
|
21
|
+
BlockQuoteStyle *bqStyle =
|
|
22
|
+
typedInput->stylesDict[@([BlockQuoteStyle getStyleType])];
|
|
23
|
+
CodeBlockStyle *cbStyle =
|
|
24
|
+
typedInput->stylesDict[@([CodeBlockStyle getStyleType])];
|
|
25
|
+
|
|
26
|
+
if (typedInput == nullptr) {
|
|
19
27
|
return NO;
|
|
20
28
|
}
|
|
21
|
-
|
|
22
|
-
// we make sure it was a backspace (text with 0 length) and it deleted
|
|
23
|
-
|
|
29
|
+
|
|
30
|
+
// we make sure it was a backspace (text with 0 length) and it deleted
|
|
31
|
+
// something (range longer than 0)
|
|
32
|
+
if (text.length > 0 || range.length == 0) {
|
|
24
33
|
return NO;
|
|
25
34
|
}
|
|
26
|
-
|
|
35
|
+
|
|
27
36
|
// find a non-newline range of the paragraph
|
|
28
|
-
NSRange paragraphRange =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
NSRange paragraphRange =
|
|
38
|
+
[typedInput->textView.textStorage.string paragraphRangeForRange:range];
|
|
39
|
+
|
|
40
|
+
NSArray *paragraphs =
|
|
41
|
+
[ParagraphsUtils getNonNewlineRangesIn:typedInput->textView
|
|
42
|
+
range:paragraphRange];
|
|
43
|
+
if (paragraphs.count == 0) {
|
|
32
44
|
return NO;
|
|
33
45
|
}
|
|
34
|
-
|
|
46
|
+
|
|
35
47
|
NSRange nonNewlineRange = [(NSValue *)paragraphs.firstObject rangeValue];
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
|
|
49
|
+
// the backspace removes the whole content of a paragraph (possibly more but
|
|
50
|
+
// has to start where the paragraph starts)
|
|
51
|
+
if (range.location == nonNewlineRange.location &&
|
|
52
|
+
range.length >= nonNewlineRange.length) {
|
|
53
|
+
|
|
54
|
+
// for lists, quotes and codeblocks present we do the following:
|
|
55
|
+
// - manually do the removing
|
|
56
|
+
// - reset typing attribtues so that the previous line styles don't get
|
|
57
|
+
// applied
|
|
58
|
+
// - reapply the paragraph style that was present so that a zero width space
|
|
59
|
+
// appears here
|
|
60
|
+
NSArray *handledStyles = @[ ulStyle, olStyle, bqStyle, cbStyle ];
|
|
61
|
+
for (id<BaseStyleProtocol> style in handledStyles) {
|
|
62
|
+
if ([style detectStyle:nonNewlineRange]) {
|
|
63
|
+
[TextInsertionUtils replaceText:text
|
|
64
|
+
at:range
|
|
65
|
+
additionalAttributes:nullptr
|
|
66
|
+
input:typedInput
|
|
67
|
+
withSelection:YES];
|
|
68
|
+
typedInput->textView.typingAttributes =
|
|
69
|
+
typedInput->defaultTypingAttributes;
|
|
70
|
+
[style addAttributes:NSMakeRange(range.location, 0) withTypingAttr:YES];
|
|
71
|
+
return YES;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// otherwise (no paragraph styles present), we just do the replacement
|
|
76
|
+
// manually and reset typing attribtues
|
|
77
|
+
[TextInsertionUtils replaceText:text
|
|
78
|
+
at:range
|
|
79
|
+
additionalAttributes:nullptr
|
|
80
|
+
input:typedInput
|
|
81
|
+
withSelection:YES];
|
|
82
|
+
typedInput->textView.typingAttributes = typedInput->defaultTypingAttributes;
|
|
83
|
+
return YES;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return NO;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Handles the specific case of backspacing a newline character, which results
|
|
91
|
+
* in merging two paragraphs.
|
|
92
|
+
*
|
|
93
|
+
* THE PROBLEM:
|
|
94
|
+
* When merging a bottom paragraph (Source) into a top paragraph (Destination),
|
|
95
|
+
* the bottom paragraph normally brings all its attributes with it. If the top
|
|
96
|
+
* paragraph is a restrictive style (like a CodeBlock), and the bottom paragraph
|
|
97
|
+
* contains a conflicting style (like an H1 Header), a standard merge would
|
|
98
|
+
* create an invalid state (e.g., a CodeBlock that is also a Header).
|
|
99
|
+
*
|
|
100
|
+
* THE SOLUTION:
|
|
101
|
+
* 1. Identifies the dominant style of the paragraph ABOVE the deleted newline
|
|
102
|
+
* (`leftParagraphStyle`).
|
|
103
|
+
* 2. Checks the paragraph BELOW the newline (`rightRange`) for any styles that
|
|
104
|
+
* conflict with or are blocked by the top style.
|
|
105
|
+
* 3. Explicitly removes those forbidden styles from the bottom paragraph
|
|
106
|
+
* *before* the merge occurs.
|
|
107
|
+
* 4. Performs the merge (deletes the newline).
|
|
108
|
+
*
|
|
109
|
+
* @return YES if the newline backspace was handled and sanitized; NO otherwise.
|
|
110
|
+
*/
|
|
111
|
+
+ (BOOL)handleParagraphStylesMergeOnBackspace:(NSRange)range
|
|
112
|
+
replacementText:(NSString *)text
|
|
113
|
+
input:(id)input {
|
|
114
|
+
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
|
|
115
|
+
if (typedInput == nullptr) {
|
|
116
|
+
return NO;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (text.length == 0) {
|
|
120
|
+
NSRange leftRange = [typedInput->textView.textStorage.string
|
|
121
|
+
paragraphRangeForRange:NSMakeRange(range.location, 0)];
|
|
122
|
+
|
|
123
|
+
id<BaseStyleProtocol> leftParagraphStyle = nullptr;
|
|
124
|
+
for (NSNumber *key in typedInput->stylesDict) {
|
|
125
|
+
id<BaseStyleProtocol> style = typedInput->stylesDict[key];
|
|
126
|
+
if ([[style class] isParagraphStyle] && [style detectStyle:leftRange]) {
|
|
127
|
+
leftParagraphStyle = style;
|
|
128
|
+
}
|
|
45
129
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return YES;
|
|
130
|
+
|
|
131
|
+
if (leftParagraphStyle == nullptr) {
|
|
132
|
+
return NO;
|
|
50
133
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
134
|
+
|
|
135
|
+
// index out of bounds
|
|
136
|
+
NSUInteger rightRangeStart = range.location + range.length;
|
|
137
|
+
if (rightRangeStart >= typedInput->textView.textStorage.string.length) {
|
|
138
|
+
return NO;
|
|
55
139
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
140
|
+
|
|
141
|
+
NSRange rightRange = [typedInput->textView.textStorage.string
|
|
142
|
+
paragraphRangeForRange:NSMakeRange(rightRangeStart, 1)];
|
|
143
|
+
|
|
144
|
+
StyleType type = [[leftParagraphStyle class] getStyleType];
|
|
145
|
+
|
|
146
|
+
NSArray *conflictingStyles = [typedInput
|
|
147
|
+
getPresentStyleTypesFrom:typedInput->conflictingStyles[@(type)]
|
|
148
|
+
range:rightRange];
|
|
149
|
+
NSArray *blockingStyles =
|
|
150
|
+
[typedInput getPresentStyleTypesFrom:typedInput->blockingStyles[@(type)]
|
|
151
|
+
range:rightRange];
|
|
152
|
+
NSArray *allToBeRemoved =
|
|
153
|
+
[conflictingStyles arrayByAddingObjectsFromArray:blockingStyles];
|
|
154
|
+
|
|
155
|
+
for (NSNumber *style in allToBeRemoved) {
|
|
156
|
+
id<BaseStyleProtocol> styleClass = typedInput->stylesDict[style];
|
|
157
|
+
|
|
158
|
+
// for ranges, we need to remove each occurence
|
|
159
|
+
NSArray<StylePair *> *allOccurences =
|
|
160
|
+
[styleClass findAllOccurences:rightRange];
|
|
161
|
+
|
|
162
|
+
for (StylePair *pair in allOccurences) {
|
|
163
|
+
[styleClass removeAttributes:[pair.rangeValue rangeValue]];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
[TextInsertionUtils replaceText:text
|
|
168
|
+
at:range
|
|
169
|
+
additionalAttributes:nullptr
|
|
170
|
+
input:typedInput
|
|
171
|
+
withSelection:YES];
|
|
61
172
|
return YES;
|
|
62
173
|
}
|
|
63
174
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import <UIKit/UIKit.h>
|
|
3
3
|
|
|
4
4
|
@interface ParagraphsUtils : NSObject
|
|
5
|
-
+ (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
|
|
5
|
+
+ (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
|
|
6
|
+
range:(NSRange)range;
|
|
6
7
|
+ (NSArray *)getNonNewlineRangesIn:(UITextView *)textView range:(NSRange)range;
|
|
7
8
|
@end
|
|
@@ -2,52 +2,66 @@
|
|
|
2
2
|
|
|
3
3
|
@implementation ParagraphsUtils
|
|
4
4
|
|
|
5
|
-
+ (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
|
|
5
|
+
+ (NSArray *)getSeparateParagraphsRangesIn:(UITextView *)textView
|
|
6
|
+
range:(NSRange)range {
|
|
6
7
|
// just in case, get full paragraphs range
|
|
7
|
-
NSRange fullRange =
|
|
8
|
-
|
|
8
|
+
NSRange fullRange =
|
|
9
|
+
[textView.textStorage.string paragraphRangeForRange:range];
|
|
10
|
+
|
|
9
11
|
// we are in an empty paragraph
|
|
10
|
-
if(fullRange.length == 0) {
|
|
11
|
-
return @[[NSValue valueWithRange:fullRange]];
|
|
12
|
+
if (fullRange.length == 0) {
|
|
13
|
+
return @[ [NSValue valueWithRange:fullRange] ];
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
|
|
14
16
|
NSMutableArray *results = [[NSMutableArray alloc] init];
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
NSInteger lastStart = fullRange.location;
|
|
17
|
-
for(int i = fullRange.location; i < fullRange.location + fullRange.length;
|
|
19
|
+
for (int i = fullRange.location; i < fullRange.location + fullRange.length;
|
|
20
|
+
i++) {
|
|
18
21
|
unichar currentChar = [textView.textStorage.string characterAtIndex:i];
|
|
19
|
-
if([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
|
|
20
|
-
NSRange paragraphRange = [textView.textStorage.string
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
|
|
23
|
+
NSRange paragraphRange = [textView.textStorage.string
|
|
24
|
+
paragraphRangeForRange:NSMakeRange(lastStart, i - lastStart)];
|
|
25
|
+
[results addObject:[NSValue valueWithRange:paragraphRange]];
|
|
26
|
+
lastStart = i + 1;
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
|
-
|
|
26
|
-
if(lastStart < fullRange.location + fullRange.length) {
|
|
27
|
-
NSRange paragraphRange = [textView.textStorage.string
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
if (lastStart < fullRange.location + fullRange.length) {
|
|
31
|
+
NSRange paragraphRange = [textView.textStorage.string
|
|
32
|
+
paragraphRangeForRange:NSMakeRange(lastStart, fullRange.location +
|
|
33
|
+
fullRange.length -
|
|
34
|
+
lastStart)];
|
|
35
|
+
[results addObject:[NSValue valueWithRange:paragraphRange]];
|
|
29
36
|
}
|
|
30
|
-
|
|
37
|
+
|
|
31
38
|
return results;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
+ (NSArray *)getNonNewlineRangesIn:(UITextView *)textView range:(NSRange)range {
|
|
35
42
|
NSMutableArray *nonNewlineRanges = [[NSMutableArray alloc] init];
|
|
36
43
|
int lastRangeLocation = range.location;
|
|
37
|
-
|
|
38
|
-
for(int i = range.location; i < range.location + range.length; i++) {
|
|
44
|
+
|
|
45
|
+
for (int i = range.location; i < range.location + range.length; i++) {
|
|
39
46
|
unichar currentChar = [textView.textStorage.string characterAtIndex:i];
|
|
40
|
-
if([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
|
|
41
|
-
if(i - lastRangeLocation > 0) {
|
|
42
|
-
[nonNewlineRanges
|
|
47
|
+
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:currentChar]) {
|
|
48
|
+
if (i - lastRangeLocation > 0) {
|
|
49
|
+
[nonNewlineRanges
|
|
50
|
+
addObject:[NSValue
|
|
51
|
+
valueWithRange:NSMakeRange(lastRangeLocation,
|
|
52
|
+
i - lastRangeLocation)]];
|
|
43
53
|
}
|
|
44
|
-
lastRangeLocation = i+1;
|
|
54
|
+
lastRangeLocation = i + 1;
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
|
-
if(lastRangeLocation < range.location + range.length) {
|
|
48
|
-
[nonNewlineRanges
|
|
57
|
+
if (lastRangeLocation < range.location + range.length) {
|
|
58
|
+
[nonNewlineRanges
|
|
59
|
+
addObject:[NSValue
|
|
60
|
+
valueWithRange:NSMakeRange(lastRangeLocation,
|
|
61
|
+
range.location + range.length -
|
|
62
|
+
lastRangeLocation)]];
|
|
49
63
|
}
|
|
50
|
-
|
|
64
|
+
|
|
51
65
|
return nonNewlineRanges;
|
|
52
66
|
}
|
|
53
67
|
|
|
@@ -13,41 +13,44 @@
|
|
|
13
13
|
+ (NSString *)stringByEscapingHtml:(NSString *)html {
|
|
14
14
|
NSMutableString *escaped = [html mutableCopy];
|
|
15
15
|
NSDictionary *escapeMap = @{
|
|
16
|
-
@"&": @"&",
|
|
17
|
-
@"<": @"<",
|
|
18
|
-
@">": @">",
|
|
16
|
+
@"&" : @"&",
|
|
17
|
+
@"<" : @"<",
|
|
18
|
+
@">" : @">",
|
|
19
19
|
};
|
|
20
|
-
|
|
21
|
-
for(NSString *key in escapeMap) {
|
|
22
|
-
[escaped replaceOccurrencesOfString:key
|
|
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
|
-
@"&": @"&",
|
|
30
|
-
@"<": @"<",
|
|
31
|
-
@">": @">",
|
|
32
|
+
@"&" : @"&",
|
|
33
|
+
@"<" : @"<",
|
|
34
|
+
@">" : @">",
|
|
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
|
|
package/ios/utils/StyleHeaders.h
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#import "BaseStyleProtocol.h"
|
|
3
|
+
#import "ImageData.h"
|
|
3
4
|
#import "LinkData.h"
|
|
4
5
|
#import "MentionParams.h"
|
|
5
6
|
|
|
@@ -20,29 +21,37 @@
|
|
|
20
21
|
@end
|
|
21
22
|
|
|
22
23
|
@interface LinkStyle : NSObject <BaseStyleProtocol>
|
|
23
|
-
- (void)addLink:(NSString*)text
|
|
24
|
+
- (void)addLink:(NSString *)text
|
|
25
|
+
url:(NSString *)url
|
|
26
|
+
range:(NSRange)range
|
|
27
|
+
manual:(BOOL)manual
|
|
28
|
+
withSelection:(BOOL)withSelection;
|
|
24
29
|
- (LinkData *)getLinkDataAt:(NSUInteger)location;
|
|
25
30
|
- (NSRange)getFullLinkRangeAt:(NSUInteger)location;
|
|
26
31
|
- (void)manageLinkTypingAttributes;
|
|
27
32
|
- (void)handleAutomaticLinks:(NSString *)word inRange:(NSRange)wordRange;
|
|
28
33
|
- (void)handleManualLinks:(NSString *)word inRange:(NSRange)wordRange;
|
|
29
|
-
- (BOOL)handleLeadingLinkReplacement:(NSRange)range
|
|
34
|
+
- (BOOL)handleLeadingLinkReplacement:(NSRange)range
|
|
35
|
+
replacementText:(NSString *)text;
|
|
30
36
|
@end
|
|
31
37
|
|
|
32
|
-
@interface MentionStyle : NSObject<BaseStyleProtocol>
|
|
33
|
-
- (void)addMention:(NSString *)indicator
|
|
38
|
+
@interface MentionStyle : NSObject <BaseStyleProtocol>
|
|
39
|
+
- (void)addMention:(NSString *)indicator
|
|
40
|
+
text:(NSString *)text
|
|
41
|
+
attributes:(NSString *)attributes;
|
|
34
42
|
- (void)addMentionAtRange:(NSRange)range params:(MentionParams *)params;
|
|
35
43
|
- (void)startMentionWithIndicator:(NSString *)indicator;
|
|
36
44
|
- (void)handleExistingMentions;
|
|
37
45
|
- (void)manageMentionEditing;
|
|
38
46
|
- (void)manageMentionTypingAttributes;
|
|
39
|
-
- (BOOL)handleLeadingMentionReplacement:(NSRange)range
|
|
47
|
+
- (BOOL)handleLeadingMentionReplacement:(NSRange)range
|
|
48
|
+
replacementText:(NSString *)text;
|
|
40
49
|
- (MentionParams *)getMentionParamsAt:(NSUInteger)location;
|
|
41
50
|
- (NSRange)getFullMentionRangeAt:(NSUInteger)location;
|
|
42
51
|
- (NSValue *)getActiveMentionRange;
|
|
43
52
|
@end
|
|
44
53
|
|
|
45
|
-
@interface HeadingStyleBase : NSObject<BaseStyleProtocol> {
|
|
54
|
+
@interface HeadingStyleBase : NSObject <BaseStyleProtocol> {
|
|
46
55
|
id input;
|
|
47
56
|
}
|
|
48
57
|
- (CGFloat)getHeadingFontSize;
|
|
@@ -60,17 +69,32 @@
|
|
|
60
69
|
@interface H3Style : HeadingStyleBase
|
|
61
70
|
@end
|
|
62
71
|
|
|
63
|
-
@interface UnorderedListStyle : NSObject<BaseStyleProtocol>
|
|
72
|
+
@interface UnorderedListStyle : NSObject <BaseStyleProtocol>
|
|
64
73
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
65
|
-
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
|
|
74
|
+
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
|
|
75
|
+
replacementText:(NSString *)text;
|
|
66
76
|
@end
|
|
67
77
|
|
|
68
|
-
@interface OrderedListStyle : NSObject<BaseStyleProtocol>
|
|
78
|
+
@interface OrderedListStyle : NSObject <BaseStyleProtocol>
|
|
69
79
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
70
|
-
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
|
|
80
|
+
- (BOOL)tryHandlingListShorcutInRange:(NSRange)range
|
|
81
|
+
replacementText:(NSString *)text;
|
|
71
82
|
@end
|
|
72
83
|
|
|
73
|
-
@interface BlockQuoteStyle : NSObject<BaseStyleProtocol>
|
|
84
|
+
@interface BlockQuoteStyle : NSObject <BaseStyleProtocol>
|
|
74
85
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
75
86
|
- (void)manageBlockquoteColor;
|
|
76
87
|
@end
|
|
88
|
+
|
|
89
|
+
@interface CodeBlockStyle : NSObject <BaseStyleProtocol>
|
|
90
|
+
- (void)manageCodeBlockFontAndColor;
|
|
91
|
+
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
92
|
+
@end
|
|
93
|
+
|
|
94
|
+
@interface ImageStyle : NSObject <BaseStyleProtocol>
|
|
95
|
+
- (void)addImage:(NSString *)uri width:(CGFloat)width height:(CGFloat)height;
|
|
96
|
+
- (void)addImageAtRange:(NSRange)range
|
|
97
|
+
imageData:(ImageData *)imageData
|
|
98
|
+
withSelection:(BOOL)withSelection;
|
|
99
|
+
- (ImageData *)getImageDataAt:(NSUInteger)location;
|
|
100
|
+
@end
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
#import <UIKit/UIKit.h>
|
|
2
2
|
|
|
3
3
|
@interface TextInsertionUtils : NSObject
|
|
4
|
-
+ (void)insertText:(NSString*)text
|
|
5
|
-
|
|
4
|
+
+ (void)insertText:(NSString *)text
|
|
5
|
+
at:(NSInteger)index
|
|
6
|
+
additionalAttributes:
|
|
7
|
+
(NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
|
|
8
|
+
input:(id)input
|
|
9
|
+
withSelection:(BOOL)withSelection;
|
|
10
|
+
+ (void)replaceText:(NSString *)text
|
|
11
|
+
at:(NSRange)range
|
|
12
|
+
additionalAttributes:
|
|
13
|
+
(NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
|
|
14
|
+
input:(id)input
|
|
15
|
+
withSelection:(BOOL)withSelection;
|
|
16
|
+
;
|
|
6
17
|
@end
|
|
@@ -1,24 +1,33 @@
|
|
|
1
1
|
#import "TextInsertionUtils.h"
|
|
2
|
-
#import "UIView+React.h"
|
|
3
2
|
#import "EnrichedTextInputView.h"
|
|
3
|
+
#import "UIView+React.h"
|
|
4
4
|
|
|
5
5
|
@implementation TextInsertionUtils
|
|
6
|
-
+ (void)insertText:(NSString*)text
|
|
6
|
+
+ (void)insertText:(NSString *)text
|
|
7
|
+
at:(NSInteger)index
|
|
8
|
+
additionalAttributes:
|
|
9
|
+
(NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
|
|
10
|
+
input:(id)input
|
|
11
|
+
withSelection:(BOOL)withSelection {
|
|
7
12
|
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
|
|
8
|
-
if(typedInput == nullptr) {
|
|
9
|
-
|
|
13
|
+
if (typedInput == nullptr) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
UITextView *textView = typedInput->textView;
|
|
11
18
|
|
|
12
|
-
NSMutableDictionary<NSAttributedStringKey, id> *copiedAttrs =
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
NSMutableDictionary<NSAttributedStringKey, id> *copiedAttrs =
|
|
20
|
+
[textView.typingAttributes mutableCopy];
|
|
21
|
+
if (additionalAttrs != nullptr) {
|
|
22
|
+
[copiedAttrs addEntriesFromDictionary:additionalAttrs];
|
|
15
23
|
}
|
|
16
|
-
|
|
17
|
-
NSAttributedString *newAttrStr =
|
|
24
|
+
|
|
25
|
+
NSAttributedString *newAttrStr =
|
|
26
|
+
[[NSAttributedString alloc] initWithString:text attributes:copiedAttrs];
|
|
18
27
|
[textView.textStorage insertAttributedString:newAttrStr atIndex:index];
|
|
19
|
-
|
|
20
|
-
if(withSelection) {
|
|
21
|
-
if(![textView isFirstResponder]) {
|
|
28
|
+
|
|
29
|
+
if (withSelection) {
|
|
30
|
+
if (![textView isFirstResponder]) {
|
|
22
31
|
[textView reactFocus];
|
|
23
32
|
}
|
|
24
33
|
textView.selectedRange = NSMakeRange(index + text.length, 0);
|
|
@@ -26,19 +35,28 @@
|
|
|
26
35
|
typedInput->recentlyChangedRange = NSMakeRange(index, text.length);
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
+ (void)replaceText:(NSString*)text
|
|
38
|
+
+ (void)replaceText:(NSString *)text
|
|
39
|
+
at:(NSRange)range
|
|
40
|
+
additionalAttributes:
|
|
41
|
+
(NSDictionary<NSAttributedStringKey, id> *)additionalAttrs
|
|
42
|
+
input:(id)input
|
|
43
|
+
withSelection:(BOOL)withSelection {
|
|
30
44
|
EnrichedTextInputView *typedInput = (EnrichedTextInputView *)input;
|
|
31
|
-
if(typedInput == nullptr) {
|
|
32
|
-
|
|
45
|
+
if (typedInput == nullptr) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
33
49
|
UITextView *textView = typedInput->textView;
|
|
34
50
|
|
|
35
51
|
[textView.textStorage replaceCharactersInRange:range withString:text];
|
|
36
|
-
if(additionalAttrs != nullptr) {
|
|
37
|
-
[textView.textStorage
|
|
52
|
+
if (additionalAttrs != nullptr) {
|
|
53
|
+
[textView.textStorage
|
|
54
|
+
addAttributes:additionalAttrs
|
|
55
|
+
range:NSMakeRange(range.location, [text length])];
|
|
38
56
|
}
|
|
39
|
-
|
|
40
|
-
if(withSelection) {
|
|
41
|
-
if(![textView isFirstResponder]) {
|
|
57
|
+
|
|
58
|
+
if (withSelection) {
|
|
59
|
+
if (![textView isFirstResponder]) {
|
|
42
60
|
[textView reactFocus];
|
|
43
61
|
}
|
|
44
62
|
textView.selectedRange = NSMakeRange(range.location + text.length, 0);
|
package/ios/utils/WordsUtils.h
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import <UIKit/UIKit.h>
|
|
2
2
|
|
|
3
3
|
@interface WordsUtils : NSObject
|
|
4
|
-
+ (NSArray<NSDictionary *> *)getAffectedWordsFromText:(NSString *)text
|
|
4
|
+
+ (NSArray<NSDictionary *> *)getAffectedWordsFromText:(NSString *)text
|
|
5
|
+
modificationRange:(NSRange)range;
|
|
5
6
|
+ (NSDictionary *)getCurrentWord:(NSString *)text range:(NSRange)range;
|
|
6
7
|
@end
|