@expensify/react-native-live-markdown 0.1.95 → 0.1.97

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.
@@ -18,6 +18,8 @@ Pod::Spec.new do |s|
18
18
 
19
19
  s.resources = "parser/react-native-live-markdown-parser.js"
20
20
 
21
+ s.dependency "hermes-engine"
22
+
21
23
  install_modules_dependencies(s)
22
24
 
23
25
  if ENV['USE_FRAMEWORKS'] && ENV['RCT_NEW_ARCH_ENABLED']
@@ -2,7 +2,11 @@
2
2
  #import "react_native_assert.h"
3
3
  #import <React/RCTAssert.h>
4
4
  #import <React/RCTFont.h>
5
- #import <JavaScriptCore/JavaScriptCore.h>
5
+
6
+ #include <jsi/jsi.h>
7
+ #include <hermes/hermes.h>
8
+
9
+ using namespace facebook;
6
10
 
7
11
  @implementation RCTMarkdownUtils {
8
12
  NSString *_prevInputString;
@@ -23,20 +27,26 @@
23
27
  return _prevAttributedString;
24
28
  }
25
29
 
26
- static JSContext *ctx = nil;
27
- static JSValue *function = nil;
28
- if (ctx == nil) {
30
+ static std::shared_ptr<jsi::Runtime> runtime;
31
+ if (runtime == nullptr) {
29
32
  NSString *path = [[NSBundle mainBundle] pathForResource:@"react-native-live-markdown-parser" ofType:@"js"];
30
33
  assert(path != nil && "[react-native-live-markdown] Markdown parser bundle not found");
31
34
  NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
32
35
  assert(content != nil && "[react-native-live-markdown] Markdown parser bundle is empty");
33
- ctx = [[JSContext alloc] init];
34
- [ctx evaluateScript:content];
35
- function = ctx[@"parseExpensiMarkToRanges"];
36
+ runtime = facebook::hermes::makeHermesRuntime();
37
+ auto codeBuffer = std::make_shared<const jsi::StringBuffer>([content UTF8String]);
38
+ runtime->evaluateJavaScript(codeBuffer, "evaluateJavaScript");
36
39
  }
37
40
 
38
- JSValue *result = [function callWithArguments:@[inputString]];
39
- NSArray *ranges = [result toArray];
41
+ jsi::Runtime &rt = *runtime;
42
+ auto text = jsi::String::createFromUtf8(rt, [inputString UTF8String]);
43
+
44
+ auto func = rt.global().getPropertyAsFunction(rt, "parseExpensiMarkToRanges");
45
+ auto output = func.call(rt, text);
46
+ if (output.isUndefined()) {
47
+ return input;
48
+ }
49
+ const auto &ranges = output.asObject(rt).asArray(rt);
40
50
 
41
51
  NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:inputString attributes:attributes];
42
52
  [attributedString beginEditing];
@@ -48,42 +58,47 @@
48
58
 
49
59
  _blockquoteRangesAndLevels = [NSMutableArray new];
50
60
 
51
- [ranges enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
52
- NSDictionary *item = obj;
53
- NSString *type = [item valueForKey:@"type"];
54
- NSInteger location = [[item valueForKey:@"start"] unsignedIntegerValue];
55
- NSInteger length = [[item valueForKey:@"length"] unsignedIntegerValue];
56
- NSInteger depth = [[item valueForKey:@"depth"] unsignedIntegerValue] ?: 1;
61
+ for (size_t i = 0, n = ranges.size(rt); i < n; ++i) {
62
+ const auto &item = ranges.getValueAtIndex(rt, i).asObject(rt);
63
+ const auto &type = item.getProperty(rt, "type").asString(rt).utf8(rt);
64
+ const auto &location = static_cast<int>(item.getProperty(rt, "start").asNumber());
65
+ const auto &length = static_cast<int>(item.getProperty(rt, "length").asNumber());
66
+ const auto &depth = item.hasProperty(rt, "depth") ? static_cast<int>(item.getProperty(rt, "depth").asNumber()) : 1;
67
+
68
+ if (length == 0 || location + length > attributedString.length) {
69
+ continue;
70
+ }
71
+
57
72
  NSRange range = NSMakeRange(location, length);
58
73
 
59
- if ([type isEqualToString:@"bold"] || [type isEqualToString:@"italic"] || [type isEqualToString:@"code"] || [type isEqualToString:@"pre"] || [type isEqualToString:@"h1"] || [type isEqualToString:@"emoji"]) {
74
+ if (type == "bold" || type == "italic" || type == "code" || type == "pre" || type == "h1" || type == "emoji") {
60
75
  UIFont *font = [attributedString attribute:NSFontAttributeName atIndex:location effectiveRange:NULL];
61
- if ([type isEqualToString:@"bold"]) {
76
+ if (type == "bold") {
62
77
  font = [RCTFont updateFont:font withWeight:@"bold"];
63
- } else if ([type isEqualToString:@"italic"]) {
78
+ } else if (type == "italic") {
64
79
  font = [RCTFont updateFont:font withStyle:@"italic"];
65
- } else if ([type isEqualToString:@"code"]) {
80
+ } else if (type == "code") {
66
81
  font = [RCTFont updateFont:font withFamily:_markdownStyle.codeFontFamily
67
82
  size:[NSNumber numberWithFloat:_markdownStyle.codeFontSize]
68
83
  weight:nil
69
84
  style:nil
70
85
  variant:nil
71
86
  scaleMultiplier:0];
72
- } else if ([type isEqualToString:@"pre"]) {
87
+ } else if (type == "pre") {
73
88
  font = [RCTFont updateFont:font withFamily:_markdownStyle.preFontFamily
74
89
  size:[NSNumber numberWithFloat:_markdownStyle.preFontSize]
75
90
  weight:nil
76
91
  style:nil
77
92
  variant:nil
78
93
  scaleMultiplier:0];
79
- } else if ([type isEqualToString:@"h1"]) {
94
+ } else if (type == "h1") {
80
95
  font = [RCTFont updateFont:font withFamily:nil
81
96
  size:[NSNumber numberWithFloat:_markdownStyle.h1FontSize]
82
97
  weight:@"bold"
83
98
  style:nil
84
99
  variant:nil
85
100
  scaleMultiplier:0];
86
- } else if ([type isEqualToString:@"emoji"]) {
101
+ } else if (type == "emoji") {
87
102
  font = [RCTFont updateFont:font withFamily:nil
88
103
  size:[NSNumber numberWithFloat:_markdownStyle.emojiFontSize]
89
104
  weight:nil
@@ -94,27 +109,27 @@
94
109
  [attributedString addAttribute:NSFontAttributeName value:font range:range];
95
110
  }
96
111
 
97
- if ([type isEqualToString:@"syntax"]) {
112
+ if (type == "syntax") {
98
113
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.syntaxColor range:range];
99
- } else if ([type isEqualToString:@"strikethrough"]) {
114
+ } else if (type == "strikethrough") {
100
115
  [attributedString addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:range];
101
- } else if ([type isEqualToString:@"code"]) {
116
+ } else if (type == "code") {
102
117
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.codeColor range:range];
103
118
  [attributedString addAttribute:NSBackgroundColorAttributeName value:_markdownStyle.codeBackgroundColor range:range];
104
- } else if ([type isEqualToString:@"mention-here"]) {
119
+ } else if (type == "mention-here") {
105
120
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.mentionHereColor range:range];
106
121
  [attributedString addAttribute:NSBackgroundColorAttributeName value:_markdownStyle.mentionHereBackgroundColor range:range];
107
- } else if ([type isEqualToString:@"mention-user"]) {
122
+ } else if (type == "mention-user") {
108
123
  // TODO: change mention color when it mentions current user
109
124
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.mentionUserColor range:range];
110
125
  [attributedString addAttribute:NSBackgroundColorAttributeName value:_markdownStyle.mentionUserBackgroundColor range:range];
111
- } else if ([type isEqualToString:@"mention-report"]) {
126
+ } else if (type == "mention-report") {
112
127
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.mentionReportColor range:range];
113
128
  [attributedString addAttribute:NSBackgroundColorAttributeName value:_markdownStyle.mentionReportBackgroundColor range:range];
114
- } else if ([type isEqualToString:@"link"]) {
129
+ } else if (type == "link") {
115
130
  [attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:range];
116
131
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.linkColor range:range];
117
- } else if ([type isEqualToString:@"blockquote"]) {
132
+ } else if (type == "blockquote") {
118
133
  CGFloat indent = (_markdownStyle.blockquoteMarginLeft + _markdownStyle.blockquoteBorderWidth + _markdownStyle.blockquotePaddingLeft) * depth;
119
134
  NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
120
135
  paragraphStyle.firstLineHeadIndent = indent;
@@ -124,17 +139,17 @@
124
139
  @"range": [NSValue valueWithRange:range],
125
140
  @"depth": @(depth)
126
141
  }];
127
- } else if ([type isEqualToString:@"pre"]) {
142
+ } else if (type == "pre") {
128
143
  [attributedString addAttribute:NSForegroundColorAttributeName value:_markdownStyle.preColor range:range];
129
144
  NSRange rangeForBackground = [inputString characterAtIndex:range.location] == '\n' ? NSMakeRange(range.location + 1, range.length - 1) : range;
130
145
  [attributedString addAttribute:NSBackgroundColorAttributeName value:_markdownStyle.preBackgroundColor range:rangeForBackground];
131
146
  // TODO: pass background color and ranges to layout manager
132
- } else if ([type isEqualToString:@"h1"]) {
147
+ } else if (type == "h1") {
133
148
  NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
134
149
  NSRange rangeWithHashAndSpace = NSMakeRange(range.location - 2, range.length + 2); // we also need to include prepending "# "
135
150
  [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:rangeWithHashAndSpace];
136
151
  }
137
- }];
152
+ }
138
153
 
139
154
  RCTApplyBaselineOffset(attributedString);
140
155
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expensify/react-native-live-markdown",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
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",