import { Component , ElementRef , Input , NgModuleFactory , Type , ɵNgModuleFactory } from '@angular/core' ; import { EXAMPLE_COMPONENTS , LiveExample } from '@ptsecurity/mosaic-examples' ; import { CopierService } from '../copier/copier.service' ; /** Regular expression that matches a file name and its extension */ const fileExtensionRegex = /(.*)\.(\w+)/ ; /** Preferred order for files of an example displayed in the viewer. */ const preferredExampleFileOrder = [ 'HTML' , 'TS' , 'CSS' ] ; @ Component ( { selector : 'example-viewer' , templateUrl : './example-viewer.html' , styleUrls : [ './example-viewer.scss' ] } ) export class ExampleViewer { /** Map of example files that should be displayed in the view-source tab. */ exampleTabs : { [ tabName ] : string ; } ; /** Data for the currently selected example. */ exampleData : LiveExample ; /** Component type for the current example. */ exampleComponentType : Type < any > | null = null ; /** Module factory that declares the example component. */ exampleModuleFactory : NgModuleFactory < any > | null = null ; /** Whether the source for the example is being displayed. */ isSourceShown = false ; isSwitcherHidden = false ; shadowHide = 'hljs-shadow_hidden' ; maxEditorLength = 15 ; lineNumbers = '' ; codeCopyDelay = 1000 ; codeCopySuccessClass : string = 'docs-example-source-copy_success' ; /** String key of the currently displayed example. */ @ Input ( ) get example ( ) { return this . _example ; } set example ( exampleName ) { if ( exampleName && exampleName !== this . _example && EXAMPLE_COMPONENTS [ exampleName ] ) { this . _example = exampleName ; this . exampleData = EXAMPLE_COMPONENTS [ exampleName ] ; this . generateExampleTabs ( ) ; this . loadExampleComponent ( ) . catch ( ( error ) => console . error ( `Could not load example '${ exampleName }': ${ error }` ) ) ; } else { console . error ( `Could not find example: ${ exampleName }` ) ; } } private _example : string | null ; constructor ( public copier , private readonly elementRef ) { this . elementRef = elementRef ; } ngAfterContentChecked ( ) { if ( ! this . lineNumbers ) { this . setLineNumbers ( ) ; } } setLineNumbers ( ) { const exampleSource = this . elementRef . nativeElement . querySelector ( '.mc-tab-body__active .docs-example-source-viewer' ) ; if ( exampleSource ) { const text = exampleSource . textContent ! . match ( /\n/g ) ; const length = text ? text . length + 1 : 0 ; this . lineNumbers = '' ; for ( let i = 1 ; i <= length ; i ++ ) { this . lineNumbers += `${ i }\n` ; } this . isSwitcherHidden = length < this . maxEditorLength ; } } toggleSourceView ( ) { this . isSourceShown = ! this . isSourceShown ; } getExampleTabNames ( ) { return this . exampleTabs ? Object . keys ( this . exampleTabs ) . sort ( ( a , b ) => { let indexA = preferredExampleFileOrder . indexOf ( a ) ; let indexB = preferredExampleFileOrder . indexOf ( b ) ; if ( indexA === - 1 ) { indexA = preferredExampleFileOrder . length ; } if ( indexB === - 1 ) { indexB = preferredExampleFileOrder . length ; } return ( indexA - indexB ) || 1 ; } ) : [ ] ; } copyCode ( event ) { const code = this . elementRef . nativeElement . querySelector ( '.docs-example-source-viewer' ) ; if ( ! code ) { return ; } const range = document . createRange ( ) ; range . selectNodeContents ( code ) ; const sel = window . getSelection ( ) ; if ( ! sel ) { return ; } sel . removeAllRanges ( ) ; sel . addRange ( range ) ; document . execCommand ( 'copy' ) ; sel . removeAllRanges ( ) ; event . target . parentNode . classList . add ( this . codeCopySuccessClass ) ; setTimeout ( ( ) => event . target . parentNode . classList . remove ( this . codeCopySuccessClass ) , this . codeCopyDelay ) ; } private async loadExampleComponent ( ) { if ( this . _example != null ) { const { componentName , module } = EXAMPLE_COMPONENTS [ this . _example ] ; const moduleExports = await import ( `@ptsecurity/mosaic-examples/fesm2020/${ module . importPath }` ) ; this . exampleComponentType = moduleExports [ componentName ] ; this . exampleModuleFactory = new ɵNgModuleFactory ( moduleExports [ module . name ] ) ; if ( typeof location !== 'undefined' && location . hash . slice ( 1 ) === this . _example ) { setTimeout ( ( ) => this . elementRef . nativeElement . scrollIntoView ( ) , 300 ) ; } } } private generateExampleTabs ( ) { this . exampleTabs = { } ; if ( this . exampleData ) { const exampleBaseFileName = `${ this . example }-example` ; const docsContentPath = `docs-content/examples-highlighted/${ this . exampleData . packagePath }` ; for ( const fileName of this . exampleData . files ) { const fileSourceName = fileName . replace ( fileExtensionRegex , '$1-$2.html' ) ; const importPath = `${ docsContentPath }/${ fileSourceName }` ; if ( fileName === `${ exampleBaseFileName }.ts` ) { this . exampleTabs [ 'TS' ] = importPath ; } else if ( fileName === `${ exampleBaseFileName }.css` ) { this . exampleTabs [ 'CSS' ] = importPath ; } else if ( fileName === `${ exampleBaseFileName }.html` ) { this . exampleTabs [ 'HTML' ] = importPath ; } else { this . exampleTabs [ fileName ] = importPath ; } } } } }