Skip to content

Commit 9257859

Browse files
committed
chore: add table docs
1 parent 2269cd0 commit 9257859

File tree

4 files changed

+375
-0
lines changed

4 files changed

+375
-0
lines changed

docs/generate.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,5 +365,6 @@ render(doc, 'forms.md');
365365
render(doc, 'destinations.md');
366366
render(doc, 'attachments.md');
367367
render(doc, 'accessibility.md');
368+
render(doc, 'table.md');
368369
render(doc, 'you_made_it.md');
369370
doc.end();

docs/generate_website.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const files = [
2424
'destinations.md',
2525
'attachments.md',
2626
'accessibility.md',
27+
'table.md',
2728
'you_made_it.md'
2829
];
2930

docs/guide.pdf

80.9 KB
Binary file not shown.

docs/table.md

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
# Tables in PDFKit
2+
3+
## The basics
4+
5+
PDFKit makes adding tables to documents quite simple, and includes many options
6+
to customize the display of the output.
7+
8+
### A simple table
9+
Basic tables can be defined without configuration:
10+
11+
doc.table({
12+
data: [
13+
['Column 1', 'Column 2', 'Column 3'],
14+
['One value goes here', 'Another one here', 'OK?']
15+
]
16+
})
17+
18+
or the more verbose way
19+
20+
doc.table()
21+
.row(['Column 1', 'Column 2', 'Column 3'])
22+
.row(['One value goes here', 'Another one here', 'OK?'])
23+
24+
![]()
25+
26+
---
27+
28+
### Defining column widths
29+
30+
Tables allow you to define the widths of columns:
31+
32+
* `*` - distributes equally, filling the whole available space (default)
33+
* `fixed value` - a fixed width based on the document content
34+
35+
Example:
36+
37+
doc.table({
38+
columnStyles: [100, "*", 200, "*"],
39+
data: [
40+
["width=100", "star-sized", "width=200", "star-sized"],
41+
[
42+
"fixed-width cells have exactly the specified width",
43+
{ content: "nothing interesting here", textColor: "grey" },
44+
{ content: "nothing interesting here", textColor: "grey" },
45+
{ content: "nothing interesting here", textColor: "grey" }
46+
],
47+
],
48+
});
49+
50+
![]()
51+
52+
---
53+
54+
### Defining row heights
55+
56+
doc.table({
57+
rowStyles: [20, 50, 70],
58+
data: [
59+
["row 1 with height 20", "column B"],
60+
["row 2 with height 50", "column B"],
61+
["row 3 with height 70", "column B"],
62+
],
63+
});
64+
65+
![]()
66+
67+
With same height:
68+
69+
doc.table({
70+
rowStyles: 40,
71+
data: [
72+
["row 1", "column B"],
73+
["row 2", "column B"],
74+
["row 3", "column B"],
75+
],
76+
});
77+
78+
![]()
79+
80+
With height from function:
81+
82+
doc.table({
83+
rowStyles: (row) => (row + 1) * 25,
84+
data: [
85+
["row 1", "column B"],
86+
["row 2", "column B"],
87+
["row 3", "column B"],
88+
],
89+
});
90+
91+
![]()
92+
93+
---
94+
95+
### Column/row spans
96+
97+
Each cell can set a rowSpan or colSpan
98+
99+
doc.table({
100+
columnStyles: [200, "*", "*"],
101+
data: [
102+
[{ colSpan: 2, content: "Header with Colspan = 2" }, "Header 3"],
103+
["Header 1", "Header 2", "Header 3"],
104+
["Sample value 1", "Sample value 2", "Sample value 3"],
105+
[
106+
{
107+
rowSpan: 3,
108+
content: "rowspan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor",
109+
},
110+
"Sample value 2",
111+
"Sample value 3",
112+
],
113+
["Sample value 2", "Sample value 3"],
114+
["Sample value 2", "Sample value 3"],
115+
[
116+
"Sample value 1",
117+
{
118+
colSpan: 2,
119+
rowSpan: 2,
120+
content: "Both:\nrowspan and colspan\ncan be defined at the same time",
121+
},
122+
],
123+
["Sample value 1"],
124+
],
125+
})
126+
127+
![]()
128+
129+
---
130+
131+
### Styling
132+
133+
No borders:
134+
135+
doc.table({
136+
rowStyles: { border: false },
137+
data: [
138+
["Header 1", "Header 2", "Header 3"],
139+
["Sample value 1", "Sample value 2", "Sample value 3"],
140+
["Sample value 1", "Sample value 2", "Sample value 3"],
141+
["Sample value 1", "Sample value 2", "Sample value 3"],
142+
["Sample value 1", "Sample value 2", "Sample value 3"],
143+
["Sample value 1", "Sample value 2", "Sample value 3"],
144+
],
145+
})
146+
147+
![]()
148+
149+
Header line only:
150+
151+
doc.table({
152+
rowStyles: (i) => {
153+
return i < 1 ? { border: [0, 0, 1, 0] } : { border: false };
154+
},
155+
data: [
156+
["Header 1", "Header 2", "Header 3"],
157+
["Sample value 1", "Sample value 2", "Sample value 3"],
158+
["Sample value 1", "Sample value 2", "Sample value 3"],
159+
["Sample value 1", "Sample value 2", "Sample value 3"],
160+
["Sample value 1", "Sample value 2", "Sample value 3"],
161+
["Sample value 1", "Sample value 2", "Sample value 3"],
162+
],
163+
})
164+
165+
![]()
166+
167+
---
168+
169+
Light Horizontal lines:
170+
171+
doc.table({
172+
rowStyles: (i) => {
173+
return i < 1
174+
? { border: [0, 0, 2, 0], borderColor: "black" }
175+
: { border: [0, 0, 1, 0], borderColor: "#aaa" };
176+
},
177+
data: [
178+
["Header 1", "Header 2", "Header 3"],
179+
["Sample value 1", "Sample value 2", "Sample value 3"],
180+
["Sample value 1", "Sample value 2", "Sample value 3"],
181+
["Sample value 1", "Sample value 2", "Sample value 3"],
182+
["Sample value 1", "Sample value 2", "Sample value 3"],
183+
["Sample value 1", "Sample value 2", "Sample value 3"],
184+
],
185+
})
186+
187+
![]()
188+
189+
---
190+
191+
But you can provide a custom styler as well
192+
193+
doc.table({
194+
// Set the style for all cells
195+
defaultStyle: { border: 1, borderColor: "gray" },
196+
// Set the style for cells based on their column
197+
columnStyles: (i) => {
198+
if (i === 0) return { border: { left: 2 }, borderColor: { left: "black" } };
199+
if (i === 2) return { border: { right: 2 }, borderColor: { right: "black" } };
200+
},
201+
// Set the style for cells based on their row
202+
rowStyles: (i) => {
203+
if (i === 0) return { border: { top: 2 }, borderColor: { top: "black" } };
204+
if (i === 3) return { border: { bottom: 2 }, borderColor: { bottom: "black" } };
205+
},
206+
data: [
207+
["Header 1", "Header 2", "Header 3"],
208+
["Sample value 1", "Sample value 2", "Sample value 3"],
209+
["Sample value 1", "Sample value 2", "Sample value 3"],
210+
["Sample value 1", "Sample value 2", "Sample value 3"],
211+
],
212+
})
213+
214+
![]()
215+
216+
---
217+
218+
Zebra style
219+
220+
doc.table({
221+
rowStyles: (i) => {
222+
if (i % 2 === 0) return { backgroundColor: "#ccc" };
223+
},
224+
data: [
225+
["Sample value 1", "Sample value 2", "Sample value 3"],
226+
["Sample value 1", "Sample value 2", "Sample value 3"],
227+
["Sample value 1", "Sample value 2", "Sample value 3"],
228+
["Sample value 1", "Sample value 2", "Sample value 3"],
229+
["Sample value 1", "Sample value 2", "Sample value 3"],
230+
],
231+
})
232+
233+
![]()
234+
235+
---
236+
237+
### Optional border
238+
239+
doc.table({
240+
data: [
241+
[
242+
{ border: [true, false, false, false], backgroundColor: "#eee", content: "border:\n[true, false, false, false]" },
243+
{ border: false, backgroundColor: "#ddd", content: "border:\nfalse" },
244+
{ border: true, backgroundColor: "#eee", content: "border:\ntrue" },
245+
],
246+
[
247+
{ rowSpan: 3, border: true, backgroundColor: "#eef", content: "rowSpan: 3\n\nborder:\ntrue" },
248+
{ border: undefined, backgroundColor: "#eee", content: "border:\nundefined (default)" },
249+
{ border: [false, false, false, true], backgroundColor: "#ddd", content: "border:\n[false, false, false, true]" },
250+
],
251+
[
252+
{ colSpan: 2, border: true, backgroundColor: "#efe", content: "colSpan: 2\n\nborder:\ntrue" },
253+
],
254+
[
255+
{ border: 0, backgroundColor: "#eee", content: "border:\n0 (same as false)" },
256+
{ border: [false, true, true, false], backgroundColor: "#ddd", content: "border:\n[false, true, true, false]" },
257+
],
258+
],
259+
})
260+
261+
![]()
262+
263+
doc.table({
264+
defaultStyle: { border: false, width: 60 },
265+
data: [
266+
["", "column 1", "column 2", "column 3"],
267+
[
268+
"row 1",
269+
{
270+
rowSpan: 3,
271+
colSpan: 3,
272+
border: true,
273+
backgroundColor: "#ccc",
274+
content:
275+
"rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]",
276+
},
277+
],
278+
["row 2"],
279+
["row 3"],
280+
],
281+
})
282+
283+
![]()
284+
285+
---
286+
287+
When defining multiple styles, the cells follow the precedence:
288+
289+
1. `defaultStyle`
290+
2. `columnStyles`
291+
3. `rowStyles`
292+
4. `cellStyle`
293+
294+
so if a table was:
295+
296+
doc.table({
297+
defaultStyle: { border: 1 },
298+
columnStyles: { border: { right: 2 } },
299+
rowStyles: { border: { bottom: 3 } },
300+
data: [
301+
[{ border: { left: 4 } }]
302+
]
303+
})
304+
305+
The resulting cell would have a style of:
306+
307+
{
308+
border: {
309+
top: 1, // From the default
310+
right: 2, // From the column
311+
bottom: 3, // From the row
312+
left: 4 // From the cell
313+
}
314+
}
315+
316+
317+
Internally, PDFKit keeps track of the current X and Y position of table as it
318+
is added to the document. This way, any calls to `text` or `table` will be placed below the table row.
319+
320+
doc
321+
.text('before')
322+
.table({
323+
data: [
324+
['Column 1', 'Column 2', 'Column 3'],
325+
['One value goes here', 'Another one here', 'OK?']
326+
]
327+
})
328+
.text('after')
329+
330+
![]()
331+
332+
## Table options
333+
334+
- `position` - The position of the table (default `{x: doc.x, y: doc.y}`)
335+
- `maxWidth` - The maximum width the table can expand to (defaults to the remaining content width (offset from the tables position))
336+
- `columnStyles` - Column definitions of the table. (default `auto`)
337+
- `rowStyles` - Row definitions of the table. (default `*`)
338+
- `defaultStyle` - Defaults to apply to every cell
339+
- `data` - The data to render (not required, you can call `.row()`). This can be an iterable (async or sync)
340+
- `debug` - Whether to show the debug lines for all the cells (default `false`)
341+
342+
## Cell options
343+
344+
- `content` - The value, will be cast to a string (boolean is converted to `Y/N`, and `null` and `undefined` are not rendered but the cell is still outlined)
345+
- `rowSpan` - How many rows this cell covers, follows the same logic as HTML `rowspan`
346+
- `colSpan` - How many columns this cell covers, follows the same logic as HTML `colspan`
347+
- `padding` - The padding for the cell (default `0.25em`)
348+
- `border` - The border for the cell (default `1pt`)
349+
- `borderColor` - The border colors for the cell (default `black`)
350+
- `font` - Font options for the cell
351+
- `backgroundColor` - Set the background color of the cell
352+
- `align` - The alignment of the cell content (default `{x: 'left', y: 'top'}`)
353+
- `textStroke` - The text stroke (default `0`)
354+
- `textStrokeColor` - Sets the text stroke color of the cells content (default `black`)
355+
- `textColor` - Sets the text color of the cells content (default `black`)
356+
- `type` - Sets the cell type (for accessibility) (default `TD`)
357+
- `debug` - Whether to show the debug lines for the cell (default `false`)
358+
359+
## Column options
360+
361+
Extends the [cell options](#cell-options) above with:
362+
363+
- `width` - The width of the column (default `*`)
364+
- `minWidth` - The minimum width of the column (default `0`)
365+
- `maxWidth` - The maximum width of the column (default `Infinity`)
366+
367+
## Row options
368+
369+
Extends the [cell options](#cell-options) above with:
370+
371+
- `height` - The height of the row (default `auto`)
372+
- `minHeight` - The minimum height of the row (default `0`)
373+
- `maxHeight` - The maximum height of the row (default `Infinity`)

0 commit comments

Comments
 (0)