Skip to content

Commit

Permalink
[feat] Support header (#171)
Browse files Browse the repository at this point in the history
  • Loading branch information
nam-hle authored May 5, 2021
1 parent 6688760 commit a0103e4
Show file tree
Hide file tree
Showing 52 changed files with 843 additions and 163 deletions.
7 changes: 3 additions & 4 deletions .README/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@
* Configurable column width.
* Text wrapping.

## Install

{"gitdown": "include", "file": "./install.md"}

## Usage

{"gitdown": "include", "file": "./usage.md"}

## API
Expand All @@ -44,8 +40,11 @@
{"gitdown": "include", "file": "./api/table/columns/padding.md"}
{"gitdown": "include", "file": "./api/table/columns/truncate.md"}
{"gitdown": "include", "file": "./api/table/columns/wrapWord.md"}

{"gitdown": "include", "file": "./api/table/column_default.md"}

{"gitdown": "include", "file": "./api/table/header.md"}

{"gitdown": "include", "file": "./api/stream/index.md"}

{"gitdown": "include", "file": "./api/get_border_characters.md"}
File renamed without changes.
1 change: 1 addition & 0 deletions .README/api/table/border.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Custom borders. The keys are any of:
- `bottomLeft`, `bottomRight`, `bottomBody`, `bottomJoin`
- `joinLeft`, `joinRight`, `joinBody`, `joinJoin`
- `bodyLeft`, `bodyRight`, `bodyJoin`
- `headerJoin`

```js
const data = [
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Default: `() => true`

It is used to tell whether to draw a horizontal line. This callback is called for each horizontal border of the table.
If the table has `n` rows, then the `index` parameter is alternatively received all numbers in range `[0, n]` inclusively.
If the table has `n` rows and contains the header, then the range will be `[0, n+1]` inclusively.

```js
const data = [
Expand Down
File renamed without changes.
44 changes: 44 additions & 0 deletions .README/api/table/header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
##### config.header

Type: `object`

Header configuration.

The header configuration inherits the most of the column's, except:
- `content` **{string}**: the header content.
- `width:` calculate based on the content width automatically.
- `alignment:` `center` be default.
- `config.border.topJoin` will be `config.border.topBody` for more prettier.

```js
const data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C'],
];

const config = {
columnDefault: {
width: 10,
},
header: {
alignment: 'center',
content: 'THE HEADER\nThis is the table about something',
},
}

console.log(table(data, config));
```

```
╔══════════════════════════════════════╗
║ THE HEADER ║
║ This is the table about something ║
╟────────────┬────────────┬────────────╢
║ 0A │ 0B │ 0C ║
╟────────────┼────────────┼────────────╢
║ 1A │ 1B │ 1C ║
╟────────────┼────────────┼────────────╢
║ 2A │ 2B │ 2C ║
╚════════════╧════════════╧════════════╝
```
File renamed without changes.
Binary file modified .README/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions .README/install.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## Install

```bash
npm install table
```
Expand Down
2 changes: 2 additions & 0 deletions .README/usage.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## Usage

```js
import { table } from 'table';

Expand Down
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Custom borders. The keys are any of:
- `bottomLeft`, `bottomRight`, `bottomBody`, `bottomJoin`
- `joinLeft`, `joinRight`, `joinBody`, `joinJoin`
- `bodyLeft`, `bodyRight`, `bodyJoin`
- `headerJoin`

```js
const data = [
Expand Down Expand Up @@ -196,6 +197,7 @@ Default: `() => true`

It is used to tell whether to draw a horizontal line. This callback is called for each horizontal border of the table.
If the table has `n` rows, then the `index` parameter is alternatively received all numbers in range `[0, n]` inclusively.
If the table has `n` rows and contains the header, then the range will be `[0, n+1]` inclusively.

```js
const data = [
Expand Down Expand Up @@ -503,6 +505,53 @@ Default: `{}`
The default configuration for all columns. Column-specific settings will overwrite the default values.


<a name="table-api-table-1-config-header"></a>
##### config.header

Type: `object`

Header configuration.

The header configuration inherits the most of the column's, except:
- `content` **{string}**: the header content.
- `width:` calculate based on the content width automatically.
- `alignment:` `center` be default.
- `config.border.topJoin` will be `config.border.topBody` for more prettier.

```js
const data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C'],
];

const config = {
columnDefault: {
width: 10,
},
header: {
alignment: 'center',
content: 'THE HEADER\nThis is the table about something',
},
}

console.log(table(data, config));
```

```
╔══════════════════════════════════════╗
║ THE HEADER ║
║ This is the table about something ║
╟────────────┬────────────┬────────────╢
║ 0A │ 0B │ 0C ║
╟────────────┼────────────┼────────────╢
║ 1A │ 1B │ 1C ║
╟────────────┼────────────┼────────────╢
║ 2A │ 2B │ 2C ║
╚════════════╧════════════╧════════════╝
```


<a name="table-api-createstream"></a>
### createStream

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"test/**/*.ts"
],
"reporter": [
"text-lcov"
"text-lcov", "text"
]
},
"repository": {
Expand Down
4 changes: 4 additions & 0 deletions src/alignString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const alignJustify = (subject: string, width: number): string => {
export const alignString = (subject: string, containerWidth: number, alignment: Alignment): string => {
const subjectWidth = stringWidth(subject);

if (subjectWidth === containerWidth) {
return subject;
}

if (subjectWidth > containerWidth) {
throw new Error('Subject parameter value width cannot be greater than the container width.');
}
Expand Down
9 changes: 2 additions & 7 deletions src/alignTableData.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import stringWidth from 'string-width';
import {
alignString,
} from './alignString';
Expand All @@ -10,13 +9,9 @@ import type {
export const alignTableData = (rows: Row[], config: BaseConfig): Row[] => {
return rows.map((row) => {
return row.map((cell, cellIndex) => {
const column = config.columns[cellIndex];
const {width, alignment} = config.columns[cellIndex];

if (stringWidth(cell) === column.width) {
return cell;
} else {
return alignString(cell, column.width, column.alignment);
}
return alignString(cell, width, alignment);
});
});
};
64 changes: 59 additions & 5 deletions src/drawBorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import type {
DrawVerticalLine,
} from './types/api';
import type {
BottomBorderConfig,
JoinBorderConfig,
TableConfig,
SeparatorGetter,
TopBorderConfig,
JoinBorderConfig,
BottomBorderConfig,
} from './types/internal';

type Separator = {
Expand All @@ -26,9 +28,18 @@ const drawBorder = (columnWidths: number[],

return drawContent(columns, {
drawSeparator: drawVerticalLine,
endSeparator: separator.right,
middleSeparator: separator.join,
startSeparator: separator.left,
separatorGetter: (index: number, columnCount: number) => {
if (index === 0) {
return separator.left;
}

if (index === columnCount) {
return separator.right;
}

return separator.join;
},

}) + '\n';
};

Expand Down Expand Up @@ -77,6 +88,49 @@ const drawBorderBottom = (columnWidths: number[],
});
};

export const createTableBorderGetter = (columnWidths: number[], config: TableConfig): SeparatorGetter => {
return (index: number, size: number) => {
if (!config.header) {
if (index === 0) {
return drawBorderTop(columnWidths, config);
}

if (index === size) {
return drawBorderBottom(columnWidths, config);
}

return drawBorderJoin(columnWidths, config);
}

// Deal with the header
if (index === 0) {
return drawBorderTop(columnWidths, {
...config,
border: {
...config.border,
topJoin: config.border.topBody,
},
});
}

if (index === 1) {
return drawBorderJoin(columnWidths, {
...config,
border: {
...config.border,
joinJoin: config.border.headerJoin,
},
});
}

if (index === size) {
return drawBorderBottom(columnWidths, config);
}

return drawBorderJoin(columnWidths, config);
};
};

export {
drawBorder,
drawBorderBottom,
Expand Down
12 changes: 5 additions & 7 deletions src/drawContent.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
type SeparatorConfig = {
drawSeparator: (index: number, size: number) => boolean,
startSeparator: string,
middleSeparator: string,
endSeparator: string,
separatorGetter: (index: number, size: number) => string,
};

/**
* Shared function to draw horizontal borders, rows or the entire table
*/

export const drawContent = (contents: string[], separatorConfig: SeparatorConfig): string => {
const {startSeparator, middleSeparator, endSeparator, drawSeparator} = separatorConfig;
const {separatorGetter, drawSeparator} = separatorConfig;
const contentSize = contents.length;
const result: string[] = [];

if (drawSeparator(0, contentSize)) {
result.push(startSeparator);
result.push(separatorGetter(0, contentSize));
}

contents.forEach((content, contentIndex) => {
result.push(content);

// Only append the middle separator if the content is not the last
if (contentIndex + 1 < contentSize && drawSeparator(contentIndex + 1, contentSize)) {
result.push(middleSeparator);
result.push(separatorGetter(contentIndex + 1, contentSize));
}
});

if (drawSeparator(contentSize, contentSize)) {
result.push(endSeparator);
result.push(separatorGetter(contentSize, contentSize));
}

return result.join('');
Expand Down
46 changes: 46 additions & 0 deletions src/drawHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
alignString,
} from './alignString';
import {
drawRow,
} from './drawRow';
import {
padString,
} from './padTableData';
import {
truncateString,
} from './truncateTableData';
import type {
TableConfig,
} from './types/internal';
import {
wrapCell,
} from './wrapCell';

export const drawHeader = (width: number, config: TableConfig): string => {
if (!config.header) {
throw new Error('Can not draw header without header configuration');
}

const {alignment, paddingRight, paddingLeft, wrapWord} = config.header;

let content = config.header.content;

content = truncateString(content, config.header.truncate);

const headerLines = wrapCell(content, width, wrapWord);

return headerLines.map((headerLine) => {
let line = alignString(headerLine, width, alignment);
line = padString(line, paddingLeft, paddingRight);

return drawRow([line], {
...config,
drawVerticalLine: (index) => {
const columnCount = config.columns.length;

return config.drawVerticalLine(index === 0 ? 0 : columnCount, columnCount);
},
});
}).join('');
};
Loading

0 comments on commit a0103e4

Please sign in to comment.