diff --git a/.changeset/serious-weeks-jam.md b/.changeset/serious-weeks-jam.md new file mode 100644 index 0000000..f151d70 --- /dev/null +++ b/.changeset/serious-weeks-jam.md @@ -0,0 +1,5 @@ +--- +'@xstools/utility': minor +--- + +add string/substring diff --git a/packages/utility/src/string/index.ts b/packages/utility/src/string/index.ts index 1dd2fd3..73d6140 100644 --- a/packages/utility/src/string/index.ts +++ b/packages/utility/src/string/index.ts @@ -1,4 +1,5 @@ export * from './case'; export * from './getWords'; +export * from './substring'; export * from './template'; export * from './trim'; diff --git a/packages/utility/src/string/substring.spec.ts b/packages/utility/src/string/substring.spec.ts new file mode 100644 index 0000000..8c95b94 --- /dev/null +++ b/packages/utility/src/string/substring.spec.ts @@ -0,0 +1,40 @@ +import { describe, expect, test } from 'bun:test'; +import { substring } from './substring'; + +describe('substring', () => { + test('normal usage', () => { + expect(substring('123', 2)).toBe('12'); + expect(substring('123', 10)).toBe('123'); + + expect(substring('今天很开心🌸🌸🌸', 6)).toBe('今天很开心🌸'); + expect('今天很开心🌸🌸🌸'.substring(0, 6)).toBe('今天很开心\ud83c'); + }); + + test('unicode support', () => { + expect(substring('𝒽𝑒𝓁𝓁𝑜 𝓌𝑜𝓇𝓁𝒹', 1)).toBe('𝒽'); + expect('𝒽𝑒𝓁𝓁𝑜 𝓌𝑜𝓇𝓁𝒹'.substring(0, 2)).toBe('𝒽'); + + expect(substring('🐶狗', 1)).toBe('🐶'); + expect('🐶狗'.substring(0, 2)).toBe('🐶'); + + expect(substring('狗狗', 1)).toBe('狗'); + expect('狗狗'.substring(0, 1)).toBe('狗'); + + // https://juejin.cn/post/7070079762429034526 + expect(substring('🐕‍🦺狗', 1)).toBe('🐕'); + expect('🐕‍🦺狗'.substring(0, 2)).toBe('🐕'); + }); + + test('empty', () => { + expect(substring('xxx', 0)).toBe(''); + expect(substring('', 0)).toBe(''); + expect(substring('', 10)).toBe(''); + + // @ts-expect-error + expect(substring({}, 10)).toBe(''); + // @ts-expect-error + expect(substring(1, 10)).toBe(''); + // @ts-expect-error + expect(substring([1], 10)).toBe(''); + }); +}); diff --git a/packages/utility/src/string/substring.ts b/packages/utility/src/string/substring.ts new file mode 100644 index 0000000..911aca6 --- /dev/null +++ b/packages/utility/src/string/substring.ts @@ -0,0 +1,21 @@ +/** + * Returns the part of this string by length. + * + * @example + * substring('123', 2) // => '12' + * substring('123', 10) // => '123' + * substring('今天很开心🌸🌸🌸', 6) // => '今天很开心🌸' + * + * --- WHY NOT NATIVE --- + * '今天很开心🌸🌸🌸'.substring(0, 6) // => '今天很开心\ud83c' + * '今天很开心🌸🌸🌸'.substring(0, 7) // => '今天很开心🌸' + */ +export const substring = (s: string, length: number): string => { + if (typeof s !== 'string') { + return ''; + } + + const temp = s.substring(0, length * 2); + + return [...temp].slice(0, length).join(''); +}; diff --git a/packages/utility/src/string/template.spec.ts b/packages/utility/src/string/template.spec.ts index 9b94bbc..2bffd2a 100644 --- a/packages/utility/src/string/template.spec.ts +++ b/packages/utility/src/string/template.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from 'bun:test'; import { template } from './template'; describe('template', () => { - test('template', () => { + test('normal usage', () => { expect(template('hello, {{name}}', { name: 'world' })).toBe('hello, world'); expect(template('hello, {{ name \n}}', { name: 'world' })).toBe('hello, world'); expect(template('hello, {{name}}', {})).toBe('hello, ');