import { matches } from '../dom' ; const PROTOCOLS = [ 'ftp://' , 'http://' , 'https://' , 'xmpp:' , 'tel:' , 'callto:' ] ; const ALL_PROTOCOLS = PROTOCOLS . concat ( [ 'mailto:' ] ) ; const MAP = PROTOCOLS . reduce < { [ key ] : boolean ; } > ( ( acc , key ) => { acc [ key ] = true ; return acc ; } , { } ) ; const EXCLUDE_ANCHORS = ':not([href=""]):not([href^="#"])' ; const getNormalizedHref = ( link ) => { return ( link . getAttribute ( 'href' ) || '' ) . trim ( ) . toLowerCase ( ) ; } ; const linkUsesProtocols = ( link ) => ALL_PROTOCOLS . some ( ( proto ) => getNormalizedHref ( link ) . startsWith ( proto ) ) ; const isEmptyAnchor = ( link ) => { const href = getNormalizedHref ( link ) ; return href === '' || MAP [ href ] ; } ; const noReferrerInfo = ( link ) => { link . setAttribute ( 'rel' , 'noreferrer nofollow noopener' ) ; } ; /**
 * make links open in a new tab
 */ const httpInNewTab = ( link ) => { if ( matches ( link , EXCLUDE_ANCHORS ) ) { const href = link . getAttribute ( 'href' ) || '' ; const hasHTTP = href . indexOf ( 'http' ) === 0 ; const isRelative = href . indexOf ( '/' ) === 0 ; if ( hasHTTP || isRelative ) { link . setAttribute ( 'target' , '_blank' ) ; } } } ; /**
 * turn these relative links into absolute links
 * (example.com/a -> http://example.com)
 */ const sanitizeRelativeHttpLinks = ( link ) => { if ( matches ( link , EXCLUDE_ANCHORS ) && ! linkUsesProtocols ( link ) && link . nodeName === 'A' ) { const url = link . getAttribute ( 'href' ) ; link . setAttribute ( 'href' , `http://${ url }` ) ; } } ; const disableAnchors = ( link ) => { if ( isEmptyAnchor ( link ) ) { link . style . pointerEvents = 'none' ; } } ; export const transformLinks = ( document ) => { const links = [ ... document . querySelectorAll ( '[href]' ) ] as HTMLLinkElement [ ] ; links . forEach ( ( link ) => { httpInNewTab ( link ) ; noReferrerInfo ( link ) ; sanitizeRelativeHttpLinks ( link ) ; disableAnchors ( link ) ; } ) ; } ;