From 86a637f0fd0c0d69155f5d9272e20a00bbfeeaa2 Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 24 Oct 2025 15:32:01 +0200 Subject: [PATCH 1/3] refactor(ios): remove HeaderConfig and simplify RichTextView theming --- example/src/App.tsx | 7 ------ ios/RichTextView.mm | 36 +++++++----------------------- ios/renderer/AttributedRenderer.m | 24 ++------------------ ios/theme/HeaderConfig.h | 10 --------- ios/theme/HeaderConfig.m | 12 ---------- ios/theme/RichTextTheme.h | 2 -- ios/theme/RichTextTheme.m | 1 - src/RichTextViewNativeComponent.ts | 25 ++------------------- src/index.tsx | 1 - 9 files changed, 12 insertions(+), 106 deletions(-) delete mode 100644 ios/theme/HeaderConfig.h delete mode 100644 ios/theme/HeaderConfig.m diff --git a/example/src/App.tsx b/example/src/App.tsx index 47af5424..1c034917 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -6,12 +6,6 @@ import { Linking, } from 'react-native'; import { RichTextView } from 'react-native-rich-text'; -import type { HeaderConfig } from 'react-native-rich-text'; - -const HEADER_CONFIG: HeaderConfig = { - scale: 2.0, - isBold: true, -}; const sampleMarkdown = `#### Welcome to the React Native Markdown component! @@ -49,7 +43,6 @@ export default function App() { style={styles.markdown} fontSize={18} fontFamily="Helvetica" - headerConfig={HEADER_CONFIG} color="#F54927" onLinkPress={handleLinkPress} /> diff --git a/ios/RichTextView.mm b/ios/RichTextView.mm index 1a74b1b9..b59a4b7f 100644 --- a/ios/RichTextView.mm +++ b/ios/RichTextView.mm @@ -11,6 +11,7 @@ #import #import "RCTFabricComponentsPlugins.h" +#import using namespace facebook::react; @@ -108,11 +109,6 @@ - (void)renderMarkdownContent:(NSString *)markdownString withProps:(const RichTe theme.baseFont = [self createFontWithFamily:fontFamily size:fontSize]; if (_textView.textColor) { theme.textColor = _textView.textColor; } - const auto &headerConfig = props.headerConfig; - - theme.headerConfig.scale = headerConfig.scale > 0 ? headerConfig.scale : 2.0; - theme.headerConfig.isBold = headerConfig.isBold; - RenderContext *renderContext = [RenderContext new]; NSMutableAttributedString *attributedText = [renderer renderRoot:ast theme:theme context:renderContext]; @@ -144,9 +140,12 @@ - (void)updateProps:(Props::Shared const &)props needsRerender = YES; } - if (oldViewProps.textColor != newViewProps.textColor) { - NSString *textColorString = [[NSString alloc] initWithUTF8String:newViewProps.textColor.c_str()]; - _textView.textColor = [self hexStringToColor:textColorString]; + if (oldViewProps.color != newViewProps.color) { + // Convert React Native SharedColor to UIColor + UIColor *color = RCTUIColorFromSharedColor(newViewProps.color); + if (color) { + _textView.textColor = color; + } needsRerender = YES; } @@ -157,10 +156,7 @@ - (void)updateProps:(Props::Shared const &)props needsRerender = YES; } - if (oldViewProps.headerConfig.scale != newViewProps.headerConfig.scale || - oldViewProps.headerConfig.isBold != newViewProps.headerConfig.isBold) { - needsRerender = YES; - } + // HeaderConfig removed - no longer needed if (needsRerender && !newViewProps.markdown.empty()) { NSString *markdownString = [[NSString alloc] initWithUTF8String:newViewProps.markdown.c_str()]; @@ -175,22 +171,6 @@ - (void)updateProps:(Props::Shared const &)props return RichTextView.class; } -- (UIColor *)hexStringToColor:(NSString *)hexString { - if (!hexString.length) return nil; - - NSString *cleanHex = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]; - if (cleanHex.length != 6) return nil; - - NSScanner *scanner = [NSScanner scannerWithString:cleanHex]; - unsigned hexValue; - if (![scanner scanHexInt:&hexValue]) return nil; - - CGFloat red = ((hexValue >> 16) & 0xFF) / 255.0f; - CGFloat green = ((hexValue >> 8) & 0xFF) / 255.0f; - CGFloat blue = (hexValue & 0xFF) / 255.0f; - - return [UIColor colorWithRed:red green:green blue:blue alpha:1.0f]; -} // MARK: - Gesture handling diff --git a/ios/renderer/AttributedRenderer.m b/ios/renderer/AttributedRenderer.m index 35681266..dd27fab0 100644 --- a/ios/renderer/AttributedRenderer.m +++ b/ios/renderer/AttributedRenderer.m @@ -231,28 +231,8 @@ - (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output withTheme:(RichTextTheme *)theme context:(RenderContext *)context { - // Determine level from attributes (default 1) - NSInteger level = [node.attributes[@"level"] integerValue]; - if (level < 1 || level > 6) level = 1; - - // Scale header size using theme configuration - CGFloat size = MAX(12.0, theme.baseFont.pointSize + (7 - level) * theme.headerConfig.scale); - - // Start with base font, apply bold if needed - UIFont *font = [UIFont fontWithName:theme.baseFont.fontName size:size]; - - // If font is not bold but headerConfig wants bold, try bold version - if (![theme.baseFont.fontName containsString:@"Bold"] && theme.headerConfig.isBold) { - // For system fonts (no fontFamily specified), use system bold directly - if ([theme.baseFont.fontName hasPrefix:@".SFUI"]) { - font = [UIFont boldSystemFontOfSize:size]; - } else { - // For specified font families, try bold version - NSString *boldFontName = [NSString stringWithFormat:@"%@-Bold", theme.baseFont.fontName]; - UIFont *boldFont = [UIFont fontWithName:boldFontName size:size]; - font = boldFont ?: [UIFont boldSystemFontOfSize:size]; - } - } + + UIFont *font = [UIFont fontWithDescriptor:[theme.baseFont.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold] size:theme.baseFont.pointSize]; for (MarkdownASTNode *child in node.children) { if (child.type == MarkdownNodeTypeText && child.content) { diff --git a/ios/theme/HeaderConfig.h b/ios/theme/HeaderConfig.h deleted file mode 100644 index 38de122e..00000000 --- a/ios/theme/HeaderConfig.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface HeaderConfig : NSObject - -@property (nonatomic, assign) CGFloat scale; -@property (nonatomic, assign) BOOL isBold; - -+ (instancetype)defaultConfig; - -@end diff --git a/ios/theme/HeaderConfig.m b/ios/theme/HeaderConfig.m deleted file mode 100644 index 6393c42e..00000000 --- a/ios/theme/HeaderConfig.m +++ /dev/null @@ -1,12 +0,0 @@ -#import "HeaderConfig.h" - -@implementation HeaderConfig - -+ (instancetype)defaultConfig { - HeaderConfig *config = [HeaderConfig new]; - config.scale = 2.0; // Default scaling factor - config.isBold = YES; // Headers are bold by default - return config; -} - -@end diff --git a/ios/theme/RichTextTheme.h b/ios/theme/RichTextTheme.h index 9c6f5e14..eae94f4c 100644 --- a/ios/theme/RichTextTheme.h +++ b/ios/theme/RichTextTheme.h @@ -1,12 +1,10 @@ #import #import -#import "HeaderConfig.h" @interface RichTextTheme : NSObject @property (nonatomic, strong) UIFont *baseFont; @property (nonatomic, strong) UIColor *textColor; -@property (nonatomic, strong) HeaderConfig *headerConfig; + (instancetype)defaultTheme; diff --git a/ios/theme/RichTextTheme.m b/ios/theme/RichTextTheme.m index 5b63e73f..290f7144 100644 --- a/ios/theme/RichTextTheme.m +++ b/ios/theme/RichTextTheme.m @@ -6,7 +6,6 @@ + (instancetype)defaultTheme { RichTextTheme *theme = [RichTextTheme new]; theme.baseFont = [UIFont systemFontOfSize:16]; theme.textColor = [UIColor blackColor]; - theme.headerConfig = [HeaderConfig defaultConfig]; return theme; } diff --git a/src/RichTextViewNativeComponent.ts b/src/RichTextViewNativeComponent.ts index 8185b1fe..790a0752 100644 --- a/src/RichTextViewNativeComponent.ts +++ b/src/RichTextViewNativeComponent.ts @@ -5,22 +5,6 @@ import { type ColorValue, } from 'react-native'; -export interface HeaderConfig { - /** - * Header scaling factor relative to base fontSize. - * @default 2.0 - * @example - * fontSize=18, scale=2.0 → H1=30pt, H2=28pt, H6=20pt - */ - scale?: CodegenTypes.Double; - /** - * Make headers bold. - * @default true - * @note fontFamily takes precedence over this setting - */ - isBold?: boolean; -} - interface NativeProps extends ViewProps { /** * Markdown content to render. @@ -30,14 +14,13 @@ interface NativeProps extends ViewProps { /** * Base font size for all text elements (in points). * - Regular text, links, lists: Use fontSize directly - * - Headers: Scaled relative to fontSize using headerConfig.scale + * - Headers: Made bold, same size as base fontSize * @example - * fontSize=18 → text=18pt, H1=30pt, H2=28pt, H6=20pt + * fontSize=18 → all text=18pt, headers are bold */ fontSize?: CodegenTypes.Int32; /** * Font family name for all text elements. - * @note Takes precedence over headerConfig.isBold for boldness */ fontFamily?: string; /** @@ -54,10 +37,6 @@ interface NativeProps extends ViewProps { * Text color in hex format. */ color?: ColorValue; - /** - * Header configuration for scaling and boldness. - */ - headerConfig?: HeaderConfig; /** * Callback fired when a link is pressed. * Receives the URL that was tapped. diff --git a/src/index.tsx b/src/index.tsx index c150e130..c56a14c7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,2 +1 @@ export { default as RichTextView } from './RichTextViewNativeComponent'; -export type { HeaderConfig } from './RichTextViewNativeComponent'; From c5c9224a3fc4031a806d9ba2e134b8603d7bda03 Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 24 Oct 2025 15:51:46 +0200 Subject: [PATCH 2/3] refactor(ios): eliminate RichTextTheme dependency and streamline text rendering in RichTextView --- ios/RichTextView.mm | 13 +++-- ios/renderer/AttributedRenderer.h | 4 +- ios/renderer/AttributedRenderer.m | 87 +++++++++++++++++-------------- ios/renderer/NodeRenderer.h | 4 +- ios/theme/RichTextTheme.h | 11 ---- ios/theme/RichTextTheme.m | 12 ----- 6 files changed, 60 insertions(+), 71 deletions(-) delete mode 100644 ios/theme/RichTextTheme.h delete mode 100644 ios/theme/RichTextTheme.m diff --git a/ios/RichTextView.mm b/ios/RichTextView.mm index b59a4b7f..aa09e9e5 100644 --- a/ios/RichTextView.mm +++ b/ios/RichTextView.mm @@ -3,7 +3,6 @@ #import "MarkdownASTNode.h" #import "AttributedRenderer.h" #import "RenderContext.h" -#import "RichTextTheme.h" #import #import @@ -100,17 +99,21 @@ - (void)renderMarkdownContent:(NSString *)markdownString withProps:(const RichTe } AttributedRenderer *renderer = [AttributedRenderer new]; - RichTextTheme *theme = [RichTextTheme defaultTheme]; CGFloat fontSize = props.fontSize > 0 ? props.fontSize : kDefaultFontSize; // Create font with family and size NSString *fontFamily = [[NSString alloc] initWithUTF8String:props.fontFamily.c_str()]; - theme.baseFont = [self createFontWithFamily:fontFamily size:fontSize]; - if (_textView.textColor) { theme.textColor = _textView.textColor; } + UIFont *font = [self createFontWithFamily:fontFamily size:fontSize]; + + // Get color from props or use textView's current color + UIColor *color = _textView.textColor ?: [UIColor blackColor]; + if (props.color) { + color = RCTUIColorFromSharedColor(props.color); + } RenderContext *renderContext = [RenderContext new]; - NSMutableAttributedString *attributedText = [renderer renderRoot:ast theme:theme context:renderContext]; + NSMutableAttributedString *attributedText = [renderer renderRoot:ast font:font color:color context:renderContext]; // Add custom attributes for links for (NSUInteger i = 0; i < renderContext.linkRanges.count; i++) { diff --git a/ios/renderer/AttributedRenderer.h b/ios/renderer/AttributedRenderer.h index f1619863..55bb0820 100644 --- a/ios/renderer/AttributedRenderer.h +++ b/ios/renderer/AttributedRenderer.h @@ -1,12 +1,12 @@ #import @class MarkdownASTNode; -@class RichTextTheme; @class RenderContext; @interface AttributedRenderer : NSObject - (NSMutableAttributedString *)renderRoot:(MarkdownASTNode *)root - theme:(RichTextTheme *)theme + font:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context; @end diff --git a/ios/renderer/AttributedRenderer.m b/ios/renderer/AttributedRenderer.m index dd27fab0..72442b73 100644 --- a/ios/renderer/AttributedRenderer.m +++ b/ios/renderer/AttributedRenderer.m @@ -2,7 +2,6 @@ #import "NodeRenderer.h" #import "RenderContext.h" #import "MarkdownASTNode.h" -#import "RichTextTheme.h" @interface ParagraphRenderer : NSObject @end @@ -22,17 +21,19 @@ - (NSAttributedString *)createTextString:(NSString *)text color:(UIColor *)color; - (void)renderChildrenOfNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context; @end @implementation AttributedRenderer - (NSMutableAttributedString *)renderRoot:(MarkdownASTNode *)root - theme:(RichTextTheme *)theme + font:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { NSMutableAttributedString *out = [[NSMutableAttributedString alloc] init]; - [self renderNodeRecursive:root into:out theme:theme context:context isTopLevel:YES]; + [self renderNodeRecursive:root into:out font:font color:color context:context isTopLevel:YES]; return out; } @@ -44,27 +45,28 @@ - (NSMutableAttributedString *)renderRoot:(MarkdownASTNode *)root * for modular, maintainable code. Performance: O(n) with shallow AST depth. */ - (void)renderNodeRecursive:(MarkdownASTNode *)node - into:(NSMutableAttributedString *)out - theme:(RichTextTheme *)theme + into:(NSMutableAttributedString *)out + font:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context isTopLevel:(BOOL)isTopLevel { id renderer = [self rendererForNode:node]; if (renderer) { - [renderer renderNode:node into:out withTheme:theme context:context]; + [renderer renderNode:node into:out withFont:font color:color context:context]; return; } // Fallback: render children for (NSUInteger i = 0; i < node.children.count; i++) { MarkdownASTNode *child = node.children[i]; - [self renderNodeRecursive:child into:out theme:theme context:context isTopLevel:NO]; + [self renderNodeRecursive:child into:out font:font color:color context:context isTopLevel:NO]; // Add spacing between paragraphs (MD4C doesn't provide empty lines between blocks) // This is intentional rendering behavior to match markdown visual expectations if (child.type == MarkdownNodeTypeParagraph && i < node.children.count - 1) { NSAttributedString *spacing = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [out appendAttributedString:spacing]; } @@ -97,14 +99,16 @@ - (NSAttributedString *)createTextString:(NSString *)text - (void)renderChildrenOfNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { for (MarkdownASTNode *child in node.children) { id renderer = [self rendererForNode:child]; if (renderer) { [renderer renderNode:child into:output - withTheme:theme + withFont:font + color:color context:context]; } } @@ -115,9 +119,10 @@ - (void)renderChildrenOfNode:(MarkdownASTNode *)node @implementation ParagraphRenderer - (BOOL)canRender:(MarkdownASTNode *)node { return node.type == MarkdownNodeTypeParagraph; } -- (void)renderNode:(MarkdownASTNode *)node - into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme +- (void)renderNode:(MarkdownASTNode *)node + into:(NSMutableAttributedString *)output + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { for (MarkdownASTNode *child in node.children) { switch (child.type) { @@ -126,8 +131,8 @@ - (void)renderNode:(MarkdownASTNode *)node NSAttributedString *text = [[NSAttributedString alloc] initWithString:child.content attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:text]; } @@ -137,7 +142,8 @@ - (void)renderNode:(MarkdownASTNode *)node LinkRenderer *linkRenderer = [LinkRenderer new]; [linkRenderer renderNode:child into:output - withTheme:theme + withFont:font + color:color context:context]; break; } @@ -146,8 +152,8 @@ - (void)renderNode:(MarkdownASTNode *)node NSAttributedString *br = [[NSAttributedString alloc] initWithString:@"\n" attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:br]; break; @@ -160,8 +166,8 @@ - (void)renderNode:(MarkdownASTNode *)node NSAttributedString *t = [[NSAttributedString alloc] initWithString:grand.content attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:t]; } @@ -174,17 +180,18 @@ - (void)renderNode:(MarkdownASTNode *)node @implementation TextRenderer - (BOOL)canRender:(MarkdownASTNode *)node { return node.type == MarkdownNodeTypeText; } -- (void)renderNode:(MarkdownASTNode *)node - into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme +- (void)renderNode:(MarkdownASTNode *)node + into:(NSMutableAttributedString *)output + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { if (!node.content) return; NSAttributedString *text = [[NSAttributedString alloc] initWithString:node.content attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:text]; } @@ -192,9 +199,10 @@ - (void)renderNode:(MarkdownASTNode *)node @implementation LinkRenderer - (BOOL)canRender:(MarkdownASTNode *)node { return node.type == MarkdownNodeTypeLink; } -- (void)renderNode:(MarkdownASTNode *)node - into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme +- (void)renderNode:(MarkdownASTNode *)node + into:(NSMutableAttributedString *)output + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { NSUInteger start = output.length; @@ -203,7 +211,7 @@ - (void)renderNode:(MarkdownASTNode *)node NSAttributedString *text = [[NSAttributedString alloc] initWithString:child.content attributes:@{ - NSFontAttributeName: theme.baseFont + NSFontAttributeName: font }]; [output appendAttributedString:text]; } @@ -227,20 +235,21 @@ - (void)renderNode:(MarkdownASTNode *)node @implementation HeadingRenderer - (BOOL)canRender:(MarkdownASTNode *)node { return node.type == MarkdownNodeTypeHeading; } -- (void)renderNode:(MarkdownASTNode *)node - into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme +- (void)renderNode:(MarkdownASTNode *)node + into:(NSMutableAttributedString *)output + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context { - UIFont *font = [UIFont fontWithDescriptor:[theme.baseFont.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold] size:theme.baseFont.pointSize]; + UIFont *boldFont = [UIFont fontWithDescriptor:[font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold] size:font.pointSize]; for (MarkdownASTNode *child in node.children) { if (child.type == MarkdownNodeTypeText && child.content) { NSAttributedString *text = [[NSAttributedString alloc] initWithString:child.content attributes:@{ - NSFontAttributeName: font, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: boldFont, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:text]; } @@ -249,8 +258,8 @@ - (void)renderNode:(MarkdownASTNode *)node NSAttributedString *spacing = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:@{ - NSFontAttributeName: theme.baseFont, - NSForegroundColorAttributeName: theme.textColor + NSFontAttributeName: font, + NSForegroundColorAttributeName: color }]; [output appendAttributedString:spacing]; } diff --git a/ios/renderer/NodeRenderer.h b/ios/renderer/NodeRenderer.h index f53df727..9fa0e76e 100644 --- a/ios/renderer/NodeRenderer.h +++ b/ios/renderer/NodeRenderer.h @@ -1,14 +1,14 @@ #import @class MarkdownASTNode; -@class RichTextTheme; @class RenderContext; @protocol NodeRenderer - (BOOL)canRender:(MarkdownASTNode *)node; - (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output - withTheme:(RichTextTheme *)theme + withFont:(UIFont *)font + color:(UIColor *)color context:(RenderContext *)context; @end diff --git a/ios/theme/RichTextTheme.h b/ios/theme/RichTextTheme.h deleted file mode 100644 index eae94f4c..00000000 --- a/ios/theme/RichTextTheme.h +++ /dev/null @@ -1,11 +0,0 @@ -#import -#import - -@interface RichTextTheme : NSObject - -@property (nonatomic, strong) UIFont *baseFont; -@property (nonatomic, strong) UIColor *textColor; - -+ (instancetype)defaultTheme; - -@end diff --git a/ios/theme/RichTextTheme.m b/ios/theme/RichTextTheme.m deleted file mode 100644 index 290f7144..00000000 --- a/ios/theme/RichTextTheme.m +++ /dev/null @@ -1,12 +0,0 @@ -#import "RichTextTheme.h" - -@implementation RichTextTheme - -+ (instancetype)defaultTheme { - RichTextTheme *theme = [RichTextTheme new]; - theme.baseFont = [UIFont systemFontOfSize:16]; - theme.textColor = [UIColor blackColor]; - return theme; -} - -@end From ac51a8aeccc098f093974ccb00fe514fcad5caa1 Mon Sep 17 00:00:00 2001 From: Gregory Moskaliuk Date: Fri, 24 Oct 2025 16:02:21 +0200 Subject: [PATCH 3/3] refactor(ios): enhance font customization in RichTextView by adding weight and style parameters --- ios/RichTextView.mm | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/ios/RichTextView.mm b/ios/RichTextView.mm index aa09e9e5..010cedd4 100644 --- a/ios/RichTextView.mm +++ b/ios/RichTextView.mm @@ -11,6 +11,7 @@ #import "RCTFabricComponentsPlugins.h" #import +#import using namespace facebook::react; @@ -24,7 +25,7 @@ - (void)setupTextView; - (void)setupConstraints; - (void)renderMarkdownContent:(NSString *)markdownString withProps:(const RichTextViewProps &)props; - (void)textTapped:(UITapGestureRecognizer *)recognizer; -- (UIFont *)createFontWithFamily:(NSString *)fontFamily size:(CGFloat)size; +- (UIFont *)createFontWithFamily:(NSString *)fontFamily size:(CGFloat)size weight:(NSString *)weight style:(NSString *)style; @end @implementation RichTextView { @@ -102,9 +103,10 @@ - (void)renderMarkdownContent:(NSString *)markdownString withProps:(const RichTe CGFloat fontSize = props.fontSize > 0 ? props.fontSize : kDefaultFontSize; - // Create font with family and size NSString *fontFamily = [[NSString alloc] initWithUTF8String:props.fontFamily.c_str()]; - UIFont *font = [self createFontWithFamily:fontFamily size:fontSize]; + NSString *fontWeight = [[NSString alloc] initWithUTF8String:props.fontWeight.c_str()]; + NSString *fontStyle = [[NSString alloc] initWithUTF8String:props.fontStyle.c_str()]; + UIFont *font = [self createFontWithFamily:fontFamily size:fontSize weight:fontWeight style:fontStyle]; // Get color from props or use textView's current color UIColor *color = _textView.textColor ?: [UIColor blackColor]; @@ -152,10 +154,12 @@ - (void)updateProps:(Props::Shared const &)props needsRerender = YES; } - if (oldViewProps.fontSize != newViewProps.fontSize || oldViewProps.fontFamily != newViewProps.fontFamily) { + if (oldViewProps.fontSize != newViewProps.fontSize || oldViewProps.fontFamily != newViewProps.fontFamily || oldViewProps.fontWeight != newViewProps.fontWeight || oldViewProps.fontStyle != newViewProps.fontStyle) { CGFloat fontSize = newViewProps.fontSize > 0 ? newViewProps.fontSize : kDefaultFontSize; NSString *fontFamily = [[NSString alloc] initWithUTF8String:newViewProps.fontFamily.c_str()]; - _textView.font = [self createFontWithFamily:fontFamily size:fontSize]; + NSString *fontWeight = [[NSString alloc] initWithUTF8String:newViewProps.fontWeight.c_str()]; + NSString *fontStyle = [[NSString alloc] initWithUTF8String:newViewProps.fontStyle.c_str()]; + _textView.font = [self createFontWithFamily:fontFamily size:fontSize weight:fontWeight style:fontStyle]; needsRerender = YES; } @@ -252,15 +256,23 @@ - (void)textTapped:(UITapGestureRecognizer *)recognizer { // MARK: - Helper methods -- (UIFont *)createFontWithFamily:(NSString *)fontFamily size:(CGFloat)size { - if (fontFamily && fontFamily.length > 0) { - UIFont *customFont = [UIFont fontWithName:fontFamily size:size]; - if (customFont) { - return customFont; - } +- (UIFont *)createFontWithFamily:(NSString *)fontFamily size:(CGFloat)size weight:(NSString *)weight style:(NSString *)style { + // Use React Native's RCTFont.updateFont for consistent font handling + NSString *fontWeight = weight && weight.length > 0 ? weight : nullptr; + NSString *fontStyle = style && style.length > 0 ? style : nullptr; + + // Handle edge case: weight "0" should be treated as nullptr + if ([fontWeight isEqualToString:@"0"]) { + fontWeight = nullptr; } - return [UIFont systemFontOfSize:size]; + return [RCTFont updateFont:nullptr + withFamily:fontFamily + size:@(size) + weight:fontWeight + style:fontStyle + variant:nullptr + scaleMultiplier:1]; } @end