From 65eddf68c017f96ceff87d2ae83dc1ccf9ae1939 Mon Sep 17 00:00:00 2001 From: "Libor M." Date: Fri, 8 Nov 2024 16:58:57 +0100 Subject: [PATCH] custom header/footer support --- examples/sections.js | 9 +++++ src/DocumentContext.js | 6 ++-- src/LayoutBuilder.js | 75 ++++++++++++++++++++++++++++++++-------- src/PageElementWriter.js | 4 +-- 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/examples/sections.js b/examples/sections.js index 19d2e0d02..179215866 100644 --- a/examples/sections.js +++ b/examples/sections.js @@ -5,6 +5,8 @@ var Roboto = require('../fonts/Roboto'); pdfmake.addFonts(Roboto); var docDefinition = { + header: function () { return 'default header'; }, + footer: function () { return 'default footer'; }, content: [ { section: [ @@ -13,6 +15,8 @@ var docDefinition = { ] }, { + header: function (currentPage, pageCount) { return 'header: ' + currentPage.toString() + ' of ' + pageCount; }, + footer: function (currentPage, pageCount) { return 'footer: ' + currentPage.toString() + ' of ' + pageCount; }, pageOrientation: 'landscape', section: [ 'SECTION 2', @@ -20,6 +24,9 @@ var docDefinition = { ] }, { + header: null, + footer: null, + pageSize: 'A7', pageOrientation: 'portrait', section: [ @@ -55,6 +62,8 @@ var docDefinition = { ] }, { + header: function (currentPage, pageCount) { return 'header in section 8: ' + currentPage.toString() + ' of ' + pageCount; }, + footer: function (currentPage, pageCount) { return 'footer in section 8: ' + currentPage.toString() + ' of ' + pageCount; }, section: [ 'SECTION 8', 'Text in section with page definition as defined in document.' diff --git a/src/DocumentContext.js b/src/DocumentContext.js index 11b414372..563eeaf3e 100644 --- a/src/DocumentContext.js +++ b/src/DocumentContext.js @@ -222,7 +222,7 @@ class DocumentContext extends EventEmitter { let currentPageOrientation = this.getCurrentPage().pageSize.orientation; let pageSize = getPageSize(this.getCurrentPage(), pageOrientation); - this.addPage(pageSize); + this.addPage(pageSize, null, this.getCurrentPage().customProperties); if (currentPageOrientation === pageSize.orientation) { this.availableWidth = currentAvailableWidth; @@ -240,14 +240,14 @@ class DocumentContext extends EventEmitter { }; } - addPage(pageSize, pageMargin = null) { + addPage(pageSize, pageMargin = null, customProperties = {}) { if (pageMargin !== null) { this.pageMargins = pageMargin; this.x = pageMargin.left; this.availableWidth = pageSize.width - pageMargin.left - pageMargin.right; } - let page = { items: [], pageSize: pageSize, pageMargins: this.pageMargins }; + let page = { items: [], pageSize: pageSize, pageMargins: this.pageMargins, customProperties: customProperties }; this.pages.push(page); this.backgroundLength.push(0); this.page = this.pages.length - 1; diff --git a/src/LayoutBuilder.js b/src/LayoutBuilder.js index 003cbd3a6..93cfa659f 100644 --- a/src/LayoutBuilder.js +++ b/src/LayoutBuilder.js @@ -7,7 +7,7 @@ import TableProcessor from './TableProcessor'; import Line from './Line'; import { isString, isValue, isNumber } from './helpers/variableType'; import { stringifyNode, getNodeId } from './helpers/node'; -import { pack, offsetVector } from './helpers/tools'; +import { pack, offsetVector, convertToDynamicContent } from './helpers/tools'; import TextInlines from './TextInlines'; import StyleContextStack from './StyleContextStack'; @@ -222,13 +222,24 @@ class LayoutBuilder { } } - addDynamicRepeatable(nodeGetter, sizeFunction) { + addDynamicRepeatable(nodeGetter, sizeFunction, customPropertyName) { let pages = this.writer.context().pages; for (let pageIndex = 0, l = pages.length; pageIndex < l; pageIndex++) { this.writer.context().page = pageIndex; - let node = nodeGetter(pageIndex + 1, l, this.writer.context().pages[pageIndex].pageSize); + let customProperties = this.writer.context().getCurrentPage().customProperties; + + let pageNodeGetter = nodeGetter; + if (customProperties[customPropertyName] || customProperties[customPropertyName] === null) { + pageNodeGetter = customProperties[customPropertyName]; + } + + if ((typeof pageNodeGetter === 'undefined') || (pageNodeGetter === null)) { + continue; + } + + let node = pageNodeGetter(pageIndex + 1, l, this.writer.context().pages[pageIndex].pageSize); if (node) { let sizes = sizeFunction(this.writer.context().getCurrentPage().pageSize, this.writer.context().getCurrentPage().pageMargins); @@ -255,13 +266,8 @@ class LayoutBuilder { height: pageMargins.bottom }); - if (header) { - this.addDynamicRepeatable(header, headerSizeFct); - } - - if (footer) { - this.addDynamicRepeatable(footer, footerSizeFct); - } + this.addDynamicRepeatable(header, headerSizeFct, 'header'); + this.addDynamicRepeatable(footer, footerSizeFct, 'footer'); } addWatermark(watermark, pdfDocument, defaultStyle) { @@ -514,23 +520,64 @@ class LayoutBuilder { // TODO: properties let page = this.writer.context().getCurrentPage(); - // TODO: background if (!page || (page && page.items.length)) { // move to new empty page // page definition inherit from current page if (sectionNode.pageSize === 'inherit') { - sectionNode.pageSize = page ? {width: page.pageSize.width, height: page.pageSize.height} : undefined; + sectionNode.pageSize = page ? { width: page.pageSize.width, height: page.pageSize.height } : undefined; } if (sectionNode.pageOrientation === 'inherit') { sectionNode.pageOrientation = page ? page.pageSize.orientation : undefined; } if (sectionNode.pageMargins === 'inherit') { - sectionNode.pageMargins = page ? page.pageMargins : undefined; + sectionNode.pageMargins = page ? page.pageMargins : undefined; + } + + if (sectionNode.header === 'inherit') { + sectionNode.header = page ? page.customProperties.header : undefined; + } + + if (sectionNode.footer === 'inherit') { + sectionNode.footer = page ? page.customProperties.footer : undefined; + } + + if (sectionNode.background === 'inherit') { + sectionNode.background = page ? page.customProperties.background : undefined; + } + + if (sectionNode.watermark === 'inherit') { + sectionNode.watermark = page ? page.customProperties.watermark : undefined; + } + + if (sectionNode.header && typeof sectionNode.header !== 'function' && sectionNode.header !== null) { + sectionNode.header = convertToDynamicContent(sectionNode.header); + } + + if (sectionNode.footer && typeof sectionNode.footer !== 'function' && sectionNode.footer !== null) { + sectionNode.footer = convertToDynamicContent(sectionNode.footer); + } + + let customProperties = {}; + if (typeof sectionNode.header !== 'undefined') { + customProperties.header = sectionNode.header; + } + + if (typeof sectionNode.footer !== 'undefined') { + customProperties.footer = sectionNode.footer; + } + + if (typeof sectionNode.background !== 'undefined') { + customProperties.background = sectionNode.background; + } + + if (typeof sectionNode.watermark !== 'undefined') { + customProperties.watermark = sectionNode.watermark; } this.writer.addPage( sectionNode.pageSize || this.pageSize, sectionNode.pageOrientation, - sectionNode.pageMargins || this.pageMargins + sectionNode.pageMargins || this.pageMargins, + customProperties ); } diff --git a/src/PageElementWriter.js b/src/PageElementWriter.js index 97fc2047c..9582f8a7d 100644 --- a/src/PageElementWriter.js +++ b/src/PageElementWriter.js @@ -83,11 +83,11 @@ class PageElementWriter extends ElementWriter { }); } - addPage(pageSize, pageOrientation, pageMargin) { + addPage(pageSize, pageOrientation, pageMargin, customProperties = {}) { let prevPage = this.page; let prevY = this.y; - this.context().addPage(normalizePageSize(pageSize, pageOrientation), normalizePageMargin(pageMargin)); + this.context().addPage(normalizePageSize(pageSize, pageOrientation), normalizePageMargin(pageMargin), customProperties); this.emit('pageChanged', { prevPage: prevPage,