import { capitalize } from './capitalize' ; import { sortedArrayInsert } from './sorted-array-insert' ; export interface NavigationDocument { id : string ; title : string ; path : string ; tableOfContents : string ; } /**
 * A class to form a navigation Prefix Trie from a list of navigation documents
 * where each document's id represents a path to a document and paths are
 * separated by the `/` character.
 */ export class NavigationTrie { id : string = '' ; path ? : string ; title : string = '' ; tableOfContents : string = '' ; children : NavigationTrie [ ] = [ ] ; constructor ( key = '' , title = '' , path = '' , tableOfContents = '' , children = [ ] ) { this . id = key ; this . title = title ; this . tableOfContents = '' ; if ( path ) { this . path = path ; } this . children = children ; } param path param doc returns insert ( path = '' , doc ) { if ( path . indexOf ( '/' ) == - 1 ) { this . appendWord ( path , doc ) ; return ; } const keyArray = path . split ( '/' ) ; const key = keyArray . shift ( ) ; const newKey = keyArray . join ( '/' ) ; const child = this . appendBranch ( key ) ; child . insert ( newKey , doc ) ; } param path param doc appendWord ( path , doc ) { let child = this . getExistingChild ( path ) ; if ( ! child ) { this . appendChild ( new NavigationTrie ( path , doc . title , doc . path , '' ) ) ; return ; } if ( child . children . length != 0 ) { child . title = doc . title ; child . tableOfContents = doc . tableOfContents ; child . appendChild ( new NavigationTrie ( '' , 'Overview' , doc . path , '' ) ) ; return ; } if ( child . path ) { throw new Error ( 'Error: attempted to insert a document with a duplicate path: ' + child . path ) ; } } param key appendBranch ( path ) { let child = this . getExistingChild ( path ) ; if ( ! child ) { child = new NavigationTrie ( path , capitalize ( path ) , '' ) ; this . appendChild ( child ) ; } else if ( child && child . children . length == 0 ) { const node = new NavigationTrie ( '' , 'Overview' , child . path , '' ) ; delete ( child . path ) ; child . appendChild ( node ) ; } return child ; } param element appendChild ( element ) { sortedArrayInsert ( element , this . children , ( a , b ) => { if ( a . id > b . id ) { return 1 ; } if ( a . id == b . id ) { return 0 ; } if ( a . id < b . id ) { return - 1 ; } } ) ; } param path getExistingChild ( path ) { return this . children . find ( ( child ) => child . id == path ) ; } } param items export const generateNavigationTrieFromDocuments = ( items = [ ] ) => { const tree = new NavigationTrie ( ) ; for ( let doc of items ) { tree . insert ( doc . id , doc ) ; } return tree ; } ;