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.
Files changed (107) hide show
  1. package/README.md +1 -5
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +3 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +1 -0
  4. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
  6. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +92 -0
  7. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +6 -0
  8. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +1 -1
  9. package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +33 -0
  10. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +6 -0
  11. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +6 -0
  12. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +6 -0
  13. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +6 -0
  14. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +6 -0
  15. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +6 -0
  16. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +5 -0
  17. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +6 -0
  18. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +5 -0
  19. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +6 -0
  20. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +6 -0
  21. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +6 -0
  22. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +9 -3
  23. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +5 -0
  24. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +5 -0
  25. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +6 -0
  26. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +4 -0
  27. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +78 -0
  28. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +80 -4
  29. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +8 -0
  30. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
  31. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
  32. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
  33. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
  34. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
  35. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
  36. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
  37. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
  38. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
  39. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +12 -13
  40. package/ios/EnrichedTextInputView.h +25 -13
  41. package/ios/EnrichedTextInputView.mm +872 -581
  42. package/ios/attachments/ImageAttachment.h +10 -0
  43. package/ios/attachments/ImageAttachment.mm +34 -0
  44. package/ios/attachments/MediaAttachment.h +23 -0
  45. package/ios/attachments/MediaAttachment.mm +31 -0
  46. package/ios/config/InputConfig.h +6 -6
  47. package/ios/config/InputConfig.mm +39 -33
  48. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
  49. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
  50. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +21 -0
  51. package/ios/inputParser/InputParser.h +5 -5
  52. package/ios/inputParser/InputParser.mm +789 -378
  53. package/ios/inputTextView/InputTextView.h +1 -1
  54. package/ios/inputTextView/InputTextView.mm +100 -59
  55. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
  56. package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
  57. package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
  58. package/ios/internals/EnrichedTextInputViewState.h +3 -1
  59. package/ios/styles/BlockQuoteStyle.mm +189 -118
  60. package/ios/styles/BoldStyle.mm +95 -63
  61. package/ios/styles/CodeBlockStyle.mm +204 -128
  62. package/ios/styles/H1Style.mm +10 -4
  63. package/ios/styles/H2Style.mm +10 -4
  64. package/ios/styles/H3Style.mm +10 -4
  65. package/ios/styles/HeadingStyleBase.mm +129 -84
  66. package/ios/styles/ImageStyle.mm +75 -73
  67. package/ios/styles/InlineCodeStyle.mm +148 -85
  68. package/ios/styles/ItalicStyle.mm +76 -52
  69. package/ios/styles/LinkStyle.mm +348 -227
  70. package/ios/styles/MentionStyle.mm +363 -246
  71. package/ios/styles/OrderedListStyle.mm +171 -106
  72. package/ios/styles/StrikethroughStyle.mm +52 -35
  73. package/ios/styles/UnderlineStyle.mm +68 -46
  74. package/ios/styles/UnorderedListStyle.mm +169 -106
  75. package/ios/utils/BaseStyleProtocol.h +2 -2
  76. package/ios/utils/ColorExtension.mm +7 -5
  77. package/ios/utils/FontExtension.mm +42 -27
  78. package/ios/utils/LayoutManagerExtension.h +1 -1
  79. package/ios/utils/LayoutManagerExtension.mm +280 -170
  80. package/ios/utils/MentionParams.h +0 -1
  81. package/ios/utils/MentionStyleProps.h +1 -1
  82. package/ios/utils/MentionStyleProps.mm +27 -20
  83. package/ios/utils/OccurenceUtils.h +42 -42
  84. package/ios/utils/OccurenceUtils.mm +142 -119
  85. package/ios/utils/ParagraphAttributesUtils.h +6 -2
  86. package/ios/utils/ParagraphAttributesUtils.mm +115 -71
  87. package/ios/utils/ParagraphsUtils.h +2 -1
  88. package/ios/utils/ParagraphsUtils.mm +40 -26
  89. package/ios/utils/StringExtension.h +1 -1
  90. package/ios/utils/StringExtension.mm +19 -16
  91. package/ios/utils/StyleHeaders.h +27 -15
  92. package/ios/utils/TextInsertionUtils.h +13 -2
  93. package/ios/utils/TextInsertionUtils.mm +38 -20
  94. package/ios/utils/WordsUtils.h +2 -1
  95. package/ios/utils/WordsUtils.mm +32 -22
  96. package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
  97. package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
  98. package/lib/module/EnrichedTextInput.js +39 -1
  99. package/lib/module/EnrichedTextInput.js.map +1 -1
  100. package/lib/module/EnrichedTextInputNativeComponent.ts +11 -0
  101. package/lib/typescript/src/EnrichedTextInput.d.ts +1 -0
  102. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  103. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +6 -0
  104. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  105. package/package.json +8 -1
  106. package/src/EnrichedTextInput.tsx +45 -0
  107. package/src/EnrichedTextInputNativeComponent.ts +11 -0
@@ -1,15 +1,21 @@
1
- #import "StyleHeaders.h"
2
1
  #import "EnrichedTextInputView.h"
3
2
  #import "FontExtension.h"
4
3
  #import "OccurenceUtils.h"
4
+ #import "StyleHeaders.h"
5
5
  #import "TextInsertionUtils.h"
6
6
 
7
7
  @implementation HeadingStyleBase
8
8
 
9
9
  // mock values since H1/2/3Style classes anyway are used
10
- + (StyleType)getStyleType { return None; }
11
- - (CGFloat)getHeadingFontSize { return 0; }
12
- - (BOOL)isHeadingBold { return false; }
10
+ + (StyleType)getStyleType {
11
+ return None;
12
+ }
13
+ - (CGFloat)getHeadingFontSize {
14
+ return 0;
15
+ }
16
+ - (BOOL)isHeadingBold {
17
+ return false;
18
+ }
13
19
 
14
20
  - (EnrichedTextInputView *)typedInput {
15
21
  return (EnrichedTextInputView *)input;
@@ -25,41 +31,54 @@
25
31
  // but if the paragraph is empty it still is of length 0
26
32
  - (void)applyStyle:(NSRange)range {
27
33
  BOOL isStylePresent = [self detectStyle:range];
28
- if(range.length >= 1) {
29
- isStylePresent ? [self removeAttributes:range] : [self addAttributes:range];
34
+ if (range.length >= 1) {
35
+ isStylePresent ? [self removeAttributes:range]
36
+ : [self addAttributes:range withTypingAttr:YES];
30
37
  } else {
31
38
  isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
32
39
  }
33
40
  }
34
41
 
35
42
  // the range will already be the proper full paragraph/s range
36
- - (void)addAttributes:(NSRange)range {
43
+ - (void)addAttributes:(NSRange)range withTypingAttr:(BOOL)withTypingAttr {
37
44
  [[self typedInput]->textView.textStorage beginEditing];
38
- [[self typedInput]->textView.textStorage enumerateAttribute:NSFontAttributeName inRange:range options:0
39
- usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
40
- UIFont *font = (UIFont *)value;
41
- if(font != nullptr) {
42
- UIFont *newFont = [font setSize:[self getHeadingFontSize]];
43
- if([self isHeadingBold]) {
44
- newFont = [newFont setBold];
45
- }
46
- [[self typedInput]->textView.textStorage addAttribute:NSFontAttributeName value:newFont range:range];
47
- }
48
- }
49
- ];
45
+ [[self typedInput]->textView.textStorage
46
+ enumerateAttribute:NSFontAttributeName
47
+ inRange:range
48
+ options:0
49
+ usingBlock:^(id _Nullable value, NSRange range,
50
+ BOOL *_Nonnull stop) {
51
+ UIFont *font = (UIFont *)value;
52
+ if (font != nullptr) {
53
+ UIFont *newFont = [font setSize:[self getHeadingFontSize]];
54
+ if ([self isHeadingBold]) {
55
+ newFont = [newFont setBold];
56
+ }
57
+ [[self typedInput]->textView.textStorage
58
+ addAttribute:NSFontAttributeName
59
+ value:newFont
60
+ range:range];
61
+ }
62
+ }];
50
63
  [[self typedInput]->textView.textStorage endEditing];
51
-
64
+
52
65
  // also toggle typing attributes
53
- [self addTypingAttributes];
66
+ if (withTypingAttr) {
67
+ [self addTypingAttributes];
68
+ }
54
69
  }
55
70
 
56
- // will always be called on empty paragraphs so only typing attributes can be changed
71
+ // will always be called on empty paragraphs so only typing attributes can be
72
+ // changed
57
73
  - (void)addTypingAttributes {
58
- UIFont *currentFontAttr = (UIFont *)[self typedInput]->textView.typingAttributes[NSFontAttributeName];
59
- if(currentFontAttr != nullptr) {
60
- NSMutableDictionary *newTypingAttrs = [[self typedInput]->textView.typingAttributes mutableCopy];
74
+ UIFont *currentFontAttr =
75
+ (UIFont *)[self typedInput]
76
+ ->textView.typingAttributes[NSFontAttributeName];
77
+ if (currentFontAttr != nullptr) {
78
+ NSMutableDictionary *newTypingAttrs =
79
+ [[self typedInput]->textView.typingAttributes mutableCopy];
61
80
  UIFont *newFont = [currentFontAttr setSize:[self getHeadingFontSize]];
62
- if([self isHeadingBold]) {
81
+ if ([self isHeadingBold]) {
63
82
  newFont = [newFont setBold];
64
83
  }
65
84
  newTypingAttrs[NSFontAttributeName] = newFont;
@@ -69,28 +88,41 @@
69
88
 
70
89
  // we need to remove the style from the whole paragraph
71
90
  - (void)removeAttributes:(NSRange)range {
72
- NSRange paragraphRange = [[self typedInput]->textView.textStorage.string paragraphRangeForRange:range];
73
-
91
+ NSRange paragraphRange = [[self typedInput]->textView.textStorage.string
92
+ paragraphRangeForRange:range];
93
+
74
94
  [[self typedInput]->textView.textStorage beginEditing];
75
- [[self typedInput]->textView.textStorage enumerateAttribute:NSFontAttributeName inRange:paragraphRange options:0
76
- usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
77
- if([self styleCondition:value :range]) {
78
- UIFont *newFont = [(UIFont *)value setSize:[[[self typedInput]->config primaryFontSize] floatValue]];
79
- if([self isHeadingBold]) {
80
- newFont = [newFont removeBold];
81
- }
82
- [[self typedInput]->textView.textStorage addAttribute:NSFontAttributeName value:newFont range:range];
83
- }
84
- }
85
- ];
95
+ [[self typedInput]->textView.textStorage
96
+ enumerateAttribute:NSFontAttributeName
97
+ inRange:paragraphRange
98
+ options:0
99
+ usingBlock:^(id _Nullable value, NSRange range,
100
+ BOOL *_Nonnull stop) {
101
+ if ([self styleCondition:value:range]) {
102
+ UIFont *newFont = [(UIFont *)value
103
+ setSize:[[[self typedInput]->config primaryFontSize]
104
+ floatValue]];
105
+ if ([self isHeadingBold]) {
106
+ newFont = [newFont removeBold];
107
+ }
108
+ [[self typedInput]->textView.textStorage
109
+ addAttribute:NSFontAttributeName
110
+ value:newFont
111
+ range:range];
112
+ }
113
+ }];
86
114
  [[self typedInput]->textView.textStorage endEditing];
87
-
115
+
88
116
  // typing attributes still need to be removed
89
- UIFont *currentFontAttr = (UIFont *)[self typedInput]->textView.typingAttributes[NSFontAttributeName];
90
- if(currentFontAttr != nullptr) {
91
- NSMutableDictionary *newTypingAttrs = [[self typedInput]->textView.typingAttributes mutableCopy];
92
- UIFont *newFont = [currentFontAttr setSize:[[[self typedInput]->config primaryFontSize] floatValue]];
93
- if([self isHeadingBold]) {
117
+ UIFont *currentFontAttr =
118
+ (UIFont *)[self typedInput]
119
+ ->textView.typingAttributes[NSFontAttributeName];
120
+ if (currentFontAttr != nullptr) {
121
+ NSMutableDictionary *newTypingAttrs =
122
+ [[self typedInput]->textView.typingAttributes mutableCopy];
123
+ UIFont *newFont = [currentFontAttr
124
+ setSize:[[[self typedInput]->config primaryFontSize] floatValue]];
125
+ if ([self isHeadingBold]) {
94
126
  newFont = [newFont removeBold];
95
127
  }
96
128
  newTypingAttrs[NSFontAttributeName] = newFont;
@@ -99,58 +131,67 @@
99
131
  }
100
132
 
101
133
  - (void)removeTypingAttributes {
102
- // all the heading still needs to be removed because this function may be called in conflicting styles logic
103
- // typing attributes already get removed in there as well
134
+ // all the heading still needs to be removed because this function may be
135
+ // called in conflicting styles logic typing attributes already get removed in
136
+ // there as well
104
137
  [self removeAttributes:[self typedInput]->textView.selectedRange];
105
138
  }
106
139
 
107
- - (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
140
+ - (BOOL)styleCondition:(id _Nullable)value:(NSRange)range {
108
141
  UIFont *font = (UIFont *)value;
109
142
  return font != nullptr && font.pointSize == [self getHeadingFontSize];
110
143
  }
111
144
 
112
145
  - (BOOL)detectStyle:(NSRange)range {
113
- if(range.length >= 1) {
114
- return [OccurenceUtils detect:NSFontAttributeName withInput:[self typedInput] inRange:range
115
- withCondition: ^BOOL(id _Nullable value, NSRange range) {
116
- return [self styleCondition:value :range];
117
- }
118
- ];
146
+ if (range.length >= 1) {
147
+ return [OccurenceUtils detect:NSFontAttributeName
148
+ withInput:[self typedInput]
149
+ inRange:range
150
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
151
+ return [self styleCondition:value:range];
152
+ }];
119
153
  } else {
120
- return [OccurenceUtils detect:NSFontAttributeName withInput:[self typedInput] atIndex:range.location checkPrevious:YES
121
- withCondition:^BOOL(id _Nullable value, NSRange range) {
122
- return [self styleCondition:value :range];
123
- }
124
- ];
154
+ return [OccurenceUtils detect:NSFontAttributeName
155
+ withInput:[self typedInput]
156
+ atIndex:range.location
157
+ checkPrevious:YES
158
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
159
+ return [self styleCondition:value:range];
160
+ }];
125
161
  }
126
162
  }
127
163
 
128
164
  - (BOOL)anyOccurence:(NSRange)range {
129
- return [OccurenceUtils any:NSFontAttributeName withInput:[self typedInput] inRange:range
130
- withCondition:^BOOL(id _Nullable value, NSRange range) {
131
- return [self styleCondition:value :range];
132
- }
133
- ];
165
+ return [OccurenceUtils any:NSFontAttributeName
166
+ withInput:[self typedInput]
167
+ inRange:range
168
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
169
+ return [self styleCondition:value:range];
170
+ }];
134
171
  }
135
172
 
136
173
  - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
137
- return [OccurenceUtils all:NSFontAttributeName withInput:[self typedInput] inRange:range
138
- withCondition:^BOOL(id _Nullable value, NSRange range) {
139
- return [self styleCondition:value :range];
140
- }
141
- ];
174
+ return [OccurenceUtils all:NSFontAttributeName
175
+ withInput:[self typedInput]
176
+ inRange:range
177
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
178
+ return [self styleCondition:value:range];
179
+ }];
142
180
  }
143
181
 
144
182
  // used to make sure headings dont persist after a newline is placed
145
183
  - (BOOL)handleNewlinesInRange:(NSRange)range replacementText:(NSString *)text {
146
184
  // in a heading and a new text ends with a newline
147
- if(
148
- [self detectStyle:[self typedInput]->textView.selectedRange] &&
149
- text.length > 0 &&
150
- [[NSCharacterSet newlineCharacterSet] characterIsMember: [text characterAtIndex:text.length-1]]
151
- ) {
185
+ if ([self detectStyle:[self typedInput]->textView.selectedRange] &&
186
+ text.length > 0 &&
187
+ [[NSCharacterSet newlineCharacterSet]
188
+ characterIsMember:[text characterAtIndex:text.length - 1]]) {
152
189
  // do the replacement manually
153
- [TextInsertionUtils replaceText:text at:range additionalAttributes:nullptr input:[self typedInput] withSelection:YES];
190
+ [TextInsertionUtils replaceText:text
191
+ at:range
192
+ additionalAttributes:nullptr
193
+ input:[self typedInput]
194
+ withSelection:YES];
154
195
  // remove the attribtues at the new selection
155
196
  [self removeAttributes:[self typedInput]->textView.selectedRange];
156
197
  return YES;
@@ -158,19 +199,23 @@
158
199
  return NO;
159
200
  }
160
201
 
161
- // backspacing a line after a heading "into" a heading will not result in the text attaining heading attributes
162
- // so, we do it manually
202
+ // backspacing a line after a heading "into" a heading will not result in the
203
+ // text attaining heading attributes so, we do it manually
163
204
  - (void)handleImproperHeadings {
164
- NSArray *occurences = [self findAllOccurences:NSMakeRange(0, [self typedInput]->textView.textStorage.string.length)];
165
- for(StylePair *pair in occurences) {
205
+ NSArray *occurences = [self
206
+ findAllOccurences:NSMakeRange(0,
207
+ [self typedInput]
208
+ ->textView.textStorage.string.length)];
209
+ for (StylePair *pair in occurences) {
166
210
  NSRange occurenceRange = [pair.rangeValue rangeValue];
167
- NSRange paragraphRange = [[self typedInput]->textView.textStorage.string paragraphRangeForRange:occurenceRange];
168
- if(!NSEqualRanges(occurenceRange, paragraphRange)) {
169
- // we have a heading but it does not span its whole paragraph - let's fix it
170
- [self addAttributes:paragraphRange];
211
+ NSRange paragraphRange = [[self typedInput]->textView.textStorage.string
212
+ paragraphRangeForRange:occurenceRange];
213
+ if (!NSEqualRanges(occurenceRange, paragraphRange)) {
214
+ // we have a heading but it does not span its whole paragraph - let's fix
215
+ // it
216
+ [self addAttributes:paragraphRange withTypingAttr:NO];
171
217
  }
172
218
  }
173
219
  }
174
220
 
175
221
  @end
176
-
@@ -1,6 +1,8 @@
1
- #import "StyleHeaders.h"
2
1
  #import "EnrichedTextInputView.h"
2
+ #import "ImageAttachment.h"
3
+ #import "MediaAttachment.h"
3
4
  #import "OccurenceUtils.h"
5
+ #import "StyleHeaders.h"
4
6
  #import "TextInsertionUtils.h"
5
7
 
6
8
  // custom NSAttributedStringKey to differentiate the image
@@ -10,9 +12,13 @@ static NSString *const ImageAttributeName = @"ImageAttributeName";
10
12
  EnrichedTextInputView *_input;
11
13
  }
12
14
 
13
- + (StyleType)getStyleType { return Image; }
15
+ + (StyleType)getStyleType {
16
+ return Image;
17
+ }
14
18
 
15
- + (BOOL)isParagraphStyle { return NO; }
19
+ + (BOOL)isParagraphStyle {
20
+ return NO;
21
+ }
16
22
 
17
23
  - (instancetype)initWithInput:(id)input {
18
24
  self = [super init];
@@ -24,7 +30,7 @@ static NSString *const ImageAttributeName = @"ImageAttributeName";
24
30
  // no-op for image
25
31
  }
26
32
 
27
- - (void)addAttributes:(NSRange)range {
33
+ - (void)addAttributes:(NSRange)range withTypingAttr:(BOOL)withTypingAttr {
28
34
  // no-op for image
29
35
  }
30
36
 
@@ -35,91 +41,104 @@ static NSString *const ImageAttributeName = @"ImageAttributeName";
35
41
  - (void)removeAttributes:(NSRange)range {
36
42
  [_input->textView.textStorage beginEditing];
37
43
  [_input->textView.textStorage removeAttribute:ImageAttributeName range:range];
38
- [_input->textView.textStorage removeAttribute:NSAttachmentAttributeName range:range];
44
+ [_input->textView.textStorage removeAttribute:NSAttachmentAttributeName
45
+ range:range];
39
46
  [_input->textView.textStorage endEditing];
40
47
  }
41
48
 
42
49
  - (void)removeTypingAttributes {
43
- NSMutableDictionary *currentAttributes = [_input->textView.typingAttributes mutableCopy];
50
+ NSMutableDictionary *currentAttributes =
51
+ [_input->textView.typingAttributes mutableCopy];
44
52
  [currentAttributes removeObjectForKey:ImageAttributeName];
45
53
  [currentAttributes removeObjectForKey:NSAttachmentAttributeName];
46
54
  _input->textView.typingAttributes = currentAttributes;
47
55
  }
48
56
 
49
- - (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
57
+ - (BOOL)styleCondition:(id _Nullable)value:(NSRange)range {
50
58
  return [value isKindOfClass:[ImageData class]];
51
59
  }
52
60
 
53
61
  - (BOOL)anyOccurence:(NSRange)range {
54
- return [OccurenceUtils any:ImageAttributeName withInput:_input inRange:range
55
- withCondition:^BOOL(id _Nullable value, NSRange range) {
56
- return [self styleCondition:value :range];
57
- }
58
- ];
62
+ return [OccurenceUtils any:ImageAttributeName
63
+ withInput:_input
64
+ inRange:range
65
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
66
+ return [self styleCondition:value:range];
67
+ }];
59
68
  }
60
69
 
61
70
  - (BOOL)detectStyle:(NSRange)range {
62
71
  if (range.length >= 1) {
63
- return [OccurenceUtils detect:ImageAttributeName withInput:_input inRange:range
64
- withCondition:^BOOL(id _Nullable value, NSRange range) {
65
- return [self styleCondition:value :range];
66
- }
67
- ];
72
+ return [OccurenceUtils detect:ImageAttributeName
73
+ withInput:_input
74
+ inRange:range
75
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
76
+ return [self styleCondition:value:range];
77
+ }];
68
78
  } else {
69
- return [OccurenceUtils detect:ImageAttributeName withInput:_input atIndex:range.location checkPrevious:YES
70
- withCondition:^BOOL(id _Nullable value, NSRange range) {
71
- return [self styleCondition:value :range];
72
- }
73
- ];
79
+ return [OccurenceUtils detect:ImageAttributeName
80
+ withInput:_input
81
+ atIndex:range.location
82
+ checkPrevious:YES
83
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
84
+ return [self styleCondition:value:range];
85
+ }];
74
86
  }
75
87
  }
76
88
 
77
- - (NSArray<StylePair *> * _Nullable)findAllOccurences:(NSRange)range {
78
- return [OccurenceUtils all:ImageAttributeName withInput:_input inRange:range
79
- withCondition:^BOOL(id _Nullable value, NSRange range) {
80
- return [self styleCondition:value :range];
81
- }
82
- ];
89
+ - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
90
+ return [OccurenceUtils all:ImageAttributeName
91
+ withInput:_input
92
+ inRange:range
93
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
94
+ return [self styleCondition:value:range];
95
+ }];
83
96
  }
84
97
 
85
- - (ImageData *)getImageDataAt:(NSUInteger)location
86
- {
98
+ - (ImageData *)getImageDataAt:(NSUInteger)location {
87
99
  NSRange imageRange = NSMakeRange(0, 0);
88
100
  NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
89
-
101
+
90
102
  // don't search at the very end of input
91
103
  NSUInteger searchLocation = location;
92
- if(searchLocation == _input->textView.textStorage.length) {
104
+ if (searchLocation == _input->textView.textStorage.length) {
93
105
  return nullptr;
94
106
  }
95
-
96
- ImageData *imageData = [_input->textView.textStorage
97
- attribute:ImageAttributeName
98
- atIndex:searchLocation
99
- longestEffectiveRange: &imageRange
100
- inRange:inputRange
101
- ];
102
-
107
+
108
+ ImageData *imageData =
109
+ [_input->textView.textStorage attribute:ImageAttributeName
110
+ atIndex:searchLocation
111
+ longestEffectiveRange:&imageRange
112
+ inRange:inputRange];
113
+
103
114
  return imageData;
104
115
  }
105
116
 
106
- - (void)addImageAtRange:(NSRange)range imageData:(ImageData *)imageData withSelection:(BOOL)withSelection
107
- {
108
- UIImage *img = [self prepareImageFromUri:imageData.uri];
109
-
110
- NSDictionary *attributes = [@{
111
- NSAttachmentAttributeName: [self prepareImageAttachement:img width:imageData.width height:imageData.height],
112
- ImageAttributeName: imageData,
113
- } mutableCopy];
114
-
117
+ - (void)addImageAtRange:(NSRange)range
118
+ imageData:(ImageData *)imageData
119
+ withSelection:(BOOL)withSelection {
120
+ if (!imageData)
121
+ return;
122
+
123
+ ImageAttachment *attachment =
124
+ [[ImageAttachment alloc] initWithImageData:imageData];
125
+ attachment.delegate = _input;
126
+
127
+ NSDictionary *attributes =
128
+ @{NSAttachmentAttributeName : attachment, ImageAttributeName : imageData};
129
+
115
130
  // Use the Object Replacement Character for Image.
116
131
  // This tells TextKit "something non-text goes here".
117
- NSString *imagePlaceholder = @"\uFFFC";
118
-
132
+ NSString *placeholderChar = @"\uFFFC";
133
+
119
134
  if (range.length == 0) {
120
- [TextInsertionUtils insertText:imagePlaceholder at:range.location additionalAttributes:attributes input:_input withSelection:withSelection];
135
+ [TextInsertionUtils insertText:placeholderChar
136
+ at:range.location
137
+ additionalAttributes:attributes
138
+ input:_input
139
+ withSelection:withSelection];
121
140
  } else {
122
- [TextInsertionUtils replaceText:imagePlaceholder
141
+ [TextInsertionUtils replaceText:placeholderChar
123
142
  at:range
124
143
  additionalAttributes:attributes
125
144
  input:_input
@@ -132,27 +151,10 @@ static NSString *const ImageAttributeName = @"ImageAttributeName";
132
151
  data.uri = uri;
133
152
  data.width = width;
134
153
  data.height = height;
135
-
136
- [self addImageAtRange:_input->textView.selectedRange imageData:data withSelection:YES];
137
- }
138
-
139
- -(NSTextAttachment *)prepareImageAttachement:(UIImage *)image width:(CGFloat)width height:(CGFloat)height
140
- {
141
-
142
- NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
143
- attachment.image = image;
144
- attachment.bounds = CGRectMake(0, 0, width, height);
145
-
146
- return attachment;
147
- }
148
154
 
149
- - (UIImage *)prepareImageFromUri:(NSString *)uri
150
- {
151
- NSURL *url = [NSURL URLWithString:uri];
152
- NSData *imgData = [NSData dataWithContentsOfURL:url];
153
- UIImage *image = [UIImage imageWithData:imgData];
154
-
155
- return image;
155
+ [self addImageAtRange:_input->textView.selectedRange
156
+ imageData:data
157
+ withSelection:YES];
156
158
  }
157
159
 
158
160
  @end