export enum EFileState { ADDED , UPDATED , RENAMED , DELETED } ; export interface IMetadata { type : EFileState ; hash : string ; fileName : string ; commented : boolean ; } /**
 * Metadata contains information about specific file - whether it was added/updated or removed, was it commented and so on.
 */ export class Metadata { metadata : IMetadata [ ] ; constructor ( private fileHolders ) { this . getAll ( ) ; } /**
     * Returns metadata for every file.
     */ getAll ( ) { if ( ! this . metadata ) { this . metadata = this . obtainMetadata ( ) || [ ] ; } if ( this . metadata . length > 0 ) { this . obtainCommentedFiles ( ) ; } return this . metadata ; } param { number } index return { IMetadata } get ( index ) { return this . metadata [ index ] ; } return { IMetadata } private obtainMetadata ( ) { const metadataFiles_v10_3_and_latest = ( ) => Array . prototype . slice . call ( document . querySelectorAll ( '.diff-file-changes .dropdown-content li:not(.hidden):not(.dropdown-menu-empty-item)' ) ) ; const metadataFiles_v9_5 = ( ) => Array . prototype . slice . call ( document . querySelectorAll ( '.file-stats li' ) ) ; const files_latest = metadataFiles_v10_3_and_latest ( ) ; if ( files_latest . length > 0 ) { if ( files_latest [ 0 ] . querySelector ( 'a i:first-child' ) ) { return this . obtainMetadata_v10_3 ( files_latest ) ; } else { return this . obtainMetadata_latest ( files_latest ) ; } } else { return this . obtainMetadata_v9_5 ( metadataFiles_v9_5 ( ) ) ; } } param { HTMLElement [ ] } rawFilesMetadata private obtainMetadata_latest ( rawFilesMetadata ) { const metadata = [ ] ; for ( let rawFileMetadata of rawFilesMetadata ) { const svgElement = rawFileMetadata . querySelector ( 'svg.diff-file-changed-icon' ) as HTMLElement ; const typeRaw = svgElement . querySelector ( 'use' ) . getAttribute ( 'xlink:href' ) . split ( '#' ) [ 1 ] ; const hash = rawFileMetadata . querySelector ( 'a' ) . getAttribute ( 'href' ) ; const fileName = rawFileMetadata . querySelector ( '.diff-changed-file' ) . getAttribute ( 'title' ) ; const isCred = svgElement . classList . contains ( 'cred' ) ; let type = EFileState . UPDATED ; if ( typeRaw === 'file-addition' ) { type = EFileState . ADDED ; } if ( typeRaw === 'file-deletion' && ! isCred ) { type = EFileState . RENAMED ; } if ( typeRaw === 'file-deletion' && isCred ) { type = EFileState . DELETED ; } const fileMetadata = { type , hash , fileName , commented : false } ; metadata . push ( fileMetadata ) ; } return metadata ; } param { HTMLElement [ ] } rawFilesMetadata private obtainMetadata_v10_3 ( rawFilesMetadata ) { let metadata = [ ] ; for ( let rawFileMetadata of rawFilesMetadata ) { const classList = rawFileMetadata . querySelector ( 'a i:first-child' ) . classList ; const hash = rawFileMetadata . querySelector ( 'a' ) . getAttribute ( 'href' ) ; let fileName = rawFileMetadata . querySelector ( '.diff-file-changes-path' ) . textContent . trim ( ) ; let type = EFileState . UPDATED ; if ( fileName . indexOf ( '→' ) !== - 1 ) { fileName = fileName . split ( '→' ) [ 1 ] . trim ( ) ; } if ( classList . contains ( 'fa-plus' ) ) { type = EFileState . ADDED ; } if ( classList . contains ( 'fa-minus' ) && ! classList . contains ( 'cred' ) ) { type = EFileState . RENAMED ; } if ( classList . contains ( 'fa-minus' ) && classList . contains ( 'cred' ) ) { type = EFileState . DELETED ; } const fileMetadata = { type , hash , fileName , commented : false } ; metadata . push ( fileMetadata ) ; } return metadata ; } param { HTMLElement [ ] } rawFilesMetadata private obtainMetadata_v9_5 ( rawFilesMetadata ) { const metadata = [ ] ; for ( let rawFileMetadata of rawFilesMetadata ) { const typeRaw = Array . prototype . slice . call ( rawFileMetadata . querySelector ( 'span:first-child' ) . classList ) ; const hash = rawFileMetadata . querySelector ( 'a' ) . getAttribute ( 'href' ) ; let fileName = rawFileMetadata . querySelector ( 'a' ) . textContent . trim ( ) ; let type = EFileState . UPDATED ; if ( fileName . indexOf ( '→' ) !== - 1 ) { fileName = fileName . split ( '→' ) [ 1 ] . trim ( ) ; } if ( ~ typeRaw . indexOf ( 'new-file' ) ) { type = EFileState . ADDED ; } if ( ~ typeRaw . indexOf ( 'renamed-file' ) ) { type = EFileState . RENAMED ; } if ( ~ typeRaw . indexOf ( 'deleted-file' ) ) { type = EFileState . DELETED ; } const fileMetadata = { type , hash , fileName , commented : false } ; metadata . push ( fileMetadata ) ; } return metadata ; } /**
     * Adds flag 'commented' to metadata for every file that was commented.
     */ private obtainCommentedFiles ( ) { const fileHolders = Array . prototype . slice . call ( this . fileHolders ) ; fileHolders . forEach ( ( fileHolder , index ) => { const metadata = this . get ( index ) ; metadata . commented = ! ! fileHolder . querySelector ( '.notes_holder' ) ; } ) ; } }