/**
 * adopted from https://github.com/microsoft/vscode/blob/10722887b8629f90cc38ee7d90d54e8246dc895f/extensions/typescript-language-features/src/utils/previewer.ts
 */ import ts from 'typescript' ; import { isNotNullOrUndefined } from '../../utils' ; function replaceLinks ( text ) { return ( text . replace ( /\{@(link|linkplain|linkcode) (https?:\/\/[^ |}]+?)(?:[| ]([^{}\n]+?))?\}/gi , ( _ , tag , link , text ? ) => { switch ( tag ) { case 'linkcode' : return `[\`${ text ? text . trim ( ) : link }\`](${ link })` ; default : return `[${ text ? text . trim ( ) : link }](${ link })` ; } } ) ) ; } function processInlineTags ( text ) { return replaceLinks ( text ) ; } function getTagBodyText ( tag ) { if ( ! tag . text ) { return undefined ; } function makeCodeblock ( text ) { if ( text . match ( /^\s*[~`]{3}/g ) ) { return text ; } return '```\n' + text + '\n```' ; } function makeExampleTag ( text ) { const captionTagMatches = text . match ( /<caption>(.*?)<\/caption>\s*(\r\n|\n)/ ) ; if ( captionTagMatches && captionTagMatches . index === 0 ) { return ( captionTagMatches [ 1 ] + '\n\n' + makeCodeblock ( text . substr ( captionTagMatches [ 0 ] . length ) ) ) ; } else { return makeCodeblock ( text ) ; } } function makeEmailTag ( text ) { const emailMatch = text . match ( /(.+)\s<([-.\w]+@[-.\w]+)>/ ) ; if ( emailMatch === null ) { return text ; } else { return `${ emailMatch [ 1 ] } ${ emailMatch [ 2 ] }` ; } } switch ( tag . name ) { case 'example' : return makeExampleTag ( ts . displayPartsToString ( tag . text ) ) ; case 'author' : return makeEmailTag ( ts . displayPartsToString ( tag . text ) ) ; case 'default' : return makeCodeblock ( ts . displayPartsToString ( tag . text ) ) ; } return processInlineTags ( ts . displayPartsToString ( tag . text ) ) ; } export function getTagDocumentation ( tag ) { function getWithType ( ) { const body = ( ts . displayPartsToString ( tag . text ) || '' ) . split ( /^(\S+)\s*-?\s*/ ) ; if ( body ?. length === 3 ) { const param = body [ 1 ] ; const doc = body [ 2 ] ; const label = `*@${ tag . name }* \`${ param }\`` ; if ( ! doc ) { return label ; } return ( label + ( doc . match ( /\r\n|\n/g ) ? '  \n' + processInlineTags ( doc ) : ` — ${ processInlineTags ( doc ) }` ) ) ; } } switch ( tag . name ) { case 'augments' : case 'extends' : case 'param' : case 'template' : return getWithType ( ) ; } const label = `*@${ tag . name }*` ; const text = getTagBodyText ( tag ) ; if ( ! text ) { return label ; } return label + ( text . match ( /\r\n|\n/g ) ? '  \n' + text : ` — ${ text }` ) ; } export function plain ( parts ) { return processInlineTags ( typeof parts === 'string' ? parts : ts . displayPartsToString ( parts ) ) ; } export function getMarkdownDocumentation ( documentation , tags ) { let result = [ ] ; if ( documentation ) { result . push ( plain ( documentation ) ) ; } if ( tags ) { result = result . concat ( tags . map ( getTagDocumentation ) ) ; } return result . filter ( isNotNullOrUndefined ) . join ( '\n\n' ) ; }