class Formatter { private str: string; private width: number; private remainingSpace: number; public alignLeft() : void { this.str = this.str + ' '.repeat(this.remainingSpace); } public alignRight() : void { this.str = ' '.repeat(this.remainingSpace) + this.str; } public alignCenter() : void { let diff = (this.width - this.str.length) / 2; let leftPadding = Math.floor(diff); let rightPadding = Math.ceil(diff); this.str = ' '.repeat(leftPadding) + this.str + ' '.repeat(rightPadding); } public wrap() : void { this.str = this.str.substr(0, this.width - 3) + '...'; } public workWithTheString(str: string) : void { this.str = str; } public theMaximumWidthIs(width: number) : void { this.width = width; this.remainingSpace = this.width - this.str.length; } public giveMeTheResult() : string { return this.str; } } export function table(data: Array>, config: any) { let formatter = new Formatter(); let formattedRows = []; for(let row in data) { for(let column in data[row]) { if(!config[column]) throw `Column ${column} not specified in config.`; formatter.workWithTheString(data[row][column]); formatter.theMaximumWidthIs(config[column].width); if(data[row][column].length <= config[column].width) switch (config[column].align) { case 'left': formatter.alignLeft(); break; case 'right': formatter.alignRight(); break; case 'center': formatter.alignCenter(); break; default: formatter.alignLeft(); break; } else formatter.wrap(); data[row][column] = formatter.giveMeTheResult(); } formattedRows.push(data[row].join('')); } return formattedRows.join('\n'); }