import colors from 'colors' ; import { DocNode , DocLinkTag , StringBuilder } from '@microsoft/tsdoc' ; import { ApiModel , IResolveDeclarationReferenceResult , ApiItem } from '@microsoft/api-extractor-model' ; import { CustomDocNodeKind } from '../nodes/CustomDocNodeKind' ; import { DocHeading } from '../nodes/DocHeading' ; import { DocNoteBox } from '../nodes/DocNoteBox' ; import { DocTable } from '../nodes/DocTable' ; import { DocTableCell } from '../nodes/DocTableCell' ; import { DocEmphasisSpan } from '../nodes/DocEmphasisSpan' ; import { MarkdownEmitter , IMarkdownEmitterContext , IMarkdownEmitterOptions } from './MarkdownEmitter' ; import { IndentedWriter } from '../utils/IndentedWriter' ; export interface ICustomMarkdownEmitterOptions extends IMarkdownEmitterOptions { contextApiItem : ApiItem | undefined ; onGetFilenameForApiItem : ( apiItem : ApiItem ) => string | undefined ; } export class CustomMarkdownEmitter extends MarkdownEmitter { private _apiModel : ApiModel ; public constructor ( apiModel ) { super ( ) ; this . _apiModel = apiModel ; } public emit ( stringBuilder , docNode , options ) { return super . emit ( stringBuilder , docNode , options ) ; } @override  protected writeNode ( docNode , context , docNodeSiblings ) { const writer = context . writer ; switch ( docNode . kind ) { case CustomDocNodeKind . Heading : { const docHeading = docNode as DocHeading ; writer . ensureSkippedLine ( ) ; let prefix ; switch ( docHeading . level ) { case 1 : prefix = '##' ; break ; case 2 : prefix = '###' ; break ; case 3 : prefix = '###' ; break ; default : prefix = '####' ; } writer . writeLine ( prefix + ' ' + this . getEscapedText ( docHeading . title ) ) ; writer . writeLine ( ) ; break ; } case CustomDocNodeKind . NoteBox : { const docNoteBox = docNode as DocNoteBox ; writer . ensureNewLine ( ) ; writer . increaseIndent ( '> ' ) ; this . writeNode ( docNoteBox . content , context , false ) ; writer . ensureNewLine ( ) ; writer . decreaseIndent ( ) ; writer . writeLine ( ) ; break ; } case CustomDocNodeKind . Table : { const docTable = docNode as DocTable ; writer . ensureSkippedLine ( ) ; context . insideTable = true ; let columnCount = 0 ; if ( docTable . header ) { columnCount = docTable . header . cells . length ; } for ( const row of docTable . rows ) { if ( row . cells . length > columnCount ) { columnCount = row . cells . length ; } } writer . write ( '| ' ) ; for ( let i = 0 ; i < columnCount ; ++ i ) { writer . write ( ' ' ) ; if ( docTable . header ) { const cell = docTable . header . cells [ i ] ; if ( cell ) { this . writeNode ( cell . content , context , false ) ; } } writer . write ( ' |' ) ; } writer . writeLine ( ) ; writer . write ( '| ' ) ; for ( let i = 0 ; i < columnCount ; ++ i ) { writer . write ( ' --- |' ) ; } writer . writeLine ( ) ; for ( const row of docTable . rows ) { writer . write ( '| ' ) ; for ( const cell of row . cells ) { writer . write ( ' ' ) ; this . writeNode ( cell . content , context , false ) ; writer . write ( ' |' ) ; } writer . writeLine ( ) ; } writer . writeLine ( ) ; context . insideTable = false ; break ; } case CustomDocNodeKind . EmphasisSpan : { const docEmphasisSpan = docNode as DocEmphasisSpan ; const oldBold = context . boldRequested ; const oldItalic = context . italicRequested ; context . boldRequested = docEmphasisSpan . bold ; context . italicRequested = docEmphasisSpan . italic ; this . writeNodes ( docEmphasisSpan . nodes , context ) ; context . boldRequested = oldBold ; context . italicRequested = oldItalic ; break ; } default : super . writeNode ( docNode , context , false ) ; } } @override  protected writeLinkTagWithCodeDestination ( docLinkTag , context ) { const options = context . options ; const result = this . _apiModel . resolveDeclarationReference ( docLinkTag . codeDestination ! , options . contextApiItem ) ; if ( result . resolvedApiItem ) { const filename = options . onGetFilenameForApiItem ( result . resolvedApiItem ) ; if ( filename ) { let linkText = docLinkTag . linkText || '' ; if ( linkText . length === 0 ) { linkText = result . resolvedApiItem . getScopedNameWithinPackage ( ) ; } if ( linkText . length > 0 ) { const encodedLinkText = this . getEscapedText ( linkText . replace ( /\s+/g , ' ' ) ) ; context . writer . write ( '[' ) ; context . writer . write ( encodedLinkText ) ; context . writer . write ( `](${ filename ! })` ) ; } else { console . log ( colors . yellow ( 'WARNING: Unable to determine link text' ) ) ; } } } else if ( result . errorMessage ) { console . log ( colors . yellow ( `WARNING: Unable to resolve reference "${ docLinkTag . codeDestination ! . emitAsTsdoc ( ) }": ` + result . errorMessage ) ) ; } } }