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