Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
fluentreports
Advanced tools
See: http://www.fluentreports.com for more information.
Fluent Reports - Data Driven PDF Reporting Engine for Node.js
npm install fluentreports
Please read the commands.md file for a overview of all the commands. The files in the docs/
folder are generated from the source code via jsdocs, so they might be more up to date.
See the simple & stupid examples for a overview on how to generate a somewhat complex report. In these reports I tried to throw in a chunk of the features to try and give you and idea how powerful the engine is and how to use certain features.
Currently has 6 example reports showing:
Please note these following reports are using the simplest report methods; to show how quickly you can create a simple report.
You have the ability to EASILY FULLY override any and all of the Headers, Footers, and Detail bands.
Really Simple Report:
// Our Simple Data in Object format:
var data = [{name: 'Elijah', age: 18}, {name: 'Abraham', age: 22}, {name: 'Gavin', age: 28}];
// Create a Report
var rpt = new Report("Report.pdf")
.pageHeader( ["Employee Ages"] ) // Add a simple (optional) page Header...
.data( data ) // Add some Data (This is required)
.detail( [['name', 200],['age', 50]]) // Layout the report in a Grid of 200px & 50px
.render(); // Render the Report (required if you want output...)
The same report in Array format:
// Our Simple Data in Array format:
var data = [['Elijah', 18], ['Abraham', 22], ['Gavin', 28]];
// Create a Report
var rpt = new Report("Report.pdf")
.pageHeader( ["Employee Ages"] ) // Add a simple (optional) page Header...
.detail( [[0, 200],[1, 50]]) // Layout the report in a grid of 200px & 50px
.render(); // Render the report
And one other sample report using a list type output:
var data = [
{item: 'Bread', count: 5, unit: 'loaf'},
{item: 'Egg', count: 3, unit: 'dozen'},
{item: 'Sugar', count: 32, unit: 'gram'},
{item: 'Carrot', count: 2, unit: 'kilo'},
{item: 'Apple', count: 3, unit: 'kilo'},
{item: 'Peanut Butter', count: 1, unit: 'jar'}
];
var rpt = new Report("grocery1.pdf")
.data( data ) // Add our Data
.pageHeader( ["My Grocery List"] ) // Add a simple header
.detail("{{count}} {{unit}} of {{item}}") // Put how we want to print out the data line.
.render(); // Render the Report (required if you want output...)
Data Driven reporting is done in basically a couple steps:
So, now looking at the above simple grocery list report; and lets spruce it up a bit.
First lets change from the default header to make a look a bit nicer for a Grocery List; so we need to create a function that will control how the header looks.
var headerFunction = function(Report) {
Report.print("My Grocery List", {fontSize: 22, bold: true, underline:true, align: "center"});
Report.newLine(2);
};
This function changes the font size to 22 point, bolds and underlines the text and centers the words "My Grocery List" on the page. Then we add 2 new blank lines to space the header from the detail records. This looks so much cleaner.
Next, I think I actually do want to continue to have the date and page number printed. But I think I would prefer them on the bottom of the page, so lets add a footer for these items. Here is our footer function that also will be printed on every page, just like the header function above.
var footerFunction = function(Report) {
Report.line(Report.currentX(), Report.maxY()-18, Report.maxX(), Report.maxY()-18);
Report.pageNumber({text: "Page {0} of {1}", footer: true, align: "right"});
Report.print("Printed: "+(new Date().toLocaleDateString()), {y: Report.maxY()-14, align: "left"});
};
Now in this function we print a line across the bottom of the page; then we use the "pageNumber" helper function to print the current page number and total number of page, then we print the current date. A couple things to point out; Report.maxY and maxX are the largest location that can be printed to before entering the margins. If you attempt to create your footer beyond the maxY coordinate; it WILL let you; but it WILL send a error to the Report.error system stating that you exceeded the margin by however many pixels so that you can fix your report.
So our new report is:
var data = [
{item: 'Bread', count: 5, unit: 'loaf'},
{item: 'Egg', count: 3, unit: 'dozen'},
{item: 'Sugar', count: 32, unit: 'gram'},
{item: 'Carrot', count: 2, unit: 'kilo'},
{item: 'Apple', count: 3, unit: 'kilo'},
{item: 'Peanut Butter', count: 1, unit: 'jar'}
];
var headerFunction = function(Report) {
Report.print("My Grocery List", {fontSize: 22, bold: true, underline:true, align: "center"});
Report.newLine(2);
};
var footerFunction = function(Report) {
Report.line(Report.currentX(), Report.maxY()-18, Report.maxX(), Report.maxY()-18);
Report.pageNumber({text: "Page {0} of {1}", footer: true, align: "right"});
Report.print("Printed: "+(new Date().toLocaleDateString()), {y: Report.maxY()-14, align: "left"});
};
var rpt = new Report("grocery2.pdf")
.margins(20) // Change the Margins to 20 pixels
.data(data) // Add our Data
.pageHeader(headerFunction) // Add a header
.pageFooter(footerFunction) // Add a footer
.detail("{{count}} {{unit}} of {{item}}") // Put how we want to print out the data line.
.render(); // Render it out
Wow, this report looks a lot cleaner and sharper. However, I think we can spruce it up a still bit more...
var detailFunction = function(Report, Data) {
if (Data.count !== 1) {
Data.item = pluralize(Data.item);
Data.unit = pluralize(Data.unit);
}
Report.box(Report.currentX()-1, Report.currentY()-1, 10, 10, {});
Report.print(numberToText(Data.count) + ' ' + Data.unit + ' of ' + Data.item, {addX: 12});
};
This is our new Detail function. I first uses a simple pluralizer to make any singular words plural if they need be. The next thing it does is draw a box for your check marks. Then it spits out your detail line with changes. Now since I can have a really large grocery list; I can make this two or three columns, so we lets modify the code to make it three columns like so:
var detailFunction = function(Report, Data) {
if (Data.count !== 1) {
Data.item = pluralize(Data.item);
Data.unit = pluralize(Data.unit);
}
var x = 0, y = 0;
if (columnCounter % 3 === 1) {
x += 200;
y = (Report.heightOfString() + 1);
} else if (columnCounter % 3 === 2) {
x += 400;
y = (Report.heightOfString() + 1);
}
Report.box(Report.currentX()+x , Report.currentY()-y, 10, 10, {});
Report.print(numberToText(Data.count) + ' ' + Data.unit + ' of ' + Data.item, {addX: x+12, addY: -(y-1)});
columnCounter++;
};
Basically it is the same functions as the prior version but we are changing the X and Y coordinates for column 2 & 3 to make them end up on the same line just in a different column. So the finished report looks this. example\demo6.js contains this report in its three different iterations.
FAQs
A simple, Fluent API for creating PDF Reports
The npm package fluentreports receives a total of 332 weekly downloads. As such, fluentreports popularity was classified as not popular.
We found that fluentreports demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.