All files / src/lib initials.ts

100% Statements 6/6
100% Branches 4/4
100% Functions 1/1
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26                                  14x 11x 22x 9x     2x    
/**
 * Monogram extraction for avatar circles and image placeholders.
 *
 * Scans for the first LETTER OR DIGIT rather than taking `charAt(0)`, so a
 * name that opens with punctuation renders a real initial instead of the
 * punctuation itself — e.g. "[E2E] Second Test Interiors" yields "E", not "[".
 * Business names routinely start with quotes, brackets, "&" or "@".
 *
 * Iterates with `Array.from` so surrogate pairs (emoji, some scripts) count as
 * one character and never get sliced in half.
 *
 * Note: this deliberately SKIPS a leading emoji to reach the first real
 * letter. `HomeownerAvatar.astro` has its own extractor that intentionally
 * keeps a leading emoji as the initial — don't consolidate the two without
 * deciding which behaviour is wanted there.
 */
export function getMonogram(raw: string | null | undefined): string {
	if (!raw) return "?";
	for (const char of Array.from(raw)) {
		if (/[\p{L}\p{N}]/u.test(char)) {
			return char.toUpperCase();
		}
	}
	return "?";
}