import repeat from 'repeat-string' ; typedef MarkdownTableOptions property { string | string [ ] } align property { boolean } padding property { boolean } delimiterStart property { boolean } delimiterStart property { boolean } delimiterEnd property { boolean } alignDelimiters property { ( value : string ) => number } stringLength param { string [ ] [ ] } table param { MarkdownTableOptions } options returns { string } export function markdownTable ( table , options ? ) { const settings = options || { } ; const align = ( settings . align || [ ] ) . concat ( ) ; const stringLength = settings . stringLength || defaultStringLength ; type { number [ ] } const alignments = [ ] ; let rowIndex = - 1 ; type { string [ ] [ ] } const cellMatrix = [ ] ; type { number [ ] [ ] } const sizeMatrix = [ ] ; type { number [ ] } const longestCellByColumn = [ ] ; let mostCellsPerRow = 0 ; type { number } let columnIndex ; type { string [ ] } let row ; type { number [ ] } let sizes ; type { number } let size ; type { string } let cell ; type { string [ ] } let lines ; type { string [ ] } let line ; type { string } let before ; type { string } let after ; type { number } let code ; while ( ++ rowIndex < table . length ) { columnIndex = - 1 ; row = [ ] ; sizes = [ ] ; if ( table [ rowIndex ] . length > mostCellsPerRow ) { mostCellsPerRow = table [ rowIndex ] . length ; } while ( ++ columnIndex < table [ rowIndex ] . length ) { cell = serialize ( table [ rowIndex ] [ columnIndex ] ) ; if ( settings . alignDelimiters !== false ) { size = stringLength ( cell ) ; sizes [ columnIndex ] = size ; if ( longestCellByColumn [ columnIndex ] === undefined || size > longestCellByColumn [ columnIndex ] ) { longestCellByColumn [ columnIndex ] = size ; } } row . push ( cell ) ; } cellMatrix [ rowIndex ] = row ; sizeMatrix [ rowIndex ] = sizes ; } columnIndex = - 1 ; if ( typeof align === 'object' && 'length' in align ) { while ( ++ columnIndex < mostCellsPerRow ) { alignments [ columnIndex ] = toAlignment ( align [ columnIndex ] ) ; } } else { code = toAlignment ( align ) ; while ( ++ columnIndex < mostCellsPerRow ) { alignments [ columnIndex ] = code ; } } columnIndex = - 1 ; row = [ ] ; sizes = [ ] ; while ( ++ columnIndex < mostCellsPerRow ) { code = alignments [ columnIndex ] ; before = '' ; after = '' ; if ( code === 99 ) { before = ':' ; after = ':' ; } else if ( code === 108 ) { before = ':' ; } else if ( code === 114 ) { after = ':' ; } size = settings . alignDelimiters === false ? 1 : Math . max ( 1 , longestCellByColumn [ columnIndex ] - before . length - after . length ) ; cell = before + repeat ( '-' , size ) + after ; if ( settings . alignDelimiters !== false ) { size = before . length + size + after . length ; if ( size > longestCellByColumn [ columnIndex ] ) { longestCellByColumn [ columnIndex ] = size ; } sizes [ columnIndex ] = size ; } row [ columnIndex ] = cell ; } cellMatrix . splice ( 1 , 0 , row ) ; sizeMatrix . splice ( 1 , 0 , sizes ) ; rowIndex = - 1 ; lines = [ ] ; while ( ++ rowIndex < cellMatrix . length ) { row = cellMatrix [ rowIndex ] ; sizes = sizeMatrix [ rowIndex ] ; columnIndex = - 1 ; line = [ ] ; while ( ++ columnIndex < mostCellsPerRow ) { cell = row [ columnIndex ] || '' ; before = '' ; after = '' ; if ( settings . alignDelimiters !== false ) { size = longestCellByColumn [ columnIndex ] - ( sizes [ columnIndex ] || 0 ) ; code = alignments [ columnIndex ] ; if ( code === 114 ) { before = repeat ( ' ' , size ) ; } else if ( code === 99 ) { if ( size % 2 ) { before = repeat ( ' ' , size / 2 + 0.5 ) ; after = repeat ( ' ' , size / 2 - 0.5 ) ; } else { before = repeat ( ' ' , size / 2 ) ; after = before ; } } else { after = repeat ( ' ' , size ) ; } } if ( settings . delimiterStart !== false && ! columnIndex ) { line . push ( '|' ) ; } if ( settings . padding !== false && ! ( settings . alignDelimiters === false && cell === '' ) && ( settings . delimiterStart !== false || columnIndex ) ) { line . push ( ' ' ) ; } if ( settings . alignDelimiters !== false ) { line . push ( before ) ; } line . push ( cell ) ; if ( settings . alignDelimiters !== false ) { line . push ( after ) ; } if ( settings . padding !== false ) { line . push ( ' ' ) ; } if ( settings . delimiterEnd !== false || columnIndex !== mostCellsPerRow - 1 ) { line . push ( '|' ) ; } } lines . push ( settings . delimiterEnd === false ? line . join ( '' ) . replace ( / +$/ , '' ) : line . join ( '' ) ) ; } return lines . join ( '\n' ) ; } param { string | null | undefined } value returns { string } function serialize ( value ) { return value === null || value === undefined ? '' : String ( value ) ; } param { string } value returns { number } function defaultStringLength ( value ) { return value . length ; } param { string } value returns { number } function toAlignment ( value ) { const code = typeof value === 'string' ? value . charCodeAt ( 0 ) : 0 ; return code === 67 || code === 99 ? 99 : code === 76 || code === 108 ? 108 : code === 82 || code === 114 ? 114 : 0 ; }