@expensify/react-native-live-markdown 0.1.273 → 0.1.275
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apple/MarkdownFormatter.h +6 -4
- package/apple/MarkdownFormatter.mm +12 -14
- package/apple/MarkdownTextFieldObserver.h +17 -0
- package/apple/MarkdownTextFieldObserver.mm +73 -0
- package/apple/MarkdownTextInputDecoratorComponentView.mm +64 -29
- package/apple/MarkdownTextInputDecoratorShadowNode.mm +4 -4
- package/apple/MarkdownTextStorageDelegate.h +13 -0
- package/apple/MarkdownTextStorageDelegate.mm +27 -0
- package/apple/MarkdownTextViewObserver.h +13 -0
- package/apple/MarkdownTextViewObserver.mm +28 -0
- package/apple/RCTMarkdownUtils.h +2 -2
- package/apple/RCTMarkdownUtils.mm +12 -35
- package/apple/RCTTextInputComponentView+Markdown.h +0 -7
- package/apple/RCTTextInputComponentView+Markdown.mm +20 -72
- package/lib/commonjs/web/utils/inputUtils.js +3 -2
- package/lib/commonjs/web/utils/inputUtils.js.map +1 -1
- package/lib/module/web/utils/inputUtils.js +3 -2
- package/lib/module/web/utils/inputUtils.js.map +1 -1
- package/lib/typescript/src/web/utils/inputUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/web/utils/inputUtils.ts +3 -2
- package/apple/RCTBackedTextFieldDelegateAdapter+Markdown.h +0 -14
- package/apple/RCTBackedTextFieldDelegateAdapter+Markdown.mm +0 -43
- package/apple/RCTUITextView+Markdown.h +0 -19
- package/apple/RCTUITextView+Markdown.mm +0 -41
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
NS_ASSUME_NONNULL_BEGIN
|
|
6
6
|
|
|
7
|
+
const NSAttributedStringKey RCTLiveMarkdownTextAttributeName = @"RCTLiveMarkdownText";
|
|
8
|
+
|
|
7
9
|
const NSAttributedStringKey RCTLiveMarkdownBlockquoteDepthAttributeName = @"RCTLiveMarkdownBlockquoteDepth";
|
|
8
10
|
|
|
9
11
|
@interface MarkdownFormatter : NSObject
|
|
10
12
|
|
|
11
|
-
- (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
- (void)formatAttributedString:(nonnull NSMutableAttributedString *)attributedString
|
|
14
|
+
withDefaultTextAttributes:(nonnull NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
|
|
15
|
+
withMarkdownRanges:(nonnull NSArray<MarkdownRange *> *)markdownRanges
|
|
16
|
+
withMarkdownStyle:(nonnull RCTMarkdownStyle *)markdownStyle;
|
|
15
17
|
|
|
16
18
|
NS_ASSUME_NONNULL_END
|
|
17
19
|
|
|
@@ -3,21 +3,19 @@
|
|
|
3
3
|
|
|
4
4
|
@implementation MarkdownFormatter
|
|
5
5
|
|
|
6
|
-
- (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
- (void)formatAttributedString:(nonnull NSMutableAttributedString *)attributedString
|
|
7
|
+
withDefaultTextAttributes:(nonnull NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
|
|
8
|
+
withMarkdownRanges:(nonnull NSArray<MarkdownRange *> *)markdownRanges
|
|
9
|
+
withMarkdownStyle:(nonnull RCTMarkdownStyle *)markdownStyle
|
|
10
10
|
{
|
|
11
|
-
|
|
11
|
+
NSRange fullRange = NSMakeRange(0, attributedString.length);
|
|
12
12
|
|
|
13
13
|
[attributedString beginEditing];
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
[attributedString addAttribute:
|
|
19
|
-
value:[NSNumber numberWithInteger:NSUnderlineStyleNone]
|
|
20
|
-
range:NSMakeRange(0, attributedString.length)];
|
|
15
|
+
[attributedString setAttributes:defaultTextAttributes range:fullRange];
|
|
16
|
+
|
|
17
|
+
// We add a custom attribute to force a different comparison mode in swizzled `_textOf` method.
|
|
18
|
+
[attributedString addAttribute:RCTLiveMarkdownTextAttributeName value:@(YES) range:fullRange];
|
|
21
19
|
|
|
22
20
|
for (MarkdownRange *markdownRange in markdownRanges) {
|
|
23
21
|
[self applyRangeToAttributedString:attributedString
|
|
@@ -28,15 +26,15 @@
|
|
|
28
26
|
defaultTextAttributes:defaultTextAttributes];
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
[attributedString.string enumerateSubstringsInRange:
|
|
29
|
+
[attributedString.string enumerateSubstringsInRange:fullRange
|
|
32
30
|
options:NSStringEnumerationByLines | NSStringEnumerationSubstringNotRequired
|
|
33
31
|
usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
|
|
34
32
|
RCTApplyBaselineOffset(attributedString, enclosingRange);
|
|
35
33
|
}];
|
|
36
34
|
|
|
37
|
-
[attributedString
|
|
35
|
+
[attributedString fixAttributesInRange:fullRange];
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
[attributedString endEditing];
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
- (void)applyRangeToAttributedString:(NSMutableAttributedString *)attributedString
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import <React/RCTUITextField.h>
|
|
3
|
+
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface MarkdownTextFieldObserver : NSObject
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithTextField:(nonnull RCTUITextField *)textField markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils;
|
|
10
|
+
|
|
11
|
+
- (void)textFieldDidChange:(UITextField *)textField;
|
|
12
|
+
|
|
13
|
+
- (void)textFieldDidEndEditing:(UITextField *)textField;
|
|
14
|
+
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#import <RNLiveMarkdown/MarkdownTextFieldObserver.h>
|
|
2
|
+
#import "react_native_assert.h"
|
|
3
|
+
|
|
4
|
+
@implementation MarkdownTextFieldObserver {
|
|
5
|
+
RCTUITextField *_textField;
|
|
6
|
+
RCTMarkdownUtils *_markdownUtils;
|
|
7
|
+
BOOL _active;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
- (instancetype)initWithTextField:(nonnull RCTUITextField *)textField markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils
|
|
11
|
+
{
|
|
12
|
+
if ((self = [super init])) {
|
|
13
|
+
react_native_assert(textField != nil);
|
|
14
|
+
react_native_assert(markdownUtils != nil);
|
|
15
|
+
|
|
16
|
+
_textField = textField;
|
|
17
|
+
_markdownUtils = markdownUtils;
|
|
18
|
+
_active = YES;
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
|
|
24
|
+
{
|
|
25
|
+
if (_active && ([keyPath isEqualToString:@"text"] || [keyPath isEqualToString:@"attributedText"])) {
|
|
26
|
+
[self applyMarkdownFormatting];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)textFieldDidChange:(__unused UITextField *)textField
|
|
31
|
+
{
|
|
32
|
+
[self applyMarkdownFormatting];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (void)textFieldDidEndEditing:(__unused UITextField *)textField
|
|
36
|
+
{
|
|
37
|
+
// In order to prevent iOS from applying underline to the whole text if text ends with a link on blur,
|
|
38
|
+
// we need to update `defaultTextAttributes` which at this point doesn't contain NSUnderline attribute yet.
|
|
39
|
+
// It seems like the setter performs deep comparision, so we differentiate the new value using a counter,
|
|
40
|
+
// otherwise this trick would work only once.
|
|
41
|
+
static NSAttributedStringKey RCTLiveMarkdownForceUpdateAttributeName = @"RCTLiveMarkdownForceUpdate";
|
|
42
|
+
static NSUInteger counter = 0;
|
|
43
|
+
NSMutableDictionary *defaultTextAttributes = [_textField.defaultTextAttributes mutableCopy];
|
|
44
|
+
defaultTextAttributes[RCTLiveMarkdownForceUpdateAttributeName] = @(counter++);
|
|
45
|
+
_textField.defaultTextAttributes = defaultTextAttributes;
|
|
46
|
+
[self applyMarkdownFormatting];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (void)applyMarkdownFormatting
|
|
50
|
+
{
|
|
51
|
+
react_native_assert(_textField.defaultTextAttributes != nil);
|
|
52
|
+
|
|
53
|
+
if (_textField.markedTextRange != nil) {
|
|
54
|
+
return; // skip formatting during multi-stage input to avoid breaking internal state
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
NSMutableAttributedString *attributedText = [_textField.attributedText mutableCopy];
|
|
58
|
+
[_markdownUtils applyMarkdownFormatting:attributedText withDefaultTextAttributes:_textField.defaultTextAttributes];
|
|
59
|
+
|
|
60
|
+
UITextRange *textRange = _textField.selectedTextRange;
|
|
61
|
+
|
|
62
|
+
_active = NO; // prevent recursion
|
|
63
|
+
_textField.attributedText = attributedText;
|
|
64
|
+
_active = YES;
|
|
65
|
+
|
|
66
|
+
// Restore cursor position
|
|
67
|
+
[_textField setSelectedTextRange:textRange notifyDelegate:NO];
|
|
68
|
+
|
|
69
|
+
// Eliminate underline blinks while typing if previous text ends with a link
|
|
70
|
+
_textField.typingAttributes = _textField.defaultTextAttributes;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@end
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
#import <react/renderer/components/RNLiveMarkdownSpec/Props.h>
|
|
3
3
|
#import <React/RCTFabricComponentsPlugins.h>
|
|
4
4
|
#import <React/RCTUITextField.h>
|
|
5
|
+
#import <React/RCTUITextView.h>
|
|
6
|
+
#import <React/RCTTextInputComponentView.h>
|
|
5
7
|
|
|
6
8
|
#import <RNLiveMarkdown/MarkdownBackedTextInputDelegate.h>
|
|
7
9
|
#import <RNLiveMarkdown/MarkdownLayoutManager.h>
|
|
10
|
+
#import <RNLiveMarkdown/MarkdownTextFieldObserver.h>
|
|
11
|
+
#import <RNLiveMarkdown/MarkdownTextViewObserver.h>
|
|
8
12
|
#import <RNLiveMarkdown/MarkdownTextInputDecoratorComponentView.h>
|
|
9
13
|
#import <RNLiveMarkdown/MarkdownTextInputDecoratorViewComponentDescriptor.h>
|
|
10
|
-
#import <RNLiveMarkdown/
|
|
14
|
+
#import <RNLiveMarkdown/MarkdownTextStorageDelegate.h>
|
|
11
15
|
#import <RNLiveMarkdown/RCTMarkdownStyle.h>
|
|
12
|
-
#import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
|
|
13
|
-
#import <RNLiveMarkdown/RCTUITextView+Markdown.h>
|
|
14
16
|
|
|
15
17
|
#import <objc/runtime.h>
|
|
16
18
|
|
|
@@ -21,10 +23,11 @@ using namespace facebook::react;
|
|
|
21
23
|
RCTMarkdownStyle *_markdownStyle;
|
|
22
24
|
NSNumber *_parserId;
|
|
23
25
|
MarkdownBackedTextInputDelegate *_markdownBackedTextInputDelegate;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
MarkdownTextStorageDelegate *_markdownTextStorageDelegate;
|
|
27
|
+
MarkdownTextViewObserver *_markdownTextViewObserver;
|
|
28
|
+
MarkdownTextFieldObserver *_markdownTextFieldObserver;
|
|
27
29
|
__weak RCTUITextView *_textView;
|
|
30
|
+
__weak RCTUITextField *_textField;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
@@ -51,21 +54,47 @@ using namespace facebook::react;
|
|
|
51
54
|
- (void)didAddSubview:(UIView *)subview
|
|
52
55
|
{
|
|
53
56
|
react_native_assert([subview isKindOfClass:[RCTTextInputComponentView class]] && "Child component of MarkdownTextInputDecoratorComponentView is not an instance of RCTTextInputComponentView.");
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
RCTTextInputComponentView *textInputComponentView = (RCTTextInputComponentView *)subview;
|
|
58
|
+
UIView<RCTBackedTextInputViewProtocol> *backedTextInputView = [textInputComponentView valueForKey:@"_backedTextInputView"];
|
|
56
59
|
|
|
57
60
|
_markdownUtils = [[RCTMarkdownUtils alloc] init];
|
|
58
61
|
[_markdownUtils setMarkdownStyle:_markdownStyle];
|
|
59
62
|
[_markdownUtils setParserId:_parserId];
|
|
60
63
|
|
|
61
|
-
[
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
if ([backedTextInputView isKindOfClass:[RCTUITextField class]]) {
|
|
65
|
+
_textField = (RCTUITextField *)backedTextInputView;
|
|
66
|
+
|
|
67
|
+
// make sure `adjustsFontSizeToFitWidth` is disabled, otherwise formatting will be overwritten
|
|
68
|
+
react_native_assert(_textField.adjustsFontSizeToFitWidth == NO);
|
|
69
|
+
|
|
70
|
+
_markdownTextFieldObserver = [[MarkdownTextFieldObserver alloc] initWithTextField:_textField markdownUtils:_markdownUtils];
|
|
71
|
+
|
|
72
|
+
// register observers for future edits
|
|
73
|
+
[_textField addTarget:_markdownTextFieldObserver action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
|
|
74
|
+
[_textField addTarget:_markdownTextFieldObserver action:@selector(textFieldDidEndEditing:) forControlEvents:UIControlEventEditingDidEnd];
|
|
75
|
+
[_textField addObserver:_markdownTextFieldObserver forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:NULL];
|
|
76
|
+
[_textField addObserver:_markdownTextFieldObserver forKeyPath:@"attributedText" options:NSKeyValueObservingOptionNew context:NULL];
|
|
77
|
+
|
|
78
|
+
// format initial value
|
|
79
|
+
[_markdownTextFieldObserver textFieldDidChange:_textField];
|
|
80
|
+
|
|
81
|
+
// TODO: register blockquotes layout manager
|
|
82
|
+
// https://github.com/Expensify/react-native-live-markdown/issues/87
|
|
83
|
+
} else if ([backedTextInputView isKindOfClass:[RCTUITextView class]]) {
|
|
84
|
+
_textView = (RCTUITextView *)backedTextInputView;
|
|
85
|
+
|
|
86
|
+
// register delegate for future edits
|
|
87
|
+
react_native_assert(_textView.textStorage.delegate == nil);
|
|
88
|
+
_markdownTextStorageDelegate = [[MarkdownTextStorageDelegate alloc] initWithTextView:_textView markdownUtils:_markdownUtils];
|
|
89
|
+
_textView.textStorage.delegate = _markdownTextStorageDelegate;
|
|
90
|
+
|
|
91
|
+
// register observer for default text attributes
|
|
92
|
+
_markdownTextViewObserver = [[MarkdownTextViewObserver alloc] initWithTextView:_textView markdownUtils:_markdownUtils];
|
|
93
|
+
[_textView addObserver:_markdownTextViewObserver forKeyPath:@"defaultTextAttributes" options:NSKeyValueObservingOptionNew context:NULL];
|
|
94
|
+
|
|
95
|
+
// format initial value
|
|
96
|
+
[_textView.textStorage setAttributedString:_textView.attributedText];
|
|
97
|
+
|
|
69
98
|
NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
|
|
70
99
|
|
|
71
100
|
// Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
|
|
@@ -91,19 +120,26 @@ using namespace facebook::react;
|
|
|
91
120
|
if (newWindow != nil) {
|
|
92
121
|
return;
|
|
93
122
|
}
|
|
94
|
-
if (_textInput != nil) {
|
|
95
|
-
[_textInput setMarkdownUtils:nil];
|
|
96
|
-
}
|
|
97
|
-
if (_adapter != nil) {
|
|
98
|
-
[_adapter setMarkdownUtils:nil];
|
|
99
|
-
}
|
|
100
123
|
if (_textView != nil) {
|
|
101
|
-
_markdownBackedTextInputDelegate = nil;
|
|
102
|
-
[_textView setMarkdownUtils:nil];
|
|
103
124
|
if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
|
|
104
125
|
[_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
|
|
105
126
|
object_setClass(_textView.layoutManager, [NSLayoutManager class]);
|
|
106
127
|
}
|
|
128
|
+
_markdownBackedTextInputDelegate = nil;
|
|
129
|
+
[_textView removeObserver:_markdownTextViewObserver forKeyPath:@"defaultTextAttributes" context:NULL];
|
|
130
|
+
_markdownTextViewObserver = nil;
|
|
131
|
+
_markdownTextStorageDelegate = nil;
|
|
132
|
+
_textView.textStorage.delegate = nil;
|
|
133
|
+
_textView = nil;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (_textField != nil) {
|
|
137
|
+
[_textField removeTarget:_markdownTextFieldObserver action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
|
|
138
|
+
[_textField removeTarget:_markdownTextFieldObserver action:@selector(textFieldDidEndEditing:) forControlEvents:UIControlEventEditingDidEnd];
|
|
139
|
+
[_textField removeObserver:_markdownTextFieldObserver forKeyPath:@"text" context:NULL];
|
|
140
|
+
[_textField removeObserver:_markdownTextFieldObserver forKeyPath:@"attributedText" context:NULL];
|
|
141
|
+
_markdownTextFieldObserver = nil;
|
|
142
|
+
_textField = nil;
|
|
107
143
|
}
|
|
108
144
|
}
|
|
109
145
|
|
|
@@ -130,11 +166,10 @@ using namespace facebook::react;
|
|
|
130
166
|
- (void)applyNewStyles
|
|
131
167
|
{
|
|
132
168
|
if (_textView != nil) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
[_textInput _setAttributedString:_backedTextInputView.attributedText];
|
|
169
|
+
[_textView.textStorage setAttributedString:_textView.attributedText];
|
|
170
|
+
}
|
|
171
|
+
if (_textField != nil) {
|
|
172
|
+
[_markdownTextFieldObserver textFieldDidChange:_textField];
|
|
138
173
|
}
|
|
139
174
|
}
|
|
140
175
|
|
|
@@ -188,8 +188,8 @@ void MarkdownTextInputDecoratorShadowNode::applyMarkdownFormattingToTextInputSta
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
// apply markdown
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
NSMutableAttributedString *newString = [nsAttributedString mutableCopy];
|
|
192
|
+
[utils applyMarkdownFormatting:newString withDefaultTextAttributes:defaultNSTextAttributes];
|
|
193
193
|
|
|
194
194
|
// create a clone of the old TextInputState and update the
|
|
195
195
|
// attributed string box to point to the string with markdown
|
|
@@ -200,8 +200,8 @@ void MarkdownTextInputDecoratorShadowNode::applyMarkdownFormattingToTextInputSta
|
|
|
200
200
|
AttributedStringBox::Mode::OpaquePointer) {
|
|
201
201
|
|
|
202
202
|
// apply markdown
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
NSMutableAttributedString *newString = [nsAttributedString mutableCopy];
|
|
204
|
+
[utils applyMarkdownFormatting:newString withDefaultTextAttributes:defaultNSTextAttributes];
|
|
205
205
|
|
|
206
206
|
// create a clone of the old TextInputState and update the
|
|
207
207
|
// attributed string box to point to the string with markdown
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import <React/RCTUITextView.h>
|
|
3
|
+
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface MarkdownTextStorageDelegate : NSObject <NSTextStorageDelegate>
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithTextView:(nonnull RCTUITextView *)textView markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils;
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#import <RNLiveMarkdown/MarkdownTextStorageDelegate.h>
|
|
2
|
+
#import "react_native_assert.h"
|
|
3
|
+
|
|
4
|
+
@implementation MarkdownTextStorageDelegate {
|
|
5
|
+
RCTUITextView *_textView;
|
|
6
|
+
RCTMarkdownUtils *_markdownUtils;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithTextView:(nonnull RCTUITextView *)textView markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils
|
|
10
|
+
{
|
|
11
|
+
if ((self = [super init])) {
|
|
12
|
+
react_native_assert(textView != nil);
|
|
13
|
+
react_native_assert(markdownUtils != nil);
|
|
14
|
+
|
|
15
|
+
_textView = textView;
|
|
16
|
+
_markdownUtils = markdownUtils;
|
|
17
|
+
}
|
|
18
|
+
return self;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta {
|
|
22
|
+
react_native_assert(_textView.defaultTextAttributes != nil);
|
|
23
|
+
|
|
24
|
+
[_markdownUtils applyMarkdownFormatting:textStorage withDefaultTextAttributes:_textView.defaultTextAttributes];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import <React/RCTUITextView.h>
|
|
3
|
+
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
@interface MarkdownTextViewObserver : NSObject
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithTextView:(nonnull RCTUITextView *)textView markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils;
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#import <RNLiveMarkdown/MarkdownTextViewObserver.h>
|
|
2
|
+
#import "react_native_assert.h"
|
|
3
|
+
|
|
4
|
+
@implementation MarkdownTextViewObserver {
|
|
5
|
+
RCTUITextView *_textView;
|
|
6
|
+
RCTMarkdownUtils *_markdownUtils;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
- (instancetype)initWithTextView:(nonnull RCTUITextView *)textView markdownUtils:(nonnull RCTMarkdownUtils *)markdownUtils
|
|
10
|
+
{
|
|
11
|
+
if ((self = [super init])) {
|
|
12
|
+
react_native_assert(textView != nil);
|
|
13
|
+
react_native_assert(markdownUtils != nil);
|
|
14
|
+
|
|
15
|
+
_textView = textView;
|
|
16
|
+
_markdownUtils = markdownUtils;
|
|
17
|
+
}
|
|
18
|
+
return self;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
|
|
22
|
+
{
|
|
23
|
+
if ([keyPath isEqualToString:@"defaultTextAttributes"]) {
|
|
24
|
+
[_textView.textStorage setAttributedString:_textView.attributedText];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@end
|
package/apple/RCTMarkdownUtils.h
CHANGED
|
@@ -8,8 +8,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
8
|
@property (nonatomic) RCTMarkdownStyle *markdownStyle;
|
|
9
9
|
@property (nonatomic) NSNumber *parserId;
|
|
10
10
|
|
|
11
|
-
- (
|
|
12
|
-
|
|
11
|
+
- (void)applyMarkdownFormatting:(nonnull NSMutableAttributedString *)attributedString
|
|
12
|
+
withDefaultTextAttributes:(nonnull NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes;
|
|
13
13
|
|
|
14
14
|
@end
|
|
15
15
|
|
|
@@ -5,11 +5,6 @@
|
|
|
5
5
|
@implementation RCTMarkdownUtils {
|
|
6
6
|
MarkdownParser *_markdownParser;
|
|
7
7
|
MarkdownFormatter *_markdownFormatter;
|
|
8
|
-
NSString *_prevInputString;
|
|
9
|
-
NSAttributedString *_prevAttributedString;
|
|
10
|
-
NSDictionary<NSAttributedStringKey, id> *_prevDefaultTextAttributes;
|
|
11
|
-
__weak RCTMarkdownStyle *_prevMarkdownStyle;
|
|
12
|
-
__weak NSNumber *_prevParserId;
|
|
13
8
|
}
|
|
14
9
|
|
|
15
10
|
- (instancetype)init
|
|
@@ -22,39 +17,21 @@
|
|
|
22
17
|
return self;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
- (
|
|
26
|
-
|
|
20
|
+
- (void)applyMarkdownFormatting:(nonnull NSMutableAttributedString *)attributedString
|
|
21
|
+
withDefaultTextAttributes:(nonnull NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
|
|
27
22
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// `_markdownStyle` and `_parserId` may not be initialized immediately due to the order of mount instructions
|
|
34
|
-
// props update will be executed after the view hierarchy is initialized.
|
|
35
|
-
if (_markdownStyle == nil || _parserId == nil) {
|
|
36
|
-
return nil;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
NSString *inputString = [input string];
|
|
40
|
-
if ([inputString isEqualToString:_prevInputString] && [defaultTextAttributes isEqualToDictionary:_prevDefaultTextAttributes] && [_markdownStyle isEqual:_prevMarkdownStyle] && [_parserId isEqualToNumber:_prevParserId]) {
|
|
41
|
-
return _prevAttributedString;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
NSArray<MarkdownRange *> *markdownRanges = [_markdownParser parse:inputString withParserId:_parserId];
|
|
23
|
+
// `_markdownStyle` and `_parserId` may not be initialized immediately due to the order of mount instructions
|
|
24
|
+
// props update will be executed after the view hierarchy is initialized.
|
|
25
|
+
if (_markdownStyle == nil || _parserId == nil) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
45
28
|
|
|
46
|
-
|
|
47
|
-
withDefaultTextAttributes:defaultTextAttributes
|
|
48
|
-
withMarkdownRanges:markdownRanges
|
|
49
|
-
withMarkdownStyle:_markdownStyle];
|
|
50
|
-
_prevInputString = inputString;
|
|
51
|
-
_prevAttributedString = attributedString;
|
|
52
|
-
_prevDefaultTextAttributes = defaultTextAttributes;
|
|
53
|
-
_prevMarkdownStyle = _markdownStyle;
|
|
54
|
-
_prevParserId = _parserId;
|
|
29
|
+
NSArray<MarkdownRange *> *markdownRanges = [_markdownParser parse:attributedString.string withParserId:_parserId];
|
|
55
30
|
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
[_markdownFormatter formatAttributedString:attributedString
|
|
32
|
+
withDefaultTextAttributes:defaultTextAttributes
|
|
33
|
+
withMarkdownRanges:markdownRanges
|
|
34
|
+
withMarkdownStyle:_markdownStyle];
|
|
58
35
|
}
|
|
59
36
|
|
|
60
37
|
@end
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
#import <React/RCTTextInputComponentView.h>
|
|
2
|
-
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
3
2
|
|
|
4
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
5
4
|
|
|
6
5
|
@interface RCTTextInputComponentView (Markdown)
|
|
7
6
|
|
|
8
|
-
@property(nonatomic, nullable, getter=getMarkdownUtils) RCTMarkdownUtils *markdownUtils;
|
|
9
|
-
|
|
10
|
-
- (void)markdown__setAttributedString:(NSAttributedString *)attributedString;
|
|
11
|
-
|
|
12
7
|
- (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText;
|
|
13
8
|
|
|
14
|
-
- (void)_setAttributedString:(NSAttributedString *)attributedString;
|
|
15
|
-
|
|
16
9
|
@end
|
|
17
10
|
|
|
18
11
|
NS_ASSUME_NONNULL_END
|
|
@@ -1,63 +1,23 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
|
|
2
|
-
#import <RNLiveMarkdown/
|
|
3
|
-
#import <React/RCTUITextView.h>
|
|
2
|
+
#import <RNLiveMarkdown/MarkdownFormatter.h>
|
|
4
3
|
#import <objc/message.h>
|
|
5
4
|
|
|
6
5
|
@implementation RCTTextInputComponentView (Markdown)
|
|
7
6
|
|
|
8
|
-
- (void)setMarkdownUtils:(RCTMarkdownUtils *)markdownUtils {
|
|
9
|
-
objc_setAssociatedObject(self, @selector(getMarkdownUtils), markdownUtils, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
- (RCTMarkdownUtils *)getMarkdownUtils {
|
|
13
|
-
return objc_getAssociatedObject(self, @selector(getMarkdownUtils));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
- (RCTUITextView *)getBackedTextInputView {
|
|
17
|
-
return [self valueForKey:@"_backedTextInputView"];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
- (void)markdown__setAttributedString:(NSAttributedString *)attributedString
|
|
21
|
-
{
|
|
22
|
-
RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
|
|
23
|
-
RCTUITextView *backedTextInputView = [self getBackedTextInputView];
|
|
24
|
-
if (markdownUtils != nil && backedTextInputView != nil) {
|
|
25
|
-
attributedString = [markdownUtils parseMarkdown:attributedString withDefaultTextAttributes:backedTextInputView.defaultTextAttributes];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Call the original method
|
|
29
|
-
[self markdown__setAttributedString:attributedString];
|
|
30
|
-
|
|
31
|
-
if (markdownUtils != nil && backedTextInputView != nil) {
|
|
32
|
-
// After adding a newline at the end of the blockquote, the typing attributes in the next line still contain
|
|
33
|
-
// NSParagraphStyle with non-zero firstLineHeadIndent and headIntent added by `_updateTypingAttributes` call.
|
|
34
|
-
// This causes the cursor to be shifted to the right instead of being located at the beginning of the line.
|
|
35
|
-
// The following code resets firstLineHeadIndent and headIndent in NSParagraphStyle in typing attributes
|
|
36
|
-
// in order to fix the position of the cursor.
|
|
37
|
-
NSDictionary<NSAttributedStringKey, id> *typingAttributes = backedTextInputView.typingAttributes;
|
|
38
|
-
if (typingAttributes[NSParagraphStyleAttributeName] != nil) {
|
|
39
|
-
NSMutableDictionary *mutableTypingAttributes = [typingAttributes mutableCopy];
|
|
40
|
-
NSMutableParagraphStyle *mutableParagraphStyle = [typingAttributes[NSParagraphStyleAttributeName] mutableCopy];
|
|
41
|
-
mutableParagraphStyle.firstLineHeadIndent = 0;
|
|
42
|
-
mutableParagraphStyle.headIndent = 0;
|
|
43
|
-
mutableTypingAttributes[NSParagraphStyleAttributeName] = mutableParagraphStyle;
|
|
44
|
-
backedTextInputView.typingAttributes = mutableTypingAttributes;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
7
|
- (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
|
|
50
8
|
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
9
|
+
__block BOOL isMarkdownTextInput = false;
|
|
10
|
+
[oldText enumerateAttribute:RCTLiveMarkdownTextAttributeName
|
|
11
|
+
inRange:NSMakeRange(0, oldText.length)
|
|
12
|
+
options:0
|
|
13
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
14
|
+
if (value) {
|
|
15
|
+
isMarkdownTextInput = true;
|
|
16
|
+
*stop = YES;
|
|
17
|
+
}
|
|
18
|
+
}];
|
|
19
|
+
if (isMarkdownTextInput) {
|
|
20
|
+
return [newText.string isEqualToString:oldText.string];
|
|
61
21
|
}
|
|
62
22
|
|
|
63
23
|
return [self markdown__textOf:newText equals:oldText];
|
|
@@ -67,25 +27,13 @@
|
|
|
67
27
|
{
|
|
68
28
|
static dispatch_once_t onceToken;
|
|
69
29
|
dispatch_once(&onceToken, ^{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
// swizzle _textOf
|
|
82
|
-
Class cls = [self class];
|
|
83
|
-
SEL originalSelector = @selector(_textOf:equals:);
|
|
84
|
-
SEL swizzledSelector = @selector(markdown__textOf:equals:);
|
|
85
|
-
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
86
|
-
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
|
87
|
-
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
88
|
-
}
|
|
30
|
+
// swizzle _textOf
|
|
31
|
+
Class cls = [self class];
|
|
32
|
+
SEL originalSelector = @selector(_textOf:equals:);
|
|
33
|
+
SEL swizzledSelector = @selector(markdown__textOf:equals:);
|
|
34
|
+
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
35
|
+
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
|
36
|
+
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
89
37
|
});
|
|
90
38
|
}
|
|
91
39
|
|
|
@@ -69,8 +69,9 @@ function parseInnerHTMLToText(target, cursorPosition, inputType) {
|
|
|
69
69
|
// If we are operating on the nodes that are children of the MarkdownTextInputElement, we need to add a newline after each
|
|
70
70
|
const isTopComponent = ((_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.contentEditable) === 'true';
|
|
71
71
|
if (isTopComponent) {
|
|
72
|
-
//
|
|
73
|
-
|
|
72
|
+
// When inputType is undefined, the first part of the replaced text is added as a text node.
|
|
73
|
+
// Because of it, we need to prevent adding new lines in this case
|
|
74
|
+
if (!inputType && node.nodeType === Node.TEXT_NODE) {
|
|
74
75
|
shouldAddNewline = false;
|
|
75
76
|
} else {
|
|
76
77
|
var _firstChild$getAttrib;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ZERO_WIDTH_SPACE","isEventComposing","nativeEvent","isComposing","keyCode","getPlaceholderValue","placeholder","length","getElementHeight","node","styles","numberOfLines","tempElement","document","createElement","setAttribute","Object","assign","style","textContent","Array","fill","join","parentElement","appendChild","height","clientHeight","removeChild","normalizeValue","value","replaceAll","parseInnerHTMLToText","target","cursorPosition","inputType","getTopParentNode","currentParentNode","parentNode","includes","_currentParentNode$pa","getAttribute","_currentParentNode","stack","text","shouldAddNewline","lastNode","childNodes","nodeName","innerHTML","_node$parentElement","pop","isTopComponent","contentEditable","nodeType","Node","TEXT_NODE","_firstChild$getAttrib","firstChild","containsEmptyBlockElement","call","_parentNode$parentEle","i","child","push","slice"],"sourceRoot":"../../../../src","sources":["web/utils/inputUtils.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["ZERO_WIDTH_SPACE","isEventComposing","nativeEvent","isComposing","keyCode","getPlaceholderValue","placeholder","length","getElementHeight","node","styles","numberOfLines","tempElement","document","createElement","setAttribute","Object","assign","style","textContent","Array","fill","join","parentElement","appendChild","height","clientHeight","removeChild","normalizeValue","value","replaceAll","parseInnerHTMLToText","target","cursorPosition","inputType","getTopParentNode","currentParentNode","parentNode","includes","_currentParentNode$pa","getAttribute","_currentParentNode","stack","text","shouldAddNewline","lastNode","childNodes","nodeName","innerHTML","_node$parentElement","pop","isTopComponent","contentEditable","nodeType","Node","TEXT_NODE","_firstChild$getAttrib","firstChild","containsEmptyBlockElement","call","_parentNode$parentEle","i","child","push","slice"],"sourceRoot":"../../../../src","sources":["web/utils/inputUtils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -59,8 +59,9 @@ function parseInnerHTMLToText(target, cursorPosition, inputType) {
|
|
|
59
59
|
// If we are operating on the nodes that are children of the MarkdownTextInputElement, we need to add a newline after each
|
|
60
60
|
const isTopComponent = ((_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.contentEditable) === 'true';
|
|
61
61
|
if (isTopComponent) {
|
|
62
|
-
//
|
|
63
|
-
|
|
62
|
+
// When inputType is undefined, the first part of the replaced text is added as a text node.
|
|
63
|
+
// Because of it, we need to prevent adding new lines in this case
|
|
64
|
+
if (!inputType && node.nodeType === Node.TEXT_NODE) {
|
|
64
65
|
shouldAddNewline = false;
|
|
65
66
|
} else {
|
|
66
67
|
var _firstChild$getAttrib;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ZERO_WIDTH_SPACE","isEventComposing","nativeEvent","isComposing","keyCode","getPlaceholderValue","placeholder","length","getElementHeight","node","styles","numberOfLines","tempElement","document","createElement","setAttribute","Object","assign","style","textContent","Array","fill","join","parentElement","appendChild","height","clientHeight","removeChild","normalizeValue","value","replaceAll","parseInnerHTMLToText","target","cursorPosition","inputType","getTopParentNode","currentParentNode","parentNode","includes","_currentParentNode$pa","getAttribute","_currentParentNode","stack","text","shouldAddNewline","lastNode","childNodes","nodeName","innerHTML","_node$parentElement","pop","isTopComponent","contentEditable","nodeType","Node","TEXT_NODE","_firstChild$getAttrib","firstChild","containsEmptyBlockElement","call","_parentNode$parentEle","i","child","push","slice"],"sourceRoot":"../../../../src","sources":["web/utils/inputUtils.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["ZERO_WIDTH_SPACE","isEventComposing","nativeEvent","isComposing","keyCode","getPlaceholderValue","placeholder","length","getElementHeight","node","styles","numberOfLines","tempElement","document","createElement","setAttribute","Object","assign","style","textContent","Array","fill","join","parentElement","appendChild","height","clientHeight","removeChild","normalizeValue","value","replaceAll","parseInnerHTMLToText","target","cursorPosition","inputType","getTopParentNode","currentParentNode","parentNode","includes","_currentParentNode$pa","getAttribute","_currentParentNode","stack","text","shouldAddNewline","lastNode","childNodes","nodeName","innerHTML","_node$parentElement","pop","isTopComponent","contentEditable","nodeType","Node","TEXT_NODE","_firstChild$getAttrib","firstChild","containsEmptyBlockElement","call","_parentNode$parentEle","i","child","push","slice"],"sourceRoot":"../../../../src","sources":["web/utils/inputUtils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputUtils.d.ts","sourceRoot":"","sources":["../../../../../src/web/utils/inputUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAC,mBAAmB,EAAE,wBAAwB,EAAC,MAAM,6BAA6B,CAAC;AAM/F,iBAAS,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,aAAa,GAAG,mBAAmB,WAEpF;AAED,iBAAS,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,UAK3D;AAED,iBAAS,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,UAcvG;AAED,iBAAS,cAAc,CAAC,KAAK,EAAE,MAAM,UAEpC;AAGD,iBAAS,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"inputUtils.d.ts","sourceRoot":"","sources":["../../../../../src/web/utils/inputUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAC,mBAAmB,EAAE,wBAAwB,EAAC,MAAM,6BAA6B,CAAC;AAM/F,iBAAS,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,aAAa,GAAG,mBAAmB,WAEpF;AAED,iBAAS,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,UAK3D;AAED,iBAAS,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,UAcvG;AAED,iBAAS,cAAc,CAAC,KAAK,EAAE,MAAM,UAEpC;AAGD,iBAAS,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAwElH;AAED,OAAO,EAAC,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,cAAc,EAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expensify/react-native-live-markdown",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.275",
|
|
4
4
|
"description": "Drop-in replacement for React Native's TextInput component with Markdown formatting.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -65,8 +65,9 @@ function parseInnerHTMLToText(target: MarkdownTextInputElement, cursorPosition:
|
|
|
65
65
|
// If we are operating on the nodes that are children of the MarkdownTextInputElement, we need to add a newline after each
|
|
66
66
|
const isTopComponent = node.parentElement?.contentEditable === 'true';
|
|
67
67
|
if (isTopComponent) {
|
|
68
|
-
//
|
|
69
|
-
|
|
68
|
+
// When inputType is undefined, the first part of the replaced text is added as a text node.
|
|
69
|
+
// Because of it, we need to prevent adding new lines in this case
|
|
70
|
+
if (!inputType && node.nodeType === Node.TEXT_NODE) {
|
|
70
71
|
shouldAddNewline = false;
|
|
71
72
|
} else {
|
|
72
73
|
const firstChild = node.firstChild as HTMLElement;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#import <React/RCTBackedTextInputDelegateAdapter.h>
|
|
2
|
-
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
3
|
-
|
|
4
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
-
|
|
6
|
-
@interface RCTBackedTextFieldDelegateAdapter (Markdown)
|
|
7
|
-
|
|
8
|
-
@property(nonatomic, nullable, getter=getMarkdownUtils) RCTMarkdownUtils *markdownUtils;
|
|
9
|
-
|
|
10
|
-
- (void)markdown_textFieldDidChange;
|
|
11
|
-
|
|
12
|
-
@end
|
|
13
|
-
|
|
14
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
#import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
|
|
2
|
-
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
3
|
-
#import <React/RCTUITextField.h>
|
|
4
|
-
#import <objc/message.h>
|
|
5
|
-
|
|
6
|
-
@implementation RCTBackedTextFieldDelegateAdapter (Markdown)
|
|
7
|
-
|
|
8
|
-
- (void)setMarkdownUtils:(RCTMarkdownUtils *)markdownUtils {
|
|
9
|
-
objc_setAssociatedObject(self, @selector(getMarkdownUtils), markdownUtils, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
- (RCTMarkdownUtils *)getMarkdownUtils {
|
|
13
|
-
return objc_getAssociatedObject(self, @selector(getMarkdownUtils));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
- (void)markdown_textFieldDidChange
|
|
17
|
-
{
|
|
18
|
-
RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
|
|
19
|
-
if (markdownUtils != nil) {
|
|
20
|
-
RCTUITextField *backedTextInputView = [self valueForKey:@"_backedTextInputView"];
|
|
21
|
-
UITextRange *range = backedTextInputView.selectedTextRange;
|
|
22
|
-
backedTextInputView.attributedText = [markdownUtils parseMarkdown:backedTextInputView.attributedText withDefaultTextAttributes:backedTextInputView.defaultTextAttributes];
|
|
23
|
-
[backedTextInputView setSelectedTextRange:range notifyDelegate:YES];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Call the original method
|
|
27
|
-
[self markdown_textFieldDidChange];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
+ (void)load
|
|
31
|
-
{
|
|
32
|
-
static dispatch_once_t onceToken;
|
|
33
|
-
dispatch_once(&onceToken, ^{
|
|
34
|
-
Class cls = [self class];
|
|
35
|
-
SEL originalSelector = @selector(textFieldDidChange);
|
|
36
|
-
SEL swizzledSelector = @selector(markdown_textFieldDidChange);
|
|
37
|
-
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
38
|
-
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
|
39
|
-
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#import <UIKit/UIKit.h>
|
|
2
|
-
#import <React/RCTUITextView.h>
|
|
3
|
-
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
4
|
-
|
|
5
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
-
|
|
7
|
-
@interface RCTUITextView (Private)
|
|
8
|
-
- (void)textDidChange;
|
|
9
|
-
@end
|
|
10
|
-
|
|
11
|
-
@interface RCTUITextView (Markdown)
|
|
12
|
-
|
|
13
|
-
@property(nonatomic, nullable, getter=getMarkdownUtils) RCTMarkdownUtils *markdownUtils;
|
|
14
|
-
|
|
15
|
-
- (void)markdown_textDidChange;
|
|
16
|
-
|
|
17
|
-
@end
|
|
18
|
-
|
|
19
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
#import <RNLiveMarkdown/RCTUITextView+Markdown.h>
|
|
2
|
-
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
3
|
-
#import <objc/message.h>
|
|
4
|
-
|
|
5
|
-
@implementation RCTUITextView (Markdown)
|
|
6
|
-
|
|
7
|
-
- (void)setMarkdownUtils:(RCTMarkdownUtils *)markdownUtils {
|
|
8
|
-
objc_setAssociatedObject(self, @selector(getMarkdownUtils), markdownUtils, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
- (RCTMarkdownUtils *)getMarkdownUtils {
|
|
12
|
-
return objc_getAssociatedObject(self, @selector(getMarkdownUtils));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
- (void)markdown_textDidChange
|
|
16
|
-
{
|
|
17
|
-
RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
|
|
18
|
-
if (markdownUtils != nil) {
|
|
19
|
-
UITextRange *range = self.selectedTextRange;
|
|
20
|
-
super.attributedText = [markdownUtils parseMarkdown:self.attributedText withDefaultTextAttributes:self.defaultTextAttributes];
|
|
21
|
-
[super setSelectedTextRange:range]; // prevents cursor from jumping at the end when typing in the middle of the text
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Call the original method
|
|
25
|
-
[self markdown_textDidChange];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
+ (void)load
|
|
29
|
-
{
|
|
30
|
-
static dispatch_once_t onceToken;
|
|
31
|
-
dispatch_once(&onceToken, ^{
|
|
32
|
-
Class cls = [self class];
|
|
33
|
-
SEL originalSelector = @selector(textDidChange);
|
|
34
|
-
SEL swizzledSelector = @selector(markdown_textDidChange);
|
|
35
|
-
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
|
36
|
-
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
|
37
|
-
method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
@end
|