@expensify/react-native-live-markdown 0.1.316 → 0.1.318
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/cpp/CMakeLists.txt +1 -0
- package/android/src/main/java/com/expensify/livemarkdown/MarkdownFormatter.java +3 -3
- package/android/src/main/java/com/expensify/livemarkdown/MarkdownStyle.java +23 -0
- package/android/src/main/java/com/expensify/livemarkdown/spans/MarkdownBackgroundSpan.java +94 -0
- package/apple/MarkdownFormatter.h +2 -0
- package/apple/MarkdownFormatter.mm +36 -6
- package/apple/MarkdownTextInputDecoratorComponentView.mm +17 -2
- package/apple/{BlockquoteTextLayoutFragment.h → MarkdownTextLayoutFragment.h} +4 -1
- package/apple/MarkdownTextLayoutFragment.mm +160 -0
- package/apple/MarkdownTextLayoutManagerDelegate.mm +22 -4
- package/apple/RCTMarkdownStyle.h +3 -0
- package/apple/RCTMarkdownStyle.mm +3 -0
- package/apple/RCTMarkdownTextBackground.h +9 -0
- package/apple/RCTMarkdownTextBackground.mm +4 -0
- package/apple/RCTMarkdownTextBackgroundWithRange.h +10 -0
- package/apple/RCTMarkdownTextBackgroundWithRange.mm +5 -0
- package/lib/commonjs/styleUtils.js +6 -3
- package/lib/commonjs/styleUtils.js.map +1 -1
- package/lib/module/styleUtils.js +6 -3
- package/lib/module/styleUtils.js.map +1 -1
- package/lib/typescript/src/styleUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/styleUtils.ts +3 -0
- package/apple/BlockquoteTextLayoutFragment.mm +0 -51
|
@@ -75,16 +75,16 @@ public class MarkdownFormatter {
|
|
|
75
75
|
break;
|
|
76
76
|
case "mention-here":
|
|
77
77
|
setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionHereColor()), start, end);
|
|
78
|
-
setSpan(ssb, new
|
|
78
|
+
setSpan(ssb, new MarkdownBackgroundSpan(markdownStyle.getMentionHereBackgroundColor(), markdownStyle.getMentionHereBorderRadius(), start, end), start, end);
|
|
79
79
|
break;
|
|
80
80
|
case "mention-user":
|
|
81
81
|
// TODO: change mention color when it mentions current user
|
|
82
82
|
setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionUserColor()), start, end);
|
|
83
|
-
setSpan(ssb, new
|
|
83
|
+
setSpan(ssb, new MarkdownBackgroundSpan(markdownStyle.getMentionUserBackgroundColor(), markdownStyle.getMentionUserBorderRadius(), start, end), start, end);
|
|
84
84
|
break;
|
|
85
85
|
case "mention-report":
|
|
86
86
|
setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getMentionReportColor()), start, end);
|
|
87
|
-
setSpan(ssb, new
|
|
87
|
+
setSpan(ssb, new MarkdownBackgroundSpan(markdownStyle.getMentionReportBackgroundColor(), markdownStyle.getMentionReportBorderRadius(), start, end), start, end);
|
|
88
88
|
break;
|
|
89
89
|
case "syntax":
|
|
90
90
|
setSpan(ssb, new MarkdownForegroundColorSpan(markdownStyle.getSyntaxColor()), start, end);
|
|
@@ -63,19 +63,27 @@ public class MarkdownStyle {
|
|
|
63
63
|
@ColorInt
|
|
64
64
|
private final int mMentionHereBackgroundColor;
|
|
65
65
|
|
|
66
|
+
private final float mMentionHereBorderRadius;
|
|
67
|
+
|
|
66
68
|
@ColorInt
|
|
67
69
|
private final int mMentionUserColor;
|
|
68
70
|
|
|
69
71
|
@ColorInt
|
|
70
72
|
private final int mMentionUserBackgroundColor;
|
|
71
73
|
|
|
74
|
+
private final float mMentionUserBorderRadius;
|
|
75
|
+
|
|
72
76
|
@ColorInt
|
|
73
77
|
private final int mMentionReportColor;
|
|
74
78
|
|
|
75
79
|
@ColorInt
|
|
76
80
|
private final int mMentionReportBackgroundColor;
|
|
77
81
|
|
|
82
|
+
private final float mMentionReportBorderRadius;
|
|
83
|
+
|
|
78
84
|
public MarkdownStyle(@NonNull ReadableMap map, @NonNull Context context) {
|
|
85
|
+
float screenDensity = context.getResources().getDisplayMetrics().density;
|
|
86
|
+
|
|
79
87
|
mSyntaxColor = parseColor(map, "syntax", "color", context);
|
|
80
88
|
mLinkColor = parseColor(map, "link", "color", context);
|
|
81
89
|
mH1FontSize = parseFloat(map, "h1", "fontSize");
|
|
@@ -95,10 +103,13 @@ public class MarkdownStyle {
|
|
|
95
103
|
mPreBackgroundColor = parseColor(map, "pre", "backgroundColor", context);
|
|
96
104
|
mMentionHereColor = parseColor(map, "mentionHere", "color", context);
|
|
97
105
|
mMentionHereBackgroundColor = parseColor(map, "mentionHere", "backgroundColor", context);
|
|
106
|
+
mMentionHereBorderRadius = parseFloat(map, "mentionHere", "borderRadius") * screenDensity;
|
|
98
107
|
mMentionUserColor = parseColor(map, "mentionUser", "color", context);
|
|
99
108
|
mMentionUserBackgroundColor = parseColor(map, "mentionUser", "backgroundColor", context);
|
|
109
|
+
mMentionUserBorderRadius = parseFloat(map, "mentionUser", "borderRadius") * screenDensity;
|
|
100
110
|
mMentionReportColor = parseColor(map, "mentionReport", "color", context);
|
|
101
111
|
mMentionReportBackgroundColor = parseColor(map, "mentionReport", "backgroundColor", context);
|
|
112
|
+
mMentionReportBorderRadius = parseFloat(map, "mentionReport", "borderRadius") * screenDensity;
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
private static int parseColor(@NonNull ReadableMap map, @NonNull String key, @NonNull String prop, @NonNull Context context) {
|
|
@@ -213,6 +224,10 @@ public class MarkdownStyle {
|
|
|
213
224
|
return mMentionHereBackgroundColor;
|
|
214
225
|
}
|
|
215
226
|
|
|
227
|
+
public float getMentionHereBorderRadius() {
|
|
228
|
+
return mMentionHereBorderRadius;
|
|
229
|
+
}
|
|
230
|
+
|
|
216
231
|
@ColorInt
|
|
217
232
|
public int getMentionUserColor() {
|
|
218
233
|
return mMentionUserColor;
|
|
@@ -223,6 +238,10 @@ public class MarkdownStyle {
|
|
|
223
238
|
return mMentionUserBackgroundColor;
|
|
224
239
|
}
|
|
225
240
|
|
|
241
|
+
public float getMentionUserBorderRadius() {
|
|
242
|
+
return mMentionUserBorderRadius;
|
|
243
|
+
}
|
|
244
|
+
|
|
226
245
|
@ColorInt
|
|
227
246
|
public int getMentionReportColor() {
|
|
228
247
|
return mMentionReportColor;
|
|
@@ -232,4 +251,8 @@ public class MarkdownStyle {
|
|
|
232
251
|
public int getMentionReportBackgroundColor() {
|
|
233
252
|
return mMentionReportBackgroundColor;
|
|
234
253
|
}
|
|
254
|
+
|
|
255
|
+
public float getMentionReportBorderRadius() {
|
|
256
|
+
return mMentionReportBorderRadius;
|
|
257
|
+
}
|
|
235
258
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
package com.expensify.livemarkdown.spans;
|
|
2
|
+
|
|
3
|
+
import android.graphics.Canvas;
|
|
4
|
+
import android.graphics.Paint;
|
|
5
|
+
import android.graphics.Path;
|
|
6
|
+
import android.graphics.RectF;
|
|
7
|
+
import android.text.StaticLayout;
|
|
8
|
+
import android.text.TextPaint;
|
|
9
|
+
import android.text.style.LineBackgroundSpan;
|
|
10
|
+
|
|
11
|
+
import androidx.annotation.ColorInt;
|
|
12
|
+
import androidx.annotation.NonNull;
|
|
13
|
+
|
|
14
|
+
public class MarkdownBackgroundSpan implements MarkdownSpan, LineBackgroundSpan {
|
|
15
|
+
|
|
16
|
+
private final int backgroundColor;
|
|
17
|
+
private final int mentionStart;
|
|
18
|
+
private final int mentionEnd;
|
|
19
|
+
private final float borderRadius;
|
|
20
|
+
|
|
21
|
+
private StaticLayout layout;
|
|
22
|
+
private Path backgroundPath;
|
|
23
|
+
|
|
24
|
+
public MarkdownBackgroundSpan(@ColorInt int backgroundColor, float borderRadius, int mentionStart, int mentionEnd) {
|
|
25
|
+
this.backgroundColor = backgroundColor;
|
|
26
|
+
this.borderRadius = borderRadius;
|
|
27
|
+
this.mentionStart = mentionStart;
|
|
28
|
+
this.mentionEnd = mentionEnd;
|
|
29
|
+
this.backgroundPath = new Path();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public void drawBackground(
|
|
34
|
+
@NonNull Canvas canvas,
|
|
35
|
+
@NonNull Paint paint,
|
|
36
|
+
int left,
|
|
37
|
+
int right,
|
|
38
|
+
int top,
|
|
39
|
+
int baseline,
|
|
40
|
+
int bottom,
|
|
41
|
+
@NonNull CharSequence text,
|
|
42
|
+
int start,
|
|
43
|
+
int end,
|
|
44
|
+
int lnum
|
|
45
|
+
) {
|
|
46
|
+
CharSequence lineText = text.subSequence(start, end);
|
|
47
|
+
if (layout == null || layout.getText() != lineText || layout.getWidth() != right || layout.getLineEnd(0) != lineText.length()) {
|
|
48
|
+
int currentLineStart = 0;
|
|
49
|
+
int currentLineEnd = lineText.length();
|
|
50
|
+
// Create layout for the current line only
|
|
51
|
+
layout = StaticLayout.Builder.obtain(lineText, currentLineStart, currentLineEnd, (TextPaint) paint, right).build();
|
|
52
|
+
|
|
53
|
+
int relativeMentionStart = mentionStart - start;
|
|
54
|
+
int relativeMentionEnd = mentionEnd - start;
|
|
55
|
+
|
|
56
|
+
boolean mentionStartsInCurrentLine = currentLineStart <= relativeMentionStart;
|
|
57
|
+
boolean mentionEndsInCurrentLine = currentLineEnd >= relativeMentionEnd;
|
|
58
|
+
|
|
59
|
+
float startX = layout.getPrimaryHorizontal(mentionStartsInCurrentLine ? relativeMentionStart: currentLineStart);
|
|
60
|
+
float endX = layout.getPrimaryHorizontal(mentionEndsInCurrentLine ? relativeMentionEnd : currentLineEnd);
|
|
61
|
+
|
|
62
|
+
Paint.FontMetrics fm = paint.getFontMetrics();
|
|
63
|
+
float startY = baseline + fm.ascent;
|
|
64
|
+
float endY = baseline + fm.descent;
|
|
65
|
+
|
|
66
|
+
RectF lineRect = new RectF(startX, startY, endX, endY);
|
|
67
|
+
backgroundPath.reset();
|
|
68
|
+
backgroundPath.addRoundRect(lineRect, createRadii(mentionStartsInCurrentLine, mentionEndsInCurrentLine), Path.Direction.CW);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
int originalColor = paint.getColor();
|
|
72
|
+
paint.setColor(backgroundColor);
|
|
73
|
+
|
|
74
|
+
canvas.drawPath(backgroundPath, paint);
|
|
75
|
+
|
|
76
|
+
paint.setColor(originalColor);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private float[] createRadii(boolean roundedLeft, boolean roundedRight) {
|
|
80
|
+
float[] radii = new float[8];
|
|
81
|
+
|
|
82
|
+
if (roundedLeft) {
|
|
83
|
+
radii[0] = radii[1] = borderRadius; // top-left
|
|
84
|
+
radii[6] = radii[7] = borderRadius; // bottom-left
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (roundedRight) {
|
|
88
|
+
radii[2] = radii[3] = borderRadius; // top-right
|
|
89
|
+
radii[4] = radii[5] = borderRadius; // bottom-right
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return radii;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -6,6 +6,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
6
6
|
|
|
7
7
|
const NSAttributedStringKey RCTLiveMarkdownTextAttributeName = @"RCTLiveMarkdownText";
|
|
8
8
|
|
|
9
|
+
const NSAttributedStringKey RCTLiveMarkdownTextBackgroundAttributeName = @"RCTLiveMarkdownTextBackground";
|
|
10
|
+
|
|
9
11
|
const NSAttributedStringKey RCTLiveMarkdownBlockquoteDepthAttributeName = @"RCTLiveMarkdownBlockquoteDepth";
|
|
10
12
|
|
|
11
13
|
@interface MarkdownFormatter : NSObject
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#import "MarkdownFormatter.h"
|
|
2
2
|
#import <React/RCTFont.h>
|
|
3
|
+
#import <RNLiveMarkdown/RCTMarkdownTextBackgroundWithRange.h>
|
|
3
4
|
|
|
4
5
|
@implementation MarkdownFormatter
|
|
5
6
|
|
|
@@ -90,15 +91,24 @@
|
|
|
90
91
|
[attributedString addAttribute:NSForegroundColorAttributeName value:markdownStyle.codeColor range:range];
|
|
91
92
|
[attributedString addAttribute:NSBackgroundColorAttributeName value:markdownStyle.codeBackgroundColor range:range];
|
|
92
93
|
} else if (type == "mention-here") {
|
|
93
|
-
[
|
|
94
|
-
|
|
94
|
+
[self applyMentionFormatting:attributedString
|
|
95
|
+
range:range
|
|
96
|
+
mentionColor:markdownStyle.mentionHereColor
|
|
97
|
+
backgroundColor:markdownStyle.mentionHereBackgroundColor
|
|
98
|
+
borderRadius:markdownStyle.mentionHereBorderRadius];
|
|
95
99
|
} else if (type == "mention-user") {
|
|
96
100
|
// TODO: change mention color when it mentions current user
|
|
97
|
-
[
|
|
98
|
-
|
|
101
|
+
[self applyMentionFormatting:attributedString
|
|
102
|
+
range:range
|
|
103
|
+
mentionColor:markdownStyle.mentionUserColor
|
|
104
|
+
backgroundColor:markdownStyle.mentionUserBackgroundColor
|
|
105
|
+
borderRadius:markdownStyle.mentionUserBorderRadius];
|
|
99
106
|
} else if (type == "mention-report") {
|
|
100
|
-
[
|
|
101
|
-
|
|
107
|
+
[self applyMentionFormatting:attributedString
|
|
108
|
+
range:range
|
|
109
|
+
mentionColor:markdownStyle.mentionReportColor
|
|
110
|
+
backgroundColor:markdownStyle.mentionReportBackgroundColor
|
|
111
|
+
borderRadius:markdownStyle.mentionReportBorderRadius];
|
|
102
112
|
} else if (type == "link") {
|
|
103
113
|
[attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:range];
|
|
104
114
|
[attributedString addAttribute:NSForegroundColorAttributeName value:markdownStyle.linkColor range:range];
|
|
@@ -118,6 +128,26 @@
|
|
|
118
128
|
}
|
|
119
129
|
}
|
|
120
130
|
|
|
131
|
+
- (void)applyMentionFormatting:(NSMutableAttributedString *)attributedString
|
|
132
|
+
range:(const NSRange)range
|
|
133
|
+
mentionColor:(UIColor *)mentionColor
|
|
134
|
+
backgroundColor:(UIColor *)backgroundColor
|
|
135
|
+
borderRadius:(CGFloat)borderRadius
|
|
136
|
+
{
|
|
137
|
+
[attributedString addAttribute:NSForegroundColorAttributeName value:mentionColor range:range];
|
|
138
|
+
if (@available(iOS 16.0, *)) {
|
|
139
|
+
RCTMarkdownTextBackground *textBackground = [[RCTMarkdownTextBackground alloc] init];
|
|
140
|
+
textBackground.color = backgroundColor;
|
|
141
|
+
textBackground.borderRadius = borderRadius;
|
|
142
|
+
|
|
143
|
+
[attributedString addAttribute:RCTLiveMarkdownTextBackgroundAttributeName
|
|
144
|
+
value:textBackground
|
|
145
|
+
range:range];
|
|
146
|
+
} else {
|
|
147
|
+
[attributedString addAttribute:NSBackgroundColorAttributeName value:backgroundColor range:range];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
121
151
|
static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText, NSRange attributedTextRange)
|
|
122
152
|
{
|
|
123
153
|
__block CGFloat maximumLineHeight = 0;
|
|
@@ -77,7 +77,7 @@ using namespace facebook::react;
|
|
|
77
77
|
react_native_assert([childView isKindOfClass:[RCTTextInputComponentView class]] && "Child component of MarkdownTextInputDecoratorComponentView is not an instance of RCTTextInputComponentView.");
|
|
78
78
|
RCTTextInputComponentView *textInputComponentView = (RCTTextInputComponentView *)childView;
|
|
79
79
|
UIView<RCTBackedTextInputViewProtocol> *backedTextInputView = [textInputComponentView valueForKey:@"_backedTextInputView"];
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
_observersAdded = true;
|
|
82
82
|
|
|
83
83
|
if ([backedTextInputView isKindOfClass:[RCTUITextField class]]) {
|
|
@@ -100,6 +100,21 @@ using namespace facebook::react;
|
|
|
100
100
|
// format initial value
|
|
101
101
|
[_markdownTextFieldObserver textFieldDidChange:_textField];
|
|
102
102
|
|
|
103
|
+
if (@available(iOS 16.0, *)) {
|
|
104
|
+
auto key = [](std::string s) {
|
|
105
|
+
std::reverse(s.begin(), s.end());
|
|
106
|
+
return @(s.c_str());
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
NSTextContainer *textContainer = [_textField valueForKey:key("reniatnoCtxet_")];
|
|
110
|
+
NSTextLayoutManager *textLayoutManager = [textContainer valueForKey:key("reganaMtuoyaLtxet_")];
|
|
111
|
+
|
|
112
|
+
_markdownTextLayoutManagerDelegate = [[MarkdownTextLayoutManagerDelegate alloc] init];
|
|
113
|
+
_markdownTextLayoutManagerDelegate.textStorage = [_textField valueForKey:key("egarotStxet_")];
|
|
114
|
+
_markdownTextLayoutManagerDelegate.markdownUtils = _markdownUtils;
|
|
115
|
+
textLayoutManager.delegate = _markdownTextLayoutManagerDelegate;
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
// TODO: register blockquotes layout manager
|
|
104
119
|
// https://github.com/Expensify/react-native-live-markdown/issues/87
|
|
105
120
|
} else if ([backedTextInputView isKindOfClass:[RCTUITextView class]]) {
|
|
@@ -229,7 +244,7 @@ using namespace facebook::react;
|
|
|
229
244
|
{
|
|
230
245
|
react_native_assert(!_observersAdded && "MarkdownTextInputDecoratorComponentView was being recycled with TextInput observers still attached");
|
|
231
246
|
[super prepareForRecycle];
|
|
232
|
-
|
|
247
|
+
|
|
233
248
|
static const auto defaultProps = std::make_shared<const MarkdownTextInputDecoratorViewProps>();
|
|
234
249
|
_props = defaultProps;
|
|
235
250
|
_markdownUtils = [[RCTMarkdownUtils alloc] init];
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/RCTMarkdownUtils.h>
|
|
2
|
+
#import <RNLiveMarkdown/RCTMarkdownTextBackgroundWithRange.h>
|
|
2
3
|
#import <UIKit/UIKit.h>
|
|
3
4
|
|
|
4
5
|
NS_ASSUME_NONNULL_BEGIN
|
|
5
6
|
|
|
6
7
|
API_AVAILABLE(ios(15.0))
|
|
7
|
-
@interface
|
|
8
|
+
@interface MarkdownTextLayoutFragment : NSTextLayoutFragment
|
|
8
9
|
|
|
9
10
|
@property (nonnull, atomic) RCTMarkdownUtils *markdownUtils;
|
|
10
11
|
|
|
11
12
|
@property NSUInteger depth;
|
|
12
13
|
|
|
14
|
+
@property NSMutableArray<RCTMarkdownTextBackgroundWithRange *> *mentions;
|
|
15
|
+
|
|
13
16
|
@end
|
|
14
17
|
|
|
15
18
|
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#import <RNLiveMarkdown/MarkdownTextLayoutFragment.h>
|
|
2
|
+
#import <RNLiveMarkdown/RCTMarkdownTextBackgroundWithRange.h>
|
|
3
|
+
|
|
4
|
+
@implementation MarkdownTextLayoutFragment
|
|
5
|
+
|
|
6
|
+
#pragma mark - overriding class methods
|
|
7
|
+
|
|
8
|
+
- (CGRect)renderingSurfaceBounds {
|
|
9
|
+
if (self.depth == 0) {
|
|
10
|
+
return [super renderingSurfaceBounds];
|
|
11
|
+
}
|
|
12
|
+
return CGRectUnion(self.boundingRect, [super renderingSurfaceBounds]);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
- (void)drawAtPoint:(CGPoint)point inContext:(CGContextRef)ctx {
|
|
16
|
+
if (self.textLineFragments.count == 0) {
|
|
17
|
+
[super drawAtPoint:point inContext:ctx];
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
[self drawBlockquoteRibbons];
|
|
22
|
+
[self drawMentions];
|
|
23
|
+
|
|
24
|
+
[super drawAtPoint:point inContext:ctx];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#pragma mark - drawing custom elements
|
|
28
|
+
|
|
29
|
+
- (void)drawBlockquoteRibbons {
|
|
30
|
+
if (self.depth == 0) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
|
|
35
|
+
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
|
|
36
|
+
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
|
|
37
|
+
CGFloat shift = marginLeft + borderWidth + paddingLeft;
|
|
38
|
+
|
|
39
|
+
[_markdownUtils.markdownStyle.blockquoteBorderColor setFill];
|
|
40
|
+
|
|
41
|
+
CGRect boundingRect = self.boundingRect;
|
|
42
|
+
for (NSUInteger level = 0; level < _depth; ++level) {
|
|
43
|
+
CGFloat x = boundingRect.origin.x + level * shift;
|
|
44
|
+
CGRect ribbonRect = CGRectMake(x, boundingRect.origin.y, borderWidth, boundingRect.size.height);
|
|
45
|
+
UIRectFill(ribbonRect);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (void)drawMentions {
|
|
50
|
+
if (self.mentions.count == 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
bool isSingleline = [self.textLineFragments count] == 1;
|
|
55
|
+
__block NSUInteger mentionIndex = 0;
|
|
56
|
+
[self.textLineFragments enumerateObjectsUsingBlock:^(NSTextLineFragment * _Nonnull lineFragment, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
57
|
+
if (lineFragment.characterRange.length == 0) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
CGRect lineBounds = lineFragment.typographicBounds;
|
|
62
|
+
NSRange lineRange = lineFragment.characterRange;
|
|
63
|
+
CGPoint lineEndLocation = [lineFragment locationForCharacterAtIndex: lineFragment.characterRange.length];
|
|
64
|
+
|
|
65
|
+
while (mentionIndex < self.mentions.count &&
|
|
66
|
+
NSMaxRange(self.mentions[mentionIndex].range) <= lineRange.location) {
|
|
67
|
+
mentionIndex++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (NSUInteger i = mentionIndex; i < self.mentions.count; i++) {
|
|
71
|
+
RCTMarkdownTextBackgroundWithRange *mention = self.mentions[i];
|
|
72
|
+
NSRange mentionRange = mention.range;
|
|
73
|
+
|
|
74
|
+
if (mentionRange.location >= NSMaxRange(lineRange)) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
NSRange intersection = NSIntersectionRange(lineRange, mentionRange);
|
|
79
|
+
CGPoint startLocation = [lineFragment locationForCharacterAtIndex:intersection.location];
|
|
80
|
+
if (isSingleline && startLocation.x == 0 && intersection.location > 0) {
|
|
81
|
+
// singleline: mention starts off screen, no need to draw background
|
|
82
|
+
// it only happens when the text input isn't focused
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
CGPoint endLocation = [lineFragment locationForCharacterAtIndex:intersection.location + intersection.length];
|
|
87
|
+
if (isSingleline && (startLocation.x > endLocation.x || (startLocation.x == endLocation.x && intersection.location == 0))) {
|
|
88
|
+
// singleline: mention is partially visible
|
|
89
|
+
// 1. starts in the middle, or
|
|
90
|
+
// 2. starts at the beginning of the line
|
|
91
|
+
endLocation = lineEndLocation;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
CGFloat width = endLocation.x - startLocation.x;
|
|
95
|
+
CGFloat x = lineBounds.origin.x + startLocation.x;
|
|
96
|
+
|
|
97
|
+
UIFont *font = [lineFragment.attributedString attribute:NSFontAttributeName
|
|
98
|
+
atIndex:intersection.location
|
|
99
|
+
effectiveRange:NULL];
|
|
100
|
+
CGFloat ascent = font.ascender;
|
|
101
|
+
CGFloat textHeight = font.lineHeight;
|
|
102
|
+
CGFloat y = lineBounds.origin.y + startLocation.y - ascent;
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
CGRect backgroundRect = CGRectMake(x,
|
|
106
|
+
y,
|
|
107
|
+
width,
|
|
108
|
+
textHeight);
|
|
109
|
+
|
|
110
|
+
BOOL isStart = (intersection.location == mention.range.location);
|
|
111
|
+
BOOL isEnd = (NSMaxRange(intersection) == NSMaxRange(mention.range));
|
|
112
|
+
UIRectCorner cornersToRound = 0;
|
|
113
|
+
if (isStart) {
|
|
114
|
+
cornersToRound |= UIRectCornerTopLeft | UIRectCornerBottomLeft;
|
|
115
|
+
}
|
|
116
|
+
if (isEnd) {
|
|
117
|
+
cornersToRound |= UIRectCornerTopRight | UIRectCornerBottomRight;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
UIBezierPath *linePath = (cornersToRound == 0)
|
|
121
|
+
? [UIBezierPath bezierPathWithRect:backgroundRect]
|
|
122
|
+
: [UIBezierPath bezierPathWithRoundedRect:backgroundRect
|
|
123
|
+
byRoundingCorners:cornersToRound
|
|
124
|
+
cornerRadii:CGSizeMake(mention.textBackground.borderRadius,
|
|
125
|
+
mention.textBackground.borderRadius)];
|
|
126
|
+
|
|
127
|
+
[mention.textBackground.color setFill];
|
|
128
|
+
[linePath fill];
|
|
129
|
+
}
|
|
130
|
+
}];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#pragma mark - helper functions
|
|
134
|
+
|
|
135
|
+
- (CGRect)boundingRect {
|
|
136
|
+
CGRect fragmentTextBounds = CGRectNull;
|
|
137
|
+
for (NSTextLineFragment *lineFragment in self.textLineFragments) {
|
|
138
|
+
if (lineFragment.characterRange.length == 0) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
CGRect lineFragmentBounds = lineFragment.typographicBounds;
|
|
142
|
+
if (CGRectIsNull(fragmentTextBounds)) {
|
|
143
|
+
fragmentTextBounds = lineFragmentBounds;
|
|
144
|
+
} else {
|
|
145
|
+
fragmentTextBounds = CGRectUnion(fragmentTextBounds, lineFragmentBounds);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
|
|
150
|
+
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
|
|
151
|
+
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
|
|
152
|
+
CGFloat shift = marginLeft + borderWidth + paddingLeft;
|
|
153
|
+
|
|
154
|
+
fragmentTextBounds.origin.x -= (paddingLeft + borderWidth) + shift * (_depth - 1);
|
|
155
|
+
fragmentTextBounds.size.width = borderWidth + shift * (_depth - 1);
|
|
156
|
+
|
|
157
|
+
return fragmentTextBounds;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import <RNLiveMarkdown/MarkdownTextLayoutManagerDelegate.h>
|
|
2
|
-
#import <RNLiveMarkdown/
|
|
2
|
+
#import <RNLiveMarkdown/MarkdownTextLayoutFragment.h>
|
|
3
3
|
#import <RNLiveMarkdown/MarkdownFormatter.h>
|
|
4
|
+
#import <RNLiveMarkdown/RCTMarkdownTextBackgroundWithRange.h>
|
|
4
5
|
|
|
5
6
|
@implementation MarkdownTextLayoutManagerDelegate
|
|
6
7
|
|
|
@@ -9,10 +10,27 @@ API_AVAILABLE(ios(15.0)){
|
|
|
9
10
|
NSInteger index = [textLayoutManager offsetFromLocation:textLayoutManager.documentRange.location toLocation:location];
|
|
10
11
|
if (index < self.textStorage.length) {
|
|
11
12
|
NSNumber *depth = [self.textStorage attribute:RCTLiveMarkdownBlockquoteDepthAttributeName atIndex:index effectiveRange:nil];
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
NSAttributedString *attributedString = [(NSTextParagraph *)textElement attributedString];
|
|
15
|
+
NSMutableArray<RCTMarkdownTextBackgroundWithRange *> *mentions = [NSMutableArray array];
|
|
16
|
+
[attributedString enumerateAttribute:RCTLiveMarkdownTextBackgroundAttributeName
|
|
17
|
+
inRange:NSMakeRange(0, attributedString.length)
|
|
18
|
+
options:0
|
|
19
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
20
|
+
if (value) {
|
|
21
|
+
RCTMarkdownTextBackgroundWithRange *textBackgroundWithRange = [[RCTMarkdownTextBackgroundWithRange alloc] init];
|
|
22
|
+
textBackgroundWithRange.textBackground = value;
|
|
23
|
+
textBackgroundWithRange.range = range;
|
|
24
|
+
|
|
25
|
+
[mentions addObject:textBackgroundWithRange];
|
|
26
|
+
}
|
|
27
|
+
}];
|
|
28
|
+
|
|
29
|
+
if (depth != nil || mentions.count > 0) {
|
|
30
|
+
MarkdownTextLayoutFragment *textLayoutFragment = [[MarkdownTextLayoutFragment alloc] initWithTextElement:textElement range:textElement.elementRange];
|
|
14
31
|
textLayoutFragment.markdownUtils = _markdownUtils;
|
|
15
|
-
textLayoutFragment.depth = [depth unsignedIntValue];
|
|
32
|
+
textLayoutFragment.depth = depth != nil ? [depth unsignedIntValue] : 0;
|
|
33
|
+
textLayoutFragment.mentions = mentions;
|
|
16
34
|
return textLayoutFragment;
|
|
17
35
|
}
|
|
18
36
|
}
|
package/apple/RCTMarkdownStyle.h
CHANGED
|
@@ -25,10 +25,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
25
25
|
@property (nonatomic) UIColor *preBackgroundColor;
|
|
26
26
|
@property (nonatomic) UIColor *mentionHereColor;
|
|
27
27
|
@property (nonatomic) UIColor *mentionHereBackgroundColor;
|
|
28
|
+
@property (nonatomic) CGFloat mentionHereBorderRadius;
|
|
28
29
|
@property (nonatomic) UIColor *mentionUserColor;
|
|
29
30
|
@property (nonatomic) UIColor *mentionUserBackgroundColor;
|
|
31
|
+
@property (nonatomic) CGFloat mentionUserBorderRadius;
|
|
30
32
|
@property (nonatomic) UIColor *mentionReportColor;
|
|
31
33
|
@property (nonatomic) UIColor *mentionReportBackgroundColor;
|
|
34
|
+
@property (nonatomic) CGFloat mentionReportBorderRadius;
|
|
32
35
|
|
|
33
36
|
- (instancetype)initWithStruct:(const facebook::react::MarkdownTextInputDecoratorViewMarkdownStyleStruct &)style;
|
|
34
37
|
|
|
@@ -33,12 +33,15 @@
|
|
|
33
33
|
|
|
34
34
|
_mentionHereColor = RCTUIColorFromSharedColor(style.mentionHere.color);
|
|
35
35
|
_mentionHereBackgroundColor = RCTUIColorFromSharedColor(style.mentionHere.backgroundColor);
|
|
36
|
+
_mentionHereBorderRadius = style.mentionHere.borderRadius;
|
|
36
37
|
|
|
37
38
|
_mentionUserColor = RCTUIColorFromSharedColor(style.mentionUser.color);
|
|
38
39
|
_mentionUserBackgroundColor = RCTUIColorFromSharedColor(style.mentionUser.backgroundColor);
|
|
40
|
+
_mentionUserBorderRadius = style.mentionUser.borderRadius;
|
|
39
41
|
|
|
40
42
|
_mentionReportColor = RCTUIColorFromSharedColor(style.mentionReport.color);
|
|
41
43
|
_mentionReportBackgroundColor = RCTUIColorFromSharedColor(style.mentionReport.backgroundColor);
|
|
44
|
+
_mentionReportBorderRadius = style.mentionReport.borderRadius;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
return self;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <RNLiveMarkdown/RCTMarkdownTextBackground.h>
|
|
3
|
+
|
|
4
|
+
@interface RCTMarkdownTextBackgroundWithRange : NSObject
|
|
5
|
+
|
|
6
|
+
@property (nonnull, atomic) RCTMarkdownTextBackground *textBackground;
|
|
7
|
+
|
|
8
|
+
@property NSRange range;
|
|
9
|
+
|
|
10
|
+
@end
|
|
@@ -60,15 +60,18 @@ function makeDefaultMarkdownStyle() {
|
|
|
60
60
|
},
|
|
61
61
|
mentionHere: {
|
|
62
62
|
color: 'green',
|
|
63
|
-
backgroundColor: 'lime'
|
|
63
|
+
backgroundColor: 'lime',
|
|
64
|
+
borderRadius: 5
|
|
64
65
|
},
|
|
65
66
|
mentionUser: {
|
|
66
67
|
color: 'blue',
|
|
67
|
-
backgroundColor: 'cyan'
|
|
68
|
+
backgroundColor: 'cyan',
|
|
69
|
+
borderRadius: 5
|
|
68
70
|
},
|
|
69
71
|
mentionReport: {
|
|
70
72
|
color: 'red',
|
|
71
|
-
backgroundColor: 'pink'
|
|
73
|
+
backgroundColor: 'pink',
|
|
74
|
+
borderRadius: 5
|
|
72
75
|
},
|
|
73
76
|
inlineImage: {
|
|
74
77
|
minWidth: 50,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","FONT_FAMILY_MONOSPACE","Platform","select","ios","default","FONT_FAMILY_EMOJI","android","makeDefaultMarkdownStyle","syntax","color","link","h1","fontSize","emoji","fontFamily","blockquote","borderColor","borderWidth","marginLeft","paddingLeft","code","backgroundColor","borderRadius","borderStyle","padding","pre","mentionHere","mentionUser","mentionReport","inlineImage","minWidth","minHeight","maxWidth","maxHeight","marginTop","marginBottom","loadingIndicator","primaryColor","secondaryColor","mergeMarkdownStyleWithDefault","input","output","undefined","Object","keys","forEach","key","outputValue","assign","parseStringWithUnitToNumber","value","parseInt","replace"],"sourceRoot":"../../src","sources":["styleUtils.ts"],"mappings":";;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAOA,MAAMC,qBAAqB,GAAGC,qBAAQ,CAACC,MAAM,CAAC;EAC5CC,GAAG,EAAE,SAAS;EACdC,OAAO,EAAE;AACX,CAAC,CAAC;AAEF,MAAMC,iBAAiB,GAAGJ,qBAAQ,CAACC,MAAM,CAAC;EACxCC,GAAG,EAAE,QAAQ;EACbG,OAAO,EAAE,kBAAkB;EAC3BF,OAAO,EAAE;AACX,CAAC,CAAC;AAEF,SAASG,wBAAwBA,CAAA,EAAkB;EACjD,OAAO;IACLC,MAAM,EAAE;MACNC,KAAK,EAAE;IACT,CAAC;IACDC,IAAI,EAAE;MACJD,KAAK,EAAE;IACT,CAAC;IACDE,EAAE,EAAE;MACFC,QAAQ,EAAE;IACZ,CAAC;IACDC,KAAK,EAAE;MACLD,QAAQ,EAAE,EAAE;MACZE,UAAU,EAAET;IACd,CAAC;IACDU,UAAU,EAAE;MACVC,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdC,UAAU,EAAE,CAAC;MACbC,WAAW,EAAE;IACf,CAAC;IACDC,IAAI,EAAE;MACJN,UAAU,EAAEd,qBAAqB;MACjCY,QAAQ,EAAE,EAAE;MACZH,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE,WAAW;MAC5BL,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdK,YAAY,EAAE,CAAC;MACfC,WAAW,EAAE,OAAO;MACpBC,OAAO,EAAE;IACX,CAAC;IACDC,GAAG,EAAE;MACHX,UAAU,EAAEd,qBAAqB;MACjCY,QAAQ,EAAE,EAAE;MACZH,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE,WAAW;MAC5BL,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdK,YAAY,EAAE,CAAC;MACfC,WAAW,EAAE,OAAO;MACpBC,OAAO,EAAE;IACX,CAAC;IACDE,WAAW,EAAE;MACXjB,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE;
|
|
1
|
+
{"version":3,"names":["_reactNative","require","FONT_FAMILY_MONOSPACE","Platform","select","ios","default","FONT_FAMILY_EMOJI","android","makeDefaultMarkdownStyle","syntax","color","link","h1","fontSize","emoji","fontFamily","blockquote","borderColor","borderWidth","marginLeft","paddingLeft","code","backgroundColor","borderRadius","borderStyle","padding","pre","mentionHere","mentionUser","mentionReport","inlineImage","minWidth","minHeight","maxWidth","maxHeight","marginTop","marginBottom","loadingIndicator","primaryColor","secondaryColor","mergeMarkdownStyleWithDefault","input","output","undefined","Object","keys","forEach","key","outputValue","assign","parseStringWithUnitToNumber","value","parseInt","replace"],"sourceRoot":"../../src","sources":["styleUtils.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/styleUtils.js
CHANGED
|
@@ -55,15 +55,18 @@ function makeDefaultMarkdownStyle() {
|
|
|
55
55
|
},
|
|
56
56
|
mentionHere: {
|
|
57
57
|
color: 'green',
|
|
58
|
-
backgroundColor: 'lime'
|
|
58
|
+
backgroundColor: 'lime',
|
|
59
|
+
borderRadius: 5
|
|
59
60
|
},
|
|
60
61
|
mentionUser: {
|
|
61
62
|
color: 'blue',
|
|
62
|
-
backgroundColor: 'cyan'
|
|
63
|
+
backgroundColor: 'cyan',
|
|
64
|
+
borderRadius: 5
|
|
63
65
|
},
|
|
64
66
|
mentionReport: {
|
|
65
67
|
color: 'red',
|
|
66
|
-
backgroundColor: 'pink'
|
|
68
|
+
backgroundColor: 'pink',
|
|
69
|
+
borderRadius: 5
|
|
67
70
|
},
|
|
68
71
|
inlineImage: {
|
|
69
72
|
minWidth: 50,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","FONT_FAMILY_MONOSPACE","select","ios","default","FONT_FAMILY_EMOJI","android","makeDefaultMarkdownStyle","syntax","color","link","h1","fontSize","emoji","fontFamily","blockquote","borderColor","borderWidth","marginLeft","paddingLeft","code","backgroundColor","borderRadius","borderStyle","padding","pre","mentionHere","mentionUser","mentionReport","inlineImage","minWidth","minHeight","maxWidth","maxHeight","marginTop","marginBottom","loadingIndicator","primaryColor","secondaryColor","mergeMarkdownStyleWithDefault","input","output","undefined","Object","keys","forEach","key","outputValue","assign","parseStringWithUnitToNumber","value","parseInt","replace"],"sourceRoot":"../../src","sources":["styleUtils.ts"],"mappings":";;AAAA,SAAQA,QAAQ,QAAO,cAAc;AAOrC,MAAMC,qBAAqB,GAAGD,QAAQ,CAACE,MAAM,CAAC;EAC5CC,GAAG,EAAE,SAAS;EACdC,OAAO,EAAE;AACX,CAAC,CAAC;AAEF,MAAMC,iBAAiB,GAAGL,QAAQ,CAACE,MAAM,CAAC;EACxCC,GAAG,EAAE,QAAQ;EACbG,OAAO,EAAE,kBAAkB;EAC3BF,OAAO,EAAE;AACX,CAAC,CAAC;AAEF,SAASG,wBAAwBA,CAAA,EAAkB;EACjD,OAAO;IACLC,MAAM,EAAE;MACNC,KAAK,EAAE;IACT,CAAC;IACDC,IAAI,EAAE;MACJD,KAAK,EAAE;IACT,CAAC;IACDE,EAAE,EAAE;MACFC,QAAQ,EAAE;IACZ,CAAC;IACDC,KAAK,EAAE;MACLD,QAAQ,EAAE,EAAE;MACZE,UAAU,EAAET;IACd,CAAC;IACDU,UAAU,EAAE;MACVC,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdC,UAAU,EAAE,CAAC;MACbC,WAAW,EAAE;IACf,CAAC;IACDC,IAAI,EAAE;MACJN,UAAU,EAAEb,qBAAqB;MACjCW,QAAQ,EAAE,EAAE;MACZH,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE,WAAW;MAC5BL,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdK,YAAY,EAAE,CAAC;MACfC,WAAW,EAAE,OAAO;MACpBC,OAAO,EAAE;IACX,CAAC;IACDC,GAAG,EAAE;MACHX,UAAU,EAAEb,qBAAqB;MACjCW,QAAQ,EAAE,EAAE;MACZH,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE,WAAW;MAC5BL,WAAW,EAAE,MAAM;MACnBC,WAAW,EAAE,CAAC;MACdK,YAAY,EAAE,CAAC;MACfC,WAAW,EAAE,OAAO;MACpBC,OAAO,EAAE;IACX,CAAC;IACDE,WAAW,EAAE;MACXjB,KAAK,EAAE,OAAO;MACdY,eAAe,EAAE;
|
|
1
|
+
{"version":3,"names":["Platform","FONT_FAMILY_MONOSPACE","select","ios","default","FONT_FAMILY_EMOJI","android","makeDefaultMarkdownStyle","syntax","color","link","h1","fontSize","emoji","fontFamily","blockquote","borderColor","borderWidth","marginLeft","paddingLeft","code","backgroundColor","borderRadius","borderStyle","padding","pre","mentionHere","mentionUser","mentionReport","inlineImage","minWidth","minHeight","maxWidth","maxHeight","marginTop","marginBottom","loadingIndicator","primaryColor","secondaryColor","mergeMarkdownStyleWithDefault","input","output","undefined","Object","keys","forEach","key","outputValue","assign","parseStringWithUnitToNumber","value","parseInt","replace"],"sourceRoot":"../../src","sources":["styleUtils.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleUtils.d.ts","sourceRoot":"","sources":["../../../src/styleUtils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iDAAiD,CAAC;AAEnF,KAAK,oBAAoB,GAAG,OAAO,CAAC;KACjC,CAAC,IAAI,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CACtD,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"styleUtils.d.ts","sourceRoot":"","sources":["../../../src/styleUtils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iDAAiD,CAAC;AAEnF,KAAK,oBAAoB,GAAG,OAAO,CAAC;KACjC,CAAC,IAAI,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CACtD,CAAC,CAAC;AAuFH,iBAAS,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,SAAS,GAAG,aAAa,CAiB7F;AAED,iBAAS,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAK1E;AAED,YAAY,EAAC,oBAAoB,EAAC,CAAC;AAEnC,OAAO,EAAC,6BAA6B,EAAE,2BAA2B,EAAC,CAAC"}
|
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.318",
|
|
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",
|
package/src/styleUtils.ts
CHANGED
|
@@ -62,14 +62,17 @@ function makeDefaultMarkdownStyle(): MarkdownStyle {
|
|
|
62
62
|
mentionHere: {
|
|
63
63
|
color: 'green',
|
|
64
64
|
backgroundColor: 'lime',
|
|
65
|
+
borderRadius: 5,
|
|
65
66
|
},
|
|
66
67
|
mentionUser: {
|
|
67
68
|
color: 'blue',
|
|
68
69
|
backgroundColor: 'cyan',
|
|
70
|
+
borderRadius: 5,
|
|
69
71
|
},
|
|
70
72
|
mentionReport: {
|
|
71
73
|
color: 'red',
|
|
72
74
|
backgroundColor: 'pink',
|
|
75
|
+
borderRadius: 5,
|
|
73
76
|
},
|
|
74
77
|
inlineImage: {
|
|
75
78
|
minWidth: 50,
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
#import <RNLiveMarkdown/BlockquoteTextLayoutFragment.h>
|
|
2
|
-
|
|
3
|
-
@implementation BlockquoteTextLayoutFragment
|
|
4
|
-
|
|
5
|
-
- (CGRect)boundingRect {
|
|
6
|
-
CGRect fragmentTextBounds = CGRectNull;
|
|
7
|
-
for (NSTextLineFragment *lineFragment in self.textLineFragments) {
|
|
8
|
-
if (lineFragment.characterRange.length == 0) {
|
|
9
|
-
continue;
|
|
10
|
-
}
|
|
11
|
-
CGRect lineFragmentBounds = lineFragment.typographicBounds;
|
|
12
|
-
if (CGRectIsNull(fragmentTextBounds)) {
|
|
13
|
-
fragmentTextBounds = lineFragmentBounds;
|
|
14
|
-
} else {
|
|
15
|
-
fragmentTextBounds = CGRectUnion(fragmentTextBounds, lineFragmentBounds);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
|
|
20
|
-
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
|
|
21
|
-
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
|
|
22
|
-
CGFloat shift = marginLeft + borderWidth + paddingLeft;
|
|
23
|
-
|
|
24
|
-
fragmentTextBounds.origin.x -= (paddingLeft + borderWidth) + shift * (_depth - 1);
|
|
25
|
-
fragmentTextBounds.size.width = borderWidth + shift * (_depth - 1);
|
|
26
|
-
|
|
27
|
-
return fragmentTextBounds;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
- (void)drawAtPoint:(CGPoint)point inContext:(CGContextRef)ctx {
|
|
31
|
-
CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft;
|
|
32
|
-
CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth;
|
|
33
|
-
CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft;
|
|
34
|
-
CGFloat shift = marginLeft + borderWidth + paddingLeft;
|
|
35
|
-
|
|
36
|
-
[_markdownUtils.markdownStyle.blockquoteBorderColor setFill];
|
|
37
|
-
|
|
38
|
-
CGRect boundingRect = self.boundingRect;
|
|
39
|
-
for (NSUInteger i = 0; i < _depth; ++i) {
|
|
40
|
-
CGRect ribbonRect = CGRectMake(boundingRect.origin.x + i * shift, boundingRect.origin.y, borderWidth, boundingRect.size.height);
|
|
41
|
-
UIRectFill(ribbonRect);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
[super drawAtPoint:point inContext:ctx];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
- (CGRect)renderingSurfaceBounds {
|
|
48
|
-
return CGRectUnion(self.boundingRect, [super renderingSurfaceBounds]);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@end
|