import * as os from 'os' ; import { Class } from '../Components/Class' ; import { Enum } from '../Components/Enum' ; import { EnumValue } from '../Components/EnumValue' ; import { Interface } from '../Components/Interface' ; import { Method } from '../Components/Method' ; import { Namespace } from '../Components/Namespace' ; import { Parameter } from '../Components/Parameter' ; import { Property } from '../Components/Property' ; import { TypeParameter } from '../Components/TypeParameter' ; import { Formatter } from '../Models/Formatter' ; import { IComponentComposite } from '../Models/IComponentComposite' ; /**
 * Export diagram class using mermaidjs format
 */ export class MermaidFormat extends Formatter { public header ( ) { return [ 'classDiagram' ] ; } public serializeClass ( comp ) { const result = [ ] ; const firstLine = [ ] ; firstLine . push ( `class ${ comp . name }` ) ; if ( comp . name === this . options . targetClass ) { firstLine . push ( ':::targetClassDiagram' ) ; } if ( comp . typeParameters . length > 0 ) { firstLine . push ( '~' ) ; firstLine . push ( comp . typeParameters . map ( ( typeParameter ) : string => this . serialize ( typeParameter ) ) . join ( ', ' ) ) ; firstLine . push ( '~' ) ; } firstLine . push ( ' {' ) ; if ( comp . extendsClass !== undefined ) { result . push ( `${ comp . extendsClass } <|-- ${ comp . name }` ) ; } if ( ! this . options . onlyClasses && comp . implementsInterfaces . length > 0 ) { comp . implementsInterfaces . map ( ( inter ) => { result . push ( `${ inter } <|.. ${ comp . name }` ) ; } ) ; } result . push ( firstLine . join ( '' ) ) ; comp . members . forEach ( ( member ) : void => { result . push ( `${ this . serialize ( member ) }` ) ; } ) ; result . push ( '}' ) ; if ( comp . isAbstract ) { result . push ( `<<abstract>> ${ comp . name }` ) ; } return result . join ( os . EOL ) ; } public addAssociation ( type1 , cardinality , type2 ) { return [ `${ type1 } ..> "${ cardinality }" ${ type2 }` ] ; } public serializeEnum ( comp ) { const result = [ ] ; let declaration = `class ${ comp . name }` ; if ( comp . values . length > 0 ) { declaration += ' {' ; } result . push ( declaration ) ; comp . values . forEach ( ( enumValue ) : void => { result . push ( `${ this . serializeEnumValue ( < EnumValue > enumValue ) }` ) ; } ) ; if ( comp . values . length > 0 ) { result . push ( '}' ) ; } result . push ( `<<enumeration>> ${ comp . name }` ) ; return result . join ( os . EOL ) ; } public serializeInterface ( comp ) { const result = [ ] ; const firstLine = [ ] ; firstLine . push ( `class ${ comp . name }` ) ; if ( comp . typeParameters . length > 0 ) { firstLine . push ( '~' ) ; firstLine . push ( comp . typeParameters . map ( ( typeParameter ) : string => this . serialize ( typeParameter ) ) . join ( ', ' ) ) ; firstLine . push ( '~' ) ; } if ( comp . extendsInterface . length > 0 ) { comp . extendsInterface . map ( ( inter ) => { result . push ( `${ inter } <|.. ${ comp . name }` ) ; } ) ; } if ( comp . members . length > 0 ) { firstLine . push ( ' {' ) ; } result . push ( firstLine . join ( '' ) ) ; comp . members . forEach ( ( member ) : void => { result . push ( `${ this . serialize ( member ) }` ) ; } ) ; if ( comp . members . length > 0 ) { result . push ( '}' ) ; } result . push ( `<<Interface>> ${ comp . name }` ) ; return result . join ( os . EOL ) ; } public serializeMethod ( comp ) { let result = { public : '+' , private : '-' , protected : '#' } [ comp . modifier ] ; result += `${ comp . name }(` ; result += comp . parameters . map ( ( parameter ) : string => this . serialize ( parameter ) ) . join ( ', ' ) ; result += `)${ ( comp . isAbstract ? '*' : '' ) }${ ( comp . isStatic ? '$' : '' ) }: ${ this . cleanType ( comp . returnType ) }` ; return result ; } public serializeNamespace ( comp ) { const result = [ ] ; comp . parts . forEach ( ( part ) : void => { result . push ( this . serialize ( part ) ) ; } ) ; return result . join ( os . EOL ) ; } public cleanType ( typeDef ) { if ( typeDef !== undefined && typeDef . includes ( '{' ) ) { return 'Inline' ; } return typeDef ; } public serializeParameter ( comp ) { let result = `${ comp . name }${ comp . isOptional || comp . hasInitializer ? '?' : '' }` ; const typeDef = this . cleanType ( comp . parameterType ) ; if ( typeDef !== undefined ) { result += `: ${ typeDef }` ; } return result ; } public serializeProperty ( comp ) { let result = { public : '+' , private : '-' , protected : '#' } [ comp . modifier ] ; result += `${ comp . name }${ ( comp . isOptional ? '?' : '' ) }${ ( comp . isAbstract ? '*' : '' ) }${ ( comp . isStatic ? '$' : '' ) }: ${ this . cleanType ( comp . returnType ) }` ; return result ; } public serializeTypeParameter ( comp ) { return `${ comp . name }` ; } public renderFiles ( files , associations ) { let indent = 0 ; return super . renderFiles ( files , associations ) . split ( os . EOL ) . map ( ( l ) => { const line = '    ' . repeat ( indent ) + l . trim ( ) ; if ( line . endsWith ( '{' ) ) { indent += 1 ; } else if ( line . endsWith ( '}' ) ) { indent -= 1 ; return line . substr ( 4 ) ; } return line ; } ) . join ( os . EOL ) ; } }