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