react-native-enriched 0.0.0 → 0.1.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 (169) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +875 -0
  3. package/ReactNativeEnriched.podspec +27 -0
  4. package/android/build.gradle +101 -0
  5. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +146 -0
  6. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +55 -0
  7. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/ComponentDescriptors.cpp +22 -0
  8. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/ComponentDescriptors.h +24 -0
  9. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +118 -0
  10. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +95 -0
  11. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +128 -0
  12. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +577 -0
  13. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/ShadowNodes.cpp +17 -0
  14. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/ShadowNodes.h +23 -0
  15. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/States.cpp +16 -0
  16. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/States.h +20 -0
  17. package/android/gradle.properties +5 -0
  18. package/android/src/main/AndroidManifest.xml +3 -0
  19. package/android/src/main/AndroidManifestNew.xml +2 -0
  20. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +535 -0
  21. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +64 -0
  22. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +292 -0
  23. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +19 -0
  24. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +40 -0
  25. package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +28 -0
  26. package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +29 -0
  27. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +24 -0
  28. package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +30 -0
  29. package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +27 -0
  30. package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +27 -0
  31. package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +30 -0
  32. package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +29 -0
  33. package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +33 -0
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +34 -0
  35. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +10 -0
  36. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +38 -0
  37. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +17 -0
  38. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +17 -0
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +17 -0
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +41 -0
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +16 -0
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +10 -0
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +24 -0
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +36 -0
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +71 -0
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +111 -0
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +9 -0
  48. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +9 -0
  49. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +49 -0
  50. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +4 -0
  51. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +4 -0
  52. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +4 -0
  53. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +4 -0
  54. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +4 -0
  55. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +5 -0
  56. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +227 -0
  57. package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +146 -0
  58. package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +173 -0
  59. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +186 -0
  60. package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +223 -0
  61. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +857 -0
  62. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +285 -0
  63. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +204 -0
  64. package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +91 -0
  65. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +73 -0
  66. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +51 -0
  67. package/android/src/main/new_arch/CMakeLists.txt +56 -0
  68. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +22 -0
  69. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +26 -0
  70. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +35 -0
  71. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +51 -0
  72. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +26 -0
  73. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +34 -0
  74. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +54 -0
  75. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +9 -0
  76. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +25 -0
  77. package/ios/EnrichedTextInputView.h +33 -0
  78. package/ios/EnrichedTextInputView.mm +1190 -0
  79. package/ios/EnrichedTextInputViewManager.mm +13 -0
  80. package/ios/config/InputConfig.h +67 -0
  81. package/ios/config/InputConfig.mm +382 -0
  82. package/ios/generated/RNEnrichedTextInputViewSpec/ComponentDescriptors.cpp +22 -0
  83. package/ios/generated/RNEnrichedTextInputViewSpec/ComponentDescriptors.h +24 -0
  84. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +118 -0
  85. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +95 -0
  86. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +128 -0
  87. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +577 -0
  88. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +384 -0
  89. package/ios/generated/RNEnrichedTextInputViewSpec/ShadowNodes.cpp +17 -0
  90. package/ios/generated/RNEnrichedTextInputViewSpec/ShadowNodes.h +23 -0
  91. package/ios/generated/RNEnrichedTextInputViewSpec/States.cpp +16 -0
  92. package/ios/generated/RNEnrichedTextInputViewSpec/States.h +20 -0
  93. package/ios/inputParser/InputParser.h +11 -0
  94. package/ios/inputParser/InputParser.mm +659 -0
  95. package/ios/inputTextView/InputTextView.h +6 -0
  96. package/ios/inputTextView/InputTextView.mm +115 -0
  97. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +17 -0
  98. package/ios/internals/EnrichedTextInputViewShadowNode.h +40 -0
  99. package/ios/internals/EnrichedTextInputViewShadowNode.mm +83 -0
  100. package/ios/internals/EnrichedTextInputViewState.cpp +10 -0
  101. package/ios/internals/EnrichedTextInputViewState.h +20 -0
  102. package/ios/styles/BlockQuoteStyle.mm +248 -0
  103. package/ios/styles/BoldStyle.mm +122 -0
  104. package/ios/styles/H1Style.mm +10 -0
  105. package/ios/styles/H2Style.mm +10 -0
  106. package/ios/styles/H3Style.mm +10 -0
  107. package/ios/styles/HeadingStyleBase.mm +144 -0
  108. package/ios/styles/InlineCodeStyle.mm +163 -0
  109. package/ios/styles/ItalicStyle.mm +110 -0
  110. package/ios/styles/LinkStyle.mm +463 -0
  111. package/ios/styles/MentionStyle.mm +476 -0
  112. package/ios/styles/OrderedListStyle.mm +225 -0
  113. package/ios/styles/StrikethroughStyle.mm +80 -0
  114. package/ios/styles/UnderlineStyle.mm +112 -0
  115. package/ios/styles/UnorderedListStyle.mm +225 -0
  116. package/ios/utils/BaseStyleProtocol.h +16 -0
  117. package/ios/utils/ColorExtension.h +6 -0
  118. package/ios/utils/ColorExtension.mm +27 -0
  119. package/ios/utils/FontExtension.h +13 -0
  120. package/ios/utils/FontExtension.mm +91 -0
  121. package/ios/utils/LayoutManagerExtension.h +6 -0
  122. package/ios/utils/LayoutManagerExtension.mm +171 -0
  123. package/ios/utils/LinkData.h +9 -0
  124. package/ios/utils/LinkData.mm +4 -0
  125. package/ios/utils/MentionParams.h +9 -0
  126. package/ios/utils/MentionParams.mm +4 -0
  127. package/ios/utils/MentionStyleProps.h +13 -0
  128. package/ios/utils/MentionStyleProps.mm +56 -0
  129. package/ios/utils/OccurenceUtils.h +37 -0
  130. package/ios/utils/OccurenceUtils.mm +124 -0
  131. package/ios/utils/ParagraphsUtils.h +7 -0
  132. package/ios/utils/ParagraphsUtils.mm +54 -0
  133. package/ios/utils/StringExtension.h +15 -0
  134. package/ios/utils/StringExtension.mm +57 -0
  135. package/ios/utils/StyleHeaders.h +74 -0
  136. package/ios/utils/StylePair.h +9 -0
  137. package/ios/utils/StylePair.mm +4 -0
  138. package/ios/utils/StyleTypeEnum.h +22 -0
  139. package/ios/utils/TextDecorationLineEnum.h +6 -0
  140. package/ios/utils/TextDecorationLineEnum.mm +4 -0
  141. package/ios/utils/TextInsertionUtils.h +6 -0
  142. package/ios/utils/TextInsertionUtils.mm +48 -0
  143. package/ios/utils/WordsUtils.h +6 -0
  144. package/ios/utils/WordsUtils.mm +88 -0
  145. package/ios/utils/ZeroWidthSpaceUtils.h +7 -0
  146. package/ios/utils/ZeroWidthSpaceUtils.mm +164 -0
  147. package/lib/module/EnrichedTextInput.js +191 -0
  148. package/lib/module/EnrichedTextInput.js.map +1 -0
  149. package/lib/module/EnrichedTextInputNativeComponent.ts +235 -0
  150. package/lib/module/index.js +4 -0
  151. package/lib/module/index.js.map +1 -0
  152. package/lib/module/normalizeHtmlStyle.js +141 -0
  153. package/lib/module/normalizeHtmlStyle.js.map +1 -0
  154. package/lib/module/package.json +1 -0
  155. package/lib/typescript/package.json +1 -0
  156. package/lib/typescript/src/EnrichedTextInput.d.ts +113 -0
  157. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -0
  158. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +160 -0
  159. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -0
  160. package/lib/typescript/src/index.d.ts +3 -0
  161. package/lib/typescript/src/index.d.ts.map +1 -0
  162. package/lib/typescript/src/normalizeHtmlStyle.d.ts +4 -0
  163. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +1 -0
  164. package/package.json +172 -1
  165. package/react-native.config.js +13 -0
  166. package/src/EnrichedTextInput.tsx +358 -0
  167. package/src/EnrichedTextInputNativeComponent.ts +235 -0
  168. package/src/index.tsx +9 -0
  169. package/src/normalizeHtmlStyle.ts +188 -0
@@ -0,0 +1,80 @@
1
+ #import "StyleHeaders.h"
2
+ #import "EnrichedTextInputView.h"
3
+ #import "OccurenceUtils.h"
4
+
5
+ @implementation StrikethroughStyle {
6
+ EnrichedTextInputView *_input;
7
+ }
8
+
9
+ + (StyleType)getStyleType { return Strikethrough; }
10
+
11
+ - (instancetype)initWithInput:(id)input {
12
+ self = [super init];
13
+ _input = (EnrichedTextInputView *)input;
14
+ return self;
15
+ }
16
+
17
+ - (void)applyStyle:(NSRange)range {
18
+ BOOL isStylePresent = [self detectStyle: range];
19
+ if(range.length >= 1) {
20
+ isStylePresent ? [self removeAttributes:range] : [self addAttributes:range];
21
+ } else {
22
+ isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
23
+ }
24
+ }
25
+
26
+ - (void)addAttributes:(NSRange)range {
27
+ [_input->textView.textStorage addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
28
+ }
29
+
30
+ - (void)addTypingAttributes {
31
+ NSMutableDictionary *newTypingAttrs = [_input->textView.typingAttributes mutableCopy];
32
+ newTypingAttrs[NSStrikethroughStyleAttributeName] = @(NSUnderlineStyleSingle);
33
+ _input->textView.typingAttributes = newTypingAttrs;
34
+ }
35
+
36
+ - (void)removeAttributes:(NSRange)range {
37
+ [_input->textView.textStorage removeAttribute:NSStrikethroughStyleAttributeName range:range];
38
+ }
39
+
40
+ - (void)removeTypingAttributes {
41
+ NSMutableDictionary *newTypingAttrs = [_input->textView.typingAttributes mutableCopy];
42
+ [newTypingAttrs removeObjectForKey: NSStrikethroughStyleAttributeName];
43
+ _input->textView.typingAttributes = newTypingAttrs;
44
+ }
45
+
46
+ - (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
47
+ NSNumber *strikethroughStyle = (NSNumber *)value;
48
+ return strikethroughStyle != nullptr && [strikethroughStyle intValue] != NSUnderlineStyleNone;
49
+ }
50
+
51
+ - (BOOL)detectStyle:(NSRange)range {
52
+ if(range.length >= 1) {
53
+ return [OccurenceUtils detect:NSStrikethroughStyleAttributeName withInput:_input inRange:range
54
+ withCondition: ^BOOL(id _Nullable value, NSRange range) {
55
+ return [self styleCondition:value :range];
56
+ }
57
+ ];
58
+ } else {
59
+ NSNumber *currenStrikethroughAttr = (NSNumber *)_input->textView.typingAttributes[NSStrikethroughStyleAttributeName];
60
+ return currenStrikethroughAttr != nullptr;
61
+ }
62
+ }
63
+
64
+ - (BOOL)anyOccurence:(NSRange)range {
65
+ return [OccurenceUtils any:NSStrikethroughStyleAttributeName withInput:_input inRange:range
66
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
67
+ return [self styleCondition:value :range];
68
+ }
69
+ ];
70
+ }
71
+
72
+ - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
73
+ return [OccurenceUtils all:NSStrikethroughStyleAttributeName withInput:_input inRange:range
74
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
75
+ return [self styleCondition:value :range];
76
+ }
77
+ ];
78
+ }
79
+
80
+ @end
@@ -0,0 +1,112 @@
1
+ #import "StyleHeaders.h"
2
+ #import "EnrichedTextInputView.h"
3
+ #import "OccurenceUtils.h"
4
+
5
+ @implementation UnderlineStyle {
6
+ EnrichedTextInputView *_input;
7
+ }
8
+
9
+ + (StyleType)getStyleType { return Underline; }
10
+
11
+ - (instancetype)initWithInput:(id)input {
12
+ self = [super init];
13
+ _input = (EnrichedTextInputView *)input;
14
+ return self;
15
+ }
16
+
17
+ - (void)applyStyle:(NSRange)range {
18
+ BOOL isStylePresent = [self detectStyle: range];
19
+ if(range.length >= 1) {
20
+ isStylePresent ? [self removeAttributes:range] : [self addAttributes:range];
21
+ } else {
22
+ isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
23
+ }
24
+ }
25
+
26
+ - (void)addAttributes:(NSRange)range {
27
+ [_input->textView.textStorage addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
28
+ }
29
+
30
+ - (void)addTypingAttributes {
31
+ NSMutableDictionary *newTypingAttrs = [_input->textView.typingAttributes mutableCopy];
32
+ newTypingAttrs[NSUnderlineStyleAttributeName] = @(NSUnderlineStyleSingle);
33
+ _input->textView.typingAttributes = newTypingAttrs;
34
+ }
35
+
36
+ - (void)removeAttributes:(NSRange)range {
37
+ [_input->textView.textStorage removeAttribute:NSUnderlineStyleAttributeName range:range];
38
+ }
39
+
40
+ - (void)removeTypingAttributes {
41
+ NSMutableDictionary *newTypingAttrs = [_input->textView.typingAttributes mutableCopy];
42
+ [newTypingAttrs removeObjectForKey: NSUnderlineStyleAttributeName];
43
+ _input->textView.typingAttributes = newTypingAttrs;
44
+ }
45
+
46
+ - (BOOL)underlinedLinkConflictsInRange:(NSRange)range {
47
+ BOOL conflicted = NO;
48
+ if([_input->config linkDecorationLine] == DecorationUnderline) {
49
+ LinkStyle *linkStyle = _input->stylesDict[@([LinkStyle getStyleType])];
50
+ conflicted = range.length > 0
51
+ ? [linkStyle anyOccurence:range]
52
+ : [linkStyle detectStyle:range];
53
+ }
54
+ return conflicted;
55
+ }
56
+
57
+ - (BOOL)underlinedMentionConflictsInRange:(NSRange)range {
58
+ BOOL conflicted = NO;
59
+ MentionStyle *mentionStyle = _input->stylesDict[@([MentionStyle getStyleType])];
60
+ if(range.length == 0) {
61
+ if([mentionStyle detectStyle:range]) {
62
+ MentionParams *params = [mentionStyle getMentionParamsAt:range.location];
63
+ conflicted = [_input->config mentionStylePropsForIndicator:params.indicator].decorationLine == DecorationUnderline;
64
+ }
65
+ } else {
66
+ NSArray *occurences = [mentionStyle findAllOccurences:range];
67
+ for(StylePair *pair in occurences) {
68
+ MentionParams *params = [mentionStyle getMentionParamsAt:[pair.rangeValue rangeValue].location];
69
+ if([_input->config mentionStylePropsForIndicator:params.indicator].decorationLine == DecorationUnderline) {
70
+ conflicted = YES;
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ return conflicted;
76
+ }
77
+
78
+ - (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
79
+ NSNumber *underlineStyle = (NSNumber *)value;
80
+ return underlineStyle != nullptr && [underlineStyle intValue] != NSUnderlineStyleNone && ![self underlinedLinkConflictsInRange:range] && ![self underlinedMentionConflictsInRange:range];
81
+ }
82
+
83
+ - (BOOL)detectStyle:(NSRange)range {
84
+ if(range.length >= 1) {
85
+ return [OccurenceUtils detect:NSUnderlineStyleAttributeName withInput:_input inRange:range
86
+ withCondition: ^BOOL(id _Nullable value, NSRange range) {
87
+ return [self styleCondition:value :range];
88
+ }
89
+ ];
90
+ } else {
91
+ NSNumber *currentUnderlineAttr = (NSNumber *)_input->textView.typingAttributes[NSUnderlineStyleAttributeName];
92
+ return [self styleCondition:currentUnderlineAttr :range];
93
+ }
94
+ }
95
+
96
+ - (BOOL)anyOccurence:(NSRange)range {
97
+ return [OccurenceUtils any:NSUnderlineStyleAttributeName withInput:_input inRange:range
98
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
99
+ return [self styleCondition:value :range];
100
+ }
101
+ ];
102
+ }
103
+
104
+ - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
105
+ return [OccurenceUtils all:NSUnderlineStyleAttributeName withInput:_input inRange:range
106
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
107
+ return [self styleCondition:value :range];
108
+ }
109
+ ];
110
+ }
111
+
112
+ @end
@@ -0,0 +1,225 @@
1
+ #import "StyleHeaders.h"
2
+ #import "EnrichedTextInputView.h"
3
+ #import "FontExtension.h"
4
+ #import "OccurenceUtils.h"
5
+ #import "ParagraphsUtils.h"
6
+ #import "TextInsertionUtils.h"
7
+
8
+ @implementation UnorderedListStyle {
9
+ EnrichedTextInputView *_input;
10
+ }
11
+
12
+ + (StyleType)getStyleType { return UnorderedList; }
13
+
14
+ - (CGFloat)getHeadIndent {
15
+ // lists are drawn manually
16
+ // margin before bullet + gap between bullet and paragraph
17
+ return [_input->config unorderedListMarginLeft] + [_input->config unorderedListGapWidth];
18
+ }
19
+
20
+ - (instancetype)initWithInput:(id)input {
21
+ self = [super init];
22
+ _input = (EnrichedTextInputView *)input;
23
+ return self;
24
+ }
25
+
26
+ - (void)applyStyle:(NSRange)range {
27
+ BOOL isStylePresent = [self detectStyle:range];
28
+ if(range.length >= 1) {
29
+ isStylePresent ? [self removeAttributes:range] : [self addAttributes:range];
30
+ } else {
31
+ isStylePresent ? [self removeTypingAttributes] : [self addTypingAttributes];
32
+ }
33
+ }
34
+
35
+ // we assume correct paragraph range is already given
36
+ - (void)addAttributes:(NSRange)range {
37
+ NSTextList *bullet = [[NSTextList alloc] initWithMarkerFormat:NSTextListMarkerDisc options:0];
38
+ NSArray *paragraphs = [ParagraphsUtils getSeparateParagraphsRangesIn:_input->textView range:range];
39
+ // if we fill empty lines with zero width spaces, we need to offset later ranges
40
+ NSInteger offset = 0;
41
+ // needed for range adjustments
42
+ NSRange preModificationRange = _input->textView.selectedRange;
43
+
44
+ // let's not emit some weird selection changes or text/html changes
45
+ _input->blockEmitting = YES;
46
+
47
+ for(NSValue *value in paragraphs) {
48
+ // take previous offsets into consideration
49
+ NSRange fixedRange = NSMakeRange([value rangeValue].location + offset, [value rangeValue].length);
50
+
51
+ // length 0 with first line, length 1 and newline with some empty lines in the middle
52
+ if(fixedRange.length == 0 ||
53
+ (fixedRange.length == 1 &&
54
+ [[NSCharacterSet newlineCharacterSet] characterIsMember: [_input->textView.textStorage.string characterAtIndex:fixedRange.location]])
55
+ ) {
56
+ [TextInsertionUtils insertText:@"\u200B" at:fixedRange.location additionalAttributes:nullptr input:_input withSelection:NO];
57
+ fixedRange = NSMakeRange(fixedRange.location, fixedRange.length + 1);
58
+ offset += 1;
59
+ }
60
+
61
+ [_input->textView.textStorage enumerateAttribute:NSParagraphStyleAttributeName inRange:fixedRange options:0
62
+ usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
63
+ NSMutableParagraphStyle *pStyle = [(NSParagraphStyle *)value mutableCopy];
64
+ pStyle.textLists = @[bullet];
65
+ pStyle.headIndent = [self getHeadIndent];
66
+ pStyle.firstLineHeadIndent = [self getHeadIndent];
67
+ [_input->textView.textStorage addAttribute:NSParagraphStyleAttributeName value:pStyle range:range];
68
+ }
69
+ ];
70
+ }
71
+
72
+ // back to emitting
73
+ _input->blockEmitting = NO;
74
+
75
+ if(preModificationRange.length == 0) {
76
+ // fix selection if only one line was possibly made a list and filled with a space
77
+ _input->textView.selectedRange = preModificationRange;
78
+ } else {
79
+ // in other cases, fix the selection with newly made offsets
80
+ _input->textView.selectedRange = NSMakeRange(preModificationRange.location, preModificationRange.length + offset);
81
+ }
82
+
83
+ // also add typing attributes
84
+ NSMutableDictionary *typingAttrs = [_input->textView.typingAttributes mutableCopy];
85
+ NSMutableParagraphStyle *pStyle = [typingAttrs[NSParagraphStyleAttributeName] mutableCopy];
86
+ pStyle.textLists = @[bullet];
87
+ pStyle.headIndent = [self getHeadIndent];
88
+ pStyle.firstLineHeadIndent = [self getHeadIndent];
89
+ typingAttrs[NSParagraphStyleAttributeName] = pStyle;
90
+ _input->textView.typingAttributes = typingAttrs;
91
+ }
92
+
93
+ // does pretty much the same as normal addAttributes, just need to get the range
94
+ - (void)addTypingAttributes {
95
+ [self addAttributes:_input->textView.selectedRange];
96
+ }
97
+
98
+ - (void)removeAttributes:(NSRange)range {
99
+ NSArray *paragraphs = [ParagraphsUtils getSeparateParagraphsRangesIn:_input->textView range:range];
100
+
101
+ [_input->textView.textStorage beginEditing];
102
+
103
+ for(NSValue *value in paragraphs) {
104
+ NSRange range = [value rangeValue];
105
+ [_input->textView.textStorage enumerateAttribute:NSParagraphStyleAttributeName inRange:range options:0
106
+ usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
107
+ NSMutableParagraphStyle *pStyle = [(NSParagraphStyle *)value mutableCopy];
108
+ pStyle.textLists = @[];
109
+ pStyle.headIndent = 0;
110
+ pStyle.firstLineHeadIndent = 0;
111
+ [_input->textView.textStorage addAttribute:NSParagraphStyleAttributeName value:pStyle range:range];
112
+ }
113
+ ];
114
+ }
115
+
116
+ [_input->textView.textStorage endEditing];
117
+
118
+ // also remove typing attributes
119
+ NSMutableDictionary *typingAttrs = [_input->textView.typingAttributes mutableCopy];
120
+ NSMutableParagraphStyle *pStyle = [typingAttrs[NSParagraphStyleAttributeName] mutableCopy];
121
+ pStyle.textLists = @[];
122
+ pStyle.headIndent = 0;
123
+ pStyle.firstLineHeadIndent = 0;
124
+ typingAttrs[NSParagraphStyleAttributeName] = pStyle;
125
+ _input->textView.typingAttributes = typingAttrs;
126
+ }
127
+
128
+ // needed for the sake of style conflicts, needs to do exactly the same as removeAttribtues
129
+ - (void)removeTypingAttributes {
130
+ [self removeAttributes:_input->textView.selectedRange];
131
+ }
132
+
133
+ // removing first list point by backspacing doesn't remove typing attributes because it doesn't run textViewDidChange
134
+ // so we try guessing that a point should be deleted here
135
+ - (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text {
136
+ if([self detectStyle:_input->textView.selectedRange] &&
137
+ NSEqualRanges(_input->textView.selectedRange, NSMakeRange(0, 0)) &&
138
+ [text isEqualToString:@""]
139
+ ) {
140
+ NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:_input->textView.selectedRange];
141
+ [self removeAttributes:paragraphRange];
142
+ return YES;
143
+ }
144
+ return NO;
145
+ }
146
+
147
+ - (BOOL)tryHandlingListShorcutInRange:(NSRange)range replacementText:(NSString *)text {
148
+ NSRange paragraphRange = [_input->textView.textStorage.string paragraphRangeForRange:range];
149
+ // space was added - check if we are both at the paragraph beginning + 1 character (which we want to be a dash)
150
+ if([text isEqualToString:@" "] && range.location - 1 == paragraphRange.location) {
151
+ unichar charBefore = [_input->textView.textStorage.string characterAtIndex:range.location - 1];
152
+ if(charBefore == '-') {
153
+ // we got a match - add a list if possible
154
+ if([_input handleStyleBlocksAndConflicts:[[self class] getStyleType] range:paragraphRange]) {
155
+ // don't emit some html updates during the replacing
156
+ BOOL prevEmitHtml = _input->emitHtml;
157
+ if(prevEmitHtml) {
158
+ _input->emitHtml = NO;
159
+ }
160
+
161
+ // remove the dash
162
+ [TextInsertionUtils replaceText:@"" at:NSMakeRange(paragraphRange.location, 1) additionalAttributes:nullptr input:_input withSelection:YES];
163
+
164
+ if(prevEmitHtml) {
165
+ _input->emitHtml = YES;
166
+ }
167
+
168
+ // add attributes on the dashless paragraph
169
+ [self addAttributes:NSMakeRange(paragraphRange.location, paragraphRange.length - 1)];
170
+ return YES;
171
+ }
172
+ }
173
+ }
174
+ return NO;
175
+ }
176
+
177
+ - (BOOL)styleCondition:(id _Nullable)value :(NSRange)range {
178
+ NSParagraphStyle *paragraph = (NSParagraphStyle *)value;
179
+ return paragraph != nullptr && paragraph.textLists.count == 1 && paragraph.textLists.firstObject.markerFormat == NSTextListMarkerDisc;
180
+ }
181
+
182
+ - (BOOL)detectStyle:(NSRange)range {
183
+ if(range.length >= 1) {
184
+ return [OccurenceUtils detect:NSParagraphStyleAttributeName withInput:_input inRange:range
185
+ withCondition: ^BOOL(id _Nullable value, NSRange range) {
186
+ return [self styleCondition:value :range];
187
+ }
188
+ ];
189
+ } else {
190
+ NSInteger searchLocation = range.location;
191
+ if(searchLocation == _input->textView.textStorage.length) {
192
+ NSParagraphStyle *pStyle = _input->textView.typingAttributes[NSParagraphStyleAttributeName];
193
+ return [self styleCondition:pStyle :NSMakeRange(0, 0)];
194
+ }
195
+
196
+ NSRange paragraphRange = NSMakeRange(0, 0);
197
+ NSRange inputRange = NSMakeRange(0, _input->textView.textStorage.length);
198
+ NSParagraphStyle *paragraph = [_input->textView.textStorage
199
+ attribute:NSParagraphStyleAttributeName
200
+ atIndex:searchLocation
201
+ longestEffectiveRange: &paragraphRange
202
+ inRange:inputRange
203
+ ];
204
+
205
+ return [self styleCondition:paragraph :NSMakeRange(0, 0)];
206
+ }
207
+ }
208
+
209
+ - (BOOL)anyOccurence:(NSRange)range {
210
+ return [OccurenceUtils any:NSParagraphStyleAttributeName withInput:_input inRange:range
211
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
212
+ return [self styleCondition:value :range];
213
+ }
214
+ ];
215
+ }
216
+
217
+ - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range {
218
+ return [OccurenceUtils all:NSParagraphStyleAttributeName withInput:_input inRange:range
219
+ withCondition:^BOOL(id _Nullable value, NSRange range) {
220
+ return [self styleCondition:value :range];
221
+ }
222
+ ];
223
+ }
224
+
225
+ @end
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+ #import "StyleTypeEnum.h"
3
+ #import "StylePair.h"
4
+
5
+ @protocol BaseStyleProtocol <NSObject>
6
+ + (StyleType)getStyleType;
7
+ - (instancetype _Nonnull)initWithInput:(id _Nonnull)input;
8
+ - (void)applyStyle:(NSRange)range;
9
+ - (void)addAttributes:(NSRange)range;
10
+ - (void)removeAttributes:(NSRange)range;
11
+ - (void)addTypingAttributes;
12
+ - (void)removeTypingAttributes;
13
+ - (BOOL)detectStyle:(NSRange)range;
14
+ - (BOOL)anyOccurence:(NSRange)range;
15
+ - (NSArray<StylePair *> *_Nullable)findAllOccurences:(NSRange)range;
16
+ @end
@@ -0,0 +1,6 @@
1
+ #import <UIKit/UIKit.h>
2
+ #pragma once
3
+
4
+ @interface UIColor (ColorExtension)
5
+ - (BOOL)isEqualToColor:(UIColor *)otherColor;
6
+ @end
@@ -0,0 +1,27 @@
1
+ #import "ColorExtension.h"
2
+
3
+ @implementation UIColor (ColorExtension)
4
+ - (BOOL)isEqualToColor:(UIColor *)otherColor {
5
+ CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();
6
+
7
+ UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color) {
8
+ if(CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome) {
9
+ const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
10
+ CGFloat components[4] = {oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]};
11
+ CGColorRef colorRef = CGColorCreate( colorSpaceRGB, components );
12
+
13
+ UIColor *color = [UIColor colorWithCGColor:colorRef];
14
+ CGColorRelease(colorRef);
15
+ return color;
16
+ } else {
17
+ return color;
18
+ }
19
+ };
20
+
21
+ UIColor *selfColor = convertColorToRGBSpace(self);
22
+ otherColor = convertColorToRGBSpace(otherColor);
23
+ CGColorSpaceRelease(colorSpaceRGB);
24
+
25
+ return [selfColor isEqual:otherColor];
26
+ }
27
+ @end
@@ -0,0 +1,13 @@
1
+ #import <UIKit/UIKit.h>
2
+ #pragma once
3
+
4
+ @interface UIFont (FontExtension)
5
+ - (BOOL)isBold;
6
+ - (UIFont *)setBold;
7
+ - (UIFont *)removeBold;
8
+ - (BOOL)isItalic;
9
+ - (UIFont *)setItalic;
10
+ - (UIFont *)removeItalic;
11
+ - (UIFont *)withFontTraits:(UIFont *)from;
12
+ - (UIFont *)setSize:(CGFloat)size;
13
+ @end
@@ -0,0 +1,91 @@
1
+ #import "FontExtension.h"
2
+ #import <React/RCTLog.h>
3
+
4
+ @implementation UIFont (FontExtension)
5
+
6
+ - (BOOL)isBold {
7
+ return (self.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold;
8
+ }
9
+
10
+ - (UIFont *)setBold {
11
+ if([self isBold]) {
12
+ return self;
13
+ }
14
+ UIFontDescriptorSymbolicTraits newTraits = (self.fontDescriptor.symbolicTraits | UIFontDescriptorTraitBold);
15
+ UIFontDescriptor *fontDescriptor = [self.fontDescriptor fontDescriptorWithSymbolicTraits:newTraits];
16
+ if(fontDescriptor != nullptr) {
17
+ return [UIFont fontWithDescriptor:fontDescriptor size:0];
18
+ } else {
19
+ RCTLogWarn(@"[EnrichedTextInput]: Couldn't apply bold trait to the font.");
20
+ return self;
21
+ }
22
+ }
23
+
24
+ - (UIFont *)removeBold {
25
+ if(![self isBold]) {
26
+ return self;
27
+ }
28
+ UIFontDescriptorSymbolicTraits newTraits = (self.fontDescriptor.symbolicTraits ^ UIFontDescriptorTraitBold);
29
+ UIFontDescriptor *fontDescriptor = [self.fontDescriptor fontDescriptorWithSymbolicTraits:newTraits];
30
+ if(fontDescriptor != nullptr) {
31
+ return [UIFont fontWithDescriptor:fontDescriptor size:0];
32
+ } else {
33
+ RCTLogWarn(@"[EnrichedTextInput]: Couldn't remove bold trait from the font.");
34
+ return self;
35
+ }
36
+ }
37
+
38
+ - (BOOL)isItalic {
39
+ return (self.fontDescriptor.symbolicTraits & UIFontDescriptorTraitItalic) == UIFontDescriptorTraitItalic;
40
+ }
41
+
42
+ - (UIFont *)setItalic {
43
+ if([self isItalic]) {
44
+ return self;
45
+ }
46
+ UIFontDescriptorSymbolicTraits newTraits = (self.fontDescriptor.symbolicTraits | UIFontDescriptorTraitItalic);
47
+ UIFontDescriptor *fontDescriptor = [self.fontDescriptor fontDescriptorWithSymbolicTraits:newTraits];
48
+ if(fontDescriptor != nullptr) {
49
+ return [UIFont fontWithDescriptor:fontDescriptor size:0];
50
+ } else {
51
+ RCTLogWarn(@"[EnrichedTextInput]: Couldn't apply italic trait to the font.");
52
+ return self;
53
+ }
54
+ }
55
+
56
+ - (UIFont *)removeItalic {
57
+ if(![self isItalic]) {
58
+ return self;
59
+ }
60
+ UIFontDescriptorSymbolicTraits newTraits = (self.fontDescriptor.symbolicTraits ^ UIFontDescriptorTraitItalic);
61
+ UIFontDescriptor *fontDescriptor = [self.fontDescriptor fontDescriptorWithSymbolicTraits:newTraits];
62
+ if(fontDescriptor != nullptr) {
63
+ return [UIFont fontWithDescriptor:fontDescriptor size:0];
64
+ } else {
65
+ RCTLogWarn(@"[EnrichedTextInput]: Couldn't remove italic trait from the font.");
66
+ return self;
67
+ }
68
+ }
69
+
70
+ - (UIFont *)withFontTraits:(UIFont *)from {
71
+ UIFont* newFont = self;
72
+ if([from isBold]) {
73
+ newFont = [newFont setBold];
74
+ }
75
+ if([from isItalic]) {
76
+ newFont = [newFont setItalic];
77
+ }
78
+ return newFont;
79
+ }
80
+
81
+ - (UIFont *)setSize:(CGFloat)size {
82
+ UIFontDescriptor *newFontDescriptor = [self.fontDescriptor fontDescriptorWithSize:size];
83
+ if(newFontDescriptor != nullptr) {
84
+ return [UIFont fontWithDescriptor:newFontDescriptor size:0];
85
+ } else {
86
+ RCTLogWarn(@"[EnrichedTextInput]: Couldn't apply heading style to the font.");
87
+ return self;
88
+ }
89
+ }
90
+
91
+ @end
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+ #import <UIKit/UIKit.h>
3
+
4
+ @interface NSLayoutManager (LayoutManagerExtension)
5
+ @property (nonatomic, weak) id input;
6
+ @end