/** * Internal dependencies */ import type { ParamValue } from '../types'; export const REFERRER_PARAM = 'nab_referrer'; export function buildUrl( url: string, args: Record< string, ParamValue | undefined > = {}, hash?: string ): string { const keys = Object.keys( args ); if ( keys.length ) { url += '?' + keys .filter( ( k ) => undefined !== args[ k ] ) .map( ( key ) => `${ key }=${ encodeURIComponent( args[ key ] ?? '' ) }` ) .map( ( arg ) => /=$/.test( arg ) ? arg.slice( 0, -1 ) : arg ) .reduce( ( search, pair ) => `${ search }&${ pair }` ); } if ( hash ) { url += '#' + hash; } return url; } export function removeArgsAndHash( url: string ): string { const { cleanUrl } = fragments( url ); return cleanUrl; } export function getHash( url: string ): string { const { hash } = fragments( url ); return hash; } export function addQueryArgs( url: string, args?: Record< string, ParamValue | undefined > ): string { args = args ?? {}; const { cleanUrl, hash } = fragments( url ); const oldArgs = getQueryArgs( url ); const newArgs = { ...( 'nab' in args || 'nab' in oldArgs ? { nab: '' } : {} ), ...oldArgs, ...args, }; return buildUrl( cleanUrl, newArgs, hash ); } export function addNabQueryArg( url: string, value: number, position: 'first' | 'last' ): string { const { cleanUrl, hash } = fragments( url ); const { nab: _, ...args } = getQueryArgs( url ); const nab = value; const newArgs = { ...( 'first' === position ? { nab } : {} ), ...args, ...( 'last' === position ? { nab } : {} ), }; return buildUrl( cleanUrl, newArgs, hash ); } export function removeQueryArgs( url: string, ...names: ReadonlyArray< string > ): string { url = url || ''; if ( 0 === names.length ) { return url; } const { cleanUrl, hash } = fragments( url ); const args = getQueryArgs( url ); for ( const key of names ) { delete args[ key ]; } return buildUrl( cleanUrl, args, hash ); } export const removeTestingArgs = ( url: string, keepNab = false ): string => removeQueryArgs( url, keepNab ? '' : 'nab', 'nabforce', 'nabstaging', 'nablog', 'nab_experiments_with_page_view', REFERRER_PARAM ); export function getQueryArg( url: string, name: string ): string | undefined { return getQueryArgs( url )[ name ]; } export function getQueryArgs( url: string ): Record< string, string > { const { search } = fragments( url ); if ( ! search ) { return {}; } const args = search.split( '&' ); return args.reduce( ( res, arg ) => { const [ key, value = '' ] = arg.split( '=' ); if ( key ) { res[ key ] = decodeURIComponent( value ); } return res; }, {} as Record< string, string > ); } // ======= // HELPERS // ======= function fragments( url: string ) { const baseUrl = 0 <= url.indexOf( '#' ) ? url.substr( 0, url.indexOf( '#' ) ) : url; const hash = 0 <= url.indexOf( '#' ) ? url.substr( url.indexOf( '#' ) + 1 ) : ''; const cleanUrl = 0 <= baseUrl.indexOf( '?' ) ? baseUrl.substr( 0, baseUrl.indexOf( '?' ) ) : baseUrl; const search = 0 <= baseUrl.indexOf( '?' ) ? baseUrl.substr( baseUrl.indexOf( '?' ) + 1 ) : ''; return { cleanUrl, search, hash, }; }