UNPKG

jspdf-autotable

Version:

Generate pdf tables with javascript (jsPDF plugin)

1,325 lines (1,307 loc) 88.8 kB
function getStringWidth(text, styles, doc) { doc.applyStyles(styles, true); var textArr = Array.isArray(text) ? text : [text]; var widestLineWidth = textArr .map(function (text) { return doc.getTextWidth(text); }) .reduce(function (a, b) { return Math.max(a, b); }, 0); return widestLineWidth; } function addTableBorder(doc, table, startPos, cursor) { var lineWidth = table.settings.tableLineWidth; var lineColor = table.settings.tableLineColor; doc.applyStyles({ lineWidth: lineWidth, lineColor: lineColor }); var fillStyle = getFillStyle(lineWidth, false); if (fillStyle) { doc.rect(startPos.x, startPos.y, table.getWidth(doc.pageSize().width), cursor.y - startPos.y, fillStyle); } } function getFillStyle(lineWidth, fillColor) { var drawLine = lineWidth > 0; var drawBackground = fillColor || fillColor === 0; if (drawLine && drawBackground) { return 'DF'; // Fill then stroke } else if (drawLine) { return 'S'; // Only stroke (transparent background) } else if (drawBackground) { return 'F'; // Only fill, no stroke } else { return null; } } function parseSpacing(value, defaultValue) { var _a, _b, _c, _d; value = value || defaultValue; if (Array.isArray(value)) { if (value.length >= 4) { return { top: value[0], right: value[1], bottom: value[2], left: value[3], }; } else if (value.length === 3) { return { top: value[0], right: value[1], bottom: value[2], left: value[1], }; } else if (value.length === 2) { return { top: value[0], right: value[1], bottom: value[0], left: value[1], }; } else if (value.length === 1) { value = value[0]; } else { value = defaultValue; } } if (typeof value === 'object') { if (typeof value.vertical === 'number') { value.top = value.vertical; value.bottom = value.vertical; } if (typeof value.horizontal === 'number') { value.right = value.horizontal; value.left = value.horizontal; } return { left: (_a = value.left) !== null && _a !== void 0 ? _a : defaultValue, top: (_b = value.top) !== null && _b !== void 0 ? _b : defaultValue, right: (_c = value.right) !== null && _c !== void 0 ? _c : defaultValue, bottom: (_d = value.bottom) !== null && _d !== void 0 ? _d : defaultValue, }; } if (typeof value !== 'number') { value = defaultValue; } return { top: value, right: value, bottom: value, left: value }; } function getPageAvailableWidth(doc, table) { var margins = parseSpacing(table.settings.margin, 0); return doc.pageSize().width - (margins.left + margins.right); } // Limitations // - No support for border spacing // - No support for transparency function parseCss(supportedFonts, element, scaleFactor, style, window) { var result = {}; var pxScaleFactor = 96 / 72; var backgroundColor = parseColor(element, function (elem) { return window.getComputedStyle(elem)['backgroundColor']; }); if (backgroundColor != null) result.fillColor = backgroundColor; var textColor = parseColor(element, function (elem) { return window.getComputedStyle(elem)['color']; }); if (textColor != null) result.textColor = textColor; var padding = parsePadding(style, scaleFactor); if (padding) result.cellPadding = padding; var borderColorSide = 'borderTopColor'; var finalScaleFactor = pxScaleFactor * scaleFactor; var btw = style.borderTopWidth; if (style.borderBottomWidth === btw && style.borderRightWidth === btw && style.borderLeftWidth === btw) { var borderWidth = (parseFloat(btw) || 0) / finalScaleFactor; if (borderWidth) result.lineWidth = borderWidth; } else { result.lineWidth = { top: (parseFloat(style.borderTopWidth) || 0) / finalScaleFactor, right: (parseFloat(style.borderRightWidth) || 0) / finalScaleFactor, bottom: (parseFloat(style.borderBottomWidth) || 0) / finalScaleFactor, left: (parseFloat(style.borderLeftWidth) || 0) / finalScaleFactor, }; // Choose border color of first available side // could be improved by supporting object as lineColor if (!result.lineWidth.top) { if (result.lineWidth.right) { borderColorSide = 'borderRightColor'; } else if (result.lineWidth.bottom) { borderColorSide = 'borderBottomColor'; } else if (result.lineWidth.left) { borderColorSide = 'borderLeftColor'; } } } var borderColor = parseColor(element, function (elem) { return window.getComputedStyle(elem)[borderColorSide]; }); if (borderColor != null) result.lineColor = borderColor; var accepted = ['left', 'right', 'center', 'justify']; if (accepted.indexOf(style.textAlign) !== -1) { result.halign = style.textAlign; } accepted = ['middle', 'bottom', 'top']; if (accepted.indexOf(style.verticalAlign) !== -1) { result.valign = style.verticalAlign; } var res = parseInt(style.fontSize || ''); if (!isNaN(res)) result.fontSize = res / pxScaleFactor; var fontStyle = parseFontStyle(style); if (fontStyle) result.fontStyle = fontStyle; var font = (style.fontFamily || '').toLowerCase(); if (supportedFonts.indexOf(font) !== -1) { result.font = font; } return result; } function parseFontStyle(style) { var res = ''; if (style.fontWeight === 'bold' || style.fontWeight === 'bolder' || parseInt(style.fontWeight) >= 700) { res = 'bold'; } if (style.fontStyle === 'italic' || style.fontStyle === 'oblique') { res += 'italic'; } return res; } function parseColor(element, styleGetter) { var cssColor = realColor(element, styleGetter); if (!cssColor) return null; var rgba = cssColor.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d*\.?\d*))?\)$/); if (!rgba || !Array.isArray(rgba)) { return null; } var color = [ parseInt(rgba[1]), parseInt(rgba[2]), parseInt(rgba[3]), ]; var alpha = parseInt(rgba[4]); if (alpha === 0 || isNaN(color[0]) || isNaN(color[1]) || isNaN(color[2])) { return null; } return color; } function realColor(elem, styleGetter) { var bg = styleGetter(elem); if (bg === 'rgba(0, 0, 0, 0)' || bg === 'transparent' || bg === 'initial' || bg === 'inherit') { if (elem.parentElement == null) { return null; } return realColor(elem.parentElement, styleGetter); } else { return bg; } } function parsePadding(style, scaleFactor) { var val = [ style.paddingTop, style.paddingRight, style.paddingBottom, style.paddingLeft, ]; var pxScaleFactor = 96 / (72 / scaleFactor); var linePadding = (parseInt(style.lineHeight) - parseInt(style.fontSize)) / scaleFactor / 2; var inputPadding = val.map(function (n) { return parseInt(n || '0') / pxScaleFactor; }); var padding = parseSpacing(inputPadding, 0); if (linePadding > padding.top) { padding.top = linePadding; } if (linePadding > padding.bottom) { padding.bottom = linePadding; } return padding; } /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var HtmlRowInput = /** @class */ (function (_super) { __extends(HtmlRowInput, _super); function HtmlRowInput(element) { var _this = _super.call(this) || this; _this._element = element; return _this; } return HtmlRowInput; }(Array)); // Base style for all themes function defaultStyles(scaleFactor) { return { font: 'helvetica', // helvetica, times, courier fontStyle: 'normal', // normal, bold, italic, bolditalic overflow: 'linebreak', // linebreak, ellipsize, visible or hidden fillColor: false, // Either false for transparent, rbg array e.g. [255, 255, 255] or gray level e.g 200 textColor: 20, halign: 'left', // left, center, right, justify valign: 'top', // top, middle, bottom fontSize: 10, cellPadding: 5 / scaleFactor, // number or {top,left,right,left,vertical,horizontal} lineColor: 200, lineWidth: 0, cellWidth: 'auto', // 'auto'|'wrap'|number minCellHeight: 0, minCellWidth: 0, }; } function getTheme(name) { var themes = { striped: { table: { fillColor: 255, textColor: 80, fontStyle: 'normal' }, head: { textColor: 255, fillColor: [41, 128, 185], fontStyle: 'bold' }, body: {}, foot: { textColor: 255, fillColor: [41, 128, 185], fontStyle: 'bold' }, alternateRow: { fillColor: 245 }, }, grid: { table: { fillColor: 255, textColor: 80, fontStyle: 'normal', lineWidth: 0.1, }, head: { textColor: 255, fillColor: [26, 188, 156], fontStyle: 'bold', lineWidth: 0, }, body: {}, foot: { textColor: 255, fillColor: [26, 188, 156], fontStyle: 'bold', lineWidth: 0, }, alternateRow: {}, }, plain: { head: { fontStyle: 'bold' }, foot: { fontStyle: 'bold' }, }, }; return themes[name]; } function parseHtml(doc, input, window, includeHiddenHtml, useCss) { var _a, _b; if (includeHiddenHtml === void 0) { includeHiddenHtml = false; } if (useCss === void 0) { useCss = false; } var tableElement; if (typeof input === 'string') { tableElement = window.document.querySelector(input); } else { tableElement = input; } var supportedFonts = Object.keys(doc.getFontList()); var scaleFactor = doc.scaleFactor(); var head = [], body = [], foot = []; if (!tableElement) { console.error('Html table could not be found with input: ', input); return { head: head, body: body, foot: foot }; } for (var i = 0; i < tableElement.rows.length; i++) { var element = tableElement.rows[i]; var tagName = (_b = (_a = element === null || element === void 0 ? void 0 : element.parentElement) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toLowerCase(); var row = parseRowContent(supportedFonts, scaleFactor, window, element, includeHiddenHtml, useCss); if (!row) continue; if (tagName === 'thead') { head.push(row); } else if (tagName === 'tfoot') { foot.push(row); } else { // Add to body both if parent is tbody or table body.push(row); } } return { head: head, body: body, foot: foot }; } function parseRowContent(supportedFonts, scaleFactor, window, row, includeHidden, useCss) { var resultRow = new HtmlRowInput(row); for (var i = 0; i < row.cells.length; i++) { var cell = row.cells[i]; var style_1 = window.getComputedStyle(cell); if (includeHidden || style_1.display !== 'none') { var cellStyles = void 0; if (useCss) { cellStyles = parseCss(supportedFonts, cell, scaleFactor, style_1, window); } resultRow.push({ rowSpan: cell.rowSpan, colSpan: cell.colSpan, styles: cellStyles, _element: cell, content: parseCellContent(cell), }); } } var style = window.getComputedStyle(row); if (resultRow.length > 0 && (includeHidden || style.display !== 'none')) { return resultRow; } } function parseCellContent(orgCell) { // Work on cloned node to make sure no changes are applied to html table var cell = orgCell.cloneNode(true); // Remove extra space and line breaks in markup to make it more similar to // what would be shown in html cell.innerHTML = cell.innerHTML.replace(/\n/g, '').replace(/ +/g, ' '); // Preserve <br> tags as line breaks in the pdf cell.innerHTML = cell.innerHTML .split(/<br.*?>/) //start with '<br' and ends with '>'. .map(function (part) { return part.trim(); }) .join('\n'); // innerText for ie return cell.innerText || cell.textContent || ''; } /** * Improved text function with halign and valign support * Inspiration from: http://stackoverflow.com/questions/28327510/align-text-right-using-jspdf/28433113#28433113 */ function autoTableText (text, x, y, styles, doc) { styles = styles || {}; var PHYSICAL_LINE_HEIGHT = 1.15; var k = doc.internal.scaleFactor; var fontSize = doc.internal.getFontSize() / k; var lineHeightFactor = doc.getLineHeightFactor ? doc.getLineHeightFactor() : PHYSICAL_LINE_HEIGHT; var lineHeight = fontSize * lineHeightFactor; var splitRegex = /\r\n|\r|\n/g; var splitText = ''; var lineCount = 1; if (styles.valign === 'middle' || styles.valign === 'bottom' || styles.halign === 'center' || styles.halign === 'right') { splitText = typeof text === 'string' ? text.split(splitRegex) : text; lineCount = splitText.length || 1; } // Align the top y += fontSize * (2 - PHYSICAL_LINE_HEIGHT); if (styles.valign === 'middle') y -= (lineCount / 2) * lineHeight; else if (styles.valign === 'bottom') y -= lineCount * lineHeight; if (styles.halign === 'center' || styles.halign === 'right') { var alignSize = fontSize; if (styles.halign === 'center') alignSize *= 0.5; if (splitText && lineCount >= 1) { for (var iLine = 0; iLine < splitText.length; iLine++) { doc.text(splitText[iLine], x - doc.getStringUnitWidth(splitText[iLine]) * alignSize, y); y += lineHeight; } return doc; } x -= doc.getStringUnitWidth(text) * alignSize; } if (styles.halign === 'justify') { doc.text(text, x, y, { maxWidth: styles.maxWidth || 100, align: 'justify', }); } else { doc.text(text, x, y); } return doc; } var globalDefaults = {}; var DocHandler = /** @class */ (function () { function DocHandler(jsPDFDocument) { this.jsPDFDocument = jsPDFDocument; this.userStyles = { // Black for versions of jspdf without getTextColor textColor: jsPDFDocument.getTextColor ? this.jsPDFDocument.getTextColor() : 0, fontSize: jsPDFDocument.internal.getFontSize(), fontStyle: jsPDFDocument.internal.getFont().fontStyle, font: jsPDFDocument.internal.getFont().fontName, // 0 for versions of jspdf without getLineWidth lineWidth: jsPDFDocument.getLineWidth ? this.jsPDFDocument.getLineWidth() : 0, // Black for versions of jspdf without getDrawColor lineColor: jsPDFDocument.getDrawColor ? this.jsPDFDocument.getDrawColor() : 0, }; } DocHandler.setDefaults = function (defaults, doc) { if (doc === void 0) { doc = null; } if (doc) { doc.__autoTableDocumentDefaults = defaults; } else { globalDefaults = defaults; } }; DocHandler.unifyColor = function (c) { if (Array.isArray(c)) { return c; } else if (typeof c === 'number') { return [c, c, c]; } else if (typeof c === 'string') { return [c]; } else { return null; } }; DocHandler.prototype.applyStyles = function (styles, fontOnly) { // Font style needs to be applied before font // https://github.com/simonbengtsson/jsPDF-AutoTable/issues/632 var _a, _b, _c; if (fontOnly === void 0) { fontOnly = false; } if (styles.fontStyle) this.jsPDFDocument.setFontStyle && this.jsPDFDocument.setFontStyle(styles.fontStyle); var _d = this.jsPDFDocument.internal.getFont(), fontStyle = _d.fontStyle, fontName = _d.fontName; if (styles.font) fontName = styles.font; if (styles.fontStyle) { fontStyle = styles.fontStyle; var availableFontStyles = this.getFontList()[fontName]; if (availableFontStyles && availableFontStyles.indexOf(fontStyle) === -1) { // Common issue was that the default bold in headers // made custom fonts not work. For example: // https://github.com/simonbengtsson/jsPDF-AutoTable/issues/653 this.jsPDFDocument.setFontStyle && this.jsPDFDocument.setFontStyle(availableFontStyles[0]); fontStyle = availableFontStyles[0]; } } this.jsPDFDocument.setFont(fontName, fontStyle); if (styles.fontSize) this.jsPDFDocument.setFontSize(styles.fontSize); if (fontOnly) { return; // Performance improvement } var color = DocHandler.unifyColor(styles.fillColor); if (color) (_a = this.jsPDFDocument).setFillColor.apply(_a, color); color = DocHandler.unifyColor(styles.textColor); if (color) (_b = this.jsPDFDocument).setTextColor.apply(_b, color); color = DocHandler.unifyColor(styles.lineColor); if (color) (_c = this.jsPDFDocument).setDrawColor.apply(_c, color); if (typeof styles.lineWidth === 'number') { this.jsPDFDocument.setLineWidth(styles.lineWidth); } }; DocHandler.prototype.splitTextToSize = function (text, size, opts) { return this.jsPDFDocument.splitTextToSize(text, size, opts); }; /** * Adds a rectangle to the PDF * @param x Coordinate (in units declared at inception of PDF document) against left edge of the page * @param y Coordinate (in units declared at inception of PDF document) against upper edge of the page * @param width Width (in units declared at inception of PDF document) * @param height Height (in units declared at inception of PDF document) * @param fillStyle A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. */ DocHandler.prototype.rect = function (x, y, width, height, fillStyle) { // null is excluded from fillStyle possible values because it isn't needed // and is prone to bugs as it's used to postpone setting the style // https://rawgit.com/MrRio/jsPDF/master/docs/jsPDF.html#rect return this.jsPDFDocument.rect(x, y, width, height, fillStyle); }; DocHandler.prototype.getLastAutoTable = function () { return this.jsPDFDocument.lastAutoTable || null; }; DocHandler.prototype.getTextWidth = function (text) { return this.jsPDFDocument.getTextWidth(text); }; DocHandler.prototype.getDocument = function () { return this.jsPDFDocument; }; DocHandler.prototype.setPage = function (page) { this.jsPDFDocument.setPage(page); }; DocHandler.prototype.addPage = function () { return this.jsPDFDocument.addPage(); }; DocHandler.prototype.getFontList = function () { return this.jsPDFDocument.getFontList(); }; DocHandler.prototype.getGlobalOptions = function () { return globalDefaults || {}; }; DocHandler.prototype.getDocumentOptions = function () { return this.jsPDFDocument.__autoTableDocumentDefaults || {}; }; DocHandler.prototype.pageSize = function () { var pageSize = this.jsPDFDocument.internal.pageSize; // JSPDF 1.4 uses get functions instead of properties on pageSize if (pageSize.width == null) { pageSize = { width: pageSize.getWidth(), height: pageSize.getHeight(), }; } return pageSize; }; DocHandler.prototype.scaleFactor = function () { return this.jsPDFDocument.internal.scaleFactor; }; DocHandler.prototype.getLineHeightFactor = function () { var doc = this.jsPDFDocument; return doc.getLineHeightFactor ? doc.getLineHeightFactor() : 1.15; }; DocHandler.prototype.getLineHeight = function (fontSize) { return (fontSize / this.scaleFactor()) * this.getLineHeightFactor(); }; DocHandler.prototype.pageNumber = function () { var pageInfo = this.jsPDFDocument.internal.getCurrentPageInfo(); if (!pageInfo) { // Only recent versions of jspdf has pageInfo return this.jsPDFDocument.internal.getNumberOfPages(); } return pageInfo.pageNumber; }; return DocHandler; }()); /* eslint-disable @typescript-eslint/no-unused-vars */ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign function assign(target, s, s1, s2, s3) { if (target == null) { throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { // eslint-disable-next-line prefer-rest-params var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; } function validateOptions (doc, global, document, current) { var _loop_1 = function (options) { if (options && typeof options !== 'object') { console.error('The options parameter should be of type object, is: ' + typeof options); } if (typeof options.extendWidth !== 'undefined') { options.tableWidth = options.extendWidth ? 'auto' : 'wrap'; console.error('Use of deprecated option: extendWidth, use tableWidth instead.'); } if (typeof options.margins !== 'undefined') { if (typeof options.margin === 'undefined') options.margin = options.margins; console.error('Use of deprecated option: margins, use margin instead.'); } if (options.startY && typeof options.startY !== 'number') { console.error('Invalid value for startY option', options.startY); delete options.startY; } if (!options.didDrawPage && (options.afterPageContent || options.beforePageContent || options.afterPageAdd)) { console.error('The afterPageContent, beforePageContent and afterPageAdd hooks are deprecated. Use didDrawPage instead'); options.didDrawPage = function (data) { doc.applyStyles(doc.userStyles); if (options.beforePageContent) options.beforePageContent(data); doc.applyStyles(doc.userStyles); if (options.afterPageContent) options.afterPageContent(data); doc.applyStyles(doc.userStyles); if (options.afterPageAdd && data.pageNumber > 1) { data.afterPageAdd(data); } doc.applyStyles(doc.userStyles); }; } [ 'createdHeaderCell', 'drawHeaderRow', 'drawRow', 'drawHeaderCell', ].forEach(function (name) { if (options[name]) { console.error("The \"".concat(name, "\" hook has changed in version 3.0, check the changelog for how to migrate.")); } }); [ ['showFoot', 'showFooter'], ['showHead', 'showHeader'], ['didDrawPage', 'addPageContent'], ['didParseCell', 'createdCell'], ['headStyles', 'headerStyles'], ].forEach(function (_a) { var current = _a[0], deprecated = _a[1]; if (options[deprecated]) { console.error("Use of deprecated option ".concat(deprecated, ". Use ").concat(current, " instead")); options[current] = options[deprecated]; } }); [ ['padding', 'cellPadding'], ['lineHeight', 'rowHeight'], 'fontSize', 'overflow', ].forEach(function (o) { var deprecatedOption = typeof o === 'string' ? o : o[0]; var style = typeof o === 'string' ? o : o[1]; if (typeof options[deprecatedOption] !== 'undefined') { if (typeof options.styles[style] === 'undefined') { options.styles[style] = options[deprecatedOption]; } console.error('Use of deprecated option: ' + deprecatedOption + ', use the style ' + style + ' instead.'); } }); for (var _b = 0, _c = [ 'styles', 'bodyStyles', 'headStyles', 'footStyles', ]; _b < _c.length; _b++) { var styleProp = _c[_b]; checkStyles(options[styleProp] || {}); } var columnStyles = options['columnStyles'] || {}; for (var _d = 0, _e = Object.keys(columnStyles); _d < _e.length; _d++) { var key = _e[_d]; checkStyles(columnStyles[key] || {}); } }; for (var _i = 0, _a = [global, document, current]; _i < _a.length; _i++) { var options = _a[_i]; _loop_1(options); } } function checkStyles(styles) { if (styles.rowHeight) { console.error('Use of deprecated style rowHeight. It is renamed to minCellHeight.'); if (!styles.minCellHeight) { styles.minCellHeight = styles.rowHeight; } } else if (styles.columnWidth) { console.error('Use of deprecated style columnWidth. It is renamed to cellWidth.'); if (!styles.cellWidth) { styles.cellWidth = styles.columnWidth; } } } function parseInput(d, current) { var doc = new DocHandler(d); var document = doc.getDocumentOptions(); var global = doc.getGlobalOptions(); validateOptions(doc, global, document, current); var options = assign({}, global, document, current); var win; if (typeof window !== 'undefined') { win = window; } var styles = parseStyles(global, document, current); var hooks = parseHooks(global, document, current); var settings = parseSettings(doc, options); var content = parseContent$1(doc, options, win); return { id: current.tableId, content: content, hooks: hooks, styles: styles, settings: settings, }; } function parseStyles(gInput, dInput, cInput) { var styleOptions = { styles: {}, headStyles: {}, bodyStyles: {}, footStyles: {}, alternateRowStyles: {}, columnStyles: {}, }; var _loop_1 = function (prop) { if (prop === 'columnStyles') { var global_1 = gInput[prop]; var document_1 = dInput[prop]; var current = cInput[prop]; styleOptions.columnStyles = assign({}, global_1, document_1, current); } else { var allOptions = [gInput, dInput, cInput]; var styles = allOptions.map(function (opts) { return opts[prop] || {}; }); styleOptions[prop] = assign({}, styles[0], styles[1], styles[2]); } }; for (var _i = 0, _a = Object.keys(styleOptions); _i < _a.length; _i++) { var prop = _a[_i]; _loop_1(prop); } return styleOptions; } function parseHooks(global, document, current) { var allOptions = [global, document, current]; var result = { didParseCell: [], willDrawCell: [], didDrawCell: [], willDrawPage: [], didDrawPage: [], }; for (var _i = 0, allOptions_1 = allOptions; _i < allOptions_1.length; _i++) { var options = allOptions_1[_i]; if (options.didParseCell) result.didParseCell.push(options.didParseCell); if (options.willDrawCell) result.willDrawCell.push(options.willDrawCell); if (options.didDrawCell) result.didDrawCell.push(options.didDrawCell); if (options.willDrawPage) result.willDrawPage.push(options.willDrawPage); if (options.didDrawPage) result.didDrawPage.push(options.didDrawPage); } return result; } function parseSettings(doc, options) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; var margin = parseSpacing(options.margin, 40 / doc.scaleFactor()); var startY = (_a = getStartY(doc, options.startY)) !== null && _a !== void 0 ? _a : margin.top; var showFoot; if (options.showFoot === true) { showFoot = 'everyPage'; } else if (options.showFoot === false) { showFoot = 'never'; } else { showFoot = (_b = options.showFoot) !== null && _b !== void 0 ? _b : 'everyPage'; } var showHead; if (options.showHead === true) { showHead = 'everyPage'; } else if (options.showHead === false) { showHead = 'never'; } else { showHead = (_c = options.showHead) !== null && _c !== void 0 ? _c : 'everyPage'; } var useCss = (_d = options.useCss) !== null && _d !== void 0 ? _d : false; var theme = options.theme || (useCss ? 'plain' : 'striped'); var horizontalPageBreak = !!options.horizontalPageBreak; var horizontalPageBreakRepeat = (_e = options.horizontalPageBreakRepeat) !== null && _e !== void 0 ? _e : null; return { includeHiddenHtml: (_f = options.includeHiddenHtml) !== null && _f !== void 0 ? _f : false, useCss: useCss, theme: theme, startY: startY, margin: margin, pageBreak: (_g = options.pageBreak) !== null && _g !== void 0 ? _g : 'auto', rowPageBreak: (_h = options.rowPageBreak) !== null && _h !== void 0 ? _h : 'auto', tableWidth: (_j = options.tableWidth) !== null && _j !== void 0 ? _j : 'auto', showHead: showHead, showFoot: showFoot, tableLineWidth: (_k = options.tableLineWidth) !== null && _k !== void 0 ? _k : 0, tableLineColor: (_l = options.tableLineColor) !== null && _l !== void 0 ? _l : 200, horizontalPageBreak: horizontalPageBreak, horizontalPageBreakRepeat: horizontalPageBreakRepeat, horizontalPageBreakBehaviour: (_m = options.horizontalPageBreakBehaviour) !== null && _m !== void 0 ? _m : 'afterAllRows', }; } function getStartY(doc, userStartY) { var previous = doc.getLastAutoTable(); var sf = doc.scaleFactor(); var currentPage = doc.pageNumber(); var isSamePageAsPreviousTable = false; if (previous && previous.startPageNumber) { var endingPage = previous.startPageNumber + previous.pageNumber - 1; isSamePageAsPreviousTable = endingPage === currentPage; } if (typeof userStartY === 'number') { return userStartY; } else if (userStartY == null || userStartY === false) { if (isSamePageAsPreviousTable && (previous === null || previous === void 0 ? void 0 : previous.finalY) != null) { // Some users had issues with overlapping tables when they used multiple // tables without setting startY so setting it here to a sensible default. return previous.finalY + 20 / sf; } } return null; } function parseContent$1(doc, options, window) { var head = options.head || []; var body = options.body || []; var foot = options.foot || []; if (options.html) { var hidden = options.includeHiddenHtml; if (window) { var htmlContent = parseHtml(doc, options.html, window, hidden, options.useCss) || {}; head = htmlContent.head || head; body = htmlContent.body || head; foot = htmlContent.foot || head; } else { console.error('Cannot parse html in non browser environment'); } } var columns = options.columns || parseColumns(head, body, foot); return { columns: columns, head: head, body: body, foot: foot, }; } function parseColumns(head, body, foot) { var firstRow = head[0] || body[0] || foot[0] || []; var result = []; Object.keys(firstRow) .filter(function (key) { return key !== '_element'; }) .forEach(function (key) { var colSpan = 1; var input; if (Array.isArray(firstRow)) { input = firstRow[parseInt(key)]; } else { input = firstRow[key]; } if (typeof input === 'object' && !Array.isArray(input)) { colSpan = (input === null || input === void 0 ? void 0 : input.colSpan) || 1; } for (var i = 0; i < colSpan; i++) { var id = void 0; if (Array.isArray(firstRow)) { id = result.length; } else { id = key + (i > 0 ? "_".concat(i) : ''); } var rowResult = { dataKey: id }; result.push(rowResult); } }); return result; } var HookData = /** @class */ (function () { function HookData(doc, table, cursor) { this.table = table; this.pageNumber = table.pageNumber; this.pageCount = this.pageNumber; this.settings = table.settings; this.cursor = cursor; this.doc = doc.getDocument(); } return HookData; }()); var CellHookData = /** @class */ (function (_super) { __extends(CellHookData, _super); function CellHookData(doc, table, cell, row, column, cursor) { var _this = _super.call(this, doc, table, cursor) || this; _this.cell = cell; _this.row = row; _this.column = column; _this.section = row.section; return _this; } return CellHookData; }(HookData)); var Table = /** @class */ (function () { function Table(input, content) { this.pageNumber = 1; // Deprecated, use pageNumber instead // Not using getter since: // https://github.com/simonbengtsson/jsPDF-AutoTable/issues/596 this.pageCount = 1; this.id = input.id; this.settings = input.settings; this.styles = input.styles; this.hooks = input.hooks; this.columns = content.columns; this.head = content.head; this.body = content.body; this.foot = content.foot; } Table.prototype.getHeadHeight = function (columns) { return this.head.reduce(function (acc, row) { return acc + row.getMaxCellHeight(columns); }, 0); }; Table.prototype.getFootHeight = function (columns) { return this.foot.reduce(function (acc, row) { return acc + row.getMaxCellHeight(columns); }, 0); }; Table.prototype.allRows = function () { return this.head.concat(this.body).concat(this.foot); }; Table.prototype.callCellHooks = function (doc, handlers, cell, row, column, cursor) { for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) { var handler = handlers_1[_i]; var data = new CellHookData(doc, this, cell, row, column, cursor); var result = handler(data) === false; // Make sure text is always string[] since user can assign string cell.text = Array.isArray(cell.text) ? cell.text : [cell.text]; if (result) { return false; } } return true; }; Table.prototype.callEndPageHooks = function (doc, cursor) { doc.applyStyles(doc.userStyles); for (var _i = 0, _a = this.hooks.didDrawPage; _i < _a.length; _i++) { var handler = _a[_i]; handler(new HookData(doc, this, cursor)); } }; Table.prototype.callWillDrawPageHooks = function (doc, cursor) { for (var _i = 0, _a = this.hooks.willDrawPage; _i < _a.length; _i++) { var handler = _a[_i]; handler(new HookData(doc, this, cursor)); } }; Table.prototype.getWidth = function (pageWidth) { if (typeof this.settings.tableWidth === 'number') { return this.settings.tableWidth; } else if (this.settings.tableWidth === 'wrap') { var wrappedWidth = this.columns.reduce(function (total, col) { return total + col.wrappedWidth; }, 0); return wrappedWidth; } else { var margin = this.settings.margin; return pageWidth - margin.left - margin.right; } }; return Table; }()); var Row = /** @class */ (function () { function Row(raw, index, section, cells, spansMultiplePages) { if (spansMultiplePages === void 0) { spansMultiplePages = false; } this.height = 0; this.raw = raw; if (raw instanceof HtmlRowInput) { this.raw = raw._element; this.element = raw._element; } this.index = index; this.section = section; this.cells = cells; this.spansMultiplePages = spansMultiplePages; } Row.prototype.getMaxCellHeight = function (columns) { var _this = this; return columns.reduce(function (acc, column) { var _a; return Math.max(acc, ((_a = _this.cells[column.index]) === null || _a === void 0 ? void 0 : _a.height) || 0); }, 0); }; Row.prototype.hasRowSpan = function (columns) { var _this = this; return (columns.filter(function (column) { var cell = _this.cells[column.index]; if (!cell) return false; return cell.rowSpan > 1; }).length > 0); }; Row.prototype.canEntireRowFit = function (height, columns) { return this.getMaxCellHeight(columns) <= height; }; Row.prototype.getMinimumRowHeight = function (columns, doc) { var _this = this; return columns.reduce(function (acc, column) { var cell = _this.cells[column.index]; if (!cell) return 0; var lineHeight = doc.getLineHeight(cell.styles.fontSize); var vPadding = cell.padding('vertical'); var oneRowHeight = vPadding + lineHeight; return oneRowHeight > acc ? oneRowHeight : acc; }, 0); }; return Row; }()); var Cell = /** @class */ (function () { function Cell(raw, styles, section) { var _a, _b; this.contentHeight = 0; this.contentWidth = 0; this.wrappedWidth = 0; this.minReadableWidth = 0; this.minWidth = 0; this.width = 0; this.height = 0; this.x = 0; this.y = 0; this.styles = styles; this.section = section; this.raw = raw; var content = raw; if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) { this.rowSpan = raw.rowSpan || 1; this.colSpan = raw.colSpan || 1; content = (_b = (_a = raw.content) !== null && _a !== void 0 ? _a : raw.title) !== null && _b !== void 0 ? _b : raw; if (raw._element) { this.raw = raw._element; } } else { this.rowSpan = 1; this.colSpan = 1; } // Stringify 0 and false, but not undefined or null var text = content != null ? '' + content : ''; var splitRegex = /\r\n|\r|\n/g; this.text = text.split(splitRegex); } Cell.prototype.getTextPos = function () { var y; if (this.styles.valign === 'top') { y = this.y + this.padding('top'); } else if (this.styles.valign === 'bottom') { y = this.y + this.height - this.padding('bottom'); } else { var netHeight = this.height - this.padding('vertical'); y = this.y + netHeight / 2 + this.padding('top'); } var x; if (this.styles.halign === 'right') { x = this.x + this.width - this.padding('right'); } else if (this.styles.halign === 'center') { var netWidth = this.width - this.padding('horizontal'); x = this.x + netWidth / 2 + this.padding('left'); } else { x = this.x + this.padding('left'); } return { x: x, y: y }; }; // TODO (v4): replace parameters with only (lineHeight) Cell.prototype.getContentHeight = function (scaleFactor, lineHeightFactor) { if (lineHeightFactor === void 0) { lineHeightFactor = 1.15; } var lineCount = Array.isArray(this.text) ? this.text.length : 1; var lineHeight = (this.styles.fontSize / scaleFactor) * lineHeightFactor; var height = lineCount * lineHeight + this.padding('vertical'); return Math.max(height, this.styles.minCellHeight); }; Cell.prototype.padding = function (name) { var padding = parseSpacing(this.styles.cellPadding, 0); if (name === 'vertical') { return padding.top + padding.bottom; } else if (name === 'horizontal') { return padding.left + padding.right; } else { return padding[name]; } }; return Cell; }()); var Column = /** @class */ (function () { function Column(dataKey, raw, index) { this.wrappedWidth = 0; this.minReadableWidth = 0; this.minWidth = 0; this.width = 0; this.dataKey = dataKey; this.raw = raw; this.index = index; } Column.prototype.getMaxCustomCellWidth = function (table) { var max = 0; for (var _i = 0, _a = table.allRows(); _i < _a.length; _i++) { var row = _a[_i]; var cell = row.cells[this.index]; if (cell && typeof cell.styles.cellWidth === 'number') { max = Math.max(max, cell.styles.cellWidth); } } return max; }; return Column; }()); // get columns can be fit into page function getColumnsCanFitInPage(doc, table, config) { var _a; if (config === void 0) { config = {}; } // Get page width var remainingWidth = getPageAvailableWidth(doc, table); // Get column data key to repeat var repeatColumnsMap = new Map(); var colIndexes = []; var columns = []; var horizontalPageBreakRepeat = []; table.settings.horizontalPageBreakRepeat; if (Array.isArray(table.settings.horizontalPageBreakRepeat)) { horizontalPageBreakRepeat = table.settings.horizontalPageBreakRepeat; // It can be a single value of type string or number (even number: 0) } else if (typeof table.settings.horizontalPageBreakRepeat === 'string' || typeof table.settings.horizontalPageBreakRepeat === 'number') { horizontalPageBreakRepeat = [table.settings.horizontalPageBreakRepeat]; } // Code to repeat the given column in split pages horizontalPageBreakRepeat.forEach(function (field) { var col = table.columns.find(function (item) { return item.dataKey === field || item.index === field; }); if (col && !repeatColumnsMap.has(col.index)) { repeatColumnsMap.set(col.index, true); colIndexes.push(col.index); columns.push(table.columns[col.index]); remainingWidth -= col.wrappedWidth; } }); var first = true; var i = (_a = config === null || config === void 0 ? void 0 : config.start) !== null && _a !== void 0 ? _a : 0; // make sure couter is initiated outside the loop while (i < table.columns.length) { // Prevent duplicates if (repeatColumnsMap.has(i)) { i++; continue; } var colWidth = table.columns[i].wrappedWidth; // Take at least one column even if it doesn't fit if (first || remainingWidth >= colWidth) { first = false; colIndexes.push(i); columns.push(table.columns[i]); remainingWidth -= colWidth; } else { break; } i++; } return { colIndexes: colIndexes, columns: columns, lastIndex: i - 1 }; } function calculateAllColumnsCanFitInPage(doc, table) { var allResults = []; for (var i = 0; i < table.columns.length; i++) { var result = getColumnsCanFitInPage(doc, table, { start: i }); if (result.columns.length) { allResults.push(result); i = result.lastIndex; } } return allResults; } function drawTable(jsPDFDoc, table) { var settings = table.settings; var startY = settings.startY; var margin = settings.margin; var cursor = { x: margin.left, y: startY, }; var sectionsHeight = table.getHeadHeight(table.columns) + table.getFootHeight(table.columns); var minTableBottomPos = startY + margin.bottom + sectionsHeight; if (settings.pageBreak === 'avoid') { var rows = table.body; var tableHeight = rows.reduce(function (acc, row) { return acc + row.height; }, 0); minTableBottomPos += tableHeight; } var doc = new DocHandler(jsPDFDoc); if (settings.pageBreak === 'always' || (settings.startY != null && minTableBottomPos > doc.pageSize().height)) { nextPage(doc); cursor.y = margin.top; } table.callWillDrawPageHooks(doc, cursor); var startPos = assign({}, cursor); table.startPageNumber = doc.pageNumber(); if (settings.horizontalPageBreak) { // managed flow for split columns printTableWithHorizontalPageBreak(doc, table, startPos, cursor); } else { // normal flow doc.applyStyles(doc.userStyles); if (settings.showHead === 'firstPage' || settings.showHead === 'everyPage') { table.head.forEach(function (row) { return printRow(doc, table, row, cursor, table.columns); }); } doc.applyStyles(doc.userStyles); table.body.forEach(function (row, index) { var isLastRow = index === table.body.length - 1; printFullRow(doc, table, row, isLastRow, startPos, cursor, table.columns); }); doc.applyStyles(doc.userStyles); if (settings.showFoot === 'lastPage' || settings.showFoot === 'everyPage') { table.foot.forEach(function (row) { return printRow(doc, table, row, cursor, table.columns); }); } } addTableBorder(doc, table, startPos, cursor); table.callEndPageHooks(doc, cursor); table.finalY = cursor.y; jsPDFDoc.lastAutoTable = table; jsPDFDoc.previousAutoTable = table; // Deprecated if (jsPDFDoc.autoTable) jsPDFDoc.autoTable.previous = table; // Deprecated doc.applyStyle