import { normalize as normalizePath } from 'path' ; import url from 'url' ; import Constants from './Constants' ; import InternalConstants from './InternalConstants' ; import MetaProperty from './MetaProperty' ; private const CONTEXT_PATH_REGEXP = /(?:\/)(?:content|apps|libs|etc|etc.clientlibs|conf|mnt\/overlay)(?:\/)/ ; private const JCR_CONTENT_PATTERN = `(.+)/${ Constants . JCR_CONTENT }/(.+)` ; private const DUMMY_ORIGIN = 'http://dummy' ; private export class PathUtils { returns public static isBrowser ( ) { return typeof window !== 'undefined' ; } param location returns public static getContextPath ( location ? ) { const path = location || this . getCurrentPathname ( ) ; if ( ! path ) { return '' ; } const matches = path . match ( CONTEXT_PATH_REGEXP ) ; const index = ( matches === null ) ? - 1 : ( matches . index || - 1 ) ; const contextPath = ( index > 0 ) ? path . slice ( 0 , index ) : '' ; return contextPath ; } param path private return public static adaptPagePath ( path , rootPath ? ) { if ( ! path ) { return '' ; } const localPath = PathUtils . internalize ( path ) ; if ( ! rootPath ) { return localPath ; } const localRootModelPath = PathUtils . sanitize ( rootPath ) ; return ( localPath === localRootModelPath ) ? '' : localPath ; } param url returns public static externalize ( url ) { const contextPath = this . getContextPath ( ) ; const externalizedPath = url . startsWith ( contextPath ) ? url : `${ contextPath }${ url }` ; return externalizedPath ; } param url returns public static internalize ( url ) { if ( ! url || ( typeof url !== 'string' ) ) { return '' ; } const contextPath = this . getContextPath ( ) ; const internalizedPath = url . replace ( new RegExp ( `^${ contextPath }/` ) , '/' ) ; return internalizedPath ; } param propertyName return public static getMetaPropertyValue ( propertyName ) { let value = null ; if ( this . isBrowser ( ) ) { const meta = document . head . querySelector ( `meta[property="${ propertyName }"]` ) ; value = meta ? meta . getAttribute ( 'content' ) : null ; } return value ; } param url public static convertToModelUrl ( url ) { return url && url . replace && url . replace ( /\.htm(l)?$/ , InternalConstants . DEFAULT_MODEL_JSON_EXTENSION ) ; } /**
     * Returns the model URL as contained in the current page URL.
     */ public static getCurrentPageModelUrl ( ) { const currentPath = this . getCurrentPathname ( ) ; let url = null ; if ( currentPath ) { url = this . convertToModelUrl ( currentPath ) || null ; } return url ; } param url returns public static getModelUrl ( url ? ) { if ( url && url . replace ) { return this . convertToModelUrl ( url ) ; } const metaModelUrl = this . getMetaPropertyValue ( MetaProperty . PAGE_MODEL_ROOT_URL ) ; if ( metaModelUrl ) { return metaModelUrl ; } return this . getCurrentPageModelUrl ( ) ; } param path public static sanitize ( path ) { if ( ! path || ( typeof path !== 'string' ) ) { return null ; } let sanitizedPath = url . parse ( path , false , true ) . pathname ; if ( sanitizedPath ) { sanitizedPath = this . internalize ( sanitizedPath ) ; const selectorIndex = sanitizedPath . indexOf ( '.' ) ; if ( selectorIndex > - 1 ) { sanitizedPath = sanitizedPath . substr ( 0 , selectorIndex ) ; } sanitizedPath = normalizePath ( sanitizedPath ) ; } return sanitizedPath ; } param path param extension public static addExtension ( path , extension ) { if ( ! extension || extension . length < 1 ) { return path ; } if ( ! extension . startsWith ( '.' ) ) { extension = `.${ extension }` ; } if ( ! path || ( path . length < 1 ) || ( path . indexOf ( extension ) > - 1 ) ) { return path ; } let extensionPath = this . normalize ( path ) ; const url = new URL ( extensionPath , DUMMY_ORIGIN ) ; let resourcePath = this . sanitize ( url . pathname ) ; resourcePath = url . origin === DUMMY_ORIGIN ? resourcePath : url . origin + resourcePath ; let pathWithoutResource = this . _extractPathWithoutResource ( url . pathname ) ; pathWithoutResource = this . _replaceExtension ( pathWithoutResource , extension ) ; extensionPath = ( resourcePath + '.' + pathWithoutResource + url . search ) . replace ( /\.\./g , '.' ) ; return extensionPath ; } param path private static _extractPathWithoutResource ( path ) { const slingElements = path . split ( '.' ) ; slingElements . shift ( ) ; return slingElements . join ( '.' ) ; } param pathWithoutResource param extension private static _replaceExtension ( pathWithoutResource , extension ) { if ( pathWithoutResource . length < 1 ) return extension ; const slingElementsWithoutResource = pathWithoutResource . split ( '/' ) ; const selectors = slingElementsWithoutResource [ 0 ] . split ( '.' ) ; let currentExtension = selectors . pop ( ) ; currentExtension = currentExtension ? currentExtension . replace ( /htm(l)?/ , '' ) : '' ; let path = selectors . join ( '.' ) + '.' + currentExtension + extension ; slingElementsWithoutResource . shift ( ) ; if ( slingElementsWithoutResource . length > 0 ) { path += slingElementsWithoutResource . join ( '/' ) ; } return path ; } param path param selector public static addSelector ( path , selector ) { if ( ! selector || ( selector . length < 1 ) ) { return path ; } if ( ! selector . startsWith ( '.' ) ) { selector = `.${ selector }` ; } if ( ! path || ( path . length < 1 ) || ( path . indexOf ( selector ) > - 1 ) ) { return path ; } const index = path . indexOf ( '.' ) || path . length ; if ( index < 0 ) { return path + selector ; } return path . slice ( 0 , index ) + selector + path . slice ( index , path . length ) ; } /**
     * Returns the current location as a string.
     */ public static getCurrentPathname ( ) { return this . isBrowser ( ) ? window . location . pathname : null ; } returns public static getCurrentURL ( ) { return this . isBrowser ( ) ? window . location . href : '' ; } param eventName param options public static dispatchGlobalCustomEvent ( eventName , options ) { if ( this . isBrowser ( ) ) { window . dispatchEvent ( new CustomEvent ( eventName , options ) ) ; } } /**
     * Joins given path segments into a string using slash.
     */ public static join ( paths ? ) { return paths ? this . normalize ( paths . filter ( ( path ) => path ) . join ( '/' ) ) : '' ; } /**
     * Normalizes given path by replacing repeated slash with a single one.
     */ public static normalize ( path ? ) { const normalizedPath = path ? path . replace ( /\/+/g , '/' ) : '' ; return normalizedPath ; } /**
     * Returns path that starts with slash.
     */ public static makeAbsolute ( path ? ) { if ( ! path || ( typeof path !== 'string' ) ) { return '' ; } return path . startsWith ( '/' ) ? path : `/${ path }` ; } /**
     * Returns path without the leading slash.
     */ public static makeRelative ( path ? ) { if ( ! path || ( typeof path !== 'string' ) ) { return '' ; } return path . startsWith ( '/' ) ? path . slice ( 1 ) : path ; } /**
     * Returns path to the direct parent.
     */ public static getParentNodePath ( path ) { if ( path && ( path . length > 0 ) ) { const splashIndex = path . lastIndexOf ( '/' ) + 1 ; if ( splashIndex < path . length ) { return path . substring ( 0 , splashIndex - 1 ) ; } } return null ; } /**
     * Checks if given path is an JCR path.
     */ public static isItem ( path ) { return new RegExp ( JCR_CONTENT_PATTERN ) . test ( path ) ; } /**
     * Returns the name of the last node of the given path.
     */ public static getNodeName ( path ) { const chunks = ( typeof path === 'string' ) ? path . replace ( /\/+/g , '/' ) . split ( /\// ) . filter ( Boolean ) : [ ] ; const result = chunks . pop ( ) || null ; return result ; } /**
     * Returns the subpath of the targetPath relative to the rootPath,
     * or the targetPath if the rootPath is not a root of the targetPath.
     */ public static subpath ( targetPath ? , rootPath ? ) { if ( ! targetPath ) { return '' ; } const targetPathChildren = PathUtils . makeRelative ( targetPath ) . split ( '/' ) ; const rootPathChildren = PathUtils . makeRelative ( rootPath ) . split ( '/' ) ; if ( targetPathChildren . length < rootPathChildren . length ) { return targetPath ; } let index ; for ( index = 0 ; index < rootPathChildren . length ; ++ index ) { if ( targetPathChildren [ index ] !== rootPathChildren [ index ] ) { break ; } } if ( index === rootPathChildren . length ) { return targetPathChildren . slice ( index ) . join ( '/' ) ; } else { return targetPath ; } } /**
     * Returns an array of segments of the path, split by the custom set of delimitators passed as an array.
     */ public static splitByDelimitators ( path , delimitators ) { let paths = [ path ] ; delimitators . forEach ( ( delimitator ) => { let newPaths = [ ] ; const delim = PathUtils . normalize ( PathUtils . makeAbsolute ( delimitator ) + '/' ) ; paths . forEach ( ( path ) => { newPaths = newPaths . concat ( path . split ( delim ) ) ; if ( path . endsWith ( delimitator ) ) { const lastPath = newPaths . splice ( newPaths . length - 1 , 1 ) [ 0 ] ; if ( lastPath !== delimitator ) { newPaths = newPaths . concat ( lastPath . split ( PathUtils . makeAbsolute ( delimitator ) ) ) ; } } newPaths = newPaths . filter ( ( path ) => path ) ; } ) ; paths = newPaths ; } ) ; return paths ; } param pagePath param dataPath public static _getJCRPath ( pagePath , dataPath ) { return [ pagePath , Constants . JCR_CONTENT , dataPath ] . join ( '/' ) ; } /**
     * Returns object containing pagePath (path to a page) and, if exists, itemPath (path to the item on that page)
     * from the passed path.
     */ public static splitPageContentPaths ( path ) { if ( ! path && ( typeof path !== 'string' ) ) { return ; } const splitPaths = path . split ( `/${ Constants . JCR_CONTENT }/` ) ; const split = { pagePath : splitPaths [ 0 ] } ; if ( splitPaths . length > 1 ) { split . itemPath = splitPaths [ 1 ] ; } return split ; } /**
     * Returns path that is no longer prefixed nor suffixed by the set of strings passed as an array.
     */ public static trimStrings ( path , strings ) { strings . forEach ( ( str ) => { while ( path . startsWith ( str ) ) { path = PathUtils . makeRelative ( path . slice ( str . length ) ) ; } while ( path . endsWith ( str ) ) { path = path . slice ( 0 , path . length - str . length ) ; if ( path . endsWith ( '/' ) ) { path = path . slice ( 0 , path . length - 1 ) ; } } } ) ; return path ; } public static _getStartStrings ( path , strings ) { let returnStr = '' ; strings . forEach ( ( str ) => { while ( path . startsWith ( str ) ) { path = PathUtils . makeRelative ( path . slice ( str . length ) ) ; returnStr = `${ returnStr }/${ str }` ; } } ) ; return PathUtils . makeRelative ( returnStr ) ; } param path param aemHost param rootPath returns public static toAEMPath ( path , aemHost , rootPath ) { const isLoadedInAEM = window . location . origin === aemHost ; if ( isLoadedInAEM ) { rootPath = rootPath . replace ( /^\/|\/$/g , '' ) ; const aemPathPrefix = `(/editor.html)?(/content/${ rootPath })?` ; if ( path . indexOf ( aemPathPrefix ) < 0 ) { const newPath = ( `${ aemPathPrefix }${ path }(.html)?` ) ; return newPath ; } } return path ; } }