From 8b5a5d4645136ef3d6ee043348e583cbbac87ee3 Mon Sep 17 00:00:00 2001 From: MaeIg Date: Tue, 25 Jan 2022 09:06:55 -0800 Subject: [PATCH] Fix capitalize Text style on IOS (#32774) Summary: On my project, I realized that capitalize style doesn't work with dates on IOS. I found [this issue](https://github.com/facebook/react-native/issues/32697) and tried to solve it. (code example: https://snack.expo.dev/maelg/capitalize-demo) | Android | IOS | Web | | ------------- | ------------- | ------------- | | ![image](https://user-images.githubusercontent.com/40902940/146158714-c658a83e-d8f3-41c9-92c8-4fc1f722f942.png) | ![image](https://user-images.githubusercontent.com/40902940/146159059-3cec1f7b-9bc7-4060-8164-79c47694b86b.png) | ![image](https://user-images.githubusercontent.com/40902940/146158095-0f94f25f-f245-4e45-9191-73520a0f6568.png) | As we can see, the behavior is different on IOS, Android and web: - **Android**: Capitalize the first letter of each word, unless it begins with a number. And put the rest in lowercase. - **IOS**: Capitalize the first letter of each word, ~~unless it begins with a number~~. And put the rest in lowercase. - **Web**: Capitalize the first letter of each word, unless it begins with a number. ~~And put the rest in lowercase.~~ This PR aims to unify behavior on Android and Ios. I am not changing the behavior which differs from the web because I don't know if it is desirable to align with the web. ## Changelog [IOS] [Changed] - Don't capitalize the first letter of a word that is starting by a number Pull Request resolved: https://github.com/facebook/react-native/pull/32774 Test Plan: I manually tested my changes on a POC app (same code: https://snack.expo.dev/maelg/capitalize-demo) on react-native v0.66.4 and react-native main branch. You can see the result here: | Android | IOS | | ------------- | ------------- | | ![image](https://user-images.githubusercontent.com/40902940/146191361-e2de26d1-3915-47dc-8707-480504af24d6.png) | ![image](https://user-images.githubusercontent.com/40902940/146161660-c869202a-104e-4d16-8f5e-db1c72b2ea5e.png) | ~~I tried to use rn-tester but it was not taking my code. I think it is because fabric was enabled so it was using other code. I tried to disable fabric but I was not able to build the app on my IOS simulator anymore:~~ On rn-tester: Reviewed By: philIip Differential Revision: D33165963 Pulled By: yungsters fbshipit-source-id: c3bf32bf33d2f109a119798eefdbb9077e904252 --- Libraries/Text/RCTTextAttributes.m | 19 ++++++++++++++++++- .../js/examples/Text/TextExample.android.js | 12 ++++++++++++ .../js/examples/Text/TextExample.ios.js | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Libraries/Text/RCTTextAttributes.m b/Libraries/Text/RCTTextAttributes.m index a66386885b4..01131cfb20e 100644 --- a/Libraries/Text/RCTTextAttributes.m +++ b/Libraries/Text/RCTTextAttributes.m @@ -237,6 +237,23 @@ NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttrib return effectiveBackgroundColor ?: [UIColor clearColor]; } +static NSString *capitalizeText(NSString *text) +{ + NSArray *words = [text componentsSeparatedByString:@" "]; + NSMutableArray *newWords = [NSMutableArray new]; + NSNumberFormatter *num = [NSNumberFormatter new]; + for (NSString *item in words) { + NSString *word; + if ([item length] > 0 && [num numberFromString:[item substringWithRange:NSMakeRange(0, 1)]] == nil) { + word = [item capitalizedString]; + } else { + word = [item lowercaseString]; + } + [newWords addObject:word]; + } + return [newWords componentsJoinedByString:@" "]; +} + - (NSString *)applyTextAttributesToText:(NSString *)text { switch (_textTransform) { @@ -248,7 +265,7 @@ NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttrib case RCTTextTransformUppercase: return [text uppercaseString]; case RCTTextTransformCapitalize: - return [text capitalizedString]; + return capitalizeText(text); } } diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js index 2efb193a634..f1f15a242fe 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.android.js +++ b/packages/rn-tester/js/examples/Text/TextExample.android.js @@ -798,6 +798,18 @@ class TextExample extends React.Component<{...}> { This text should be CAPITALIZED. + + Capitalize a date: + + the 9th of november, 1998 + + + + Capitalize a 2 digit date: + + the 25th of december + + Mixed: uppercase LoWeRcAsE diff --git a/packages/rn-tester/js/examples/Text/TextExample.ios.js b/packages/rn-tester/js/examples/Text/TextExample.ios.js index 623900fc9d9..b6272d55931 100644 --- a/packages/rn-tester/js/examples/Text/TextExample.ios.js +++ b/packages/rn-tester/js/examples/Text/TextExample.ios.js @@ -1160,6 +1160,18 @@ exports.examples = [ This text should be CAPITALIZED. + + Capitalize a date: + + the 9th of november, 1998 + + + + Capitalize a 2 digit date: + + the 25th of december + + Mixed: uppercase LoWeRcAsE