@expensify/react-native-live-markdown 0.1.192 → 0.1.193
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/MarkdownParser.h +12 -0
- package/apple/MarkdownParser.mm +68 -0
- package/apple/RCTMarkdownUtils.mm +13 -38
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <RNLiveMarkdown/MarkdownRange.h>
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
@interface MarkdownParser : NSObject
|
|
7
|
+
|
|
8
|
+
- (NSArray<MarkdownRange *> *)parse:(NSString *)text withParserId:(NSNumber *)parserId;
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_END
|
|
11
|
+
|
|
12
|
+
@end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#import "MarkdownParser.h"
|
|
2
|
+
#import <RNLiveMarkdown/MarkdownGlobal.h>
|
|
3
|
+
#import <React/RCTLog.h>
|
|
4
|
+
#import <mutex>
|
|
5
|
+
|
|
6
|
+
@implementation MarkdownParser {
|
|
7
|
+
NSString *_prevText;
|
|
8
|
+
NSNumber *_prevParserId;
|
|
9
|
+
NSArray<MarkdownRange *> *_prevMarkdownRanges;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
- (NSArray<MarkdownRange *> *)parse:(NSString *)text withParserId:(nonnull NSNumber *)parserId {
|
|
13
|
+
@synchronized (self) {
|
|
14
|
+
if ([text isEqualToString:_prevText] && [parserId isEqualToNumber:_prevParserId]) {
|
|
15
|
+
return _prevMarkdownRanges;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static std::mutex workletRuntimeMutex; // this needs to be global since the worklet runtime is also global
|
|
19
|
+
const auto lock = std::lock_guard<std::mutex>(workletRuntimeMutex);
|
|
20
|
+
|
|
21
|
+
const auto &markdownRuntime = expensify::livemarkdown::getMarkdownRuntime();
|
|
22
|
+
jsi::Runtime &rt = markdownRuntime->getJSIRuntime();
|
|
23
|
+
|
|
24
|
+
const auto &markdownWorklet = expensify::livemarkdown::getMarkdownWorklet([parserId intValue]);
|
|
25
|
+
|
|
26
|
+
const auto &input = jsi::String::createFromUtf8(rt, [text UTF8String]);
|
|
27
|
+
|
|
28
|
+
jsi::Value output;
|
|
29
|
+
try {
|
|
30
|
+
output = markdownRuntime->runGuarded(markdownWorklet, input);
|
|
31
|
+
} catch (const jsi::JSError &error) {
|
|
32
|
+
// Skip formatting, runGuarded will show the error in LogBox
|
|
33
|
+
_prevText = text;
|
|
34
|
+
_prevParserId = parserId;
|
|
35
|
+
_prevMarkdownRanges = @[];
|
|
36
|
+
return _prevMarkdownRanges;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
NSMutableArray<MarkdownRange *> *markdownRanges = [[NSMutableArray alloc] init];
|
|
40
|
+
try {
|
|
41
|
+
const auto &ranges = output.asObject(rt).asArray(rt);
|
|
42
|
+
for (size_t i = 0, n = ranges.size(rt); i < n; ++i) {
|
|
43
|
+
const auto &item = ranges.getValueAtIndex(rt, i).asObject(rt);
|
|
44
|
+
const auto &type = item.getProperty(rt, "type").asString(rt).utf8(rt);
|
|
45
|
+
const auto &start = static_cast<int>(item.getProperty(rt, "start").asNumber());
|
|
46
|
+
const auto &length = static_cast<int>(item.getProperty(rt, "length").asNumber());
|
|
47
|
+
const auto &depth = item.hasProperty(rt, "depth") ? static_cast<int>(item.getProperty(rt, "depth").asNumber()) : 1;
|
|
48
|
+
|
|
49
|
+
NSRange range = NSMakeRange(start, length);
|
|
50
|
+
MarkdownRange *markdownRange = [[MarkdownRange alloc] initWithType:@(type.c_str()) range:range depth:depth];
|
|
51
|
+
[markdownRanges addObject:markdownRange];
|
|
52
|
+
}
|
|
53
|
+
} catch (const jsi::JSError &error) {
|
|
54
|
+
RCTLogWarn(@"[react-native-live-markdown] Incorrect schema of worklet parser output: %s", error.getMessage().c_str());
|
|
55
|
+
_prevText = text;
|
|
56
|
+
_prevParserId = parserId;
|
|
57
|
+
_prevMarkdownRanges = @[];
|
|
58
|
+
return _prevMarkdownRanges;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
_prevText = text;
|
|
62
|
+
_prevParserId = parserId;
|
|
63
|
+
_prevMarkdownRanges = markdownRanges;
|
|
64
|
+
return _prevMarkdownRanges;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
2
2
|
#import <RNLiveMarkdown/MarkdownGlobal.h>
|
|
3
|
-
#import <RNLiveMarkdown/
|
|
3
|
+
#import <RNLiveMarkdown/MarkdownParser.h>
|
|
4
4
|
#import "react_native_assert.h"
|
|
5
5
|
#import <React/RCTAssert.h>
|
|
6
6
|
#import <React/RCTFont.h>
|
|
7
7
|
#include <jsi/jsi.h>
|
|
8
8
|
|
|
9
9
|
@implementation RCTMarkdownUtils {
|
|
10
|
+
MarkdownParser *_markdownParser;
|
|
10
11
|
NSString *_prevInputString;
|
|
11
12
|
NSAttributedString *_prevAttributedString;
|
|
12
13
|
NSDictionary<NSAttributedStringKey, id> *_prevTextAttributes;
|
|
@@ -14,6 +15,15 @@
|
|
|
14
15
|
__weak NSNumber *_prevParserId;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
- (instancetype)init
|
|
19
|
+
{
|
|
20
|
+
if (self = [super init]) {
|
|
21
|
+
_markdownParser = [MarkdownParser new];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return self;
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
- (NSAttributedString *)parseMarkdown:(nullable NSAttributedString *)input withAttributes:(nullable NSDictionary<NSAttributedStringKey,id> *)attributes
|
|
18
28
|
{
|
|
19
29
|
@synchronized (self) {
|
|
@@ -26,43 +36,8 @@
|
|
|
26
36
|
return _prevAttributedString;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
auto markdownRuntime = expensify::livemarkdown::getMarkdownRuntime();
|
|
33
|
-
jsi::Runtime &rt = markdownRuntime->getJSIRuntime();
|
|
34
|
-
|
|
35
|
-
auto markdownWorklet = expensify::livemarkdown::getMarkdownWorklet([_parserId intValue]);
|
|
36
|
-
|
|
37
|
-
NSMutableArray *markdownRanges = [[NSMutableArray alloc] init];
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const auto &text = jsi::String::createFromUtf8(rt, [inputString UTF8String]);
|
|
41
|
-
const auto &output = markdownRuntime->runGuarded(markdownWorklet, text);
|
|
42
|
-
const auto &ranges = output.asObject(rt).asArray(rt);
|
|
43
|
-
|
|
44
|
-
for (size_t i = 0, n = ranges.size(rt); i < n; ++i) {
|
|
45
|
-
const auto &item = ranges.getValueAtIndex(rt, i).asObject(rt);
|
|
46
|
-
const auto &type = item.getProperty(rt, "type").asString(rt).utf8(rt);
|
|
47
|
-
const auto &start = static_cast<int>(item.getProperty(rt, "start").asNumber());
|
|
48
|
-
const auto &length = static_cast<int>(item.getProperty(rt, "length").asNumber());
|
|
49
|
-
const auto &depth = item.hasProperty(rt, "depth") ? static_cast<int>(item.getProperty(rt, "depth").asNumber()) : 1;
|
|
50
|
-
|
|
51
|
-
NSRange range = NSMakeRange(start, length);
|
|
52
|
-
MarkdownRange *markdownRange = [[MarkdownRange alloc] initWithType:@(type.c_str()) range:range depth:depth];
|
|
53
|
-
[markdownRanges addObject:markdownRange];
|
|
54
|
-
}
|
|
55
|
-
} catch (const jsi::JSError &error) {
|
|
56
|
-
RCTLogWarn(@"[react-native-live-markdown] Incorrect schema of worklet parser output: %s", error.getMessage().c_str());
|
|
57
|
-
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:inputString attributes:attributes];
|
|
58
|
-
_prevInputString = inputString;
|
|
59
|
-
_prevAttributedString = attributedString;
|
|
60
|
-
_prevTextAttributes = attributes;
|
|
61
|
-
_prevMarkdownStyle = _markdownStyle;
|
|
62
|
-
_prevParserId = _parserId;
|
|
63
|
-
return attributedString;
|
|
64
|
-
}
|
|
65
|
-
|
|
39
|
+
NSArray<MarkdownRange *> *markdownRanges = [_markdownParser parse:inputString withParserId:_parserId];
|
|
40
|
+
|
|
66
41
|
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:inputString attributes:attributes];
|
|
67
42
|
[attributedString beginEditing];
|
|
68
43
|
|
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.193",
|
|
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",
|