Skip to content

Commit 033273b

Browse files
authored
🤖 Merge PR DefinitelyTyped#72856 Add .table() and .row() to PDFKit by @armaneous
1 parent 1a60e1b commit 033273b

3 files changed

Lines changed: 336 additions & 1 deletion

File tree

types/pdfkit/index.d.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,106 @@ declare namespace PDFKit.Mixins {
398398
image(src: ImageSrc, options?: ImageOption): this;
399399
}
400400

401+
interface CellStyle {
402+
/** The border for the cell (default 1pt) */
403+
border?: boolean | number | Array<boolean | number> | {
404+
top?: number;
405+
right?: number;
406+
bottom?: number;
407+
left?: number;
408+
} | undefined;
409+
/** The border colors for the cell (default black) */
410+
borderColor?: string | Array<string> | {
411+
top?: ColorValue;
412+
right?: ColorValue;
413+
bottom?: ColorValue;
414+
left?: ColorValue;
415+
};
416+
/** Set the background color of the cell */
417+
backgroundColor?: ColorValue;
418+
}
419+
420+
interface TableOptions {
421+
/** The position of the table (default {x: doc.x, y: doc.y}) */
422+
position?: { x?: number; y?: number };
423+
/** The maximum width the table can expand to (defaults to the remaining content width (offset from the tables position)) */
424+
maxWidth?: number;
425+
/** Column definitions of the table. (default auto) */
426+
columnStyles?: number | Array<number | string> | CellStyle | ((row: number) => number | CellStyle | undefined);
427+
/** Row definitions of the table. (default *) */
428+
rowStyles?: number | Array<number | string> | CellStyle | ((row: number) => number | CellStyle | undefined);
429+
/** Defaults to apply to every cell */
430+
defaultStyle?:
431+
& (number | Array<number | string> | CellStyle | ((row: number) => number | CellStyle | undefined))
432+
& { width?: number };
433+
/** Whether to show the debug lines for all the cells (default false) */
434+
debug?: boolean;
435+
}
436+
437+
interface TableOptionsWithData extends TableOptions {
438+
/** The data to render (not required, you can call .row()). This can be an iterable (async or sync) */
439+
data: Array<Array<string | CellOptions>>;
440+
}
441+
442+
interface CellOptions extends CellStyle {
443+
/** The value, will be cast to a string (null and undefined are not rendered but the cell is still outlined) */
444+
text?: string | undefined | null;
445+
/** How many rows this cell covers, follows the same logic as HTML rowspan */
446+
rowSpan?: number;
447+
/** How many columns this cell covers, follows the same logic as HTML colspan */
448+
colSpan?: number;
449+
/** The padding for the cell (default 0.25em) */
450+
padding?: string;
451+
/** Font options for the cell */
452+
font?: any;
453+
/** The alignment of the cell text (default {x: 'left', y: 'top'}) */
454+
align?: { x?: "right" | "left"; y?: "top" | "bottom" };
455+
/** The text stroke (default 0) */
456+
textStroke?: number | boolean;
457+
/** Sets the text stroke color of the cells text (default black) */
458+
textStrokeColor?: ColorValue;
459+
/** Sets the text color of the cells text (default black) */
460+
textColor?: ColorValue;
461+
/** Sets the cell type (for accessibility) (default TD) */
462+
type?: string;
463+
/** Sets any text options you wish to provide (such as rotation) */
464+
textOptions?: TextOptions;
465+
/** Whether to show the debug lines for the cell (default false) */
466+
debug?: boolean;
467+
}
468+
469+
interface ColumnOptions extends CellOptions {
470+
/** The width of the column (default *) */
471+
width?: string | number;
472+
/** The minimum width of the column (default 0) */
473+
minWidth?: string | number;
474+
/** The maximum width of the column (default Infinity) */
475+
maxWidth?: string | number;
476+
}
477+
478+
interface RowOptions extends CellOptions {
479+
/** The height of the row (default auto) */
480+
height?: string | number;
481+
/** The minimum height of the row (default 0) */
482+
minHeight?: string | number;
483+
/** The maximum height of the row (default Infinity) */
484+
maxHeight?: string | number;
485+
}
486+
487+
interface PDFTableObject {
488+
/** Add a row of data (null and undefined are not rendered) */
489+
row(data: Array<string | undefined | null | RowOptions>): this;
490+
/** Indicates to the table that it is finished, allowing the table to flush its cell buffer (which should be empty unless there is rowSpans) */
491+
end(): PDFDocument;
492+
}
493+
494+
interface PDFTable {
495+
/** Draw a table in PDFKit document. */
496+
table(options?: TableOptions): PDFTableObject;
497+
/** Draw a table in PDFKit document. */
498+
table(options: TableOptionsWithData): PDFDocument;
499+
}
500+
401501
interface TextOptions {
402502
/** Set to false to disable line wrapping all together */
403503
lineBreak?: boolean | undefined;
@@ -705,6 +805,7 @@ declare namespace PDFKit {
705805
Mixins.PDFAnnotation,
706806
Mixins.PDFColor,
707807
Mixins.PDFImage,
808+
Mixins.PDFTable,
708809
Mixins.PDFText,
709810
Mixins.PDFVector,
710811
Mixins.PDFFont,
@@ -926,6 +1027,11 @@ declare module "pdfkit/js/mixins/images" {
9261027
export = PDFKitImage;
9271028
}
9281029

1030+
declare module "pdfkit/js/mixins/table" {
1031+
var PDFKitTable: PDFKit.Mixins.PDFTable;
1032+
export = PDFKitTable;
1033+
}
1034+
9291035
declare module "pdfkit/js/mixins/text" {
9301036
var PDFKitText: PDFKit.Mixins.PDFText;
9311037
export = PDFKitText;

types/pdfkit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "@types/pdfkit",
4-
"version": "0.13.9999",
4+
"version": "0.14.9999",
55
"projects": [
66
"http://pdfkit.org"
77
],

types/pdfkit/pdfkit-tests.ts

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,235 @@ doc.image(
207207
},
208208
).text("Scale", 320, 265);
209209

210+
// $ExpectType PDFDocument
211+
doc.table({
212+
data: [
213+
["Column 1", "Column 2", "Column 3"],
214+
["One value goes here", "Another one here", "OK?"],
215+
],
216+
});
217+
218+
// $ExpectType PDFTableObject
219+
doc.table()
220+
.row(["Column 1", "Column 2", "Column 3"])
221+
.row(["One value goes here", "Another one here", "OK?"]);
222+
223+
doc.table({
224+
columnStyles: [100, "*", 200, "*"],
225+
data: [
226+
["width=100", "star-sized", "width=200", "star-sized"],
227+
[
228+
"fixed-width cells have exactly the specified width",
229+
{ text: "nothing interesting here", textColor: "grey" },
230+
{ text: "nothing interesting here", textColor: "grey" },
231+
{ text: "nothing interesting here", textColor: "grey" },
232+
],
233+
],
234+
});
235+
236+
doc.table({
237+
rowStyles: [20, 50, 70],
238+
data: [
239+
["row 1 with height 20", "column B"],
240+
["row 2 with height 50", "column B"],
241+
["row 3 with height 70", "column B"],
242+
],
243+
});
244+
245+
doc.table({
246+
rowStyles: 40,
247+
data: [
248+
["row 1", "column B"],
249+
["row 2", "column B"],
250+
["row 3", "column B"],
251+
],
252+
});
253+
254+
doc.table({
255+
rowStyles: (row) => (row + 1) * 25,
256+
data: [
257+
["row 1", "column B"],
258+
["row 2", "column B"],
259+
["row 3", "column B"],
260+
],
261+
});
262+
263+
doc.table({
264+
columnStyles: [200, "*", "*"],
265+
data: [
266+
[{ colSpan: 2, text: "Header with Colspan = 2" }, "Header 3"],
267+
["Header 1", "Header 2", "Header 3"],
268+
["Sample value 1", "Sample value 2", "Sample value 3"],
269+
[
270+
{
271+
rowSpan: 3,
272+
text:
273+
"rowspan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor",
274+
},
275+
"Sample value 2",
276+
"Sample value 3",
277+
],
278+
["Sample value 2", "Sample value 3"],
279+
["Sample value 2", "Sample value 3"],
280+
[
281+
"Sample value 1",
282+
{
283+
colSpan: 2,
284+
rowSpan: 2,
285+
text: "Both:\nrowspan and colspan\ncan be defined at the same time",
286+
},
287+
],
288+
["Sample value 1"],
289+
],
290+
});
291+
292+
doc.table({
293+
rowStyles: { border: false },
294+
data: [
295+
["Header 1", "Header 2", "Header 3"],
296+
["Sample value 1", "Sample value 2", "Sample value 3"],
297+
["Sample value 1", "Sample value 2", "Sample value 3"],
298+
["Sample value 1", "Sample value 2", "Sample value 3"],
299+
["Sample value 1", "Sample value 2", "Sample value 3"],
300+
["Sample value 1", "Sample value 2", "Sample value 3"],
301+
],
302+
});
303+
304+
doc.table({
305+
rowStyles: (i) => {
306+
return i < 1 ? { border: [0, 0, 1, 0] } : { border: false };
307+
},
308+
data: [
309+
["Header 1", "Header 2", "Header 3"],
310+
["Sample value 1", "Sample value 2", "Sample value 3"],
311+
["Sample value 1", "Sample value 2", "Sample value 3"],
312+
["Sample value 1", "Sample value 2", "Sample value 3"],
313+
["Sample value 1", "Sample value 2", "Sample value 3"],
314+
["Sample value 1", "Sample value 2", "Sample value 3"],
315+
],
316+
});
317+
318+
doc.table({
319+
rowStyles: (i) => {
320+
return i < 1
321+
? { border: [0, 0, 2, 0], borderColor: "black" }
322+
: { border: [0, 0, 1, 0], borderColor: "#aaa" };
323+
},
324+
data: [
325+
["Header 1", "Header 2", "Header 3"],
326+
["Sample value 1", "Sample value 2", "Sample value 3"],
327+
["Sample value 1", "Sample value 2", "Sample value 3"],
328+
["Sample value 1", "Sample value 2", "Sample value 3"],
329+
["Sample value 1", "Sample value 2", "Sample value 3"],
330+
["Sample value 1", "Sample value 2", "Sample value 3"],
331+
],
332+
});
333+
334+
doc.table({
335+
// Set the style for all cells
336+
defaultStyle: { border: 1, borderColor: "gray" },
337+
// Set the style for cells based on their column
338+
columnStyles: (i) => {
339+
if (i === 0) return { border: { left: 2 }, borderColor: { left: "black" } };
340+
if (i === 2) return { border: { right: 2 }, borderColor: { right: "black" } };
341+
},
342+
// Set the style for cells based on their row
343+
rowStyles: (i) => {
344+
if (i === 0) return { border: { top: 2 }, borderColor: { top: "black" } };
345+
if (i === 3) return { border: { bottom: 2 }, borderColor: { bottom: "black" } };
346+
},
347+
data: [
348+
["Header 1", "Header 2", "Header 3"],
349+
["Sample value 1", "Sample value 2", "Sample value 3"],
350+
["Sample value 1", "Sample value 2", "Sample value 3"],
351+
["Sample value 1", "Sample value 2", "Sample value 3"],
352+
],
353+
});
354+
355+
doc.table({
356+
rowStyles: (i) => {
357+
if (i % 2 === 0) return { backgroundColor: "#ccc" };
358+
},
359+
data: [
360+
["Sample value 1", "Sample value 2", "Sample value 3"],
361+
["Sample value 1", "Sample value 2", "Sample value 3"],
362+
["Sample value 1", "Sample value 2", "Sample value 3"],
363+
["Sample value 1", "Sample value 2", "Sample value 3"],
364+
["Sample value 1", "Sample value 2", "Sample value 3"],
365+
],
366+
});
367+
368+
doc.table({
369+
data: [
370+
[
371+
{
372+
border: [true, false, false, false],
373+
backgroundColor: "#eee",
374+
text: "border:\n[true, false, false, false]",
375+
},
376+
{ border: false, backgroundColor: "#ddd", text: "border:\nfalse" },
377+
{ border: true, backgroundColor: "#eee", text: "border:\ntrue" },
378+
],
379+
[
380+
{ rowSpan: 3, border: true, backgroundColor: "#eef", text: "rowSpan: 3\n\nborder:\ntrue" },
381+
{ border: undefined, backgroundColor: "#eee", text: "border:\nundefined (default)" },
382+
{
383+
border: [false, false, false, true],
384+
backgroundColor: "#ddd",
385+
text: "border:\n[false, false, false, true]",
386+
},
387+
],
388+
[
389+
{ colSpan: 2, border: true, backgroundColor: "#efe", text: "colSpan: 2\n\nborder:\ntrue" },
390+
],
391+
[
392+
{ border: 0, backgroundColor: "#eee", text: "border:\n0 (same as false)" },
393+
{
394+
border: [false, true, true, false],
395+
backgroundColor: "#ddd",
396+
text: "border:\n[false, true, true, false]",
397+
},
398+
],
399+
],
400+
});
401+
402+
doc.table({
403+
defaultStyle: { border: false, width: 60 },
404+
data: [
405+
["", "column 1", "column 2", "column 3"],
406+
[
407+
"row 1",
408+
{
409+
rowSpan: 3,
410+
colSpan: 3,
411+
border: true,
412+
backgroundColor: "#ccc",
413+
text: "rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]",
414+
},
415+
],
416+
["row 2"],
417+
["row 3"],
418+
],
419+
});
420+
421+
doc.table({
422+
defaultStyle: { border: 1 },
423+
columnStyles: { border: { right: 2 } },
424+
rowStyles: { border: { bottom: 3 } },
425+
data: [
426+
[{ border: { left: 4 } }],
427+
],
428+
});
429+
430+
doc.text("before")
431+
.table({
432+
data: [
433+
["Column 1", "Column 2", "Column 3"],
434+
["One value goes here", "Another one here", "OK?"],
435+
],
436+
})
437+
.text("after");
438+
210439
doc.text("Scale", { align: "justify" });
211440

212441
doc.text("Baseline - string literal", { baseline: "alphabetic" });

0 commit comments

Comments
 (0)