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