first-character.ts 781 B

1234567891011121314151617181920212223242526
  1. export default function firstCharacter(str: string): string {
  2. if (!str) {
  3. return ''
  4. }
  5. if (Intl?.Segmenter) {
  6. try {
  7. const segmenter = new Intl.Segmenter(undefined, {
  8. granularity: 'grapheme',
  9. })
  10. // eslint-disable-next-line no-unreachable-loop
  11. for (const { segment } of segmenter.segment(str)) {
  12. return segment
  13. }
  14. } catch {
  15. // Fall back to the code point approach below.
  16. }
  17. }
  18. // NOTE: .charAt(0), [0], and .substring(0, 1) will all split multi-byte
  19. // characters (e.g. emojis) into multiple characters, but the spread operator
  20. // will keep them mostly intact. This still isn't perfect, so the grapheme
  21. // segmenter above is preferred when available.
  22. const [first] = [...str]
  23. return first ?? ''
  24. }