import { CommonModule } from '@angular/common' ; import { Component , NgModule } from '@angular/core' ; import * as _ from 'lodash' ; import * as dv from '@deja-vu/core' ; import * as allocator from '@deja-vu/allocator' ; import * as authentication from '@deja-vu/authentication' ; import * as authorization from '@deja-vu/authorization' ; import * as comment from '@deja-vu/comment' ; import * as event from '@deja-vu/event' ; import * as follow from '@deja-vu/follow' ; import * as geolocation from '@deja-vu/geolocation' ; import * as group from '@deja-vu/group' ; import * as label from '@deja-vu/label' ; import * as passkey from '@deja-vu/passkey' ; import * as property from '@deja-vu/property' ; import * as ranking from '@deja-vu/ranking' ; import * as rating from '@deja-vu/rating' ; import * as scoring from '@deja-vu/scoring' ; import * as task from '@deja-vu/task' ; import * as transfer from '@deja-vu/transfer' ; import * as dvDocs from '@deja-vu/core/pkg/documentation.json' ; dv [ 'documentation' ] = dvDocs ; import * as authenDocs from '@deja-vu/authentication/pkg/documentation.json' ; authentication [ 'documentation' ] = authenDocs ; import * as authoriDocs from '@deja-vu/authorization/pkg/documentation.json' ; authorization [ 'documentation' ] = authoriDocs ; import * as commentDocs from '@deja-vu/comment/pkg/documentation.json' ; comment [ 'documentation' ] = commentDocs ; import * as eventDocs from '@deja-vu/event/pkg/documentation.json' ; event [ 'documentation' ] = eventDocs ; import * as followDocs from '@deja-vu/follow/pkg/documentation.json' ; follow [ 'documentation' ] = followDocs ; import * as geolocDocs from '@deja-vu/geolocation/pkg/documentation.json' ; geolocation [ 'documentation' ] = geolocDocs ; import * as groupDocs from '@deja-vu/group/pkg/documentation.json' ; group [ 'documentation' ] = groupDocs ; import * as labelDocs from '@deja-vu/label/pkg/documentation.json' ; label [ 'documentation' ] = labelDocs ; import * as passkeyDocs from '@deja-vu/passkey/pkg/documentation.json' ; passkey [ 'documentation' ] = passkeyDocs ; import * as propertyDocs from '@deja-vu/property/pkg/documentation.json' ; property [ 'documentation' ] = propertyDocs ; import * as rankingDocs from '@deja-vu/ranking/pkg/documentation.json' ; ranking [ 'documentation' ] = rankingDocs ; import * as ratingDocs from '@deja-vu/rating/pkg/documentation.json' ; rating [ 'documentation' ] = ratingDocs ; import * as scoringDocs from '@deja-vu/scoring/pkg/documentation.json' ; scoring [ 'documentation' ] = scoringDocs ; import * as taskDocs from '@deja-vu/task/pkg/documentation.json' ; task [ 'documentation' ] = taskDocs ; import * as transferDocs from '@deja-vu/transfer/pkg/documentation.json' ; transfer [ 'documentation' ] = transferDocs ; import { App , ComponentInputs , ConceptComponentDefinition , ConceptDefinition , OMNIPRESENT_INPUTS } from './datatypes' ; import { TextComponent } from './text/text.component' ; const importedConcepts = { allocator , authentication , authorization , comment , event , follow , geolocation , group , label , passkey , property , ranking , rating , scoring , task , transfer } ; const outputTypeRegex = /EventEmitter<(.*)>/ ; /**
 * Converts a string of HTML to a string of the text it would render
 * (i.e. strips tags and converts codes to characters)
 */ function htmlToText ( html ) { const div = document . createElement ( 'div' ) ; div . style . display = 'none' ; div . innerHTML = html ; const text = div . innerText ; div . remove ( ) ; return text ; } function getNgModule ( importedModule ) { return Object . entries ( importedModule ) . filter ( ( [ key ] ) => key . endsWith ( 'Module' ) ) [ 0 ] [ 1 ] ; } const modules = Object . values ( importedConcepts ) . map ( getNgModule ) ; importedConcepts [ 'dv' ] = dv ; const componentSuffix = 'Component' ; const configWizardComponentName = 'ConfigWizardComponent' ; function isComponent ( f ) { return f && _ . isString ( f . name ) && f . name . endsWith ( componentSuffix ) ; } function isConceptComponent ( f ) { return isComponent ( f ) && f . name !== configWizardComponentName ; } function isConfigWizardComponent ( f ) { return isComponent ( f ) && f . name === configWizardComponentName ; } function removeSurroundingQuotes ( s ) { if ( s . length <= 1 ) { return s ; } const first = _ . first ( s ) ; const last = _ . last ( s ) ; if ( first === last && ( last === '"' || last === "'" ) ) { return s . slice ( 1 , - 1 ) ; } return s ; } function conceptDefinitionFromModule ( importedModule , moduleName ) { return { name : moduleName , components : Object . values ( importedModule ) . filter ( isConceptComponent ) . map ( ( component ) : ConceptComponentDefinition => { const inputs = OMNIPRESENT_INPUTS . slice ( ) ; const outputs = [ ] ; const componentInputs = { } ; _ . forEach ( component . propDecorators , ( val , key ) => { const type = val [ 0 ] . type . prototype . ngMetadataName ; if ( type === 'Input' ) { inputs . push ( key ) ; } else if ( type === 'Output' ) { outputs . push ( key ) ; } } ) ; let instance ; try { instance = new component ( ) ; } catch { instance = { } ; } const componentInputNames = inputs . filter ( ( input ) => isComponent ( _ . get ( instance , [ input , 'type' ] ) ) ) ; const template = component . decorators [ 0 ] . args [ 0 ] . template ; if ( componentInputNames . length > 0 ) { const div = document . createElement ( 'div' ) ; div . innerHTML = template ; const includes = Array . from ( div . getElementsByTagName ( 'dv-include' ) ) ; includes . forEach ( ( include ) => { const inputName = include . getAttribute ( '[component]' ) ; const inputsAttr = ( include . getAttribute ( '[inputs]' ) || '' ) ; const inputsRes = /{([\s\S]*?)}/ . exec ( inputsAttr ) ; if ( inputsRes && inputsRes [ 1 ] ) { componentInputs [ inputName ] = _ . fromPairs ( inputsRes [ 1 ] . split ( ',' ) . map ( ( s1 ) => s1 . split ( ':' ) ) . filter ( ( [ ioName , propertyName ] ) => ioName && propertyName ) . map ( ( [ ioName , propertyName ] ) => [ removeSurroundingQuotes ( ioName . trim ( ) ) , propertyName . trim ( ) ] ) . filter ( ( [ ioName , propertyName ] ) => ioName && propertyName ) ) ; } } ) ; div . remove ( ) ; } componentInputNames . forEach ( ( componentInputName ) => { if ( ! componentInputs [ componentInputName ] ) { componentInputs [ componentInputName ] = { } ; } } ) ; if ( template . includes ( 'ng-content' ) ) { inputs . push ( '*content' ) ; componentInputs [ '*content' ] = { } ; } inputs . sort ( ) ; outputs . sort ( ) ; const componentName = _ . kebabCase ( component . name . slice ( 0 , componentSuffix . length * - 1 ) ) ; let description = '' ; const ioDescriptions = { hidden : '(boolean) If true, do not display the component' } ; const moduleDocs = importedModule [ 'documentation' ] ; if ( moduleDocs ) { const componentDocs = moduleDocs . components . find ( ( c ) => c . name === component . name ) ; if ( componentDocs ) { description = htmlToText ( componentDocs . description ) ; componentDocs . outputsClass . forEach ( ( ioDocs ) => { ioDocs . type = _ . get ( outputTypeRegex . exec ( ioDocs . defaultValue ) , 1 ) || _ . get ( outputTypeRegex . exec ( ioDocs . type ) , 1 ) || 'any' ; } ) ; [ ... componentDocs . inputsClass , ... componentDocs . outputsClass ] . forEach ( ( ioDocs ) => { let { type , description : ioDescription } = ioDocs ; const { defaultValue , name } = ioDocs ; if ( ! type ) { if ( defaultValue ) { try { type = typeof eval ( defaultValue ) ; } catch ( e ) { type = 'any' ; } } else { type = 'any' ; } } ioDescription = ioDescription || '' ; ioDescriptions [ name ] = `(${ type }) ${ htmlToText ( ioDescription ) }` ; } ) ; } } return { name : componentName , component , inputs , outputs , componentInputs , description , ioDescriptions } ; } ) . sort ( ( cd1 , cd2 ) => cd1 . name < cd2 . name ? - 1 : 1 ) , configWizardComponent : Object . values ( importedModule ) . find ( isConfigWizardComponent ) } ; } export const conceptDefinitions = _ . map ( importedConcepts , conceptDefinitionFromModule ) ; const dvConceptIdx = conceptDefinitions . findIndex ( ( cd ) => cd . name === 'dv' ) ; const [ dvConcept ] = conceptDefinitions . splice ( dvConceptIdx , 1 ) ; App . conceptDefinitions = conceptDefinitions ; App . dvConcept = dvConcept ; export const dvCoreComponents = dvConcept . components . map ( ( { component : c } ) => < any > c ) ; dvConcept . components . push ( ( { name : 'text' , component : < Component > TextComponent , inputs : [ ] , outputs : [ ] , componentInputs : { } , description : 'Display custom text, images, and other content' , ioDescriptions : { } } ) ) ; @ NgModule ( { imports : [ CommonModule ] . concat ( modules ) , exports : modules , declarations : [ ] } ) export class ConceptModule { }