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
package/ios/styles/LinkStyle.mm
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
#import "StyleHeaders.h"
|
|
2
1
|
#import "EnrichedTextInputView.h"
|
|
3
2
|
#import "OccurenceUtils.h"
|
|
3
|
+
#import "StyleHeaders.h"
|
|
4
4
|
#import "TextInsertionUtils.h"
|
|
5
5
|
#import "UIView+React.h"
|
|
6
6
|
#import "WordsUtils.h"
|
|
7
7
|
|
|
8
|
-
// custom NSAttributedStringKeys to differentiate manually added and
|
|
8
|
+
// custom NSAttributedStringKeys to differentiate manually added and
|
|
9
|
+
// automatically detected links
|
|
9
10
|
static NSString *const ManualLinkAttributeName = @"ManualLinkAttributeName";
|
|
10
|
-
static NSString *const AutomaticLinkAttributeName =
|
|
11
|
+
static NSString *const AutomaticLinkAttributeName =
|
|
12
|
+
@"AutomaticLinkAttributeName";
|
|
11
13
|
|
|
12
14
|
@implementation LinkStyle {
|
|
13
15
|
EnrichedTextInputView *_input;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
+ (StyleType)getStyleType {
|
|
18
|
+
+ (StyleType)getStyleType {
|
|
19
|
+
return Link;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
+ (BOOL)isParagraphStyle {
|
|
23
|
+
return NO;
|
|
24
|
+
}
|
|
17
25
|
|
|
18
26
|
- (instancetype)initWithInput:(id)input {
|
|
19
27
|
self = [super init];
|
|
@@ -25,7 +33,7 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
25
33
|
// no-op for links
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
- (void)addAttributes:(NSRange)range {
|
|
36
|
+
- (void)addAttributes:(NSRange)range withTypingAttr:(BOOL)withTypingAttr {
|
|
29
37
|
// no-op for links
|
|
30
38
|
}
|
|
31
39
|
|
|
@@ -37,25 +45,39 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
37
45
|
- (void)removeAttributes:(NSRange)range {
|
|
38
46
|
NSArray<StylePair *> *links = [self findAllOccurences:range];
|
|
39
47
|
[_input->textView.textStorage beginEditing];
|
|
40
|
-
for(StylePair *pair in links) {
|
|
41
|
-
NSRange linkRange =
|
|
42
|
-
|
|
43
|
-
[_input->textView.textStorage removeAttribute:
|
|
44
|
-
|
|
45
|
-
[_input->textView.textStorage
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
for (StylePair *pair in links) {
|
|
49
|
+
NSRange linkRange =
|
|
50
|
+
[self getFullLinkRangeAt:[pair.rangeValue rangeValue].location];
|
|
51
|
+
[_input->textView.textStorage removeAttribute:ManualLinkAttributeName
|
|
52
|
+
range:linkRange];
|
|
53
|
+
[_input->textView.textStorage removeAttribute:AutomaticLinkAttributeName
|
|
54
|
+
range:linkRange];
|
|
55
|
+
[_input->textView.textStorage addAttribute:NSForegroundColorAttributeName
|
|
56
|
+
value:[_input->config primaryColor]
|
|
57
|
+
range:linkRange];
|
|
58
|
+
[_input->textView.textStorage addAttribute:NSUnderlineColorAttributeName
|
|
59
|
+
value:[_input->config primaryColor]
|
|
60
|
+
range:linkRange];
|
|
61
|
+
[_input->textView.textStorage addAttribute:NSStrikethroughColorAttributeName
|
|
62
|
+
value:[_input->config primaryColor]
|
|
63
|
+
range:linkRange];
|
|
64
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
65
|
+
[_input->textView.textStorage
|
|
66
|
+
removeAttribute:NSUnderlineStyleAttributeName
|
|
67
|
+
range:linkRange];
|
|
49
68
|
}
|
|
50
69
|
}
|
|
51
70
|
[_input->textView.textStorage endEditing];
|
|
52
|
-
|
|
71
|
+
|
|
53
72
|
// adjust typing attributes as well
|
|
54
|
-
NSMutableDictionary *newTypingAttrs =
|
|
55
|
-
|
|
73
|
+
NSMutableDictionary *newTypingAttrs =
|
|
74
|
+
[_input->textView.typingAttributes mutableCopy];
|
|
75
|
+
newTypingAttrs[NSForegroundColorAttributeName] =
|
|
76
|
+
[_input->config primaryColor];
|
|
56
77
|
newTypingAttrs[NSUnderlineColorAttributeName] = [_input->config primaryColor];
|
|
57
|
-
newTypingAttrs[NSStrikethroughColorAttributeName] =
|
|
58
|
-
|
|
78
|
+
newTypingAttrs[NSStrikethroughColorAttributeName] =
|
|
79
|
+
[_input->config primaryColor];
|
|
80
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
59
81
|
[newTypingAttrs removeObjectForKey:NSUnderlineStyleAttributeName];
|
|
60
82
|
}
|
|
61
83
|
_input->textView.typingAttributes = newTypingAttrs;
|
|
@@ -63,41 +85,56 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
63
85
|
|
|
64
86
|
// used for conflicts, we have to remove the whole link
|
|
65
87
|
- (void)removeTypingAttributes {
|
|
66
|
-
NSRange linkRange =
|
|
88
|
+
NSRange linkRange =
|
|
89
|
+
[self getFullLinkRangeAt:_input->textView.selectedRange.location];
|
|
67
90
|
[_input->textView.textStorage beginEditing];
|
|
68
|
-
[_input->textView.textStorage removeAttribute:ManualLinkAttributeName
|
|
69
|
-
|
|
70
|
-
[_input->textView.textStorage
|
|
71
|
-
|
|
72
|
-
[_input->textView.textStorage addAttribute:
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
[_input->textView.textStorage removeAttribute:ManualLinkAttributeName
|
|
92
|
+
range:linkRange];
|
|
93
|
+
[_input->textView.textStorage removeAttribute:AutomaticLinkAttributeName
|
|
94
|
+
range:linkRange];
|
|
95
|
+
[_input->textView.textStorage addAttribute:NSForegroundColorAttributeName
|
|
96
|
+
value:[_input->config primaryColor]
|
|
97
|
+
range:linkRange];
|
|
98
|
+
[_input->textView.textStorage addAttribute:NSUnderlineColorAttributeName
|
|
99
|
+
value:[_input->config primaryColor]
|
|
100
|
+
range:linkRange];
|
|
101
|
+
[_input->textView.textStorage addAttribute:NSStrikethroughColorAttributeName
|
|
102
|
+
value:[_input->config primaryColor]
|
|
103
|
+
range:linkRange];
|
|
104
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
105
|
+
[_input->textView.textStorage removeAttribute:NSUnderlineStyleAttributeName
|
|
106
|
+
range:linkRange];
|
|
75
107
|
}
|
|
76
108
|
[_input->textView.textStorage endEditing];
|
|
77
|
-
|
|
109
|
+
|
|
78
110
|
// adjust typing attributes as well
|
|
79
|
-
NSMutableDictionary *newTypingAttrs =
|
|
80
|
-
|
|
111
|
+
NSMutableDictionary *newTypingAttrs =
|
|
112
|
+
[_input->textView.typingAttributes mutableCopy];
|
|
113
|
+
newTypingAttrs[NSForegroundColorAttributeName] =
|
|
114
|
+
[_input->config primaryColor];
|
|
81
115
|
newTypingAttrs[NSUnderlineColorAttributeName] = [_input->config primaryColor];
|
|
82
|
-
newTypingAttrs[NSStrikethroughColorAttributeName] =
|
|
83
|
-
|
|
116
|
+
newTypingAttrs[NSStrikethroughColorAttributeName] =
|
|
117
|
+
[_input->config primaryColor];
|
|
118
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
84
119
|
[newTypingAttrs removeObjectForKey:NSUnderlineStyleAttributeName];
|
|
85
120
|
}
|
|
86
121
|
_input->textView.typingAttributes = newTypingAttrs;
|
|
87
122
|
}
|
|
88
123
|
|
|
89
|
-
- (BOOL)styleCondition:(id _Nullable)value
|
|
124
|
+
- (BOOL)styleCondition:(id _Nullable)value:(NSRange)range {
|
|
90
125
|
NSString *linkValue = (NSString *)value;
|
|
91
126
|
return linkValue != nullptr;
|
|
92
127
|
}
|
|
93
128
|
|
|
94
129
|
- (BOOL)detectStyle:(NSRange)range {
|
|
95
|
-
if(range.length >= 1) {
|
|
96
|
-
BOOL onlyLinks = [OccurenceUtils
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
130
|
+
if (range.length >= 1) {
|
|
131
|
+
BOOL onlyLinks = [OccurenceUtils
|
|
132
|
+
detectMultiple:@[ ManualLinkAttributeName, AutomaticLinkAttributeName ]
|
|
133
|
+
withInput:_input
|
|
134
|
+
inRange:range
|
|
135
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
136
|
+
return [self styleCondition:value:range];
|
|
137
|
+
}];
|
|
101
138
|
return onlyLinks ? [self isSingleLinkIn:range] : NO;
|
|
102
139
|
} else {
|
|
103
140
|
return [self getLinkDataAt:range.location] != nullptr;
|
|
@@ -105,67 +142,90 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
105
142
|
}
|
|
106
143
|
|
|
107
144
|
- (BOOL)anyOccurence:(NSRange)range {
|
|
108
|
-
return [OccurenceUtils
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
145
|
+
return [OccurenceUtils
|
|
146
|
+
anyMultiple:@[ ManualLinkAttributeName, AutomaticLinkAttributeName ]
|
|
147
|
+
withInput:_input
|
|
148
|
+
inRange:range
|
|
149
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
150
|
+
return [self styleCondition:value:range];
|
|
151
|
+
}];
|
|
113
152
|
}
|
|
114
153
|
|
|
115
154
|
- (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
|
|
116
|
-
return [OccurenceUtils
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
155
|
+
return [OccurenceUtils
|
|
156
|
+
allMultiple:@[ ManualLinkAttributeName, AutomaticLinkAttributeName ]
|
|
157
|
+
withInput:_input
|
|
158
|
+
inRange:range
|
|
159
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
160
|
+
return [self styleCondition:value:range];
|
|
161
|
+
}];
|
|
121
162
|
}
|
|
122
163
|
|
|
123
164
|
// MARK: - Public non-standard methods
|
|
124
165
|
|
|
125
|
-
- (void)addLink:(NSString*)text
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
166
|
+
- (void)addLink:(NSString *)text
|
|
167
|
+
url:(NSString *)url
|
|
168
|
+
range:(NSRange)range
|
|
169
|
+
manual:(BOOL)manual
|
|
170
|
+
withSelection:(BOOL)withSelection {
|
|
171
|
+
NSString *currentText =
|
|
172
|
+
[_input->textView.textStorage.string substringWithRange:range];
|
|
173
|
+
|
|
174
|
+
NSMutableDictionary<NSAttributedStringKey, id> *newAttrs =
|
|
175
|
+
[[NSMutableDictionary<NSAttributedStringKey, id> alloc] init];
|
|
129
176
|
newAttrs[NSForegroundColorAttributeName] = [_input->config linkColor];
|
|
130
177
|
newAttrs[NSUnderlineColorAttributeName] = [_input->config linkColor];
|
|
131
178
|
newAttrs[NSStrikethroughColorAttributeName] = [_input->config linkColor];
|
|
132
|
-
if([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
179
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
133
180
|
newAttrs[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
|
|
134
181
|
}
|
|
135
|
-
if(manual) {
|
|
182
|
+
if (manual) {
|
|
136
183
|
newAttrs[ManualLinkAttributeName] = [url copy];
|
|
137
184
|
} else {
|
|
138
185
|
newAttrs[AutomaticLinkAttributeName] = [url copy];
|
|
139
186
|
}
|
|
140
|
-
|
|
141
|
-
if(range.length == 0) {
|
|
187
|
+
|
|
188
|
+
if (range.length == 0) {
|
|
142
189
|
// insert link
|
|
143
|
-
[TextInsertionUtils insertText:text
|
|
144
|
-
|
|
190
|
+
[TextInsertionUtils insertText:text
|
|
191
|
+
at:range.location
|
|
192
|
+
additionalAttributes:newAttrs
|
|
193
|
+
input:_input
|
|
194
|
+
withSelection:withSelection];
|
|
195
|
+
} else if ([currentText isEqualToString:text]) {
|
|
145
196
|
// apply link attributes
|
|
146
197
|
[_input->textView.textStorage addAttributes:newAttrs range:range];
|
|
147
|
-
// TextInsertionUtils take care of the selection but here we have to
|
|
148
|
-
// ONLY with manual links, automatic ones
|
|
149
|
-
|
|
198
|
+
// TextInsertionUtils take care of the selection but here we have to
|
|
199
|
+
// manually set it behind the link ONLY with manual links, automatic ones
|
|
200
|
+
// don't need the selection fix
|
|
201
|
+
if (manual && withSelection) {
|
|
150
202
|
[_input->textView reactFocus];
|
|
151
|
-
_input->textView.selectedRange =
|
|
203
|
+
_input->textView.selectedRange =
|
|
204
|
+
NSMakeRange(range.location + text.length, 0);
|
|
152
205
|
}
|
|
153
206
|
} else {
|
|
154
207
|
// replace text with link
|
|
155
|
-
[TextInsertionUtils replaceText:text
|
|
208
|
+
[TextInsertionUtils replaceText:text
|
|
209
|
+
at:range
|
|
210
|
+
additionalAttributes:newAttrs
|
|
211
|
+
input:_input
|
|
212
|
+
withSelection:withSelection];
|
|
156
213
|
}
|
|
157
|
-
|
|
214
|
+
|
|
158
215
|
// mandatory connected links check
|
|
159
|
-
NSDictionary *currentWord =
|
|
160
|
-
|
|
216
|
+
NSDictionary *currentWord =
|
|
217
|
+
[WordsUtils getCurrentWord:_input->textView.textStorage.string
|
|
218
|
+
range:_input->textView.selectedRange];
|
|
219
|
+
if (currentWord != nullptr) {
|
|
161
220
|
// get word properties
|
|
162
221
|
NSString *wordText = (NSString *)[currentWord objectForKey:@"word"];
|
|
163
222
|
NSValue *wordRangeValue = (NSValue *)[currentWord objectForKey:@"range"];
|
|
164
|
-
if(wordText != nullptr && wordRangeValue != nullptr) {
|
|
165
|
-
[self removeConnectedLinksIfNeeded:wordText
|
|
223
|
+
if (wordText != nullptr && wordRangeValue != nullptr) {
|
|
224
|
+
[self removeConnectedLinksIfNeeded:wordText
|
|
225
|
+
range:[wordRangeValue rangeValue]];
|
|
166
226
|
}
|
|
167
227
|
}
|
|
168
|
-
|
|
228
|
+
|
|
169
229
|
[self manageLinkTypingAttributes];
|
|
170
230
|
}
|
|
171
231
|
|
|
@@ -174,36 +234,37 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
174
234
|
NSRange manualLinkRange = NSMakeRange(0, 0);
|
|
175
235
|
NSRange automaticLinkRange = NSMakeRange(0, 0);
|
|
176
236
|
NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
|
|
177
|
-
|
|
237
|
+
|
|
178
238
|
// don't search at the very end of input
|
|
179
239
|
NSUInteger searchLocation = location;
|
|
180
|
-
if(searchLocation == _input->textView.textStorage.length) {
|
|
240
|
+
if (searchLocation == _input->textView.textStorage.length) {
|
|
181
241
|
return nullptr;
|
|
182
242
|
}
|
|
183
|
-
|
|
184
|
-
NSString *manualUrl =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if((manualUrl == nullptr && automaticUrl == nullptr) || (manualLinkRange.length == 0 && automaticLinkRange.length == 0)) {
|
|
243
|
+
|
|
244
|
+
NSString *manualUrl =
|
|
245
|
+
[_input->textView.textStorage attribute:ManualLinkAttributeName
|
|
246
|
+
atIndex:searchLocation
|
|
247
|
+
longestEffectiveRange:&manualLinkRange
|
|
248
|
+
inRange:inputRange];
|
|
249
|
+
NSString *automaticUrl =
|
|
250
|
+
[_input->textView.textStorage attribute:AutomaticLinkAttributeName
|
|
251
|
+
atIndex:searchLocation
|
|
252
|
+
longestEffectiveRange:&automaticLinkRange
|
|
253
|
+
inRange:inputRange];
|
|
254
|
+
|
|
255
|
+
if ((manualUrl == nullptr && automaticUrl == nullptr) ||
|
|
256
|
+
(manualLinkRange.length == 0 && automaticLinkRange.length == 0)) {
|
|
198
257
|
return nullptr;
|
|
199
258
|
}
|
|
200
|
-
|
|
259
|
+
|
|
201
260
|
NSString *linkUrl = manualUrl == nullptr ? automaticUrl : manualUrl;
|
|
202
|
-
NSRange linkRange =
|
|
203
|
-
|
|
261
|
+
NSRange linkRange =
|
|
262
|
+
manualUrl == nullptr ? automaticLinkRange : manualLinkRange;
|
|
263
|
+
|
|
204
264
|
LinkData *data = [[LinkData alloc] init];
|
|
205
265
|
data.url = linkUrl;
|
|
206
|
-
data.text =
|
|
266
|
+
data.text =
|
|
267
|
+
[_input->textView.textStorage.string substringWithRange:linkRange];
|
|
207
268
|
return data;
|
|
208
269
|
}
|
|
209
270
|
|
|
@@ -212,64 +273,71 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
212
273
|
NSRange manualLinkRange = NSMakeRange(0, 0);
|
|
213
274
|
NSRange automaticLinkRange = NSMakeRange(0, 0);
|
|
214
275
|
NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
|
|
215
|
-
|
|
276
|
+
|
|
216
277
|
// get the previous index if possible when at the very end of input
|
|
217
278
|
NSUInteger searchLocation = location;
|
|
218
|
-
if(searchLocation == _input->textView.textStorage.length) {
|
|
219
|
-
if(searchLocation == 0) {
|
|
279
|
+
if (searchLocation == _input->textView.textStorage.length) {
|
|
280
|
+
if (searchLocation == 0) {
|
|
220
281
|
return NSMakeRange(0, 0);
|
|
221
282
|
} else {
|
|
222
283
|
searchLocation = searchLocation - 1;
|
|
223
284
|
}
|
|
224
285
|
}
|
|
225
|
-
|
|
226
|
-
NSString *manualLink =
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
];
|
|
238
|
-
|
|
286
|
+
|
|
287
|
+
NSString *manualLink =
|
|
288
|
+
[_input->textView.textStorage attribute:ManualLinkAttributeName
|
|
289
|
+
atIndex:searchLocation
|
|
290
|
+
longestEffectiveRange:&manualLinkRange
|
|
291
|
+
inRange:inputRange];
|
|
292
|
+
NSString *automaticLink =
|
|
293
|
+
[_input->textView.textStorage attribute:AutomaticLinkAttributeName
|
|
294
|
+
atIndex:searchLocation
|
|
295
|
+
longestEffectiveRange:&automaticLinkRange
|
|
296
|
+
inRange:inputRange];
|
|
297
|
+
|
|
239
298
|
return manualLink == nullptr
|
|
240
|
-
|
|
241
|
-
|
|
299
|
+
? automaticLink == nullptr ? NSMakeRange(0, 0) : automaticLinkRange
|
|
300
|
+
: manualLinkRange;
|
|
242
301
|
}
|
|
243
302
|
|
|
244
303
|
- (void)manageLinkTypingAttributes {
|
|
245
|
-
// link's typing attribtues need to be removed at ALL times whenever we have
|
|
304
|
+
// link's typing attribtues need to be removed at ALL times whenever we have
|
|
305
|
+
// some link around
|
|
246
306
|
BOOL removeAttrs = NO;
|
|
247
|
-
|
|
248
|
-
if(_input->textView.selectedRange.length == 0) {
|
|
307
|
+
|
|
308
|
+
if (_input->textView.selectedRange.length == 0) {
|
|
249
309
|
// check before
|
|
250
|
-
if(_input->textView.selectedRange.location >= 1) {
|
|
251
|
-
if([self detectStyle:NSMakeRange(
|
|
310
|
+
if (_input->textView.selectedRange.location >= 1) {
|
|
311
|
+
if ([self detectStyle:NSMakeRange(
|
|
312
|
+
_input->textView.selectedRange.location - 1,
|
|
313
|
+
1)]) {
|
|
252
314
|
removeAttrs = YES;
|
|
253
315
|
}
|
|
254
316
|
}
|
|
255
317
|
// check after
|
|
256
|
-
if(_input->textView.selectedRange.location <
|
|
257
|
-
|
|
318
|
+
if (_input->textView.selectedRange.location <
|
|
319
|
+
_input->textView.textStorage.length) {
|
|
320
|
+
if ([self detectStyle:NSMakeRange(_input->textView.selectedRange.location,
|
|
321
|
+
1)]) {
|
|
258
322
|
removeAttrs = YES;
|
|
259
323
|
}
|
|
260
324
|
}
|
|
261
325
|
} else {
|
|
262
|
-
if([self anyOccurence:_input->textView.selectedRange]) {
|
|
326
|
+
if ([self anyOccurence:_input->textView.selectedRange]) {
|
|
263
327
|
removeAttrs = YES;
|
|
264
328
|
}
|
|
265
329
|
}
|
|
266
|
-
|
|
267
|
-
if(removeAttrs) {
|
|
268
|
-
NSMutableDictionary *newTypingAttrs =
|
|
269
|
-
|
|
270
|
-
newTypingAttrs[
|
|
271
|
-
|
|
272
|
-
|
|
330
|
+
|
|
331
|
+
if (removeAttrs) {
|
|
332
|
+
NSMutableDictionary *newTypingAttrs =
|
|
333
|
+
[_input->textView.typingAttributes mutableCopy];
|
|
334
|
+
newTypingAttrs[NSForegroundColorAttributeName] =
|
|
335
|
+
[_input->config primaryColor];
|
|
336
|
+
newTypingAttrs[NSUnderlineColorAttributeName] =
|
|
337
|
+
[_input->config primaryColor];
|
|
338
|
+
newTypingAttrs[NSStrikethroughColorAttributeName] =
|
|
339
|
+
[_input->config primaryColor];
|
|
340
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
273
341
|
[newTypingAttrs removeObjectForKey:NSUnderlineStyleAttributeName];
|
|
274
342
|
}
|
|
275
343
|
_input->textView.typingAttributes = newTypingAttrs;
|
|
@@ -278,78 +346,106 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
278
346
|
|
|
279
347
|
// handles detecting and removing automatic links
|
|
280
348
|
- (void)handleAutomaticLinks:(NSString *)word inRange:(NSRange)wordRange {
|
|
281
|
-
InlineCodeStyle *inlineCodeStyle =
|
|
282
|
-
|
|
283
|
-
|
|
349
|
+
InlineCodeStyle *inlineCodeStyle =
|
|
350
|
+
[_input->stylesDict objectForKey:@([InlineCodeStyle getStyleType])];
|
|
351
|
+
MentionStyle *mentionStyle =
|
|
352
|
+
[_input->stylesDict objectForKey:@([MentionStyle getStyleType])];
|
|
353
|
+
CodeBlockStyle *codeBlockStyle =
|
|
354
|
+
[_input->stylesDict objectForKey:@([CodeBlockStyle getStyleType])];
|
|
355
|
+
|
|
284
356
|
if (inlineCodeStyle == nullptr || mentionStyle == nullptr) {
|
|
285
357
|
return;
|
|
286
358
|
}
|
|
287
|
-
|
|
359
|
+
|
|
288
360
|
// we don't recognize links along mentions
|
|
289
361
|
if ([mentionStyle anyOccurence:wordRange]) {
|
|
290
362
|
return;
|
|
291
363
|
}
|
|
292
|
-
|
|
364
|
+
|
|
293
365
|
// we don't recognize links among inline code
|
|
294
366
|
if ([inlineCodeStyle anyOccurence:wordRange]) {
|
|
295
367
|
return;
|
|
296
368
|
}
|
|
297
|
-
|
|
369
|
+
|
|
370
|
+
// we don't recognize links in codeblocks
|
|
371
|
+
if ([codeBlockStyle anyOccurence:wordRange]) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
298
375
|
// remove connected different links
|
|
299
376
|
[self removeConnectedLinksIfNeeded:word range:wordRange];
|
|
300
|
-
|
|
377
|
+
|
|
301
378
|
// we don't recognize automatic links along manual ones
|
|
302
379
|
__block BOOL manualLinkPresent = NO;
|
|
303
|
-
[_input->textView.textStorage
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
380
|
+
[_input->textView.textStorage
|
|
381
|
+
enumerateAttribute:ManualLinkAttributeName
|
|
382
|
+
inRange:wordRange
|
|
383
|
+
options:0
|
|
384
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
385
|
+
NSString *urlValue = (NSString *)value;
|
|
386
|
+
if (urlValue != nullptr) {
|
|
387
|
+
manualLinkPresent = YES;
|
|
388
|
+
*stop = YES;
|
|
389
|
+
}
|
|
390
|
+
}];
|
|
391
|
+
if (manualLinkPresent) {
|
|
312
392
|
return;
|
|
313
393
|
}
|
|
314
|
-
|
|
315
|
-
NSRegularExpression *fullRegex = [NSRegularExpression
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
394
|
+
|
|
395
|
+
NSRegularExpression *fullRegex = [NSRegularExpression
|
|
396
|
+
regularExpressionWithPattern:@"http(s)?:\\/\\/"
|
|
397
|
+
@"www\\.[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-"
|
|
398
|
+
@"z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)"
|
|
399
|
+
options:0
|
|
400
|
+
error:nullptr];
|
|
401
|
+
NSRegularExpression *wwwRegex = [NSRegularExpression
|
|
402
|
+
regularExpressionWithPattern:@"www\\.[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-"
|
|
403
|
+
@"z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)"
|
|
404
|
+
options:0
|
|
405
|
+
error:nullptr];
|
|
406
|
+
NSRegularExpression *bareRegex = [NSRegularExpression
|
|
407
|
+
regularExpressionWithPattern:@"[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-z]{2,"
|
|
408
|
+
@"6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)"
|
|
409
|
+
options:0
|
|
410
|
+
error:nullptr];
|
|
411
|
+
|
|
328
412
|
NSString *regexPassedUrl = nullptr;
|
|
329
|
-
|
|
330
|
-
if ([fullRegex numberOfMatchesInString:word
|
|
413
|
+
|
|
414
|
+
if ([fullRegex numberOfMatchesInString:word
|
|
415
|
+
options:0
|
|
416
|
+
range:NSMakeRange(0, word.length)]) {
|
|
331
417
|
regexPassedUrl = word;
|
|
332
|
-
} else if ([wwwRegex numberOfMatchesInString:word
|
|
418
|
+
} else if ([wwwRegex numberOfMatchesInString:word
|
|
419
|
+
options:0
|
|
420
|
+
range:NSMakeRange(0, word.length)]) {
|
|
333
421
|
regexPassedUrl = word;
|
|
334
|
-
} else if ([bareRegex numberOfMatchesInString:word
|
|
422
|
+
} else if ([bareRegex numberOfMatchesInString:word
|
|
423
|
+
options:0
|
|
424
|
+
range:NSMakeRange(0, word.length)]) {
|
|
335
425
|
regexPassedUrl = word;
|
|
336
426
|
} else if ([self anyOccurence:wordRange]) {
|
|
337
|
-
// there was some automatic link (because anyOccurence is true and we are
|
|
338
|
-
// still, it didn't pass any regex - needs
|
|
427
|
+
// there was some automatic link (because anyOccurence is true and we are
|
|
428
|
+
// sure there are no manual links) still, it didn't pass any regex - needs
|
|
429
|
+
// to be removed
|
|
339
430
|
[self removeAttributes:wordRange];
|
|
340
431
|
}
|
|
341
|
-
|
|
342
|
-
if(regexPassedUrl != nullptr) {
|
|
432
|
+
|
|
433
|
+
if (regexPassedUrl != nullptr) {
|
|
343
434
|
// add style only if needed
|
|
344
435
|
BOOL addStyle = YES;
|
|
345
|
-
if([self detectStyle:wordRange]) {
|
|
436
|
+
if ([self detectStyle:wordRange]) {
|
|
346
437
|
LinkData *currentData = [self getLinkDataAt:wordRange.location];
|
|
347
|
-
if(currentData != nullptr && currentData.url != nullptr &&
|
|
438
|
+
if (currentData != nullptr && currentData.url != nullptr &&
|
|
439
|
+
[currentData.url isEqualToString:regexPassedUrl]) {
|
|
348
440
|
addStyle = NO;
|
|
349
441
|
}
|
|
350
442
|
}
|
|
351
|
-
if(addStyle) {
|
|
352
|
-
[self addLink:word
|
|
443
|
+
if (addStyle) {
|
|
444
|
+
[self addLink:word
|
|
445
|
+
url:regexPassedUrl
|
|
446
|
+
range:wordRange
|
|
447
|
+
manual:NO
|
|
448
|
+
withSelection:NO];
|
|
353
449
|
// emit onLinkDetected if style was added
|
|
354
450
|
[_input emitOnLinkDetectedEvent:word url:regexPassedUrl range:wordRange];
|
|
355
451
|
}
|
|
@@ -363,57 +459,83 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
363
459
|
__block NSString *manualLinkMaxValue = @"";
|
|
364
460
|
__block NSInteger manualLinkMinIdx = -1;
|
|
365
461
|
__block NSInteger manualLinkMaxIdx = -1;
|
|
366
|
-
|
|
367
|
-
[_input->textView.textStorage
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
462
|
+
|
|
463
|
+
[_input->textView.textStorage
|
|
464
|
+
enumerateAttribute:ManualLinkAttributeName
|
|
465
|
+
inRange:wordRange
|
|
466
|
+
options:0
|
|
467
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
468
|
+
NSString *urlValue = (NSString *)value;
|
|
469
|
+
if (urlValue != nullptr) {
|
|
470
|
+
NSInteger linkMin = range.location;
|
|
471
|
+
NSInteger linkMax = range.location + range.length - 1;
|
|
472
|
+
if (manualLinkMinIdx == -1 || linkMin < manualLinkMinIdx) {
|
|
473
|
+
manualLinkMinIdx = linkMin;
|
|
474
|
+
manualLinkMinValue = value;
|
|
475
|
+
}
|
|
476
|
+
if (manualLinkMaxIdx == -1 || linkMax > manualLinkMaxIdx) {
|
|
477
|
+
manualLinkMaxIdx = linkMax;
|
|
478
|
+
manualLinkMaxValue = value;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}];
|
|
482
|
+
|
|
384
483
|
// no manual links
|
|
385
|
-
if(manualLinkMinIdx == -1 || manualLinkMaxIdx == -1) {
|
|
484
|
+
if (manualLinkMinIdx == -1 || manualLinkMaxIdx == -1) {
|
|
386
485
|
return;
|
|
387
486
|
}
|
|
388
|
-
|
|
487
|
+
|
|
389
488
|
// heuristic for refreshing manual links:
|
|
390
489
|
// we update the Manual attribute between the bounds of existing ones
|
|
391
490
|
// we do that only if the bounds point to the same url
|
|
392
|
-
// this way manual link gets "extended" only if some characters were added
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
[_input->textView.textStorage addAttribute:
|
|
398
|
-
|
|
399
|
-
|
|
491
|
+
// this way manual link gets "extended" only if some characters were added
|
|
492
|
+
// inside it
|
|
493
|
+
if ([manualLinkMinValue isEqualToString:manualLinkMaxValue]) {
|
|
494
|
+
NSRange newRange =
|
|
495
|
+
NSMakeRange(manualLinkMinIdx, manualLinkMaxIdx - manualLinkMinIdx + 1);
|
|
496
|
+
[_input->textView.textStorage addAttribute:NSForegroundColorAttributeName
|
|
497
|
+
value:[_input->config linkColor]
|
|
498
|
+
range:newRange];
|
|
499
|
+
[_input->textView.textStorage addAttribute:NSUnderlineColorAttributeName
|
|
500
|
+
value:[_input->config linkColor]
|
|
501
|
+
range:newRange];
|
|
502
|
+
[_input->textView.textStorage addAttribute:NSStrikethroughColorAttributeName
|
|
503
|
+
value:[_input->config linkColor]
|
|
504
|
+
range:newRange];
|
|
505
|
+
if ([_input->config linkDecorationLine] == DecorationUnderline) {
|
|
506
|
+
[_input->textView.textStorage addAttribute:NSUnderlineStyleAttributeName
|
|
507
|
+
value:@(NSUnderlineStyleSingle)
|
|
508
|
+
range:newRange];
|
|
400
509
|
}
|
|
401
|
-
[_input->textView.textStorage addAttribute:ManualLinkAttributeName
|
|
510
|
+
[_input->textView.textStorage addAttribute:ManualLinkAttributeName
|
|
511
|
+
value:manualLinkMinValue
|
|
512
|
+
range:newRange];
|
|
402
513
|
}
|
|
403
|
-
|
|
514
|
+
|
|
404
515
|
// link typing attributes need to be fixed after these changes
|
|
405
516
|
[self manageLinkTypingAttributes];
|
|
406
517
|
}
|
|
407
518
|
|
|
408
|
-
// replacing whole input (that starts with a link) with a manually typed letter
|
|
409
|
-
|
|
519
|
+
// replacing whole input (that starts with a link) with a manually typed letter
|
|
520
|
+
// improperly applies link's attributes to all the following text
|
|
521
|
+
- (BOOL)handleLeadingLinkReplacement:(NSRange)range
|
|
522
|
+
replacementText:(NSString *)text {
|
|
410
523
|
// whole textView range gets replaced with a single letter
|
|
411
|
-
if(_input->textView.textStorage.string.length > 0 &&
|
|
524
|
+
if (_input->textView.textStorage.string.length > 0 &&
|
|
525
|
+
NSEqualRanges(
|
|
526
|
+
range, NSMakeRange(0, _input->textView.textStorage.string.length)) &&
|
|
527
|
+
text.length == 1) {
|
|
412
528
|
// first character detection is enough for the removal to be done
|
|
413
|
-
if([self detectStyle:NSMakeRange(0, 1)]) {
|
|
414
|
-
[self
|
|
529
|
+
if ([self detectStyle:NSMakeRange(0, 1)]) {
|
|
530
|
+
[self
|
|
531
|
+
removeAttributes:NSMakeRange(
|
|
532
|
+
0, _input->textView.textStorage.string.length)];
|
|
415
533
|
// do the replacing manually
|
|
416
|
-
[TextInsertionUtils replaceText:text
|
|
534
|
+
[TextInsertionUtils replaceText:text
|
|
535
|
+
at:range
|
|
536
|
+
additionalAttributes:nullptr
|
|
537
|
+
input:_input
|
|
538
|
+
withSelection:YES];
|
|
417
539
|
return YES;
|
|
418
540
|
}
|
|
419
541
|
}
|
|
@@ -429,32 +551,39 @@ static NSString *const AutomaticLinkAttributeName = @"AutomaticLinkAttributeName
|
|
|
429
551
|
}
|
|
430
552
|
|
|
431
553
|
- (void)removeConnectedLinksIfNeeded:(NSString *)word range:(NSRange)wordRange {
|
|
432
|
-
BOOL anyAutomatic =
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
554
|
+
BOOL anyAutomatic =
|
|
555
|
+
[OccurenceUtils any:AutomaticLinkAttributeName
|
|
556
|
+
withInput:_input
|
|
557
|
+
inRange:wordRange
|
|
558
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
559
|
+
return [self styleCondition:value:range];
|
|
560
|
+
}];
|
|
561
|
+
BOOL anyManual =
|
|
562
|
+
[OccurenceUtils any:ManualLinkAttributeName
|
|
563
|
+
withInput:_input
|
|
564
|
+
inRange:wordRange
|
|
565
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
566
|
+
return [self styleCondition:value:range];
|
|
567
|
+
}];
|
|
568
|
+
|
|
443
569
|
// both manual and automatic links are somewhere - delete!
|
|
444
|
-
if(anyAutomatic && anyManual) {
|
|
570
|
+
if (anyAutomatic && anyManual) {
|
|
445
571
|
[self removeAttributes:wordRange];
|
|
446
572
|
[self manageLinkTypingAttributes];
|
|
447
573
|
}
|
|
448
|
-
|
|
449
|
-
// we are now sure there is only one type of link there - and make sure it
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
574
|
+
|
|
575
|
+
// we are now sure there is only one type of link there - and make sure it
|
|
576
|
+
// covers the whole word
|
|
577
|
+
BOOL onlyLinks = [OccurenceUtils
|
|
578
|
+
detectMultiple:@[ ManualLinkAttributeName, AutomaticLinkAttributeName ]
|
|
579
|
+
withInput:_input
|
|
580
|
+
inRange:wordRange
|
|
581
|
+
withCondition:^BOOL(id _Nullable value, NSRange range) {
|
|
582
|
+
return [self styleCondition:value:range];
|
|
583
|
+
}];
|
|
584
|
+
|
|
456
585
|
// only one link might be present!
|
|
457
|
-
if(onlyLinks && ![self isSingleLinkIn:wordRange]) {
|
|
586
|
+
if (onlyLinks && ![self isSingleLinkIn:wordRange]) {
|
|
458
587
|
[self removeAttributes:wordRange];
|
|
459
588
|
[self manageLinkTypingAttributes];
|
|
460
589
|
}
|