Back

100% Statements 10/10
66.66% Branches 4/6
100% Functions 3/3
100% Lines 9/9

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 27 28 29 30 31 32 33 34 35 36 37 38 39 40  4x                   4x                 4x 52x                 8x 8x 6x 6x       2x    
// Order matters: Edge and Opera also claim Chrome, and Chrome also claims Safari.
const BROWSERS: [ RegExp, string ][] = [
	[ /\bEdg(e|A|iOS)?\//, 'Edge' ],
	[ /\bOPR\//, 'Opera' ],
	[ /\b(Firefox|FxiOS)\//, 'Firefox' ],
	[ /\bHeadlessChrome\//, 'Headless Chrome' ],
	[ /\b(Chrome|CriOS)\//, 'Chrome' ],
	[ /\bVersion\/[\d.]+.*\bSafari\//, 'Safari' ],
];
 
// iOS before macOS: iPhone user agents say "like Mac OS X".
const SYSTEMS: [ RegExp, string ][] = [
	[ /\b(iPhone|iPad|iPod)\b/, 'iOS' ],
	[ /\bAndroid\b/, 'Android' ],
	[ /\bWindows\b/, 'Windows' ],
	[ /\b(Macintosh|Mac OS X)\b/, 'macOS' ],
	[ /\bCrOS\b/, 'ChromeOS' ],
	[ /\bLinux\b/, 'Linux' ],
];
 
const find = ( list: [ RegExp, string ][], userAgent: string ) =>
	list.find( ( [ pattern ] ) => pattern.test( userAgent ) )?.[ 1 ];
 
/**
 * A short name for the client behind a user agent, such as "Firefox · macOS" or "curl".
 *
 * @param userAgent - The User-Agent header.
 * @return The browser and system, or the product name for other clients.
 */
export function summarizeUserAgent( userAgent: string ): string {
	const browser = find( BROWSERS, userAgent );
	if ( browser ) {
		const system = find( SYSTEMS, userAgent );
		return system ? `${ browser } · ${ system }` : browser;
	}
 
	// Scripts and bots: "curl/8.14.1" → "curl".
	return userAgent.split( /[\s/;(]/ )[ 0 ] || userAgent;
}