Created
October 17, 2024 04:44
-
-
Save AndrewDongminYoo/759c2665cf25751884bea643616780e3 to your computer and use it in GitHub Desktop.
Dart extension methods for applying camelCase and snake_case to strings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extension StringExtensions on String { | |
| /// 문자열을 스네이크 케이스로 변환하는 `toSnakeCase()` 메서드를 사용하여 [String] 클래스를 확장 | |
| /// | |
| /// 스네이크 케이스는 단어는 밑줄(`_`)로 구분하고 모든 문자는 소문자로 구분하는 명명 규칙입니다. | |
| /// 이 메서드는 문자열의 문자를 반복하여 문자열의 시작 부분에 없는 대문자 앞에 밑줄을 추가하고 모든 문자를 소문자로 변환 | |
| /// | |
| /// Example: | |
| /// ```dart | |
| /// 'HelloWorld'.toSnakeCase(); // 'hello_world' | |
| /// 'XMLHTTPRequest'.toSnakeCase(); // 'xmlhttp_request' | |
| /// ``` | |
| String toSnakeCase() { | |
| // 변환된 문자열을 저장하기 위한 빈 StringBuffer | |
| final buffer = StringBuffer(); | |
| // 이전 문자가 밑줄이었는지 여부를 추적하기 위해 부울 변수 | |
| var previousUnderscore = false; | |
| // for 루프를 사용하여 입력 문자열의 각 문자를 반복 | |
| for (var i = 0; i < length; i++) { | |
| // 각 문자에 대해 해당 문자가 공백(' ')인지 하이픈('-')인지 확인 | |
| if (this[i] == ' ' || this[i] == '-') { | |
| // 이전 문자가 밑줄이 아닌 경우 버퍼에 밑줄('_')을 추가하고 previousUnderscore를 true로 설정 | |
| if (!previousUnderscore) { | |
| buffer.write('_'); | |
| previousUnderscore = true; | |
| } | |
| // 두 조건 중 하나라도 참이면 버퍼에 밑줄('_')을 추가 | |
| // - 문자가 대문자인 경우 첫 번째 문자인지 또는 이전 문자가 밑줄이었는지 | |
| // - 이전 문자가 소문자인지 또는 다음 문자가 소문자인지 | |
| } else if (this[i].toUpperCase() == this[i] && | |
| this[i].toLowerCase() != this[i]) { | |
| if (i != 0 && !previousUnderscore) { | |
| // 현재 문자가 대문자이고 이전 문자가 소문자이거나 다음 문자가 소문자인 경우 | |
| if (this[i - 1].toLowerCase() == this[i - 1] || | |
| (i + 1 < length && this[i + 1].toLowerCase() == this[i + 1])) { | |
| buffer.write('_'); | |
| } | |
| } | |
| // 밑줄 대소문자를 처리한 후 현재 문자의 소문자 버전을 버퍼에 추가하고 previousUnderscore를 false로 설정 | |
| buffer.write(this[i].toLowerCase()); | |
| previousUnderscore = false; | |
| // 문자가 공백, 하이픈, 대문자가 아닌 경우 단순히 버퍼에 해당 문자를 추가하고 previousUnderscore를 false로 설정 | |
| } else { | |
| buffer.write(this[i]); | |
| previousUnderscore = false; | |
| } | |
| } | |
| // 모든 문자를 반복한 후 toString() 메서드를 사용하여 버퍼를 문자열로 반환 | |
| return buffer.toString(); | |
| } | |
| /// 문자열을 입력으로 받아 camelCase 형식(첫 단어는 소문자로, 그 이후의 각 단어는 대문자로 시작하는 명명 규칙)으로 변환하는 함수 | |
| /// | |
| /// 이 메서드는 단어가 아닌 문자(예: 공백, 구두점 등)와 일치하는 정규식을 사용하여 입력 문자열을 단어 배열로 분할합니다. | |
| /// 그런 다음 단어를 반복하여 각 단어의 첫 글자는 대문자로, 나머지는 소문자로 변환합니다. | |
| /// 결과 문자열은 첫 번째 문자가 소문자로 반환됩니다. | |
| /// | |
| /// Example: | |
| /// | |
| /// ```dart | |
| /// 'hello_world'.toCamelCase(); // 'helloWorld' | |
| /// 'XML_HTTP_REQUEST'.toCamelCase(); // 'xmlHttpRequest' | |
| /// ``` | |
| String toCamelCase() { | |
| // 먼저 단어가 아닌 모든 문자(예: 공백, 구두점 등)와 일치하는 정규식을 사용하여 입력 문자열을 단어 배열로 분할합니다. | |
| final words = split(RegExp(r'[!@#<>?":`~;[\]\\|=+)(*&^%-\s_]+')); | |
| // 입력 문자열이 비어 있거나 결과 단어 배열이 비어 있으면 빈 문자열을 반환합니다. | |
| if (isEmpty || words.isEmpty) { | |
| return ''; | |
| } | |
| // 처리할 단어가 있는 경우 새 StringBuffer 객체를 생성하여 대/소문자 대/소문자 문자열을 만듭니다. | |
| final buffer = StringBuffer(); | |
| // 그런 다음 배열의 각 단어를 반복합니다: | |
| for (final word in words) { | |
| // 단어가 비어 있지 않으면 단어의 첫 글자를 대문자로 하고 StringBuffer에 추가한 다음 나머지 단어는 소문자로 추가합니다. | |
| if (word.isNotEmpty) { | |
| buffer.write(word[0].toUpperCase() + word.substring(1).toLowerCase()); | |
| } | |
| } | |
| // 모든 단어를 처리한 후 StringBuffer를 문자열로 변환하여 출력 변수에 저장합니다. | |
| final output = buffer.toString(); | |
| // 마지막으로 첫 번째 문자가 소문자로 된 새 문자열을 반환하고 나머지 출력 문자열을 반환합니다. | |
| return output[0].toLowerCase() + output.substring(1); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 📦 Package imports: | |
| import 'package:flutter_test/flutter_test.dart'; | |
| // 🌎 Project imports: | |
| import 'case_converter.dart'; | |
| void main() { | |
| group('StringExtensions', () { | |
| group('toSnakeCase', () { | |
| test('converts camelCase to snake_case', () { | |
| expect('camelCase'.toSnakeCase(), 'camel_case'); | |
| expect('snakeCase'.toSnakeCase(), 'snake_case'); | |
| expect('PascalCase'.toSnakeCase(), 'pascal_case'); | |
| }); | |
| test('handles leading and trailing uppercase characters', () { | |
| expect('LeadingUppercase'.toSnakeCase(), 'leading_uppercase'); | |
| expect('TrailingUppercase'.toSnakeCase(), 'trailing_uppercase'); | |
| }); | |
| test('handles consecutive uppercase characters', () { | |
| expect('HTTPRequest'.toSnakeCase(), 'http_request'); | |
| expect('XMLHTTPRequest'.toSnakeCase(), 'xmlhttp_request'); | |
| }); | |
| test('handles empty string', () { | |
| expect(''.toSnakeCase(), ''); | |
| }); | |
| test('handles string with only lowercase characters', () { | |
| expect('lowercase'.toSnakeCase(), 'lowercase'); | |
| }); | |
| test('handles string with only uppercase characters', () { | |
| expect('UPPERCASE'.toSnakeCase(), 'uppercase'); | |
| }); | |
| test('handles string with Title Case', () { | |
| expect('Awesome Title Case'.toSnakeCase(), 'awesome_title_case'); | |
| expect('MixedCaseString'.toSnakeCase(), 'mixed_case_string'); | |
| expect('mixedCaseString'.toSnakeCase(), 'mixed_case_string'); | |
| }); | |
| test('handles dash-case', () { | |
| expect('dash-is-also-good'.toSnakeCase(), 'dash_is_also_good'); | |
| expect('string--with--dashes'.toSnakeCase(), 'string_with_dashes'); | |
| }); | |
| }); | |
| test('handles string with numbers', () { | |
| expect('string123'.toSnakeCase(), 'string123'); | |
| expect('123string'.toSnakeCase(), '123string'); | |
| expect('string123String'.toSnakeCase(), 'string123_string'); | |
| }); | |
| test('handles string with special characters', () { | |
| expect(r'string@#$%'.toSnakeCase(), r'string@#$%'); | |
| expect(r'@#$%string'.toSnakeCase(), r'@#$%string'); | |
| expect(r'string@#$%String'.toSnakeCase(), r'string@#$%_string'); | |
| }); | |
| test('handles string with consecutive spaces', () { | |
| expect('string with spaces'.toSnakeCase(), 'string_with_spaces'); | |
| }); | |
| test('handles string with leading and trailing spaces', () { | |
| expect(' leadingSpace '.toSnakeCase(), '_leading_space_'); | |
| expect(' leadingSpace'.toSnakeCase(), '_leading_space'); | |
| expect('trailingSpace '.toSnakeCase(), 'trailing_space_'); | |
| }); | |
| test('handles string with leading and trailing dashes', () { | |
| expect('-leadingDash-'.toSnakeCase(), '_leading_dash_'); | |
| expect('-leadingDash'.toSnakeCase(), '_leading_dash'); | |
| expect('trailingDash-'.toSnakeCase(), 'trailing_dash_'); | |
| }); | |
| }); | |
| group('toCamelCase', () { | |
| test('converts snake_case to camelCase', () { | |
| expect('snake_case'.toCamelCase(), 'snakeCase'); | |
| expect( | |
| 'snake_case_with_multiple_words'.toCamelCase(), | |
| 'snakeCaseWithMultipleWords', | |
| ); | |
| }); | |
| test('converts kebab-case to camelCase', () { | |
| expect('kebab-case'.toCamelCase(), 'kebabCase'); | |
| expect( | |
| 'kebab-case-with-multiple-words'.toCamelCase(), | |
| 'kebabCaseWithMultipleWords', | |
| ); | |
| }); | |
| test('converts space-separated words to camelCase', () { | |
| expect('space separated words'.toCamelCase(), 'spaceSeparatedWords'); | |
| expect( | |
| 'multiple space separated words'.toCamelCase(), | |
| 'multipleSpaceSeparatedWords', | |
| ); | |
| }); | |
| test('handles leading and trailing underscores', () { | |
| expect('_leading_underscore'.toCamelCase(), 'leadingUnderscore'); | |
| expect('trailing_underscore_'.toCamelCase(), 'trailingUnderscore'); | |
| }); | |
| test('handles leading and trailing hyphens', () { | |
| expect('-leading-hyphen'.toCamelCase(), 'leadingHyphen'); | |
| expect('trailing-hyphen-'.toCamelCase(), 'trailingHyphen'); | |
| }); | |
| test('handles leading and trailing spaces', () { | |
| expect(' leading space'.toCamelCase(), 'leadingSpace'); | |
| expect('trailing space '.toCamelCase(), 'trailingSpace'); | |
| }); | |
| test('handles consecutive separators', () { | |
| expect('snake__case'.toCamelCase(), 'snakeCase'); | |
| expect('kebab--case'.toCamelCase(), 'kebabCase'); | |
| expect('space separated words'.toCamelCase(), 'spaceSeparatedWords'); | |
| }); | |
| test('handles mixed separators', () { | |
| expect('snake_kebab-case'.toCamelCase(), 'snakeKebabCase'); | |
| expect('kebab-snake_case'.toCamelCase(), 'kebabSnakeCase'); | |
| expect( | |
| 'space separated_kebab-case'.toCamelCase(), | |
| 'spaceSeparatedKebabCase', | |
| ); | |
| }); | |
| test('handles empty string', () { | |
| expect(''.toCamelCase(), ''); | |
| }); | |
| test('handles string with only uppercase characters', () { | |
| expect('UPPERCASE'.toCamelCase(), 'uppercase'); | |
| }); | |
| test('handles string with only lowercase characters', () { | |
| expect('lowercase'.toCamelCase(), 'lowercase'); | |
| }); | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment