mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Improve correctness of textTransform: capitalize (#47219)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47219 We received reports that textTransform does not correctly match the web behaviour for capitalize, eg. capitalized characters should not be lowercased when using `capitalize`. Example input: 'hello WORLD', should become 'Hello WORLD'. Changelog: [General][Fixed] TextTransform: capitalize better reflects the web behaviour Reviewed By: NickGerleman Differential Revision: D65023821 fbshipit-source-id: 8ba5fdbd7afb1460193bf82a2f4021c3aff2110a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
33e1ae13f8
commit
dc2000c875
@@ -9,8 +9,7 @@
|
||||
|
||||
#import <React/RCTDynamicTypeRamp.h>
|
||||
#import <React/RCTTextDecorationLineType.h>
|
||||
|
||||
#import "RCTTextTransform.h"
|
||||
#import <React/RCTTextTransform.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -278,19 +278,15 @@ NSString *const RCTTextAttributesTagAttributeName = @"RCTTextAttributesTagAttrib
|
||||
|
||||
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:@" "];
|
||||
NSMutableString *result = [[NSMutableString alloc] initWithString:text];
|
||||
[result
|
||||
enumerateSubstringsInRange:NSMakeRange(0, text.length)
|
||||
options:NSStringEnumerationByWords
|
||||
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
|
||||
[result replaceCharactersInRange:NSMakeRange(substringRange.location, 1)
|
||||
withString:[[substring substringToIndex:1] uppercaseString]];
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *)applyTextAttributesToText:(NSString *)text
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <React/RCTTextAttributes.h>
|
||||
|
||||
@interface RCTTextAttributesTest : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTextAttributesTest
|
||||
|
||||
- (void)testCapitalize
|
||||
{
|
||||
RCTTextAttributes *attrs = [RCTTextAttributes new];
|
||||
attrs.textTransform = RCTTextTransformCapitalize;
|
||||
|
||||
NSString *input = @"hello WORLD from ReAcT nAtIvE 2a !b c";
|
||||
NSString *output = @"Hello WORLD From ReAcT NAtIvE 2a !B C";
|
||||
XCTAssertEqualObjects([attrs applyTextAttributesToText:input], output);
|
||||
}
|
||||
|
||||
- (void)testUppercase
|
||||
{
|
||||
RCTTextAttributes *attrs = [RCTTextAttributes new];
|
||||
attrs.textTransform = RCTTextTransformUppercase;
|
||||
|
||||
NSString *input = @"hello WORLD from ReAcT nAtIvE 2a !b c";
|
||||
NSString *output = @"HELLO WORLD FROM REACT NATIVE 2A !B C";
|
||||
XCTAssertEqualObjects([attrs applyTextAttributesToText:input], output);
|
||||
}
|
||||
|
||||
- (void)testLowercase
|
||||
{
|
||||
RCTTextAttributes *attrs = [RCTTextAttributes new];
|
||||
attrs.textTransform = RCTTextTransformLowercase;
|
||||
|
||||
NSString *input = @"hello WORLD from ReAcT nAtIvE 2a !b c";
|
||||
NSString *output = @"hello world from react native 2a !b c";
|
||||
XCTAssertEqualObjects([attrs applyTextAttributesToText:input], output);
|
||||
}
|
||||
|
||||
@end
|
||||
+2
-7
@@ -48,13 +48,8 @@ public enum TextTransform {
|
||||
StringBuilder res = new StringBuilder(text.length());
|
||||
int start = wordIterator.first();
|
||||
for (int end = wordIterator.next(); end != BreakIterator.DONE; end = wordIterator.next()) {
|
||||
String word = text.substring(start, end);
|
||||
if (Character.isLetterOrDigit(word.charAt(0))) {
|
||||
res.append(Character.toUpperCase(word.charAt(0)));
|
||||
res.append(word.substring(1).toLowerCase());
|
||||
} else {
|
||||
res.append(word);
|
||||
}
|
||||
res.append(Character.toUpperCase(text.charAt(start)));
|
||||
res.append(text.substring(start + 1, end));
|
||||
start = end;
|
||||
}
|
||||
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.text
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class TextTransformTest {
|
||||
@Test
|
||||
fun textTransformCapitalize() {
|
||||
val input = "hello WORLD from ReAcT nAtIvE 2a !b c"
|
||||
val output = "Hello WORLD From ReAcT NAtIvE 2a !B C"
|
||||
assertThat(TextTransform.apply(input, TextTransform.CAPITALIZE)).isEqualTo(output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textTransformUppercase() {
|
||||
val input = "hello WORLD from ReAcT nAtIvE 2a !b c"
|
||||
val output = "HELLO WORLD FROM REACT NATIVE 2A !B C"
|
||||
assertThat(TextTransform.apply(input, TextTransform.UPPERCASE)).isEqualTo(output)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textTransformLowercase() {
|
||||
val input = "hello WORLD from ReAcT nAtIvE 2a !b c"
|
||||
val output = "hello world from react native 2a !b c"
|
||||
assertThat(TextTransform.apply(input, TextTransform.LOWERCASE)).isEqualTo(output)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user