@expensify/react-native-live-markdown 0.1.245 → 0.1.247
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.
|
@@ -1,17 +1,29 @@
|
|
|
1
|
+
#import <react/debug/react_native_assert.h>
|
|
1
2
|
#import <react/renderer/components/RNLiveMarkdownSpec/Props.h>
|
|
3
|
+
#import <React/RCTFabricComponentsPlugins.h>
|
|
4
|
+
#import <React/RCTUITextField.h>
|
|
2
5
|
|
|
6
|
+
#import <RNLiveMarkdown/MarkdownLayoutManager.h>
|
|
7
|
+
#import <RNLiveMarkdown/MarkdownShadowFamilyRegistry.h>
|
|
3
8
|
#import <RNLiveMarkdown/MarkdownTextInputDecoratorComponentView.h>
|
|
4
|
-
#import <RNLiveMarkdown/
|
|
9
|
+
#import <RNLiveMarkdown/MarkdownTextInputDecoratorViewComponentDescriptor.h>
|
|
10
|
+
#import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
|
|
5
11
|
#import <RNLiveMarkdown/RCTMarkdownStyle.h>
|
|
12
|
+
#import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
|
|
13
|
+
#import <RNLiveMarkdown/RCTUITextView+Markdown.h>
|
|
6
14
|
|
|
7
|
-
#import <
|
|
8
|
-
#import "MarkdownShadowFamilyRegistry.h"
|
|
9
|
-
#import "RCTFabricComponentsPlugins.h"
|
|
15
|
+
#import <objc/runtime.h>
|
|
10
16
|
|
|
11
17
|
using namespace facebook::react;
|
|
12
18
|
|
|
13
19
|
@implementation MarkdownTextInputDecoratorComponentView {
|
|
14
|
-
|
|
20
|
+
RCTMarkdownUtils *_markdownUtils;
|
|
21
|
+
RCTMarkdownStyle *_markdownStyle;
|
|
22
|
+
NSNumber *_parserId;
|
|
23
|
+
__weak RCTTextInputComponentView *_textInput;
|
|
24
|
+
__weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
|
|
25
|
+
__weak RCTBackedTextFieldDelegateAdapter *_adapter;
|
|
26
|
+
__weak RCTUITextView *_textView;
|
|
15
27
|
ShadowNodeFamily::Shared _decoratorFamily;
|
|
16
28
|
}
|
|
17
29
|
|
|
@@ -31,10 +43,6 @@ using namespace facebook::react;
|
|
|
31
43
|
if (self = [super initWithFrame:frame]) {
|
|
32
44
|
static const auto defaultProps = std::make_shared<const MarkdownTextInputDecoratorViewProps>();
|
|
33
45
|
_props = defaultProps;
|
|
34
|
-
|
|
35
|
-
_view = [[MarkdownTextInputDecoratorView alloc] init];
|
|
36
|
-
|
|
37
|
-
self.contentView = _view;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
return self;
|
|
@@ -43,11 +51,11 @@ using namespace facebook::react;
|
|
|
43
51
|
- (void)updateState:(const facebook::react::State::Shared &)state oldState:(const facebook::react::State::Shared &)oldState
|
|
44
52
|
{
|
|
45
53
|
auto data = std::static_pointer_cast<MarkdownTextInputDecoratorShadowNode::ConcreteState const>(state)->getData();
|
|
46
|
-
|
|
54
|
+
|
|
47
55
|
if (_decoratorFamily != nullptr) {
|
|
48
56
|
MarkdownShadowFamilyRegistry::unregisterFamilyForUpdates(_decoratorFamily);
|
|
49
57
|
}
|
|
50
|
-
|
|
58
|
+
|
|
51
59
|
_decoratorFamily = data.decoratorFamily;
|
|
52
60
|
MarkdownShadowFamilyRegistry::registerFamilyForUpdates(_decoratorFamily);
|
|
53
61
|
}
|
|
@@ -57,26 +65,103 @@ using namespace facebook::react;
|
|
|
57
65
|
MarkdownShadowFamilyRegistry::unregisterFamilyForUpdates(_decoratorFamily);
|
|
58
66
|
_decoratorFamily = nullptr;
|
|
59
67
|
}
|
|
60
|
-
|
|
68
|
+
|
|
61
69
|
[super willMoveToSuperview:newSuperview];
|
|
62
70
|
}
|
|
63
71
|
|
|
72
|
+
- (void)didMoveToWindow {
|
|
73
|
+
if (self.superview == nil) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
NSArray *viewsArray = self.superview.subviews;
|
|
78
|
+
NSUInteger currentIndex = [viewsArray indexOfObject:self];
|
|
79
|
+
|
|
80
|
+
react_native_assert(currentIndex != 0 && currentIndex != NSNotFound && "Error while finding current component.");
|
|
81
|
+
UIView *view = [viewsArray objectAtIndex:currentIndex - 1];
|
|
82
|
+
|
|
83
|
+
react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView.");
|
|
84
|
+
_textInput = (RCTTextInputComponentView *)view;
|
|
85
|
+
_backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
|
|
86
|
+
|
|
87
|
+
_markdownUtils = [[RCTMarkdownUtils alloc] init];
|
|
88
|
+
react_native_assert(_markdownStyle != nil);
|
|
89
|
+
[_markdownUtils setMarkdownStyle:_markdownStyle];
|
|
90
|
+
[_markdownUtils setParserId:_parserId];
|
|
91
|
+
|
|
92
|
+
[_textInput setMarkdownUtils:_markdownUtils];
|
|
93
|
+
if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) {
|
|
94
|
+
RCTUITextField *textField = (RCTUITextField *)_backedTextInputView;
|
|
95
|
+
_adapter = [textField valueForKey:@"textInputDelegateAdapter"];
|
|
96
|
+
[_adapter setMarkdownUtils:_markdownUtils];
|
|
97
|
+
} else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
|
|
98
|
+
_textView = (RCTUITextView *)_backedTextInputView;
|
|
99
|
+
[_textView setMarkdownUtils:_markdownUtils];
|
|
100
|
+
NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
|
|
101
|
+
|
|
102
|
+
// Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
|
|
103
|
+
// Consider removing this fix if it is no longer needed after migrating to TextKit 2.
|
|
104
|
+
CGSize contentSize = _textView.contentSize;
|
|
105
|
+
CGRect textBounds = [layoutManager usedRectForTextContainer:_textView.textContainer];
|
|
106
|
+
contentSize.height = textBounds.size.height + _textView.textContainerInset.top + _textView.textContainerInset.bottom;
|
|
107
|
+
[_textView setContentSize:contentSize];
|
|
108
|
+
|
|
109
|
+
layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
|
|
110
|
+
object_setClass(layoutManager, [MarkdownLayoutManager class]);
|
|
111
|
+
[layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];
|
|
112
|
+
} else {
|
|
113
|
+
react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
- (void)willMoveToWindow:(UIWindow *)newWindow
|
|
118
|
+
{
|
|
119
|
+
if (_textInput != nil) {
|
|
120
|
+
[_textInput setMarkdownUtils:nil];
|
|
121
|
+
}
|
|
122
|
+
if (_adapter != nil) {
|
|
123
|
+
[_adapter setMarkdownUtils:nil];
|
|
124
|
+
}
|
|
125
|
+
if (_textView != nil) {
|
|
126
|
+
[_textView setMarkdownUtils:nil];
|
|
127
|
+
if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
|
|
128
|
+
[_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
|
|
129
|
+
object_setClass(_textView.layoutManager, [NSLayoutManager class]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
64
134
|
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
65
135
|
{
|
|
66
136
|
const auto &oldViewProps = *std::static_pointer_cast<MarkdownTextInputDecoratorViewProps const>(_props);
|
|
67
137
|
const auto &newViewProps = *std::static_pointer_cast<MarkdownTextInputDecoratorViewProps const>(props);
|
|
68
138
|
|
|
69
139
|
if (oldViewProps.parserId != newViewProps.parserId) {
|
|
70
|
-
|
|
140
|
+
_parserId = @(newViewProps.parserId);
|
|
141
|
+
[_markdownUtils setParserId:_parserId];
|
|
71
142
|
}
|
|
72
143
|
|
|
73
144
|
// TODO: if (oldViewProps.markdownStyle != newViewProps.markdownStyle)
|
|
74
|
-
|
|
75
|
-
[
|
|
145
|
+
_markdownStyle = [[RCTMarkdownStyle alloc] initWithStruct:newViewProps.markdownStyle];
|
|
146
|
+
[_markdownUtils setMarkdownStyle:_markdownStyle];
|
|
147
|
+
|
|
148
|
+
// TODO: call applyNewStyles only if needed
|
|
149
|
+
[self applyNewStyles];
|
|
76
150
|
|
|
77
151
|
[super updateProps:props oldProps:oldProps];
|
|
78
152
|
}
|
|
79
153
|
|
|
154
|
+
- (void)applyNewStyles
|
|
155
|
+
{
|
|
156
|
+
if (_textView != nil) {
|
|
157
|
+
// We want to use `textStorage` for applying markdown when possible. Currently it's only available for UITextView
|
|
158
|
+
[_textView textDidChange];
|
|
159
|
+
} else {
|
|
160
|
+
// apply new styles
|
|
161
|
+
[_textInput _setAttributedString:_backedTextInputView.attributedText];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
80
165
|
Class<RCTComponentViewProtocol> MarkdownTextInputDecoratorViewCls(void)
|
|
81
166
|
{
|
|
82
167
|
return MarkdownTextInputDecoratorComponentView.class;
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/MarkdownTextInputDecoratorViewManager.h>
|
|
2
|
-
#import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
|
|
3
2
|
|
|
4
3
|
@implementation MarkdownTextInputDecoratorViewManager
|
|
5
4
|
|
|
6
5
|
RCT_EXPORT_MODULE(MarkdownTextInputDecoratorView)
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
return [[MarkdownTextInputDecoratorView alloc] init];
|
|
11
|
-
}
|
|
7
|
+
RCT_EXPORT_VIEW_PROPERTY(markdownStyle, NSDictionary)
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
// implemented in MarkdownTextInputDecoratorView updateProps:
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
RCT_CUSTOM_VIEW_PROPERTY(parserId, NSNumber, MarkdownTextInputDecoratorView)
|
|
19
|
-
{
|
|
20
|
-
// implemented in MarkdownTextInputDecoratorView updateProps:
|
|
21
|
-
}
|
|
9
|
+
RCT_EXPORT_VIEW_PROPERTY(parserId, NSNumber)
|
|
22
10
|
|
|
23
11
|
@end
|
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.247",
|
|
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",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#import <UIKit/UIKit.h>
|
|
2
|
-
#import <RNLiveMarkdown/RCTMarkdownStyle.h>
|
|
3
|
-
|
|
4
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
-
|
|
6
|
-
@interface MarkdownTextInputDecoratorView : UIView
|
|
7
|
-
|
|
8
|
-
- (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle;
|
|
9
|
-
|
|
10
|
-
- (void)setParserId:(NSNumber *)parserId;
|
|
11
|
-
|
|
12
|
-
@end
|
|
13
|
-
|
|
14
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#import <React/RCTUITextField.h>
|
|
2
|
-
#import "react_native_assert.h"
|
|
3
|
-
|
|
4
|
-
#import <RNLiveMarkdown/MarkdownLayoutManager.h>
|
|
5
|
-
#import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
|
|
6
|
-
#import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
|
|
7
|
-
#import <RNLiveMarkdown/RCTUITextView+Markdown.h>
|
|
8
|
-
|
|
9
|
-
#import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
|
|
10
|
-
|
|
11
|
-
#import <objc/runtime.h>
|
|
12
|
-
|
|
13
|
-
@implementation MarkdownTextInputDecoratorView {
|
|
14
|
-
RCTMarkdownUtils *_markdownUtils;
|
|
15
|
-
RCTMarkdownStyle *_markdownStyle;
|
|
16
|
-
NSNumber *_parserId;
|
|
17
|
-
__weak RCTTextInputComponentView *_textInput;
|
|
18
|
-
__weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
|
|
19
|
-
__weak RCTBackedTextFieldDelegateAdapter *_adapter;
|
|
20
|
-
__weak RCTUITextView *_textView;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
- (void)didMoveToWindow {
|
|
24
|
-
if (self.superview.superview == nil) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
NSArray *viewsArray = self.superview.superview.subviews;
|
|
29
|
-
NSUInteger currentIndex = [viewsArray indexOfObject:self.superview];
|
|
30
|
-
|
|
31
|
-
react_native_assert(currentIndex != 0 && currentIndex != NSNotFound && "Error while finding current component.");
|
|
32
|
-
UIView *view = [viewsArray objectAtIndex:currentIndex - 1];
|
|
33
|
-
|
|
34
|
-
react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView.");
|
|
35
|
-
_textInput = (RCTTextInputComponentView *)view;
|
|
36
|
-
_backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
|
|
37
|
-
|
|
38
|
-
_markdownUtils = [[RCTMarkdownUtils alloc] init];
|
|
39
|
-
react_native_assert(_markdownStyle != nil);
|
|
40
|
-
[_markdownUtils setMarkdownStyle:_markdownStyle];
|
|
41
|
-
[_markdownUtils setParserId:_parserId];
|
|
42
|
-
|
|
43
|
-
[_textInput setMarkdownUtils:_markdownUtils];
|
|
44
|
-
if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) {
|
|
45
|
-
RCTUITextField *textField = (RCTUITextField *)_backedTextInputView;
|
|
46
|
-
_adapter = [textField valueForKey:@"textInputDelegateAdapter"];
|
|
47
|
-
[_adapter setMarkdownUtils:_markdownUtils];
|
|
48
|
-
} else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
|
|
49
|
-
_textView = (RCTUITextView *)_backedTextInputView;
|
|
50
|
-
[_textView setMarkdownUtils:_markdownUtils];
|
|
51
|
-
NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
|
|
52
|
-
|
|
53
|
-
// Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
|
|
54
|
-
// Consider removing this fix if it is no longer needed after migrating to TextKit 2.
|
|
55
|
-
CGSize contentSize = _textView.contentSize;
|
|
56
|
-
CGRect textBounds = [layoutManager usedRectForTextContainer:_textView.textContainer];
|
|
57
|
-
contentSize.height = textBounds.size.height + _textView.textContainerInset.top + _textView.textContainerInset.bottom;
|
|
58
|
-
[_textView setContentSize:contentSize];
|
|
59
|
-
|
|
60
|
-
layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
|
|
61
|
-
object_setClass(layoutManager, [MarkdownLayoutManager class]);
|
|
62
|
-
[layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];
|
|
63
|
-
} else {
|
|
64
|
-
react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
- (void)willMoveToWindow:(UIWindow *)newWindow
|
|
69
|
-
{
|
|
70
|
-
if (_textInput != nil) {
|
|
71
|
-
[_textInput setMarkdownUtils:nil];
|
|
72
|
-
}
|
|
73
|
-
if (_adapter != nil) {
|
|
74
|
-
[_adapter setMarkdownUtils:nil];
|
|
75
|
-
}
|
|
76
|
-
if (_textView != nil) {
|
|
77
|
-
[_textView setMarkdownUtils:nil];
|
|
78
|
-
if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
|
|
79
|
-
[_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
|
|
80
|
-
object_setClass(_textView.layoutManager, [NSLayoutManager class]);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
- (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle
|
|
86
|
-
{
|
|
87
|
-
_markdownStyle = markdownStyle;
|
|
88
|
-
[_markdownUtils setMarkdownStyle:markdownStyle];
|
|
89
|
-
[self applyNewStyles];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
- (void)setParserId:(NSNumber *)parserId
|
|
93
|
-
{
|
|
94
|
-
_parserId = parserId;
|
|
95
|
-
[_markdownUtils setParserId:parserId];
|
|
96
|
-
[self applyNewStyles];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
- (void)applyNewStyles
|
|
100
|
-
{
|
|
101
|
-
if (_textView != nil) {
|
|
102
|
-
// We want to use `textStorage` for applying markdown when possible. Currently it's only available for UITextView
|
|
103
|
-
[_textView textDidChange];
|
|
104
|
-
} else {
|
|
105
|
-
// apply new styles
|
|
106
|
-
[_textInput _setAttributedString:_backedTextInputView.attributedText];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
@end
|