@harbortouch/skytab-analytics-report-utils 0.38.1 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MFOOIOP4.js → chunk-HKSLZ6DJ.js} +416 -366
- package/dist/exporters/excel/index.d.cts +2 -2
- package/dist/exporters/excel/index.d.ts +2 -2
- package/dist/exporters/exportBuilder.cjs +99 -28
- package/dist/exporters/exportBuilder.d.cts +5 -5
- package/dist/exporters/exportBuilder.d.ts +5 -5
- package/dist/exporters/exportBuilder.js +46 -25
- package/dist/exporters/pdf/fonts/Lato-Bold.ttf +0 -0
- package/dist/exporters/pdf/fonts/Lato-Regular.ttf +0 -0
- package/dist/exporters/pdf/index.cjs +164 -70
- package/dist/exporters/pdf/index.d.cts +7 -5
- package/dist/exporters/pdf/index.d.ts +7 -5
- package/dist/exporters/pdf/index.js +158 -70
- package/dist/index.cjs +415 -365
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/{report-ZRoya9wR.d.cts → report-BNVH_1-b.d.cts} +13 -1
- package/dist/{report-ZRoya9wR.d.ts → report-BNVH_1-b.d.ts} +13 -1
- package/dist/{types-BPT5hjCR.d.ts → types-MalWTEdo.d.cts} +10 -1
- package/dist/{types-BPT5hjCR.d.cts → types-MalWTEdo.d.ts} +10 -1
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/exporters/pdf/index.ts
|
|
2
2
|
import PDFDocument from "pdfkit";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
3
5
|
|
|
4
6
|
// src/exporters/pdf/pdf.utils.ts
|
|
5
7
|
var sanitizePdfText = (text) => {
|
|
@@ -10,38 +12,75 @@ var sanitizePdfText = (text) => {
|
|
|
10
12
|
return leadingSpaces + text.trimStart().replace(/€/g, "EUR ").replace(
|
|
11
13
|
/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]|[\u{1F900}-\u{1F9FF}]|[\u{1FA00}-\u{1FA6F}]|[\u{1FA70}-\u{1FAFF}]|[\u{FE00}-\u{FE0F}]|[\u{1F004}]|[\u{1F0CF}]|[\u{1F18E}]|[\u{1F191}-\u{1F19A}]|[\u{1F1E6}-\u{1F1FF}]|[\u{1F201}-\u{1F251}]/gu,
|
|
12
14
|
""
|
|
13
|
-
).replace(/[\x00-\x1F\x7F]/g, " ").replace(/[
|
|
15
|
+
).replace(/[\x00-\x1F\x7F-\x9F]/g, " ").replace(/ /g, " ").replace(/[^\x20-\x7E\xA1-\xFF]/g, "").replace(/\s+/g, " ").trim();
|
|
14
16
|
};
|
|
15
17
|
|
|
18
|
+
// src/exporters/pdf/constants.ts
|
|
19
|
+
var ZOOM_FACTOR = 1.44;
|
|
20
|
+
var FONT_REGULAR = "Lato";
|
|
21
|
+
var FONT_BOLD = "Lato-Bold";
|
|
22
|
+
var DEFAULT_TEXT_COLOR = "#000000";
|
|
23
|
+
var HEADER_BACKGROUND_COLOR = "#f9fafb";
|
|
24
|
+
var ZEBRA_BACKGROUND_COLOR = "#fafbfc";
|
|
25
|
+
var SEPARATOR_COLOR = "#E4E5E5";
|
|
26
|
+
var SECTION_TITLE_FONT_SIZE = 1.17 * 6 * ZOOM_FACTOR;
|
|
27
|
+
var DEFAULT_FONT_SIZE = 5 * ZOOM_FACTOR;
|
|
28
|
+
var BODY_FONT_SIZE = 6 * ZOOM_FACTOR;
|
|
29
|
+
var TABLE_CELL_PADDING = 4;
|
|
30
|
+
var DEFAULT_ROW_HEIGHT = 25;
|
|
31
|
+
var MIN_COLUMN_WIDTH = 35;
|
|
32
|
+
var MARGINS = { top: 30, bottom: 30, left: 30, right: 30 };
|
|
33
|
+
var PAGE_SIZE = "LETTER";
|
|
34
|
+
var PAGE_LAYOUT = "landscape";
|
|
35
|
+
var SECTION_GAP = 18;
|
|
36
|
+
var MIN_SECTION_HEIGHT = 75;
|
|
37
|
+
var HEADER_RULE_COLOR = "#000000";
|
|
38
|
+
var HEADER_RULE_WIDTH = 1.5;
|
|
39
|
+
var HEADER_SPACING_FACTOR = 0.7;
|
|
40
|
+
|
|
16
41
|
// src/exporters/pdf/index.ts
|
|
17
|
-
var
|
|
18
|
-
var FONT_REGULAR = "Helvetica";
|
|
19
|
-
var COLOR_BLACK = "#000000";
|
|
20
|
-
var COLOR_HEADER_BACKGROUND = "#D3D3D3";
|
|
21
|
-
var COLOR_ROW_BACKGROUND_ALTERNATE = "#F5F5F5";
|
|
42
|
+
var FONTS_DIR = fileURLToPath(new URL("./fonts", import.meta.url));
|
|
22
43
|
var PdfExporter = class {
|
|
44
|
+
registerFonts(doc) {
|
|
45
|
+
doc.registerFont(FONT_REGULAR, join(FONTS_DIR, "Lato-Regular.ttf"));
|
|
46
|
+
doc.registerFont(FONT_BOLD, join(FONTS_DIR, "Lato-Bold.ttf"));
|
|
47
|
+
}
|
|
23
48
|
generate(content) {
|
|
24
|
-
const doc = new PDFDocument({
|
|
49
|
+
const doc = new PDFDocument({
|
|
50
|
+
margin: MARGINS.top,
|
|
51
|
+
size: PAGE_SIZE,
|
|
52
|
+
layout: PAGE_LAYOUT
|
|
53
|
+
});
|
|
54
|
+
this.registerFonts(doc);
|
|
25
55
|
const buffers = [];
|
|
26
56
|
return new Promise((resolve, reject) => {
|
|
27
57
|
doc.on("data", (chunk) => buffers.push(chunk));
|
|
28
58
|
doc.on("end", () => resolve(Buffer.concat(buffers)));
|
|
29
59
|
doc.on("error", reject);
|
|
30
60
|
try {
|
|
61
|
+
const pageBottom = doc.page.height - doc.page.margins.bottom;
|
|
62
|
+
let currentY = doc.page.margins.top;
|
|
31
63
|
content.sections.forEach((section, index) => {
|
|
32
|
-
const
|
|
64
|
+
const sanitized = this.sanitizeSections(section);
|
|
33
65
|
if (index > 0) {
|
|
34
|
-
|
|
66
|
+
if (currentY + SECTION_GAP + MIN_SECTION_HEIGHT > pageBottom) {
|
|
67
|
+
doc.addPage();
|
|
68
|
+
currentY = doc.page.margins.top;
|
|
69
|
+
} else {
|
|
70
|
+
currentY += SECTION_GAP;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (sanitized.filters && sanitized.filters.length > 0) {
|
|
74
|
+
currentY = this.drawFilters(doc, sanitized.filters, currentY);
|
|
35
75
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
currentY = this.drawSectionTitle(doc, sanitizedSections.title);
|
|
76
|
+
if (sanitized.appliedFilters !== void 0) {
|
|
77
|
+
currentY = this.drawAppliedFilters(doc, sanitized.appliedFilters, currentY);
|
|
39
78
|
}
|
|
40
|
-
if (
|
|
41
|
-
currentY = this.
|
|
79
|
+
if (sanitized.title && sanitized.table) {
|
|
80
|
+
currentY = this.drawSectionTitle(doc, sanitized.title, currentY);
|
|
42
81
|
}
|
|
43
|
-
if (
|
|
44
|
-
this.drawTable(doc,
|
|
82
|
+
if (sanitized.table) {
|
|
83
|
+
currentY = this.drawTable(doc, sanitized.table, currentY);
|
|
45
84
|
}
|
|
46
85
|
});
|
|
47
86
|
doc.end();
|
|
@@ -50,21 +89,27 @@ var PdfExporter = class {
|
|
|
50
89
|
}
|
|
51
90
|
});
|
|
52
91
|
}
|
|
53
|
-
sanitizeSections(
|
|
54
|
-
const sanitized = { title: sanitizePdfText(
|
|
55
|
-
if (
|
|
56
|
-
sanitized.filters =
|
|
92
|
+
sanitizeSections(section) {
|
|
93
|
+
const sanitized = { title: sanitizePdfText(section.title) };
|
|
94
|
+
if (section.filters) {
|
|
95
|
+
sanitized.filters = section.filters.map((filter) => ({
|
|
96
|
+
label: sanitizePdfText(filter.label),
|
|
97
|
+
value: sanitizePdfText(filter.value)
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
if (section.appliedFilters !== void 0) {
|
|
101
|
+
sanitized.appliedFilters = section.appliedFilters.map((filter) => ({
|
|
57
102
|
label: sanitizePdfText(filter.label),
|
|
58
103
|
value: sanitizePdfText(filter.value)
|
|
59
104
|
}));
|
|
60
105
|
}
|
|
61
|
-
if (
|
|
106
|
+
if (section.table) {
|
|
62
107
|
sanitized.table = {
|
|
63
|
-
columns:
|
|
108
|
+
columns: section.table.columns.map((col) => ({
|
|
64
109
|
...col,
|
|
65
110
|
header: sanitizePdfText(col.header)
|
|
66
111
|
})),
|
|
67
|
-
rows:
|
|
112
|
+
rows: section.table.rows.map((row) => {
|
|
68
113
|
const sanitizedRow = {};
|
|
69
114
|
for (const [key, value] of Object.entries(row)) {
|
|
70
115
|
sanitizedRow[key] = typeof value === "string" ? sanitizePdfText(value) : value;
|
|
@@ -75,26 +120,45 @@ var PdfExporter = class {
|
|
|
75
120
|
}
|
|
76
121
|
return sanitized;
|
|
77
122
|
}
|
|
78
|
-
drawSectionTitle(doc, title) {
|
|
79
|
-
doc.
|
|
80
|
-
doc.
|
|
81
|
-
|
|
123
|
+
drawSectionTitle(doc, title, startY) {
|
|
124
|
+
const left = doc.page.margins.left;
|
|
125
|
+
const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
|
|
126
|
+
doc.fillColor(DEFAULT_TEXT_COLOR).font(FONT_REGULAR).fontSize(SECTION_TITLE_FONT_SIZE).text(title, left, startY, { align: "left", width: usableWidth });
|
|
127
|
+
const spacing = SECTION_TITLE_FONT_SIZE * HEADER_SPACING_FACTOR;
|
|
128
|
+
const ruleY = doc.y + spacing;
|
|
129
|
+
doc.strokeColor(HEADER_RULE_COLOR).lineWidth(HEADER_RULE_WIDTH).moveTo(left, ruleY).lineTo(left + usableWidth, ruleY).stroke();
|
|
130
|
+
return ruleY + spacing;
|
|
82
131
|
}
|
|
83
|
-
drawFilters(doc, filters) {
|
|
84
|
-
doc.
|
|
85
|
-
doc.
|
|
86
|
-
filters.forEach((filter) => {
|
|
87
|
-
|
|
132
|
+
drawFilters(doc, filters, startY) {
|
|
133
|
+
const left = doc.page.margins.left;
|
|
134
|
+
doc.fillColor(DEFAULT_TEXT_COLOR).font(FONT_BOLD).fontSize(BODY_FONT_SIZE);
|
|
135
|
+
filters.forEach((filter, i) => {
|
|
136
|
+
if (i === 0) {
|
|
137
|
+
doc.text(filter.label, left, startY, { continued: true });
|
|
138
|
+
} else {
|
|
139
|
+
doc.font(FONT_BOLD).fontSize(BODY_FONT_SIZE).text(filter.label, { continued: true });
|
|
140
|
+
}
|
|
88
141
|
doc.font(FONT_REGULAR).text(`: ${filter.value}`);
|
|
89
142
|
});
|
|
143
|
+
doc.moveDown(0.5);
|
|
144
|
+
return doc.y;
|
|
145
|
+
}
|
|
146
|
+
drawAppliedFilters(doc, filters, startY) {
|
|
147
|
+
doc.fillColor(DEFAULT_TEXT_COLOR).font(FONT_BOLD).fontSize(BODY_FONT_SIZE).text("Applied Filters:", doc.page.margins.left, startY, { continued: filters.length === 0 });
|
|
148
|
+
if (filters.length === 0) {
|
|
149
|
+
doc.font(FONT_REGULAR).text(" None");
|
|
150
|
+
} else {
|
|
151
|
+
filters.forEach((filter) => {
|
|
152
|
+
doc.font(FONT_BOLD).fontSize(BODY_FONT_SIZE).text(filter.label, { continued: true });
|
|
153
|
+
doc.font(FONT_REGULAR).text(`: ${filter.value}`);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
90
156
|
doc.moveDown(1);
|
|
91
157
|
return doc.y;
|
|
92
158
|
}
|
|
93
|
-
drawTable(doc, table, startY
|
|
159
|
+
drawTable(doc, table, startY) {
|
|
94
160
|
const columns = table.columns.length > 0 ? table.columns.map((c) => ({ ...c })) : [{ header: "No data", key: "no_data", width: 100 }];
|
|
95
161
|
const rows = table.rows ?? [];
|
|
96
|
-
const baseCellPadding = 4;
|
|
97
|
-
const minColumnWidth = 35;
|
|
98
162
|
const columnCount = columns.length;
|
|
99
163
|
const headerFontSize = columnCount > 13 ? 8 : columnCount > 10 ? 9 : columnCount > 7 ? 10 : 11;
|
|
100
164
|
const dataFontSize = columnCount > 13 ? 7 : columnCount > 10 ? 8 : columnCount > 7 ? 9 : 10;
|
|
@@ -115,19 +179,26 @@ var PdfExporter = class {
|
|
|
115
179
|
}
|
|
116
180
|
});
|
|
117
181
|
const contentWidth = Math.max(headerTextWidth, maxDataWidth);
|
|
118
|
-
col.width = Math.max(contentWidth +
|
|
119
|
-
headerMinWidths.set(col, headerMinWidth +
|
|
182
|
+
col.width = Math.max(contentWidth + TABLE_CELL_PADDING * 2 + headerWidthSlack, MIN_COLUMN_WIDTH);
|
|
183
|
+
headerMinWidths.set(col, headerMinWidth + TABLE_CELL_PADDING * 2 + headerWidthSlack);
|
|
120
184
|
});
|
|
121
185
|
const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
|
|
122
|
-
const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ??
|
|
186
|
+
const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
123
187
|
if (totalColumnWidth > usableWidth) {
|
|
124
188
|
const scale = usableWidth / totalColumnWidth;
|
|
125
189
|
columns.forEach((c) => {
|
|
126
|
-
const headerMin = headerMinWidths.get(c) ??
|
|
127
|
-
c.width = Math.max(Math.floor((c.width ??
|
|
190
|
+
const headerMin = headerMinWidths.get(c) ?? MIN_COLUMN_WIDTH;
|
|
191
|
+
c.width = Math.max(Math.floor((c.width ?? MIN_COLUMN_WIDTH) * scale), headerMin, MIN_COLUMN_WIDTH);
|
|
192
|
+
});
|
|
193
|
+
} else if (totalColumnWidth < usableWidth) {
|
|
194
|
+
const scale = usableWidth / totalColumnWidth;
|
|
195
|
+
columns.forEach((c) => {
|
|
196
|
+
c.width = Math.floor((c.width ?? MIN_COLUMN_WIDTH) * scale);
|
|
128
197
|
});
|
|
198
|
+
const expanded = columns.reduce((sum, c) => sum + (c.width ?? 0), 0);
|
|
199
|
+
columns[columns.length - 1].width = (columns[columns.length - 1].width ?? 0) + (usableWidth - expanded);
|
|
129
200
|
}
|
|
130
|
-
const tableWidth = columns.reduce((sum, c) => sum + (c.width ??
|
|
201
|
+
const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
131
202
|
const pageBottom = doc.page.height - doc.page.margins.bottom;
|
|
132
203
|
const calculateRowHeight = (row, isHeader = false) => {
|
|
133
204
|
const fontSize = isHeader ? headerFontSize : dataFontSize;
|
|
@@ -136,17 +207,22 @@ var PdfExporter = class {
|
|
|
136
207
|
columns.forEach((col) => {
|
|
137
208
|
const cellValue = isHeader ? col.header : row?.[col.key] !== void 0 ? String(row[col.key]) : "";
|
|
138
209
|
const textWidth = doc.widthOfString(cellValue);
|
|
139
|
-
const availableWidth = (col.width ??
|
|
210
|
+
const availableWidth = (col.width ?? MIN_COLUMN_WIDTH) - TABLE_CELL_PADDING * 2;
|
|
140
211
|
const lines = Math.ceil(textWidth / availableWidth);
|
|
141
212
|
if (lines > maxLines) {
|
|
142
213
|
maxLines = lines;
|
|
143
214
|
}
|
|
144
215
|
});
|
|
145
|
-
return Math.max(maxLines * (fontSize + 2) +
|
|
216
|
+
return Math.max(maxLines * (fontSize + 2) + TABLE_CELL_PADDING * 2, DEFAULT_ROW_HEIGHT);
|
|
146
217
|
};
|
|
147
218
|
const headerHeight = calculateRowHeight(null, true);
|
|
148
|
-
const drawTableHeader = (y) => this.drawHeader(doc, columns, y, tableWidth, headerHeight,
|
|
149
|
-
let
|
|
219
|
+
const drawTableHeader = (y) => this.drawHeader(doc, columns, y, tableWidth, headerHeight, TABLE_CELL_PADDING, headerFontSize, MIN_COLUMN_WIDTH);
|
|
220
|
+
let tableStartY = startY;
|
|
221
|
+
if (tableStartY + headerHeight > pageBottom) {
|
|
222
|
+
doc.addPage();
|
|
223
|
+
tableStartY = doc.page.margins.top;
|
|
224
|
+
}
|
|
225
|
+
let currentY = drawTableHeader(tableStartY);
|
|
150
226
|
doc.font(FONT_REGULAR).fontSize(dataFontSize);
|
|
151
227
|
rows.forEach((row, rowIndex) => {
|
|
152
228
|
const currentRowHeight = calculateRowHeight(row, false);
|
|
@@ -158,56 +234,68 @@ var PdfExporter = class {
|
|
|
158
234
|
currentY = this.drawRow(
|
|
159
235
|
doc,
|
|
160
236
|
row,
|
|
161
|
-
rowIndex,
|
|
162
237
|
columns,
|
|
163
238
|
currentY,
|
|
164
|
-
tableWidth,
|
|
165
239
|
currentRowHeight,
|
|
166
|
-
|
|
240
|
+
TABLE_CELL_PADDING,
|
|
167
241
|
dataFontSize,
|
|
168
|
-
|
|
242
|
+
MIN_COLUMN_WIDTH,
|
|
243
|
+
rowIndex
|
|
169
244
|
);
|
|
170
245
|
});
|
|
246
|
+
const left = doc.page.margins.left;
|
|
247
|
+
const closingRuleY = currentY + SECTION_TITLE_FONT_SIZE * HEADER_SPACING_FACTOR;
|
|
248
|
+
doc.strokeColor(HEADER_RULE_COLOR).lineWidth(HEADER_RULE_WIDTH).moveTo(left, closingRuleY).lineTo(left + tableWidth, closingRuleY).stroke();
|
|
249
|
+
return closingRuleY;
|
|
171
250
|
}
|
|
172
251
|
drawHeader(doc, columns, startY, tableWidth, headerHeight, cellPadding, headerFontSize, minColumnWidth) {
|
|
173
|
-
|
|
174
|
-
doc.
|
|
175
|
-
|
|
176
|
-
|
|
252
|
+
const left = doc.page.margins.left;
|
|
253
|
+
doc.rect(left, startY, tableWidth, headerHeight).fill(HEADER_BACKGROUND_COLOR);
|
|
254
|
+
doc.strokeColor(SEPARATOR_COLOR).lineWidth(0.5).moveTo(left, startY).lineTo(left + tableWidth, startY).stroke();
|
|
255
|
+
let xPosition = left;
|
|
256
|
+
doc.fillColor(DEFAULT_TEXT_COLOR).font(FONT_BOLD).fontSize(headerFontSize);
|
|
257
|
+
const headerLineHeight = doc.currentLineHeight(true);
|
|
258
|
+
const headerTextY = startY + Math.max((headerHeight - headerLineHeight) / 2, 0);
|
|
177
259
|
columns.forEach((col) => {
|
|
178
|
-
doc.
|
|
179
|
-
doc.text(col.header, xPosition + cellPadding, startY + cellPadding, {
|
|
260
|
+
doc.text(col.header, xPosition + cellPadding, headerTextY, {
|
|
180
261
|
width: (col.width ?? minColumnWidth) - cellPadding * 2,
|
|
262
|
+
height: headerLineHeight,
|
|
181
263
|
align: "left",
|
|
182
|
-
lineBreak: false
|
|
264
|
+
lineBreak: false,
|
|
265
|
+
ellipsis: true
|
|
183
266
|
});
|
|
184
267
|
xPosition += col.width ?? minColumnWidth;
|
|
185
268
|
});
|
|
186
|
-
doc.moveTo(
|
|
187
|
-
doc.moveTo(doc.page.margins.left, startY + headerHeight).lineTo(xPosition, startY + headerHeight).stroke();
|
|
269
|
+
doc.strokeColor(SEPARATOR_COLOR).lineWidth(0.5).moveTo(left, startY + headerHeight).lineTo(left + tableWidth, startY + headerHeight).stroke();
|
|
188
270
|
return startY + headerHeight;
|
|
189
271
|
}
|
|
190
|
-
drawRow(doc, row,
|
|
191
|
-
doc.
|
|
192
|
-
|
|
193
|
-
|
|
272
|
+
drawRow(doc, row, columns, currentY, rowHeight, cellPadding, dataFontSize, minColumnWidth, rowIndex = 0) {
|
|
273
|
+
const left = doc.page.margins.left;
|
|
274
|
+
const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? minColumnWidth), 0);
|
|
275
|
+
if (rowIndex % 2 === 1) {
|
|
276
|
+
doc.rect(left, currentY, tableWidth, rowHeight).fill(ZEBRA_BACKGROUND_COLOR);
|
|
194
277
|
}
|
|
195
|
-
|
|
196
|
-
doc.
|
|
197
|
-
|
|
198
|
-
|
|
278
|
+
doc.font(FONT_REGULAR).fontSize(dataFontSize).fillColor(DEFAULT_TEXT_COLOR);
|
|
279
|
+
const dataLineHeight = doc.currentLineHeight(true);
|
|
280
|
+
const dataTextY = currentY + Math.max((rowHeight - dataLineHeight) / 2, 0);
|
|
281
|
+
let xPosition = left;
|
|
282
|
+
columns.forEach((col, i) => {
|
|
199
283
|
const rawValue = row[col.key];
|
|
200
284
|
const cellValue = typeof rawValue === "string" || typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : "";
|
|
201
285
|
const isNumeric = typeof rawValue === "number" || typeof rawValue === "string" && rawValue !== "" && !isNaN(Number(rawValue));
|
|
202
|
-
doc.text(cellValue, xPosition + cellPadding,
|
|
286
|
+
doc.text(cellValue, xPosition + cellPadding, dataTextY, {
|
|
203
287
|
width: (col.width ?? minColumnWidth) - cellPadding * 2,
|
|
288
|
+
height: dataLineHeight,
|
|
204
289
|
align: isNumeric ? "right" : "left",
|
|
205
|
-
lineBreak: false
|
|
290
|
+
lineBreak: false,
|
|
291
|
+
ellipsis: true
|
|
206
292
|
});
|
|
207
293
|
xPosition += col.width ?? minColumnWidth;
|
|
294
|
+
if (i < columns.length - 1) {
|
|
295
|
+
doc.strokeColor(SEPARATOR_COLOR).lineWidth(0.5).moveTo(xPosition, currentY).lineTo(xPosition, currentY + rowHeight).stroke();
|
|
296
|
+
}
|
|
208
297
|
});
|
|
209
|
-
doc.moveTo(
|
|
210
|
-
doc.moveTo(doc.page.margins.left, currentY + rowHeight).lineTo(xPosition, currentY + rowHeight).stroke();
|
|
298
|
+
doc.strokeColor(SEPARATOR_COLOR).lineWidth(0.5).moveTo(left, currentY + rowHeight).lineTo(left + tableWidth, currentY + rowHeight).stroke();
|
|
211
299
|
return currentY + rowHeight;
|
|
212
300
|
}
|
|
213
301
|
};
|