From f5a541ba39d22cbe37cbbd8100b3b740b4247ba3 Mon Sep 17 00:00:00 2001 From: Nahiyan Kamal Date: Sat, 6 Mar 2021 16:10:53 +0100 Subject: [PATCH] feat: Width Limit (#343) * feat: Width Limit of Column * Updated dependencies --- src/internalTable/internal-table-printer.ts | 126 ++++++--- src/internalTable/internal-table.ts | 2 + src/internalTable/table-pre-processors.ts | 26 +- src/models/internal-table.ts | 2 +- src/utils/colored-console-line.ts | 2 +- src/utils/string-utils.ts | 56 ++++ src/utils/table-helpers.ts | 107 ++++---- .../__snapshots__/lineWidthLimit.test.ts.snap | 27 ++ test/lineWidthLimit.test.ts | 76 ++++++ test/readme/readmeExamples1.test.ts | 97 +++++++ test/readme/readmeExamples2.test.ts | 77 ++++++ test/readme/readmeExamples3.test.ts | 33 +++ test/readme/readmeExamplesBasic.test.ts | 37 +++ test/readmeExamples.test.ts | 253 ------------------ test/utils/console-utils.test.ts | 8 +- test/utils/string-utils.test.ts | 12 + yarn.lock | 12 +- 17 files changed, 585 insertions(+), 368 deletions(-) create mode 100644 src/utils/string-utils.ts create mode 100644 test/__snapshots__/lineWidthLimit.test.ts.snap create mode 100644 test/lineWidthLimit.test.ts create mode 100644 test/readme/readmeExamples1.test.ts create mode 100644 test/readme/readmeExamples2.test.ts create mode 100644 test/readme/readmeExamples3.test.ts create mode 100644 test/readme/readmeExamplesBasic.test.ts delete mode 100644 test/readmeExamples.test.ts create mode 100644 test/utils/string-utils.test.ts diff --git a/src/internalTable/internal-table-printer.ts b/src/internalTable/internal-table-printer.ts index 81969535..8f4dbeeb 100644 --- a/src/internalTable/internal-table-printer.ts +++ b/src/internalTable/internal-table-printer.ts @@ -1,5 +1,6 @@ import { Column, Row } from '../models/internal-table'; import ColoredConsoleLine from '../utils/colored-console-line'; +import { textWithPadding, limitWidth } from '../utils/string-utils'; import { defaultHeaderAlignment, defaultHeaderFontColor, @@ -12,48 +13,95 @@ import { createHeaderAsRow, createRow, renderTableHorizontalBorders, - textWithPadding, + getWidthLimitedColumnsArray, } from '../utils/table-helpers'; import { TableInternal } from './internal-table'; import { preProcessColumns, preProcessRows } from './table-pre-processors'; -function renderLine( +// ║ Index ║ ║ ║ +const renderOneLine = ( tableStyle: TABLE_STYLE_DETAILS, columns: Column[], - row: Row, - isHeader?: boolean -): string { + currentLineIndex: number, + widthLimitedColumnsArray: { [key: string]: string[] }, + isHeader: boolean | undefined, + row: Row +): string => { const line = new ColoredConsoleLine(); - line.addWithColor(defaultRowFontColor, tableStyle.vertical); - + line.addCharsWithColor(defaultRowFontColor, tableStyle.vertical); columns.forEach((column) => { - line.addWithColor(defaultRowFontColor, ' '); - line.addWithColor( - (isHeader && defaultHeaderFontColor) || column.color || row.color, // column color is prioritized as row color + const thisLineHasText = + currentLineIndex < widthLimitedColumnsArray[column.name].length; + + const textForThisLine: string = thisLineHasText + ? cellText(widthLimitedColumnsArray[column.name][currentLineIndex]) + : ''; + + line.addCharsWithColor(defaultRowFontColor, ' '); + line.addCharsWithColor( + (isHeader && defaultHeaderFontColor) || column.color || row.color, textWithPadding( - `${cellText(row.text[column.name])}`, + textForThisLine, column.alignment || defaultRowAlignment, - column.max_ln || 20 + column.maxLen || 20 ) ); - line.addWithColor(defaultRowFontColor, ` ${tableStyle.vertical}`); + line.addCharsWithColor(defaultRowFontColor, ` ${tableStyle.vertical}`); }); - return line.renderConsole(); -} +}; + +// ║ Bold ║ text ║ value ║ +// ║ Index ║ ║ ║ +const renderWidthLimitedLines = ( + tableStyle: TABLE_STYLE_DETAILS, + columns: Column[], + row: Row, + isHeader?: boolean +): string[] => { + // { col1: ['How', 'Is', 'Going'], col2: ['I am', 'Tom'], } + const widthLimitedColumnsArray = getWidthLimitedColumnsArray(columns, row); + + const totalLines = Object.values(widthLimitedColumnsArray).reduce( + (a, b) => Math.max(a, b.length), + 0 + ); + + const ret = []; + for ( + let currentLineIndex = 0; + currentLineIndex < totalLines; + currentLineIndex += 1 + ) { + const singleLine = renderOneLine( + tableStyle, + columns, + currentLineIndex, + widthLimitedColumnsArray, + isHeader, + row + ); + + ret.push(singleLine); + } + + return ret; +}; // ║ 1 ║ I would like some red wine please ║ 10.212 ║ -function renderRow(table: TableInternal, row: Row): string[] { - const ret: string[] = []; - ret.push(renderLine(table.tableStyle, table.columns, row)); +const renderRow = (table: TableInternal, row: Row): string[] => { + let ret: string[] = []; + ret = ret.concat( + renderWidthLimitedLines(table.tableStyle, table.columns, row) + ); return ret; -} +}; /* The analysis Result ╔═══════╦═══════════════════════════════════════╦════════╗ */ -function renderTableTitle(table: TableInternal): string[] { +const renderTableTitle = (table: TableInternal): string[] => { const ret: string[] = []; if (table.title === undefined) { @@ -64,7 +112,7 @@ function renderTableTitle(table: TableInternal): string[] { const reducer = (accumulator: number, currentValue: number) => // ║ cell ║, 2 spaces + cellTextSize + one border on the left accumulator + currentValue + 2 + 1; - return table.columns.map((m) => m.max_ln || 20).reduce(reducer, 1); + return table.columns.map((m) => m.maxLen || 20).reduce(reducer, 1); }; const titleWithPadding = textWithPadding( @@ -73,56 +121,58 @@ function renderTableTitle(table: TableInternal): string[] { getTableWidth() ); const styledText = new ColoredConsoleLine(); - styledText.addWithColor(defaultHeaderFontColor, titleWithPadding); + styledText.addCharsWithColor(defaultHeaderFontColor, titleWithPadding); // The analysis Result ret.push(styledText.renderConsole()); return ret; -} +}; /* ╔═══════╦═══════════════════════════════════════╦════════╗ ║ index ║ text ║ value ║ ╟═══════╬═══════════════════════════════════════╬════════╢ */ -function renderTableHeaders(table: TableInternal): string[] { - const ret: string[] = []; +const renderTableHeaders = (table: TableInternal): string[] => { + let ret: string[] = []; // ╔═══════╦═══════════════════════════════════════╦════════╗ ret.push( renderTableHorizontalBorders( table.tableStyle.headerTop, - table.columns.map((m) => m.max_ln || 20) + table.columns.map((m) => m.maxLen || 20) ) ); // ║ index ║ text ║ value ║ const row = createHeaderAsRow(createRow, table.columns); - ret.push(renderLine(table.tableStyle, table.columns, row, true)); + ret = ret.concat( + renderWidthLimitedLines(table.tableStyle, table.columns, row, true) + ); // ╟═══════╬═══════════════════════════════════════╬════════╢ ret.push( renderTableHorizontalBorders( table.tableStyle.headerBottom, - table.columns.map((m) => m.max_ln || 20) + table.columns.map((m) => m.maxLen || 20) ) ); return ret; -} +}; -function renderTableEnding(table: TableInternal): string[] { +const renderTableEnding = (table: TableInternal): string[] => { const ret: string[] = []; // ╚═══════╩═══════════════════════════════════════╩════════╝ ret.push( renderTableHorizontalBorders( table.tableStyle.tableBottom, - table.columns.map((m) => m.max_ln || 20) + table.columns.map((m) => m.maxLen || 20) ) ); return ret; -} +}; -export function renderTable(table: TableInternal): string { +export const renderTable = (table: TableInternal): string => { preProcessColumns(table); // enable / disable cols, find maxLn of each col/ computed Columns preProcessRows(table); // sort and filter @@ -136,14 +186,14 @@ export function renderTable(table: TableInternal): string { }); renderTableEnding(table).forEach((row) => ret.push(row)); return ret.join('\n'); -} +}; -export function renderSimpleTable(rows: any[]) { +export const renderSimpleTable = (rows: any[]) => { const table = new TableInternal(); table.addRows(rows); return renderTable(table); -} +}; -export function printSimpleTable(rows: any[]) { +export const printSimpleTable = (rows: any[]) => { console.log(renderSimpleTable(rows)); -} +}; diff --git a/src/internalTable/internal-table.ts b/src/internalTable/internal-table.ts index c4fc0f1a..16916dc1 100644 --- a/src/internalTable/internal-table.ts +++ b/src/internalTable/internal-table.ts @@ -16,6 +16,7 @@ interface ColumnOptionsRaw { title?: string; // the value that will be printed, if not present this will be 'name' alignment?: ALIGNMENT; color?: COLOR; + maxLen?: number; } export interface ComputedColumn extends ColumnOptionsRaw { @@ -89,6 +90,7 @@ export class TableInternal { name: column.name, title: column.title || column.name, ...objIfExists('color', column.color as COLOR), + ...objIfExists('maxLen', column.maxLen), alignment: column.alignment || defaultRowAlignment, })) || []; } diff --git a/src/internalTable/table-pre-processors.ts b/src/internalTable/table-pre-processors.ts index 1dd48307..dffc9f84 100644 --- a/src/internalTable/table-pre-processors.ts +++ b/src/internalTable/table-pre-processors.ts @@ -3,7 +3,7 @@ import { Column, Row } from '../models/internal-table'; import { findMaxLenOfColumn } from '../utils/table-helpers'; import { ComputedColumn, TableInternal } from './internal-table'; -function createComputedColumnsIfNecessary(table: TableInternal) { +const createComputedColumnsIfNecessary = (table: TableInternal) => { if (table.computedColumns.length) { table.computedColumns.forEach((computedColumn: ComputedColumn) => { table.addColumn(computedColumn.name); @@ -12,40 +12,40 @@ function createComputedColumnsIfNecessary(table: TableInternal) { }); }); } -} +}; -function disableColumnsIfNecessary(table: TableInternal) { +const disableColumnsIfNecessary = (table: TableInternal) => { if (table.enabledColumns.length) { table.columns = table.columns.filter((col: Column) => table.enabledColumns.includes(col.name) ); } -} +}; -function enableColumnsIfNecessary(table: TableInternal) { +const enableColumnsIfNecessary = (table: TableInternal) => { if (table.disabledColumns.length) { table.columns = table.columns.filter( (col: Column) => !table.disabledColumns.includes(col.name) ); } -} +}; -function findMaxColumnLength(table: TableInternal) { +const findMaxColumnLength = (table: TableInternal) => { table.columns.forEach((column) => { - column.max_ln = findMaxLenOfColumn(column, table.rows); + column.maxLen = findMaxLenOfColumn(column, table.rows); }); -} +}; -export function preProcessColumns(table: TableInternal) { +export const preProcessColumns = (table: TableInternal) => { createComputedColumnsIfNecessary(table); enableColumnsIfNecessary(table); disableColumnsIfNecessary(table); findMaxColumnLength(table); -} +}; -export function preProcessRows(table: TableInternal) { +export const preProcessRows = (table: TableInternal) => { const newRows = table.rows .filter((r) => table.filterFunction(r.text)) .sort((r1, r2) => table.sortFunction(r1.text, r2.text)); table.rows = newRows; -} +}; diff --git a/src/models/internal-table.ts b/src/models/internal-table.ts index 0c7cd060..843bb2e2 100644 --- a/src/models/internal-table.ts +++ b/src/models/internal-table.ts @@ -12,7 +12,7 @@ export interface Column { title: string; alignment?: ALIGNMENT; color?: COLOR; - max_ln?: number; + maxLen?: number; } export interface Row { diff --git a/src/utils/colored-console-line.ts b/src/utils/colored-console-line.ts index 48300559..d04143bd 100644 --- a/src/utils/colored-console-line.ts +++ b/src/utils/colored-console-line.ts @@ -30,7 +30,7 @@ export default class ColoredConsoleLine { this.text = ''; } - addWithColor(color: COLOR, text: string) { + addCharsWithColor(color: COLOR, text: string) { this.text += colorString(color, text); } diff --git a/src/utils/string-utils.ts b/src/utils/string-utils.ts new file mode 100644 index 00000000..aa5ca6cb --- /dev/null +++ b/src/utils/string-utils.ts @@ -0,0 +1,56 @@ +import findWidthInConsole from './console-utils'; +import { ALIGNMENT } from './table-constants'; +import { cellText } from './table-helpers'; + +// ("How are you?",center, 20) => " How are you? " +// ("How are you?",right, 20) => " How are you?" +export const textWithPadding = ( + text: string, + alignment: ALIGNMENT, + mxColumnLen: number +): string => { + const curTextSize = findWidthInConsole(text); + // alignments for center padding case + const leftPadding = Math.floor((mxColumnLen - curTextSize) / 2); + const rightPadding = mxColumnLen - leftPadding - curTextSize; + switch (alignment) { + case 'left': + return text.concat(' '.repeat(mxColumnLen - curTextSize)); + case 'center': + return ' ' + .repeat(leftPadding) + .concat(text) + .concat(' '.repeat(rightPadding)); + case 'right': + default: + return ' '.repeat(mxColumnLen - curTextSize).concat(text); + } +}; + +// ("How are you?",10) => ["How are ", "you?"] +export const limitWidth = (inpStr: string, width: number): string[] => { + const ret: string[] = []; + + const spaceSeparatedStrings = inpStr.split(' '); + + let now: string[] = []; + let cnt = 0; + spaceSeparatedStrings.forEach((strWithoutSpace) => { + const consoleWidth = findWidthInConsole(strWithoutSpace); + if (cnt + consoleWidth <= width) { + cnt += consoleWidth + 1; // 1 for the space + now.push(strWithoutSpace); + } else { + ret.push(now.join(' ')); + now = [strWithoutSpace]; + cnt = consoleWidth + 1; + } + }); + ret.push(now.join(' ')); + + return ret; +}; + +// ("How are you?",10) => ["How are ", "you?"] +export const biggestWordInSentence = (inpStr: string): number => + inpStr.split(' ').reduce((a, b) => Math.max(a, findWidthInConsole(b)), 0); diff --git a/src/utils/table-helpers.ts b/src/utils/table-helpers.ts index 74fb13be..245882bc 100644 --- a/src/utils/table-helpers.ts +++ b/src/utils/table-helpers.ts @@ -1,7 +1,12 @@ import { Dictionary } from '../models/common'; import { Column, Row } from '../models/internal-table'; import findWidthInConsole from './console-utils'; -import { ALIGNMENT, COLOR } from './table-constants'; +import { biggestWordInSentence, limitWidth } from './string-utils'; +import { COLOR } from './table-constants'; + +// takes any input that is given by user and converts to string +export const cellText = (text: string | number): string => + text === undefined || text === null ? '' : `${text}`; export interface RowOptionsRaw { color: string; @@ -11,41 +16,18 @@ export interface RowOptions { color: COLOR; } -export function convertRawRowOptionsToStandard( +export const convertRawRowOptionsToStandard = ( options?: RowOptionsRaw -): RowOptions | undefined { +): RowOptions | undefined => { if (options) { return { color: options.color as COLOR, }; } return undefined; -} +}; -export function textWithPadding( - text: string, - alignment: ALIGNMENT, - mxColumnLen: number -): string { - const curTextSize = findWidthInConsole(text); - // alignments for center padding case - const leftPadding = Math.floor((mxColumnLen - curTextSize) / 2); - const rightPadding = mxColumnLen - leftPadding - curTextSize; - switch (alignment) { - case 'left': - return text.concat(' '.repeat(mxColumnLen - curTextSize)); - case 'center': - return ' ' - .repeat(leftPadding) - .concat(text) - .concat(' '.repeat(rightPadding)); - case 'right': - default: - return ' '.repeat(mxColumnLen - curTextSize).concat(text); - } -} - -export function createTableHorizontalBorders( +export const createTableHorizontalBorders = ( { left, mid, @@ -53,7 +35,7 @@ export function createTableHorizontalBorders( other, }: { left: string; mid: string; right: string; other: string }, column_lengths: number[] -) { +) => { // ╚ let ret = left; @@ -69,48 +51,69 @@ export function createTableHorizontalBorders( // ╚═══════╩═══════════════════════════════════════╩════════╝ ret += right; return ret; -} +}; -export function createColum(name: string): Column { - return { name, title: name }; -} +export const createColum = (name: string): Column => ({ name, title: name }); -export function createRow(color: COLOR, text: Dictionary): Row { - return { color, text }; -} +export const createRow = (color: COLOR, text: Dictionary): Row => ({ + color, + text, +}); -export function findMaxLenOfColumn(column: Column, rows: Row[]): number { - const columnTitle = column.title; +export const findMaxLenOfColumn = (column: Column, rows: Row[]): number => { const columnId = column.name; - let maxLen = findWidthInConsole(`${columnTitle}`); + const columnTitle = column.title; - rows.forEach((row) => { - maxLen = Math.max( - maxLen, - findWidthInConsole(`${row.text[columnId] || ''}`) + if (column.maxLen) { + // if customer input is mentioned a max width, lets see if all other can fit here + // if others cant fit find the max word length so that at least the table can be printed + const ret = Math.max(column.maxLen, biggestWordInSentence(columnTitle)); + return rows.reduce( + (acc, row) => + Math.max(acc, biggestWordInSentence(cellText(row.text[columnId]))), + ret ); + } + + let maxLen = findWidthInConsole(columnTitle); + + rows.forEach((row) => { + maxLen = Math.max(maxLen, findWidthInConsole(cellText(row.text[columnId]))); }); return maxLen; -} +}; -export function renderTableHorizontalBorders( +export const renderTableHorizontalBorders = ( style: any, column_lengths: number[] -): string { +): string => { const str = createTableHorizontalBorders(style, column_lengths); return str; -} +}; -export function createHeaderAsRow(createRowFn: any, columns: Column[]): Row { +export const createHeaderAsRow = (createRowFn: any, columns: Column[]): Row => { const headerColor: COLOR = 'white_bold'; const row: Row = createRowFn(headerColor, {}); columns.forEach((column) => { row.text[column.name] = column.title; }); return row; -} +}; -export function cellText(text: string): string { - return text === undefined || text === null ? '' : text; -} +// { col1: ['How', 'Is', 'Going'], col2: ['I am', 'Tom'], } +export const getWidthLimitedColumnsArray = ( + columns: Column[], + row: Row +): { [key: string]: string[] } => { + const ret: { [key: string]: string[] } = {}; + + columns.forEach((column) => { + ret[column.name] = limitWidth( + cellText(row.text[column.name]), + column.maxLen || 20 + ); + }); + + return ret; +}; diff --git a/test/__snapshots__/lineWidthLimit.test.ts.snap b/test/__snapshots__/lineWidthLimit.test.ts.snap new file mode 100644 index 00000000..2388dbea --- /dev/null +++ b/test/__snapshots__/lineWidthLimit.test.ts.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing column max Width Simple Line Limit 1`] = ` +"┌──────────────────────┬──────────────────┬────────┐ +│ red_left_align_index │ right_align_text │ green  │ +├──────────────────────┼──────────────────┼────────┤ +│ 2  │ This row is blue │ 10.212 │ +│ 3  │  I would like │ 10.212 │ +│   │  some red wine │   │ +│   │  please │   │ +│ 4  │  I would like │ 10.212 │ +│   │  some cyan wine │   │ +│   │  please │   │ +│ 5  │  I would like │ 10.212 │ +│   │  some white_bold │   │ +│   │  wine please │   │ +│ 6  │  I would like │ 10.212 │ +│   │ some crimson sky │   │ +│   │  please │   │ +│ 7  │  I would like │  20  │ +│   │  some green │   │ +│   │  gemuse please │   │ +│ 8  │  I would like │  100  │ +│   │  some gelb │   │ +│   │  bananen bitte │   │ +└──────────────────────┴──────────────────┴────────┘" +`; diff --git a/test/lineWidthLimit.test.ts b/test/lineWidthLimit.test.ts new file mode 100644 index 00000000..93b87f8e --- /dev/null +++ b/test/lineWidthLimit.test.ts @@ -0,0 +1,76 @@ +import { Table } from '../index'; + +describe('Testing column max Width', () => { + it('Simple Line Limit', () => { + // Create a table + const p = new Table({ + columns: [ + { name: 'red_left_align_index', alignment: 'left', color: 'red' }, + { name: 'right_align_text', alignment: 'right', maxLen: 10 }, + { name: 'green', alignment: 'center', color: 'green' }, + ], + }); + + // add rows with color + p.addRow( + { + red_left_align_index: 2, + right_align_text: 'This row is blue', + green: 10.212, + }, + { color: 'blue' } + ); + p.addRow( + { + red_left_align_index: 3, + right_align_text: 'I would like some red wine please', + green: 10.212, + }, + { color: 'red' } + ); + p.addRow( + { + red_left_align_index: 4, + right_align_text: 'I would like some cyan wine please', + green: 10.212, + }, + { color: 'cyan' } + ); + p.addRow( + { + red_left_align_index: 5, + right_align_text: 'I would like some white_bold wine please', + green: 10.212, + }, + { color: 'white_bold' } + ); + p.addRow( + { + red_left_align_index: 6, + right_align_text: 'I would like some crimson sky please', + green: 10.212, + }, + { color: 'crimson' } + ); + p.addRow( + { + red_left_align_index: 7, + right_align_text: 'I would like some green gemuse please', + green: 20.0, + }, + { color: 'green' } + ); + p.addRow( + { + red_left_align_index: 8, + right_align_text: 'I would like some gelb bananen bitte', + green: 100, + }, + { color: 'yellow' } + ); + + // print + expect(p.render()).toMatchSnapshot(); + p.printTable(); + }); +}); diff --git a/test/readme/readmeExamples1.test.ts b/test/readme/readmeExamples1.test.ts new file mode 100644 index 00000000..9deb6a58 --- /dev/null +++ b/test/readme/readmeExamples1.test.ts @@ -0,0 +1,97 @@ +import { Table } from '../../index'; + +describe('Example: 1', () => { + it('Readme Example: screenshots generator for style', () => { + // Create a table + + const p1 = new Table(); + + // add rows with color + p1.addRow({ index: 1, text: 'red wine', value: 10.9 }); + p1.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); + + // print + p1.printTable(); + + const p2 = new Table(); + + // add rows with color + p2.addRow({ index: 1, text: 'red wine', value: 10.9 }); + p2.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); + + // print + const returned = p2.printTable(); + expect(returned).toBeUndefined(); + }); + + it('Readme Example: Header Title with alignment', () => { + const p = new Table({ + columns: [ + { name: 'index', alignment: 'left', color: 'blue' }, // with alignment and color + { name: 'text', alignment: 'right' }, + { name: 'is_priority_today', title: 'Is This Priority?' }, // with Title as separate Text + ], + }); + + p.addRow({ index: 1, text: 'red wine', value: 10.212 }, { color: 'green' }); + p.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); + p.addRow( + { index: 3, text: 'gelb bananen', value: 100, is_priority_today: 'Y' }, + { color: 'yellow' } + ); + p.addRow( + { index: 3, text: 'rosa hemd wie immer', value: 100 }, + { color: 'cyan' } + ); + p.printTable(); + }); + + it('table With all colored rows', () => { + // Create a table + const p = new Table({ + columns: [ + { name: 'index', alignment: 'left' }, + { name: 'text', alignment: 'right' }, + { name: 'value' }, + ], + }); + + // add rows with color + p.addRow( + { index: 2, text: 'I would like some blue poison please', value: 10.212 }, + { color: 'blue' } + ); + p.addRow( + { index: 3, text: 'I would like some red wine please', value: 10.212 }, + { color: 'red' } + ); + p.addRow( + { index: 4, text: 'I would like some cyan wine please', value: 10.212 }, + { color: 'cyan' } + ); + p.addRow( + { + index: 5, + text: 'I would like some white_bold wine please', + value: 10.212, + }, + { color: 'white_bold' } + ); + p.addRow( + { index: 6, text: 'I would like some crimson sky please', value: 10.212 }, + { color: 'crimson' } + ); + p.addRow( + { index: 7, text: 'I would like some green gemuse please', value: 20.0 }, + { color: 'green' } + ); + p.addRow( + { index: 8, text: 'I would like some gelb bananen bitte', value: 100 }, + { color: 'yellow' } + ); + + // print + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); +}); diff --git a/test/readme/readmeExamples2.test.ts b/test/readme/readmeExamples2.test.ts new file mode 100644 index 00000000..83b89c21 --- /dev/null +++ b/test/readme/readmeExamples2.test.ts @@ -0,0 +1,77 @@ +import { Table } from '../../index'; + +describe('Example: 2', () => { + it('simple table constructor', () => { + // Create a table + const p = new Table(['index', 'text', 'value']); + + // add rows with color + p.addRow( + { index: 1, text: 'I would like some red wine please', value: 10.212 }, + { color: 'red' } + ); + p.addRow( + { index: 2, text: 'I would like some green gemuse please', value: 20.0 }, + { color: 'green' } + ); + p.addRow( + { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, + { color: 'yellow' } + ); + + // print + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); + + it('without color', () => { + // Create a table + const p = new Table(['index', 'text', 'value']); + + // add rows with color + p.addRow({ + index: 1, + text: 'I would like some red wine please', + value: 10.212, + }); + p.addRow({ + index: 2, + text: 'I would like some green gemuse please', + value: 20.0, + }); + p.addRow({ + index: 3, + text: 'I would like some gelb bananen bitte', + value: 100, + }); + + // print + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); + + it('batch insert', () => { + // Create a table + const p = new Table(['index', 'text', 'value']); + + // add rows with color + p.addRow({ + index: 1, + text: 'I would like some red wine please', + value: 10.212, + }); + p.addRow({ + index: 2, + text: 'I would like some green gemuse please', + value: 20.0, + }); + p.addRows([ + { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, + { index: 4, text: 'I hope batch update is working', value: 300 }, + ]); + + // print + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); +}); diff --git a/test/readme/readmeExamples3.test.ts b/test/readme/readmeExamples3.test.ts new file mode 100644 index 00000000..68f83c92 --- /dev/null +++ b/test/readme/readmeExamples3.test.ts @@ -0,0 +1,33 @@ +import { Table } from '../../index'; + +describe('Example: 3', () => { + it('create column from rows', () => { + // Create a table + const p = new Table(); + + // add rows with color + p.addRow({ + index: 1, + text: 'I would like some red wine please', + value: 10.212, + amigo: 'Markit', + }); + p.addRow({ + index: 2, + text: 'I would like some green gemuse please', + value: 20.0, + }); + p.addRows([ + { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, + { + index: 4, + text: 'I hope batch update is working', + value: 300, + comment: 'best Result', + }, + ]); + + // print + p.printTable(); + }); +}); diff --git a/test/readme/readmeExamplesBasic.test.ts b/test/readme/readmeExamplesBasic.test.ts new file mode 100644 index 00000000..a040b9c2 --- /dev/null +++ b/test/readme/readmeExamplesBasic.test.ts @@ -0,0 +1,37 @@ +import { Table } from '../../index'; + +describe('Example: Basic', () => { + it('Readme Example1', () => { + // Create a table + const p = new Table(); + + // add rows with color + p.addRow({ index: 1, text: 'red wine please', value: 10.212 }); + p.addRow({ index: 2, text: 'green gemuse please', value: 20.0 }); + p.addRows([ + // adding multiple rows are possible + { index: 3, text: 'gelb bananen bitte', value: 100 }, + { index: 4, text: 'update is working', value: 300 }, + ]); + + // print + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); + + it('Readme Example2', () => { + // Create a table + const p = new Table(); + p.addRow({ index: 1, text: 'red wine', value: 10.212 }, { color: 'red' }); + p.addRow( + { index: 2, text: 'green gemuse', value: 20.0 }, + { color: 'green' } + ); + p.addRow( + { index: 3, text: 'gelb bananen', value: 100 }, + { color: 'yellow' } + ); + const returned = p.printTable(); + expect(returned).toBeUndefined(); + }); +}); diff --git a/test/readmeExamples.test.ts b/test/readmeExamples.test.ts deleted file mode 100644 index 0343c9c2..00000000 --- a/test/readmeExamples.test.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { Table } from '../index'; - -describe('Example: Print a simple Table', () => { - it('Readme Example1', () => { - // Create a table - const p = new Table(); - - // add rows with color - p.addRow({ index: 1, text: 'red wine please', value: 10.212 }); - p.addRow({ index: 2, text: 'green gemuse please', value: 20.0 }); - p.addRows([ - // adding multiple rows are possible - { index: 3, text: 'gelb bananen bitte', value: 100 }, - { index: 4, text: 'update is working', value: 300 }, - ]); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('Readme Example2', () => { - // Create a table - const p = new Table(); - p.addRow({ index: 1, text: 'red wine', value: 10.212 }, { color: 'red' }); - p.addRow( - { index: 2, text: 'green gemuse', value: 20.0 }, - { color: 'green' } - ); - p.addRow( - { index: 3, text: 'gelb bananen', value: 100 }, - { color: 'yellow' } - ); - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('Readme Example: screenshots generator for style', () => { - // Create a table - - const p1 = new Table(); - - // add rows with color - p1.addRow({ index: 1, text: 'red wine', value: 10.9 }); - p1.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); - - // print - p1.printTable(); - - const p2 = new Table(); - - // add rows with color - p2.addRow({ index: 1, text: 'red wine', value: 10.9 }); - p2.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); - - // print - const returned = p2.printTable(); - expect(returned).toBeUndefined(); - }); - - it('Readme Example: Header Title with alignment', () => { - const p = new Table({ - columns: [ - { name: 'index', alignment: 'left', color: 'blue' }, // with alignment and color - { name: 'text', alignment: 'right' }, - { name: 'is_priority_today', title: 'Is This Priority?' }, // with Title as separate Text - ], - }); - - p.addRow({ index: 1, text: 'red wine', value: 10.212 }, { color: 'green' }); - p.addRow({ index: 2, text: 'green gemuse', value: 20.0 }); - p.addRow( - { index: 3, text: 'gelb bananen', value: 100, is_priority_today: 'Y' }, - { color: 'yellow' } - ); - p.addRow( - { index: 3, text: 'rosa hemd wie immer', value: 100 }, - { color: 'cyan' } - ); - p.printTable(); - }); - - it('table With all colored rows', () => { - // Create a table - const p = new Table({ - columns: [ - { name: 'index', alignment: 'left' }, - { name: 'text', alignment: 'right' }, - { name: 'value' }, - ], - }); - - // add rows with color - p.addRow( - { index: 2, text: 'I would like some blue poison please', value: 10.212 }, - { color: 'blue' } - ); - p.addRow( - { index: 3, text: 'I would like some red wine please', value: 10.212 }, - { color: 'red' } - ); - p.addRow( - { index: 4, text: 'I would like some cyan wine please', value: 10.212 }, - { color: 'cyan' } - ); - p.addRow( - { - index: 5, - text: 'I would like some white_bold wine please', - value: 10.212, - }, - { color: 'white_bold' } - ); - p.addRow( - { index: 6, text: 'I would like some crimson sky please', value: 10.212 }, - { color: 'crimson' } - ); - p.addRow( - { index: 7, text: 'I would like some green gemuse please', value: 20.0 }, - { color: 'green' } - ); - p.addRow( - { index: 8, text: 'I would like some gelb bananen bitte', value: 100 }, - { color: 'yellow' } - ); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('simple table constructor', () => { - // Create a table - const p = new Table(['index', 'text', 'value']); - - // add rows with color - p.addRow( - { index: 1, text: 'I would like some red wine please', value: 10.212 }, - { color: 'red' } - ); - p.addRow( - { index: 2, text: 'I would like some green gemuse please', value: 20.0 }, - { color: 'green' } - ); - p.addRow( - { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, - { color: 'yellow' } - ); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('without color', () => { - // Create a table - const p = new Table(['index', 'text', 'value']); - - // add rows with color - p.addRow({ - index: 1, - text: 'I would like some red wine please', - value: 10.212, - }); - p.addRow({ - index: 2, - text: 'I would like some green gemuse please', - value: 20.0, - }); - p.addRow({ - index: 3, - text: 'I would like some gelb bananen bitte', - value: 100, - }); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('batch insert', () => { - // Create a table - const p = new Table(['index', 'text', 'value']); - - // add rows with color - p.addRow({ - index: 1, - text: 'I would like some red wine please', - value: 10.212, - }); - p.addRow({ - index: 2, - text: 'I would like some green gemuse please', - value: 20.0, - }); - p.addRows([ - { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, - { index: 4, text: 'I hope batch update is working', value: 300 }, - ]); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('column creation', () => { - // Create a table - const p = new Table(); - - // add rows with color - p.addRows([ - { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, - { index: 4, text: 'I hope batch update is working', value: 300 }, - ]); - - p.addColumn('extra_column1'); - p.addColumns(['extra_column2', 'extra_column3']); - - // print - const returned = p.printTable(); - expect(returned).toBeUndefined(); - }); - - it('create column from rows', () => { - // Create a table - const p = new Table(); - - // add rows with color - p.addRow({ - index: 1, - text: 'I would like some red wine please', - value: 10.212, - amigo: 'Markit', - }); - p.addRow({ - index: 2, - text: 'I would like some green gemuse please', - value: 20.0, - }); - p.addRows([ - { index: 3, text: 'I would like some gelb bananen bitte', value: 100 }, - { - index: 4, - text: 'I hope batch update is working', - value: 300, - comment: 'best Result', - }, - ]); - - // print - p.printTable(); - }); -}); diff --git a/test/utils/console-utils.test.ts b/test/utils/console-utils.test.ts index 245d237d..885b248d 100644 --- a/test/utils/console-utils.test.ts +++ b/test/utils/console-utils.test.ts @@ -4,15 +4,15 @@ import findWidthInConsole from '../../src/utils/console-utils'; describe('Console Width Calculation', () => { it('Simplest test: Colored Line', () => { const line = new ColoredConsoleLine(); - line.addWithColor('red', 'red'); - line.addWithColor('green', 'green'); - line.addWithColor('white_bold', 'white'); + line.addCharsWithColor('red', 'red'); + line.addCharsWithColor('green', 'green'); + line.addCharsWithColor('white_bold', 'white'); expect(findWidthInConsole(line.renderConsole())).toBe(13); }); it('Simplest test: Colored Foreign Language', () => { const line = new ColoredConsoleLine(); - line.addWithColor('red', '한'); + line.addCharsWithColor('red', '한'); expect(findWidthInConsole(line.renderConsole())).toBe(2); }); diff --git a/test/utils/string-utils.test.ts b/test/utils/string-utils.test.ts new file mode 100644 index 00000000..f5125950 --- /dev/null +++ b/test/utils/string-utils.test.ts @@ -0,0 +1,12 @@ +import chalk from 'chalk'; +import { limitWidth } from '../../src/utils/string-utils'; + +describe('Example: Print a simple Table with cell colors', () => { + it('cell colors are working', () => { + expect(limitWidth('as da s', 2)).toMatchObject(['as', 'da', 's']); + expect(limitWidth('as', 2)).toMatchObject(['as']); + expect( + limitWidth(chalk.bgMagenta('magenta'), chalk.bgMagenta('magenta').length) + ).toMatchObject([chalk.bgMagenta('magenta')]); + }); +}); diff --git a/yarn.lock b/yarn.lock index dba32094..232e858a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2313,9 +2313,9 @@ editor@~1.0.0: integrity sha1-YMf4e9YrzGqJT6jM1q+3gjok90I= electron-to-chromium@^1.3.649: - version "1.3.681" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.681.tgz#facd915ae46a020e8be566a2ecdc0b9444439be9" - integrity sha512-W6uYvSUTHuyX2DZklIESAqx57jfmGjUkd7Z3RWqLdj9Mmt39ylhBuvFXlskQnvBHj0MYXIeQI+mjiwVddZLSvA== + version "1.3.682" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.682.tgz#f4b5c8d4479df96b61e508a721d6c32c1262ef23" + integrity sha512-zok2y37qR00U14uM6qBz/3iIjWHom2eRfC2S1StA0RslP7x34jX+j4mxv80t8OEOHLJPVG54ZPeaFxEI7gPrwg== emittery@^0.7.1: version "0.7.2" @@ -7612,9 +7612,9 @@ uuid@^8.3.0: integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" - integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^7.0.0: version "7.1.0"