module import tc from '@spaceavocado/type-check' ; param { string } s param { string } prefix return { boolean } export function hasPrefix ( s , prefix ) { if ( prefix . length == 0 || s . length == 0 ) { return false ; } if ( prefix . length <= s . length ) { if ( s . slice ( 0 , prefix . length ) == prefix ) { return true ; } } return false ; } param { string } s param { string } suffix return { boolean } export function hasSuffix ( s , suffix ) { if ( suffix . length == 0 || s . length == 0 ) { return false ; } if ( suffix . length <= s . length ) { if ( s . slice ( - 1 * suffix . length ) == suffix ) { return true ; } } return false ; } param { string } s param { string } prefix return { string } export function trimPrefix ( s , prefix ) { if ( prefix . length > 0 && hasPrefix ( s , prefix ) ) { return s . substr ( prefix . length ) ; } return s ; } param { string } a param { string } b return { string } export function joinPath ( a , b ) { const aSlash = hasSuffix ( a , '/' ) ; const bSlash = hasPrefix ( b , '/' ) ; if ( aSlash && bSlash ) { return a + b . slice ( 1 ) ; } if ( ! aSlash && ! bSlash ) { return a + '/' + b ; } return a + b ; } param { string } a param { string } b throws return { boolean } export function urlMatch ( a , b ) { let sections = a . split ( '?' ) ; if ( sections . length > 2 ) { throw new Error ( 'invalid URL' ) ; } a = sections [ 0 ] ; sections = b . split ( '?' ) ; if ( sections . length > 2 ) { throw new Error ( 'invalid URL' ) ; } b = sections [ 0 ] ; if ( hasPrefix ( a , '/' ) == false ) { a = `/${ a }` ; } if ( hasSuffix ( a , '/' ) == false ) { a = `${ a }/` ; } if ( hasPrefix ( b , '/' ) == false ) { b = `/${ b }` ; } if ( hasSuffix ( b , '/' ) == false ) { b = `${ b }/` ; } return a == b ; } param { string } haystack param { string } prefix throws return { boolean } export function urlPrefix ( haystack , prefix ) { if ( haystack . length == 0 || prefix . length == 0 ) { return false ; } if ( hasPrefix ( haystack , '/' ) == false ) { haystack = `/${ haystack }` ; } if ( hasPrefix ( prefix , '/' ) == false ) { prefix = `/${ prefix }` ; } return hasPrefix ( haystack , prefix ) ; } /**
 * Parsed URL object.
 */ interface ParsedURL { /** URL base path without query or hash */ base : string ; /** Query params */ query : { [ k ] : string ; } ; /** Hash string */ hash : string ; } param { string } path throws return { ParsedURL } export function parseURL ( path ) { let hash = '' ; let sections = path . split ( '#' ) ; if ( sections . length > 2 ) { throw new Error ( 'invalid URL' ) ; } else if ( sections . length == 2 ) { path = sections [ 0 ] ; hash = sections [ 1 ] ; } sections = path . split ( '?' ) ; if ( sections . length > 2 ) { throw new Error ( 'invalid URL' ) ; } const result = { base : sections [ 0 ] , query : { } , hash : hash , } ; if ( sections . length == 2 ) { const entries = sections [ 1 ] . split ( '&' ) ; for ( const entry of entries ) { const keyValue = entry . split ( '=' ) ; result . query [ keyValue [ 0 ] ] = keyValue [ 1 ] ; } } return result ; } param { string } path param { object ? } query param { string } hash return { string } export function fullURL ( path , query , hash ) { let queryPath = '' ; if ( tc . not . isNullOrUndefined ( query ) ) { for ( const key in query ) { if ( query . hasOwnProperty ( key ) ) { if ( queryPath . length > 0 ) { queryPath += '&' ; } queryPath += `${ key }=${ query [ key ] }` ; } } if ( queryPath . length > 0 ) { path = `${ path }?${ queryPath }` ; } } if ( hash . length > 0 ) { path = `${ path }#${ hash }` ; } return path ; } /**
 * History location object
 */ export interface HistoryLocation { /** A unique string representing this location. */ key : string ; /** The path of the URL. */ pathname : string ; /** The URL query string. */ search : string ; /** The URL hash fragment. */ hash : string ; /** Extra state for this location. */ state : string ; } param { HistoryLocation } location return { string } export function historyFullURL ( location ) { return `${ location . pathname }${ location . search }${ location . hash }` ; } param { string } s return { boolean } export function isWholeNumber ( s ) { return s . match ( /^0$|^[1-9]\d*$/ ) !== null ; } param { string } s return { boolean } export function isFloatNumber ( s ) { return s . match ( /^\d*\.\d*$/ ) !== null ; } param { object } o return { object } export function deepClone ( o ) { if ( tc . isNullOrUndefined ( o ) || tc . not . isObject ( o ) ) { return { } ; } return JSON . parse ( JSON . stringify ( o ) ) ; }