@expensify/react-native-live-markdown 0.1.189 → 0.1.190
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/MarkdownRange.h +15 -0
- package/apple/MarkdownRange.mm +15 -0
- package/apple/RCTMarkdownUtils.mm +38 -28
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
@interface MarkdownRange : NSObject
|
|
6
|
+
|
|
7
|
+
@property (nonatomic, strong) NSString *type;
|
|
8
|
+
@property (nonatomic) NSRange range;
|
|
9
|
+
@property (nonatomic) NSUInteger depth;
|
|
10
|
+
|
|
11
|
+
- (instancetype)initWithType:(NSString *)type range:(NSRange)range depth:(NSUInteger)depth;
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_END
|
|
14
|
+
|
|
15
|
+
@end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#import "MarkdownRange.h"
|
|
2
|
+
|
|
3
|
+
@implementation MarkdownRange
|
|
4
|
+
|
|
5
|
+
- (instancetype)initWithType:(NSString *)type range:(NSRange)range depth:(NSUInteger)depth {
|
|
6
|
+
self = [super init];
|
|
7
|
+
if (self) {
|
|
8
|
+
_type = type;
|
|
9
|
+
_range = range;
|
|
10
|
+
_depth = depth;
|
|
11
|
+
}
|
|
12
|
+
return self;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
2
2
|
#import <RNLiveMarkdown/MarkdownGlobal.h>
|
|
3
|
+
#import <RNLiveMarkdown/MarkdownRange.h>
|
|
3
4
|
#import "react_native_assert.h"
|
|
4
5
|
#import <React/RCTAssert.h>
|
|
5
6
|
#import <React/RCTFont.h>
|
|
@@ -32,22 +33,14 @@
|
|
|
32
33
|
jsi::Runtime &rt = markdownRuntime->getJSIRuntime();
|
|
33
34
|
|
|
34
35
|
auto markdownWorklet = expensify::livemarkdown::getMarkdownWorklet([_parserId intValue]);
|
|
36
|
+
|
|
37
|
+
NSMutableArray *markdownRanges = [[NSMutableArray alloc] init];
|
|
35
38
|
|
|
36
39
|
try {
|
|
37
40
|
const auto &text = jsi::String::createFromUtf8(rt, [inputString UTF8String]);
|
|
38
41
|
const auto &output = markdownRuntime->runGuarded(markdownWorklet, text);
|
|
39
42
|
const auto &ranges = output.asObject(rt).asArray(rt);
|
|
40
43
|
|
|
41
|
-
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:inputString attributes:attributes];
|
|
42
|
-
[attributedString beginEditing];
|
|
43
|
-
|
|
44
|
-
// If the attributed string ends with underlined text, blurring the single-line input imprints the underline style across the whole string.
|
|
45
|
-
// It looks like a bug in iOS, as there is no underline style to be found in the attributed string, especially after formatting.
|
|
46
|
-
// This is a workaround that applies the NSUnderlineStyleNone to the string before iterating over ranges which resolves this problem.
|
|
47
|
-
[attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleNone] range:NSMakeRange(0, attributedString.length)];
|
|
48
|
-
|
|
49
|
-
_blockquoteRangesAndLevels = [NSMutableArray new];
|
|
50
|
-
|
|
51
44
|
for (size_t i = 0, n = ranges.size(rt); i < n; ++i) {
|
|
52
45
|
const auto &item = ranges.getValueAtIndex(rt, i).asObject(rt);
|
|
53
46
|
const auto &type = item.getProperty(rt, "type").asString(rt).utf8(rt);
|
|
@@ -55,20 +48,10 @@
|
|
|
55
48
|
const auto &length = static_cast<int>(item.getProperty(rt, "length").asNumber());
|
|
56
49
|
const auto &depth = item.hasProperty(rt, "depth") ? static_cast<int>(item.getProperty(rt, "depth").asNumber()) : 1;
|
|
57
50
|
|
|
58
|
-
|
|
51
|
+
NSRange range = NSMakeRange(start, length);
|
|
52
|
+
MarkdownRange *markdownRange = [[MarkdownRange alloc] initWithType:@(type.c_str()) range:range depth:depth];
|
|
53
|
+
[markdownRanges addObject:markdownRange];
|
|
59
54
|
}
|
|
60
|
-
|
|
61
|
-
RCTApplyBaselineOffset(attributedString);
|
|
62
|
-
|
|
63
|
-
[attributedString endEditing];
|
|
64
|
-
|
|
65
|
-
_prevInputString = inputString;
|
|
66
|
-
_prevAttributedString = attributedString;
|
|
67
|
-
_prevTextAttributes = attributes;
|
|
68
|
-
_prevMarkdownStyle = _markdownStyle;
|
|
69
|
-
_prevParserId = _parserId;
|
|
70
|
-
|
|
71
|
-
return attributedString;
|
|
72
55
|
} catch (const jsi::JSError &error) {
|
|
73
56
|
RCTLogWarn(@"[react-native-live-markdown] Incorrect schema of worklet parser output: %s", error.getMessage().c_str());
|
|
74
57
|
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:inputString attributes:attributes];
|
|
@@ -79,18 +62,45 @@
|
|
|
79
62
|
_prevParserId = _parserId;
|
|
80
63
|
return attributedString;
|
|
81
64
|
}
|
|
65
|
+
|
|
66
|
+
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:inputString attributes:attributes];
|
|
67
|
+
[attributedString beginEditing];
|
|
68
|
+
|
|
69
|
+
// If the attributed string ends with underlined text, blurring the single-line input imprints the underline style across the whole string.
|
|
70
|
+
// It looks like a bug in iOS, as there is no underline style to be found in the attributed string, especially after formatting.
|
|
71
|
+
// This is a workaround that applies the NSUnderlineStyleNone to the string before iterating over ranges which resolves this problem.
|
|
72
|
+
[attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleNone] range:NSMakeRange(0, attributedString.length)];
|
|
73
|
+
|
|
74
|
+
_blockquoteRangesAndLevels = [NSMutableArray new];
|
|
75
|
+
|
|
76
|
+
for (MarkdownRange *markdownRange in markdownRanges) {
|
|
77
|
+
[self applyRangeToAttributedString:attributedString
|
|
78
|
+
type:std::string([markdownRange.type UTF8String])
|
|
79
|
+
range:markdownRange.range
|
|
80
|
+
depth:markdownRange.depth];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
RCTApplyBaselineOffset(attributedString);
|
|
84
|
+
|
|
85
|
+
[attributedString endEditing];
|
|
86
|
+
|
|
87
|
+
_prevInputString = inputString;
|
|
88
|
+
_prevAttributedString = attributedString;
|
|
89
|
+
_prevTextAttributes = attributes;
|
|
90
|
+
_prevMarkdownStyle = _markdownStyle;
|
|
91
|
+
_prevParserId = _parserId;
|
|
92
|
+
|
|
93
|
+
return attributedString;
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
- (void)applyRangeToAttributedString:(NSMutableAttributedString *)attributedString type:(const std::string)type
|
|
86
|
-
if (length == 0 ||
|
|
97
|
+
- (void)applyRangeToAttributedString:(NSMutableAttributedString *)attributedString type:(const std::string)type range:(NSRange)range depth:(const int)depth {
|
|
98
|
+
if (range.length == 0 || range.location + range.length > attributedString.length) {
|
|
87
99
|
return;
|
|
88
100
|
}
|
|
89
101
|
|
|
90
|
-
NSRange range = NSMakeRange(start, length);
|
|
91
|
-
|
|
92
102
|
if (type == "bold" || type == "italic" || type == "code" || type == "pre" || type == "h1" || type == "emoji") {
|
|
93
|
-
UIFont *font = [attributedString attribute:NSFontAttributeName atIndex:
|
|
103
|
+
UIFont *font = [attributedString attribute:NSFontAttributeName atIndex:range.location effectiveRange:NULL];
|
|
94
104
|
if (type == "bold") {
|
|
95
105
|
font = [RCTFont updateFont:font withWeight:@"bold"];
|
|
96
106
|
} else if (type == "italic") {
|
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.190",
|
|
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",
|