-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inline code block support #43
Changes from all commits
0f03d58
b50207f
f3205d7
f5eca79
b7882fe
55f3289
8350fa6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface RCTTextCodeBlockStyle : NSLayoutManager | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#import "RCTTextCodeBlockStyle.h" | ||
#import "RCTTextAttributes.h" | ||
|
||
@implementation RCTTextCodeBlockStyle | ||
|
||
- (UIColor*)hexStringToColor:(NSString *)stringToConvert | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use Already existing mechanism for colour in RN? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome, +1. |
||
{ | ||
NSString *noHashString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""]; | ||
NSScanner *stringScanner = [NSScanner scannerWithString:noHashString]; | ||
|
||
unsigned hex; | ||
if (![stringScanner scanHexInt:&hex]) return nil; | ||
int r = (hex >> 16) & 0xFF; | ||
int g = (hex >> 8) & 0xFF; | ||
int b = (hex) & 0xFF; | ||
|
||
return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:1.0f]; | ||
} | ||
|
||
-(void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { | ||
[super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin]; | ||
|
||
if ((glyphsToShow.location + glyphsToShow.length) > [[self textStorage] length]) { | ||
return; | ||
} | ||
|
||
[[self textStorage] enumerateAttribute:RCTTextAttributesIsTextCodeBlockStyleAttributeName | ||
inRange:glyphsToShow | ||
options:0 | ||
usingBlock:^(NSDictionary *textCodeBlockStyle, NSRange range, __unused BOOL *stop) { | ||
|
||
NSString *backgroundColor = [textCodeBlockStyle objectForKey:@"backgroundColor"]; | ||
NSString *borderColor = [textCodeBlockStyle objectForKey:@"borderColor"]; | ||
float borderRadius = [[textCodeBlockStyle objectForKey:@"borderRadius"] floatValue]; | ||
float borderWidth = [[textCodeBlockStyle objectForKey:@"borderWidth"] floatValue]; | ||
float horizontalOffset = 5; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't it be exposed to JS? |
||
float verticalOffset = 2; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't it be exposed to JS? |
||
|
||
CGContextRef context = UIGraphicsGetCurrentContext(); | ||
CGContextSetFillColorWithColor(context, [self hexStringToColor:backgroundColor].CGColor); | ||
CGContextSetStrokeColorWithColor(context, [self hexStringToColor:borderColor].CGColor); | ||
|
||
if (!backgroundColor) { | ||
return; | ||
} | ||
|
||
// Enumerates line fragments intersecting with the whole text container. | ||
[self enumerateLineFragmentsForGlyphRange:range | ||
usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer * _Nonnull textContainer, NSRange lineGlyphRange, BOOL * _Nonnull stop) { | ||
|
||
__block UIBezierPath *textCodeBlockStylePath = nil; | ||
|
||
NSRange lineRange = NSIntersectionRange(range, lineGlyphRange); | ||
|
||
[self enumerateEnclosingRectsForGlyphRange:lineRange | ||
withinSelectedGlyphRange:lineRange | ||
inTextContainer:textContainer | ||
usingBlock:^(CGRect enclosingRect, __unused BOOL *anotherStop) { | ||
|
||
BOOL isFirstLine = range.location >= lineGlyphRange.location; | ||
BOOL isLastLine = range.length + range.location <= lineGlyphRange.length + lineGlyphRange.location; | ||
long corners = ( | ||
(isFirstLine ? (UIRectCornerTopLeft | UIRectCornerBottomLeft) : 0) | | ||
(isLastLine ? (UIRectCornerTopRight | UIRectCornerBottomRight) : 0) | ||
); | ||
|
||
CGRect resultRect = CGRectMake( | ||
enclosingRect.origin.x, | ||
enclosingRect.origin.y + (borderWidth / 2) + verticalOffset, | ||
enclosingRect.size.width + ((isFirstLine && isLastLine) || isLastLine ? 0 : horizontalOffset), | ||
enclosingRect.size.height - (borderWidth * 2) | ||
); | ||
|
||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:resultRect byRoundingCorners:corners cornerRadii:CGSizeMake(borderRadius, borderRadius)]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we set those values here?
|
||
|
||
if (textCodeBlockStylePath) { | ||
[textCodeBlockStylePath appendPath:path]; | ||
} else { | ||
textCodeBlockStylePath = path; | ||
} | ||
|
||
textCodeBlockStylePath.lineWidth = borderWidth; | ||
[textCodeBlockStylePath stroke]; | ||
[textCodeBlockStylePath fill]; | ||
}]; | ||
}]; | ||
|
||
}]; | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @format | ||
* @flow strict-local | ||
*/ | ||
|
||
import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; | ||
|
||
export type TextCodeBlockStyleProp = $ReadOnly<{| | ||
/** | ||
* The background color of the text code block. | ||
*/ | ||
backgroundColor?: ?ColorValue, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have seen There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
/** | ||
* The border color of the text code block. | ||
*/ | ||
borderColor?: ?ColorValue, | ||
|
||
/** | ||
* The border radius of the text code block. | ||
*/ | ||
borderRadius?: ?number, | ||
|
||
/** | ||
* The border width of the text code block. | ||
*/ | ||
borderWidth?: ?number, | ||
|}>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for using custom LayoutManager?
There are already other attributes like background colour and they don't require the change.
I guess we want to merge it later upstream so I think it makes sense to avoid introducing new mechanisms if they are not needed. However, I'm not sure we need it while writing this comment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks that it's a standard approach https://levelup.gitconnected.com/background-with-rounded-corners-in-uitextview-1c095c708d14