@expensify/react-native-live-markdown 0.1.195 → 0.1.196

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,116 @@
1
+ package com.expensify.livemarkdown;
2
+
3
+ import android.content.res.AssetManager;
4
+ import android.text.SpannableStringBuilder;
5
+ import android.text.Spanned;
6
+
7
+ import androidx.annotation.NonNull;
8
+
9
+ import com.expensify.livemarkdown.spans.*;
10
+ import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
11
+
12
+ import java.util.List;
13
+ import java.util.Objects;
14
+
15
+ public class MarkdownFormatter {
16
+ private final @NonNull AssetManager mAssetManager;
17
+
18
+ public MarkdownFormatter(@NonNull AssetManager assetManager) {
19
+ mAssetManager = assetManager;
20
+ }
21
+
22
+ public void format(SpannableStringBuilder ssb, List<MarkdownRange> markdownRanges, @NonNull MarkdownStyle markdownStyle) {
23
+ Objects.requireNonNull(markdownStyle, "mMarkdownStyle is null");
24
+ removeSpans(ssb);
25
+ applyRanges(ssb, markdownRanges, markdownStyle);
26
+ }
27
+
28
+ private void removeSpans(SpannableStringBuilder ssb) {
29
+ // We shouldn't use `removeSpans()` because it also removes SpellcheckSpan, SuggestionSpan etc.
30
+ MarkdownSpan[] spans = ssb.getSpans(0, ssb.length(), MarkdownSpan.class);
31
+ for (MarkdownSpan span : spans) {
32
+ ssb.removeSpan(span);
33
+ }
34
+ }
35
+
36
+ private void applyRanges(SpannableStringBuilder ssb, List<MarkdownRange> markdownRanges, @NonNull MarkdownStyle markdownStyle) {
37
+ for (MarkdownRange markdownRange : markdownRanges) {
38
+ applyRange(ssb, markdownRange, markdownStyle);
39
+ }
40
+ }
41
+
42
+ private void applyRange(SpannableStringBuilder ssb, MarkdownRange markdownRange, MarkdownStyle markdownStyle) {
43
+ String type = markdownRange.getType();
44
+ int start = markdownRange.getStart();
45
+ int end = start + markdownRange.getLength();
46
+ switch (type) {
47
+ case "bold":
48
+ setSpan(ssb, new MarkdownBoldSpan(), start, end);
49
+ break;
50
+ case "italic":
51
+ setSpan(ssb, new MarkdownItalicSpan(), start, end);
52
+ break;
53
+ case "strikethrough":
54
+ setSpan(ssb, new MarkdownStrikethroughSpan(), start, end);
55
+ break;
56
+ case "emoji":
57
+ setSpan(ssb, new MarkdownEmojiSpan(markdownStyle.getEmojiFontSize()), start, end);
58
+ break;
59
+ case "mention-here":
60
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionHereColor()), start, end);
61
+ setSpan(ssb, new MarkdownBackgroundColorSpan(markdownStyle.getMentionHereBackgroundColor()), start, end);
62
+ break;
63
+ case "mention-user":
64
+ // TODO: change mention color when it mentions current user
65
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionUserColor()), start, end);
66
+ setSpan(ssb, new MarkdownBackgroundColorSpan(markdownStyle.getMentionUserBackgroundColor()), start, end);
67
+ break;
68
+ case "mention-report":
69
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionReportColor()), start, end);
70
+ setSpan(ssb, new MarkdownBackgroundColorSpan(markdownStyle.getMentionReportBackgroundColor()), start, end);
71
+ break;
72
+ case "syntax":
73
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getSyntaxColor()), start, end);
74
+ break;
75
+ case "link":
76
+ setSpan(ssb, new MarkdownUnderlineSpan(), start, end);
77
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getLinkColor()), start, end);
78
+ break;
79
+ case "code":
80
+ setSpan(ssb, new MarkdownFontFamilySpan(markdownStyle.getCodeFontFamily(), mAssetManager), start, end);
81
+ setSpan(ssb, new MarkdownFontSizeSpan(markdownStyle.getCodeFontSize()), start, end);
82
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getCodeColor()), start, end);
83
+ setSpan(ssb, new MarkdownBackgroundColorSpan(markdownStyle.getCodeBackgroundColor()), start, end);
84
+ break;
85
+ case "pre":
86
+ setSpan(ssb, new MarkdownFontFamilySpan(markdownStyle.getPreFontFamily(), mAssetManager), start, end);
87
+ setSpan(ssb, new MarkdownFontSizeSpan(markdownStyle.getPreFontSize()), start, end);
88
+ setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getPreColor()), start, end);
89
+ setSpan(ssb, new MarkdownBackgroundColorSpan(markdownStyle.getPreBackgroundColor()), start, end);
90
+ break;
91
+ case "h1":
92
+ setSpan(ssb, new MarkdownBoldSpan(), start, end);
93
+ CustomLineHeightSpan[] spans = ssb.getSpans(0, ssb.length(), CustomLineHeightSpan.class);
94
+ if (spans.length >= 1) {
95
+ int lineHeight = spans[0].getLineHeight();
96
+ setSpan(ssb, new MarkdownLineHeightSpan(lineHeight * 1.5f), start, end);
97
+ }
98
+ // NOTE: size span must be set after line height span to avoid height jumps
99
+ setSpan(ssb, new MarkdownFontSizeSpan(markdownStyle.getH1FontSize()), start, end);
100
+ break;
101
+ case "blockquote":
102
+ MarkdownBlockquoteSpan span = new MarkdownBlockquoteSpan(
103
+ markdownStyle.getBlockquoteBorderColor(),
104
+ markdownStyle.getBlockquoteBorderWidth(),
105
+ markdownStyle.getBlockquoteMarginLeft(),
106
+ markdownStyle.getBlockquotePaddingLeft(),
107
+ markdownRange.getDepth());
108
+ setSpan(ssb, span, start, end);
109
+ break;
110
+ }
111
+ }
112
+
113
+ private void setSpan(SpannableStringBuilder ssb, MarkdownSpan span, int start, int end) {
114
+ ssb.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
115
+ }
116
+ }
@@ -1,26 +1,21 @@
1
1
  package com.expensify.livemarkdown;
2
2
 
3
- import android.content.res.AssetManager;
4
3
  import android.text.SpannableStringBuilder;
5
- import android.text.Spanned;
6
4
 
7
5
  import androidx.annotation.NonNull;
8
6
 
9
- import com.expensify.livemarkdown.spans.*;
10
7
  import com.facebook.react.bridge.ReactContext;
11
- import com.facebook.react.views.text.internal.span.CustomLineHeightSpan;
12
8
 
13
9
  import java.util.List;
14
- import java.util.Objects;
15
10
 
16
11
  public class MarkdownUtils {
17
12
  public MarkdownUtils(@NonNull ReactContext reactContext) {
18
- mAssetManager = reactContext.getAssets();
19
13
  mMarkdownParser = new MarkdownParser(reactContext);
14
+ mMarkdownFormatter = new MarkdownFormatter(reactContext.getAssets());
20
15
  }
21
16
 
22
- private final @NonNull AssetManager mAssetManager;
23
17
  private final @NonNull MarkdownParser mMarkdownParser;
18
+ private final @NonNull MarkdownFormatter mMarkdownFormatter;
24
19
 
25
20
  private MarkdownStyle mMarkdownStyle;
26
21
  private int mParserId;
@@ -34,98 +29,8 @@ public class MarkdownUtils {
34
29
  }
35
30
 
36
31
  public void applyMarkdownFormatting(SpannableStringBuilder ssb) {
37
- Objects.requireNonNull(mMarkdownStyle, "mMarkdownStyle is null");
38
-
39
- removeSpans(ssb);
40
-
41
32
  String text = ssb.toString();
42
33
  List<MarkdownRange> markdownRanges = mMarkdownParser.parse(text, mParserId);
43
-
44
- for (MarkdownRange markdownRange : markdownRanges) {
45
- applyRange(ssb, markdownRange);
46
- }
47
- }
48
-
49
- private void applyRange(SpannableStringBuilder ssb, MarkdownRange markdownRange) {
50
- String type = markdownRange.getType();
51
- int start = markdownRange.getStart();
52
- int end = start + markdownRange.getLength();
53
- switch (type) {
54
- case "bold":
55
- setSpan(ssb, new MarkdownBoldSpan(), start, end);
56
- break;
57
- case "italic":
58
- setSpan(ssb, new MarkdownItalicSpan(), start, end);
59
- break;
60
- case "strikethrough":
61
- setSpan(ssb, new MarkdownStrikethroughSpan(), start, end);
62
- break;
63
- case "emoji":
64
- setSpan(ssb, new MarkdownEmojiSpan(mMarkdownStyle.getEmojiFontSize()), start, end);
65
- break;
66
- case "mention-here":
67
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getMentionHereColor()), start, end);
68
- setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getMentionHereBackgroundColor()), start, end);
69
- break;
70
- case "mention-user":
71
- // TODO: change mention color when it mentions current user
72
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getMentionUserColor()), start, end);
73
- setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getMentionUserBackgroundColor()), start, end);
74
- break;
75
- case "mention-report":
76
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getMentionReportColor()), start, end);
77
- setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getMentionReportBackgroundColor()), start, end);
78
- break;
79
- case "syntax":
80
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getSyntaxColor()), start, end);
81
- break;
82
- case "link":
83
- setSpan(ssb, new MarkdownUnderlineSpan(), start, end);
84
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getLinkColor()), start, end);
85
- break;
86
- case "code":
87
- setSpan(ssb, new MarkdownFontFamilySpan(mMarkdownStyle.getCodeFontFamily(), mAssetManager), start, end);
88
- setSpan(ssb, new MarkdownFontSizeSpan(mMarkdownStyle.getCodeFontSize()), start, end);
89
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getCodeColor()), start, end);
90
- setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getCodeBackgroundColor()), start, end);
91
- break;
92
- case "pre":
93
- setSpan(ssb, new MarkdownFontFamilySpan(mMarkdownStyle.getPreFontFamily(), mAssetManager), start, end);
94
- setSpan(ssb, new MarkdownFontSizeSpan(mMarkdownStyle.getPreFontSize()), start, end);
95
- setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getPreColor()), start, end);
96
- setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getPreBackgroundColor()), start, end);
97
- break;
98
- case "h1":
99
- setSpan(ssb, new MarkdownBoldSpan(), start, end);
100
- CustomLineHeightSpan[] spans = ssb.getSpans(0, ssb.length(), CustomLineHeightSpan.class);
101
- if (spans.length >= 1) {
102
- int lineHeight = spans[0].getLineHeight();
103
- setSpan(ssb, new MarkdownLineHeightSpan(lineHeight * 1.5f), start, end);
104
- }
105
- // NOTE: size span must be set after line height span to avoid height jumps
106
- setSpan(ssb, new MarkdownFontSizeSpan(mMarkdownStyle.getH1FontSize()), start, end);
107
- break;
108
- case "blockquote":
109
- MarkdownBlockquoteSpan span = new MarkdownBlockquoteSpan(
110
- mMarkdownStyle.getBlockquoteBorderColor(),
111
- mMarkdownStyle.getBlockquoteBorderWidth(),
112
- mMarkdownStyle.getBlockquoteMarginLeft(),
113
- mMarkdownStyle.getBlockquotePaddingLeft(),
114
- markdownRange.getDepth());
115
- setSpan(ssb, span, start, end);
116
- break;
117
- }
118
- }
119
-
120
- private void setSpan(SpannableStringBuilder ssb, MarkdownSpan span, int start, int end) {
121
- ssb.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
122
- }
123
-
124
- private void removeSpans(SpannableStringBuilder ssb) {
125
- // We shouldn't use `removeSpans()` because it also removes SpellcheckSpan, SuggestionSpan etc.
126
- MarkdownSpan[] spans = ssb.getSpans(0, ssb.length(), MarkdownSpan.class);
127
- for (MarkdownSpan span : spans) {
128
- ssb.removeSpan(span);
129
- }
34
+ mMarkdownFormatter.format(ssb, markdownRanges, mMarkdownStyle);
130
35
  }
131
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expensify/react-native-live-markdown",
3
- "version": "0.1.195",
3
+ "version": "0.1.196",
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",