@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.
@@ -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/MarkdownRange.h>
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
- static std::mutex runtimeMutex;
30
- auto lock = std::lock_guard<std::mutex>(runtimeMutex);
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.192",
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",