@expensify/react-native-live-markdown 0.1.198 → 0.1.200
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/android/src/main/java/com/expensify/livemarkdown/MarkdownFormatter.java +25 -9
- package/android/src/main/java/com/expensify/livemarkdown/MarkdownParser.java +46 -33
- package/android/src/main/java/com/expensify/livemarkdown/MarkdownTextWatcher.java +2 -2
- package/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java +9 -3
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
|
|
|
8
8
|
|
|
9
9
|
import com.expensify.livemarkdown.spans.*;
|
|
10
10
|
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
|
|
11
|
+
import com.facebook.systrace.Systrace;
|
|
11
12
|
|
|
12
13
|
import java.util.List;
|
|
13
14
|
import java.util.Objects;
|
|
@@ -20,22 +21,37 @@ public class MarkdownFormatter {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
public void format(SpannableStringBuilder ssb, List<MarkdownRange> markdownRanges, @NonNull MarkdownStyle markdownStyle) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
try {
|
|
25
|
+
Systrace.beginSection(0, "format");
|
|
26
|
+
Objects.requireNonNull(markdownStyle, "mMarkdownStyle is null");
|
|
27
|
+
removeSpans(ssb);
|
|
28
|
+
applyRanges(ssb, markdownRanges, markdownStyle);
|
|
29
|
+
} finally {
|
|
30
|
+
Systrace.endSection(0);
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
private void removeSpans(SpannableStringBuilder ssb) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
ssb.
|
|
35
|
+
try {
|
|
36
|
+
Systrace.beginSection(0, "removeSpans");
|
|
37
|
+
// We shouldn't use `removeSpans()` because it also removes SpellcheckSpan, SuggestionSpan etc.
|
|
38
|
+
MarkdownSpan[] spans = ssb.getSpans(0, ssb.length(), MarkdownSpan.class);
|
|
39
|
+
for (MarkdownSpan span : spans) {
|
|
40
|
+
ssb.removeSpan(span);
|
|
41
|
+
}
|
|
42
|
+
} finally {
|
|
43
|
+
Systrace.endSection(0);
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
private void applyRanges(SpannableStringBuilder ssb, List<MarkdownRange> markdownRanges, @NonNull MarkdownStyle markdownStyle) {
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
try {
|
|
49
|
+
Systrace.beginSection(0, "applyRanges");
|
|
50
|
+
for (MarkdownRange markdownRange : markdownRanges) {
|
|
51
|
+
applyRange(ssb, markdownRange, markdownStyle);
|
|
52
|
+
}
|
|
53
|
+
} finally {
|
|
54
|
+
Systrace.endSection(0);
|
|
39
55
|
}
|
|
40
56
|
}
|
|
41
57
|
|
|
@@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
|
|
|
5
5
|
import com.facebook.react.bridge.ReactContext;
|
|
6
6
|
import com.facebook.react.util.RNLog;
|
|
7
7
|
import com.facebook.soloader.SoLoader;
|
|
8
|
+
import com.facebook.systrace.Systrace;
|
|
8
9
|
|
|
9
10
|
import org.json.JSONArray;
|
|
10
11
|
import org.json.JSONException;
|
|
@@ -31,46 +32,58 @@ public class MarkdownParser {
|
|
|
31
32
|
private native String nativeParse(String text, int parserId);
|
|
32
33
|
|
|
33
34
|
public synchronized List<MarkdownRange> parse(String text, int parserId) {
|
|
34
|
-
if (text.equals(mPrevText) && parserId == mPrevParserId) {
|
|
35
|
-
return mPrevMarkdownRanges;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
String json;
|
|
39
35
|
try {
|
|
40
|
-
|
|
41
|
-
} catch (Exception e) {
|
|
42
|
-
// Skip formatting, runGuarded will show the error in LogBox
|
|
43
|
-
mPrevText = text;
|
|
44
|
-
mPrevParserId = parserId;
|
|
45
|
-
mPrevMarkdownRanges = Collections.emptyList();
|
|
46
|
-
return mPrevMarkdownRanges;
|
|
47
|
-
}
|
|
36
|
+
Systrace.beginSection(0, "parse");
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
38
|
+
if (text.equals(mPrevText) && parserId == mPrevParserId) {
|
|
39
|
+
return mPrevMarkdownRanges;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
String json;
|
|
43
|
+
try {
|
|
44
|
+
Systrace.beginSection(0, "nativeParse");
|
|
45
|
+
json = nativeParse(text, parserId);
|
|
46
|
+
} catch (Exception e) {
|
|
47
|
+
// Skip formatting, runGuarded will show the error in LogBox
|
|
48
|
+
mPrevText = text;
|
|
49
|
+
mPrevParserId = parserId;
|
|
50
|
+
mPrevMarkdownRanges = Collections.emptyList();
|
|
51
|
+
return mPrevMarkdownRanges;
|
|
52
|
+
} finally {
|
|
53
|
+
Systrace.endSection(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
List<MarkdownRange> markdownRanges = new LinkedList<>();
|
|
57
|
+
try {
|
|
58
|
+
Systrace.beginSection(0, "markdownRanges");
|
|
59
|
+
JSONArray ranges = new JSONArray(json);
|
|
60
|
+
for (int i = 0; i < ranges.length(); i++) {
|
|
61
|
+
JSONObject range = ranges.getJSONObject(i);
|
|
62
|
+
String type = range.getString("type");
|
|
63
|
+
int start = range.getInt("start");
|
|
64
|
+
int length = range.getInt("length");
|
|
65
|
+
int depth = range.optInt("depth", 1);
|
|
66
|
+
if (length == 0 || start + length > text.length()) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
markdownRanges.add(new MarkdownRange(type, start, length, depth));
|
|
60
70
|
}
|
|
61
|
-
|
|
71
|
+
} catch (JSONException e) {
|
|
72
|
+
RNLog.w(mReactContext, "[react-native-live-markdown] Incorrect schema of worklet parser output: " + e.getMessage());
|
|
73
|
+
mPrevText = text;
|
|
74
|
+
mPrevParserId = parserId;
|
|
75
|
+
mPrevMarkdownRanges = Collections.emptyList();
|
|
76
|
+
return mPrevMarkdownRanges;
|
|
77
|
+
} finally {
|
|
78
|
+
Systrace.endSection(0);
|
|
62
79
|
}
|
|
63
|
-
|
|
64
|
-
RNLog.w(mReactContext, "[react-native-live-markdown] Incorrect schema of worklet parser output: " + e.getMessage());
|
|
80
|
+
|
|
65
81
|
mPrevText = text;
|
|
66
82
|
mPrevParserId = parserId;
|
|
67
|
-
mPrevMarkdownRanges =
|
|
83
|
+
mPrevMarkdownRanges = markdownRanges;
|
|
68
84
|
return mPrevMarkdownRanges;
|
|
85
|
+
} finally {
|
|
86
|
+
Systrace.endSection(0);
|
|
69
87
|
}
|
|
70
|
-
|
|
71
|
-
mPrevText = text;
|
|
72
|
-
mPrevParserId = parserId;
|
|
73
|
-
mPrevMarkdownRanges = markdownRanges;
|
|
74
|
-
return mPrevMarkdownRanges;
|
|
75
88
|
}
|
|
76
89
|
}
|
|
@@ -25,8 +25,8 @@ public class MarkdownTextWatcher implements TextWatcher {
|
|
|
25
25
|
|
|
26
26
|
@Override
|
|
27
27
|
public void afterTextChanged(Editable editable) {
|
|
28
|
-
if (editable instanceof SpannableStringBuilder) {
|
|
29
|
-
mMarkdownUtils.applyMarkdownFormatting(
|
|
28
|
+
if (editable instanceof SpannableStringBuilder ssb) {
|
|
29
|
+
mMarkdownUtils.applyMarkdownFormatting(ssb);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -5,6 +5,7 @@ import android.text.SpannableStringBuilder;
|
|
|
5
5
|
import androidx.annotation.NonNull;
|
|
6
6
|
|
|
7
7
|
import com.facebook.react.bridge.ReactContext;
|
|
8
|
+
import com.facebook.systrace.Systrace;
|
|
8
9
|
|
|
9
10
|
import java.util.List;
|
|
10
11
|
|
|
@@ -29,8 +30,13 @@ public class MarkdownUtils {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
public void applyMarkdownFormatting(SpannableStringBuilder ssb) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
try {
|
|
34
|
+
Systrace.beginSection(0, "applyMarkdownFormatting");
|
|
35
|
+
String text = ssb.toString();
|
|
36
|
+
List<MarkdownRange> markdownRanges = mMarkdownParser.parse(text, mParserId);
|
|
37
|
+
mMarkdownFormatter.format(ssb, markdownRanges, mMarkdownStyle);
|
|
38
|
+
} finally {
|
|
39
|
+
Systrace.endSection(0);
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
}
|
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.200",
|
|
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",
|