Skip to content

Commit a4d24ce

Browse files
authored
feat: support eliding padding in header separator (#17)
Closes #16
1 parent 7be98b0 commit a4d24ce

File tree

6 files changed

+102
-17
lines changed

6 files changed

+102
-17
lines changed

readme.md

+44-8
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ tablemark([
3737

3838
... displays as:
3939

40+
<!-- prettier-ignore-start -->
4041
| Name | Age | Is cool |
4142
| :---- | :---- | :------ |
4243
| Bob | 21 | false |
4344
| Sarah | 22 | true |
4445
| Lee | 23 | true |
46+
<!-- prettier-ignore-end -->
4547

4648
## api
4749

@@ -55,14 +57,15 @@ tablemark (input: InputData, options?: TablemarkOptions): string
5557
* an array of objects or iterables
5658
* `TablemarkOptions` options:
5759

58-
| key | type | default | description |
59-
| :------------: | :----------: | :--------: | ---------------------------------------------- |
60-
| `columns` | `Array<string \| ColumnDescriptor>` | - | Array of column descriptors. |
61-
| `caseHeaders` | `boolean` | `true` | Sentence case headers derived from keys. |
62-
| `toCellText` | `(input: unknown) => string` | - | Provide a custom "toString" function. |
63-
| `wrapWidth` | `number` | `Infinity` | Wrap cell text at this length. |
64-
| `wrapWithGutters` | `boolean` | `false` | Add sides (`\| <content> \|`) to wrapped rows. |
65-
| `lineEnding` | `string` | `"\n"` | String used at end-of-line. |
60+
| key | type | default | description |
61+
| :------------------: | :---------------------------------: | :--------: | --------------------------------------------------------------- |
62+
| `columns` | `Array<string \| ColumnDescriptor>` | - | Array of column descriptors. |
63+
| `caseHeaders` | `boolean` | `true` | Sentence case headers derived from keys. |
64+
| `toCellText` | `(input: unknown) => string` | - | Provide a custom "toString" function. |
65+
| `padHeaderSeparator` | `boolean` | `true` | Whether to pad gutters of the header separator (alignment) row. |
66+
| `wrapWidth` | `number` | `Infinity` | Wrap cell text at this length. |
67+
| `wrapWithGutters` | `boolean` | `false` | Add sides (`\| <content> \|`) to wrapped rows. |
68+
| `lineEnding` | `string` | `"\n"` | String used at end-of-line. |
6669

6770
The `columns` array can either contain objects, in which case their
6871
`name` and `align` properties will be used to alter the display of
@@ -103,11 +106,44 @@ tablemark([
103106

104107
... displays as:
105108

109+
<!-- prettier-ignore-start -->
106110
| first name | how old | are they cool |
107111
| :--------- | :-----: | :------------ |
108112
| Bob | 21 | false |
109113
| Sarah | 22 | true |
110114
| Lee | 23 | true |
115+
<!-- prettier-ignore-end -->
116+
117+
### `options.padHeaderSeparator`
118+
119+
```js
120+
tablemark(
121+
[
122+
{ name: "Bob", age: 21, isCool: false },
123+
{ name: "Sarah", age: 22, isCool: true },
124+
{ name: "Lee", age: 23, isCool: true }
125+
],
126+
{
127+
columns: [{ align: "left" }, { align: "center" }, { align: "right" }]
128+
}
129+
)
130+
131+
// | first name | how old | are they cool |
132+
// |:-----------|:-------:|--------------:|
133+
// | Bob | 21 | false |
134+
// | Sarah | 22 | true |
135+
// | Lee | 23 | true |
136+
```
137+
138+
... displays as:
139+
140+
<!-- prettier-ignore-start -->
141+
| first name | how old | are they cool |
142+
|:-----------|:-------:|--------------:|
143+
| Bob | 21 | false |
144+
| Sarah | 22 | true |
145+
| Lee | 23 | true |
146+
<!-- prettier-ignore-end -->
111147

112148
### `options.toCellText`
113149

src/index.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,25 @@ export default (input: InputData, options: TablemarkOptions = {}): string => {
3232
// header line
3333
table += row(alignments, widths, titles, config)
3434

35+
const dashLengthOffset = config.padHeaderSeparator ? 2 : 0
36+
3537
// header separator
3638
table += line(
3739
alignments.map(
3840
(align, i) =>
3941
(align === alignmentOptions.left || align === alignmentOptions.center
4042
? ":"
4143
: "-") +
42-
"-".repeat(widths[i] - 2) +
44+
"-".repeat(widths[i] - dashLengthOffset) +
4345
(align === alignmentOptions.right || align === alignmentOptions.center
4446
? ":"
4547
: "-")
4648
),
4749
config,
48-
true
50+
{
51+
forceGutters: true,
52+
isHeaderSeparator: true
53+
}
4954
)
5055

5156
// table body

src/types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ export interface TablemarkOptions {
6363
* Text to use as the line ending, `\n` by default.
6464
*/
6565
lineEnding?: string
66+
67+
/**
68+
* Include padding on the header separator row, `true` by default.
69+
*/
70+
padHeaderSeparator?: boolean
6671
}
6772

6873
export type TablemarkOptionsNormalized = Omit<

src/utilities.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,25 @@ export const toCellText: ToCellText = v => {
4848
export const line = (
4949
columns: readonly string[],
5050
config: TablemarkOptionsNormalized,
51-
forceGutters = false
51+
{
52+
forceGutters = false,
53+
isHeaderSeparator = false
54+
}: {
55+
forceGutters?: boolean
56+
isHeaderSeparator?: boolean
57+
} = {}
5258
): string => {
5359
const gutters = forceGutters ? true : config.wrapWithGutters
60+
let padding = " "
61+
62+
if (isHeaderSeparator && !config.padHeaderSeparator) {
63+
padding = ""
64+
}
5465

5566
return (
56-
(gutters ? "| " : " ") +
57-
columns.join(gutters ? " | " : " ") +
58-
(gutters ? " |" : " ") +
67+
(gutters ? `|${padding}` : ` ${padding}`) +
68+
columns.join(gutters ? `${padding}|${padding}` : `${padding} ${padding}`) +
69+
(gutters ? `${padding}|` : `${padding} `) +
5970
config.lineEnding
6071
)
6172
}
@@ -78,11 +89,11 @@ export const row = (
7889
}
7990

8091
if (height === 1) {
81-
return line(first, config, true)
92+
return line(first, config, { forceGutters: true })
8293
}
8394

8495
const lines = new Array(height)
85-
lines[0] = line(first, config, true)
96+
lines[0] = line(first, config, { forceGutters: true })
8697

8798
for (let v = 1; v < height; v++) {
8899
lines[v] = new Array(width)
@@ -117,7 +128,8 @@ export const normalizeOptions = (
117128
columns: [],
118129
lineEnding: "\n",
119130
wrapWidth: Infinity,
120-
wrapWithGutters: false
131+
wrapWithGutters: false,
132+
padHeaderSeparator: true
121133
}
122134

123135
Object.assign(defaults, options)

tests/cases.ts

+8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ test("gutters", t => {
5151
t.is(result, cases.gutters.expected)
5252
})
5353

54+
test("can disable header separator row padding", t => {
55+
const result = tablemark(
56+
cases.padHeaderSeparator.input,
57+
cases.padHeaderSeparator.options
58+
)
59+
t.is(result, cases.padHeaderSeparator.expected)
60+
})
61+
5462
test("pipes in content", t => {
5563
const result = tablemark(cases.pipes.input, cases.pipes.options)
5664
t.is(result, cases.pipes.expected)

tests/fixtures/inputs.ts

+19
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,25 @@ const testCases: Record<string, TestCase> = {
192192
"| Lee | 23 | true |"
193193
].join(EOL) + EOL
194194
},
195+
padHeaderSeparator: {
196+
input: [
197+
{ name: "Bob", age: 21, isCool: false },
198+
{ name: "Sarah", age: 22, isCool: true },
199+
{ name: "Lee", age: 23, isCool: true }
200+
],
201+
options: {
202+
columns: [{ align: "left" }, { align: "right" }, { align: "center" }],
203+
padHeaderSeparator: false
204+
},
205+
expected:
206+
[
207+
"| Name | Age | Is cool |",
208+
"|:------|------:|:-------:|",
209+
"| Bob | 21 | false |",
210+
"| Sarah | 22 | true |",
211+
"| Lee | 23 | true |"
212+
].join(EOL) + EOL
213+
},
195214
pipes: {
196215
input: [{ content: "yes | no" }],
197216
expected:

0 commit comments

Comments
 (0)