Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-hogan-pdf

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-hogan-pdf - npm Package Compare versions

Comparing version 1.0.2 to 2.0.0

33

lib/generate.js

@@ -5,7 +5,5 @@ 'use strict';

const Hogan = require('hogan.js');
const unmarshal = require('./unmarshal');
const PDF = require('./pdf');
const xmlToPdf = require('xml-to-pdf');
const fs = require('fs');
const path = require('path');
const concat = require('concat-stream');

@@ -53,3 +51,3 @@ const generate = {

unmarshal.xmlToObject(xml, callback);
callback(null, xml);
});

@@ -59,15 +57,5 @@ },

fileToStream(filePath, locals, callback) {
generate.render(filePath, locals, (err, data) => {
generate.render(filePath, locals, (err, xml) => {
if (err) return callback(err);
let pdf, doc;
try {
pdf = new PDF(data, { basePath: path.dirname(filePath) });
doc = pdf.render();
} catch (e) {
return callback(e);
}
callback(null, doc);
xmlToPdf.toStream(xml, path.dirname(filePath), callback);
});

@@ -77,8 +65,5 @@ },

fileToBuffer(filePath, locals, callback) {
generate.fileToStream(filePath, locals, (err, doc) => {
generate.render(filePath, locals, (err, xml) => {
if (err) return callback(err);
doc.pipe(concat(data => {
if (doc.filename) data.filename = doc.filename;
callback(null, data);
}));
xmlToPdf.toBuffer(xml, path.dirname(filePath), callback);
});

@@ -88,7 +73,5 @@ },

fileToFile(filePath, locals, destFile, callback) {
generate.fileToStream(filePath, locals, (err, doc) => {
generate.render(filePath, locals, (err, xml) => {
if (err) return callback(err);
let stream = fs.createWriteStream(destFile);
doc.pipe(stream);
stream.on('finish', callback);
xmlToPdf.toFile(xml, path.dirname(filePath), destFile, callback);
});

@@ -95,0 +78,0 @@ },

{
"name": "express-hogan-pdf",
"version": "1.0.2",
"version": "2.0.0",
"description": "PDF generation using Hogan.js to template XML. Can be used as an express view engine or can output to a PDF stream, buffer, or file",
"main": "lib/generate.js",
"scripts": {
"test": "run-s test:lint test:unit test:cover test:cover-check",
"pretest": "npm run test:lint",
"test": "npm run test:unit",
"posttest": "npm run test:cover-check",
"test:lint": "eslint .",
"test:unit": "mocha test/unit --recursive --require test/unit/helper",
"test:cover": "istanbul cover _mocha -- -R dot test/unit --recursive --require test/unit/helper",
"test:unit": "istanbul cover _mocha -- test/unit --recursive",
"test:cover-check": "istanbul check-coverage"

@@ -20,3 +21,3 @@ },

"engines": {
"node": ">=4"
"node": ">=6"
},

@@ -28,19 +29,17 @@ "bugs": {

"dependencies": {
"concat-stream": "^1.6.0",
"debug": "^2.1.2",
"deep-extend": "^0.5.0",
"hogan.js": "^3.0.2",
"pdfkit": "^0.8.1",
"underscore": "^1.8.2",
"xml2js": "^0.4.17"
"debug": "^4.1.1",
"xml-to-pdf": "^1.0.4"
},
"peerDependencies": {
"hogan.js": ">3"
},
"devDependencies": {
"chai": "^3.5.0",
"eslint": "^3.13.1",
"hogan.js": "^3.0.2",
"chai": "^4.2.0",
"eslint": "^5.12.1",
"istanbul": "^0.4.3",
"mocha": "^3.1.2",
"npm-run-all": "^4.0.2",
"sinon": "^1.14.1",
"sinon-chai": "^2.7.0"
"mocha": "^5.2.0",
"sinon": "^7.2.3",
"sinon-chai": "^3.3.0"
}
}

@@ -75,60 +75,60 @@ # express-hogan-pdf

The document must be wrapped in <pdf></pdf> tags
The document must be wrapped in `<pdf></pdf>` tags
- <config> Configuration section:
+ <document> PDFKit document options, eg: <document size="A4"/>
+ <title> Set document title
+ <meta> Set PDF meta details such as <author>, <subject>, or <keywords>
+ <colors> Color aliases, eg <colors darkred="#880000"/>
+ <fonts> Font aliases, eg <fonts comic="Comic Sans Regular"/>
+ <title> Set document title
+ <styles> Add or change page tag style definintions, eg: <styles><redtext extends="span" color="red"/></styles>
- `<config>` Configuration section:
+ `<document>` PDFKit document options, eg: `<document size="A4"/>`
+ `<title>` Set document title
+ `<meta>` Set PDF meta details such as `<author>`, `<subject>`, or `<keywords>`
+ `<colors>` Color aliases, eg `<colors darkred="#880000"/>`
+ `<fonts>` Font aliases, eg `<fonts comic="Comic Sans Regular"/>`
+ `<filename>` Set document filename
+ `<title>` Set document title
+ `<styles>` Add or change page tag style definintions, eg: `<styles><redtext extends="span" color="red"/></styles>`
* Elements attributes can include:
* extends="String" Style definition to extend
* display="String" Can be "block" or "inline"
* Elements attributes can include:
- marginLeft="Number" Margin left
- marginRight="Number" Margin right
- paddingLeft="Number" Padding left
- paddingRight="Number" Padding right
- color="String" Text color or alias
- font="String" Font alias, name or path
- size="Number" Font size
- underline="Boolean" Underline text
- strike="Boolean" Strikethrough text
- lineGap="Number" Line gap between wrapped lines
- paragraphGap="Number" Gaps between paragraphs
- align="String" text alignment
- pre="Boolean" Respect exact whitespace in tags
- trim="Boolean" Trim whitespace at start of each line
- `extends="String"` Style definition to extend
- `display="String"` Can be `block` or `inline`
- `marginLeft="Number"` Margin left
- `marginRight="Number"` Margin right
- `paddingLeft="Number"` Padding left
- `paddingRight="Number"` Padding right
- `color="String"` Text color or alias
- `font="String"` Font alias, name or path
- `size="Number"` Font size
- `underline="Boolean"` Underline text
- `strike="Boolean"` Strikethrough text
- `lineGap="Number"` Line gap between wrapped lines
- `paragraphGap="Number"` Gaps between paragraphs
- `align="String"` text alignment
- `pre="Boolean"` Respect exact whitespace in tags
- `trim="Boolean"` Trim whitespace at start of each line
* Block elements can also include the following attributes:
- marginTop="Number" Margin top
- marginBottom="Number" Margin bottom
- paddingTop="Number" Padding top
- paddingBottom="Number" Padding bottom
- width="Number" Width as an absolute or as a percentage of the parent block
- height="Number" Height as an absolute or as a percentage of the page height within the page margins
- backgroundColor="String" Background color or color alias. Background will only be filled if both a height and width are given
- border="Number" Border width. A border will only be drawn if both a height and width are given
- borderColor="String" Border color or color alias
- <page> A page to render. Can take any PDFKit page options, such as page
- `marginTop="Number"` Margin top
- `marginBottom="Number"` Margin bottom
- `paddingTop="Number"` Padding top
- `paddingBottom="Number"` Padding bottom
- `width="Number"` Width as an absolute or as a percentage of the parent block
- `height="Number"` Height as an absolute or as a percentage of the page height within the page margins
- `backgroundColor="String"` Background color or color alias. Background will only be filled if both a height and width are given
- `border="Number"` Border width. A border will only be drawn if both a height and width are given
- `borderColor="String"` Border color or color alias
- `<page>` A page to render. Can take any PDFKit page options, such as page
+ Predefined styles and tags that are similar to HTML include:
* <div>
* <p>
* <span>
* <strong>
* <small>
* <indent> Indent text by `paddingLeft` and show a left bar of `thickness` and `color`
- thickness="Number" Width of indent bar
- color="String" Color or color alias of indent bar
* <hr> Horizontal rule divider line
- thickness="Number" Height of divider line
- color="String" Color or color alias of divider line
* <row> A container for a set of columns
* <column> A left-aligned column within a row. Columns wrap within the row if the next column can't fit within the row's width
* <img> Draw an image
- src="String" Source of the image to draw relative to the template file
- scale="Number" Size of image relative to its original
- fit="Boolean" Fit image within the width and height without chaning its aspect ratio
* <a> Create a web link for the contained text.
- href="String" The link to go to when clicked. If no `href` is specified an href is created by adding `https://` to the beginning of the text
* `<div>`
* `<p>`
* `<span>`
* `<strong>`
* `<small>`
* `<indent>` Indent text by `paddingLeft` and show a left bar of `thickness` and `color`
- `thickness="Number"` Width of indent bar
- `color="String"` Color or color alias of indent bar
* `<hr>` Horizontal rule divider line
- `thickness="Number"` Height of divider line
- `color="String"` Color or color alias of divider line
* `<row>` A container for a set of columns
* `<column>` A left-aligned column within a row. Columns wrap within the row if the next column can't fit within the row's width
* `<img>` Draw an image
- `src="String"` Source of the image to draw relative to the template file
- `scale="Number"` Size of image relative to its original
- `fit="Boolean"` Fit image within the width and height without chaning its aspect ratio
* `<a>` Create a web link for the contained text.
- `href="String"` The link to go to when clicked. If no `href` is specified an href is created by adding `https://` to the beginning of the text
'use strict';
let sinon = require('sinon');
const chai = require('chai');
chai.should();
chai.use(require('sinon-chai'));
const fs = require('fs');
const generate = require('../../../lib/generate');
const Hogan = require('hogan.js');
const unmarshal = require('../../../lib/unmarshal');
const PDF = require('../../../lib/pdf');
const ConcatStream = new require('concat-stream');
const xmlToPdf = require('xml-to-pdf');

@@ -15,3 +18,5 @@ describe('generate', () => {

stubs = {};
filename = 'filename';
stubs.compiled = {};
stubs.rendered = '<pdf>Rendered</pdf>';
filename = 'path/to/filename.xml';
locals = {

@@ -28,5 +33,3 @@ foo: 'bar',

beforeEach(() => {
stubs.compiled = {};
sinon.stub(Hogan, 'compile').returns(stubs.compiled);
stubs.fileData = new Buffer('<pdf>fileData</pdf>');

@@ -97,5 +100,2 @@ sinon.stub(fs, 'readFile').yields(null, stubs.fileData);

stubs.template.render.returns(stubs.rendered);
stubs.obj = {};
sinon.stub(unmarshal, 'xmlToObject').yields(null, stubs.obj);
});

@@ -105,3 +105,2 @@

generate.compile.restore();
unmarshal.xmlToObject.restore();
});

@@ -143,13 +142,6 @@

it('should unmarshal the compiled xml to an object', () => {
it('should callback the rendered xml', () => {
generate.render(filename, locals, callback);
unmarshal.xmlToObject.should.have.been.calledWithExactly(stubs.rendered, sinon.match.func);
callback.should.have.been.calledWithExactly(null, stubs.rendered);
});
it('should callback an unmarshalling error', () => {
let err = new Error();
unmarshal.xmlToObject.yields(err);
generate.render(filename, locals, callback);
callback.should.have.been.calledWithExactly(err);
});
});

@@ -159,7 +151,4 @@

beforeEach(() => {
stubs.obj = {};
sinon.stub(generate, 'render').yields(null, stubs.obj);
stubs.doc = {};
sinon.stub(PDF.prototype, 'render').returns(stubs.doc);
sinon.stub(generate, 'render').yields(null, stubs.rendered);
sinon.stub(xmlToPdf, 'toStream');
});

@@ -169,3 +158,3 @@

generate.render.restore();
PDF.prototype.render.restore();
xmlToPdf.toStream.restore();
});

@@ -189,14 +178,6 @@

it('should render a PDF from the unmarshalled data', () => {
it('should render a PDF to a stream', () => {
generate.fileToStream(filename, locals, callback);
PDF.prototype.render.should.have.been.calledWithExactly();
callback.should.have.been.calledWithExactly(null, stubs.doc);
xmlToPdf.toStream.should.have.been.calledWithExactly(stubs.rendered, 'path/to', callback);
});
it('should callback a PDF rendering error', () => {
let err = new Error();
PDF.prototype.render.throws(err);
generate.fileToStream(filename, locals, callback);
callback.should.have.been.calledWithExactly(err);
});
});

@@ -206,10 +187,9 @@

beforeEach(() => {
stubs.doc = {
pipe: sinon.stub()
};
sinon.stub(generate, 'fileToStream').yields(null, stubs.doc);
sinon.stub(generate, 'render').yields(null, stubs.rendered);
sinon.stub(xmlToPdf, 'toBuffer');
});
afterEach(() => {
generate.fileToStream.restore();
generate.render.restore();
xmlToPdf.toBuffer.restore();
});

@@ -221,10 +201,10 @@

it('should call fileToStream', () => {
it('should render the template given by the filename', () => {
generate.fileToBuffer(filename, locals, callback);
generate.fileToStream.should.have.been.calledWithExactly(filename, locals, sinon.match.func);
generate.render.should.have.been.calledWithExactly(filename, locals, sinon.match.func);
});
it('should callback with error from fileToStream', () => {
it('should callback with render error', () => {
let err = new Error();
generate.fileToStream.yields(err);
generate.render.yields(err);
generate.fileToBuffer(filename, locals, callback);

@@ -234,29 +214,6 @@ callback.should.have.been.calledWithExactly(err);

it('should pipe the document to contact to provide a buffer', done => {
it('should render a PDF to a stream', () => {
generate.fileToBuffer(filename, locals, callback);
stubs.doc.pipe.should.have.been.calledWithExactly(sinon.match.instanceOf(ConcatStream));
let concat = stubs.doc.pipe.getCall(0).args[0];
concat.write([1, 2, 3]);
concat.write([4, 5, 6]);
concat.end();
concat.on('finish', () => {
callback.should.have.been.calledWithExactly(null, [1, 2, 3, 4, 5, 6]);
done();
});
xmlToPdf.toBuffer.should.have.been.calledWithExactly(stubs.rendered, 'path/to', callback);
});
it('should copy the filename from the stream', done => {
stubs.doc.filename = 'filename';
generate.fileToBuffer(filename, locals, callback);
let concat = stubs.doc.pipe.getCall(0).args[0];
concat.write([1, 2, 3]);
concat.end();
concat.on('finish', () => {
let data = callback.args[0][1];
data.filename.should.equal('filename');
done();
});
});
});

@@ -269,15 +226,9 @@

destFileName = 'destfile';
stubs.doc = {
pipe: sinon.stub(),
};
stubs.stream = {
on: sinon.stub()
};
sinon.stub(generate, 'fileToStream').yields(null, stubs.doc);
sinon.stub(fs, 'createWriteStream').returns(stubs.stream);
sinon.stub(generate, 'render').yields(null, stubs.rendered);
sinon.stub(xmlToPdf, 'toFile');
});
afterEach(() => {
generate.fileToStream.restore();
fs.createWriteStream.restore();
generate.render.restore();
xmlToPdf.toFile.restore();
});

@@ -289,10 +240,10 @@

it('should call fileToStream', () => {
it('should render the template given by the filename', () => {
generate.fileToFile(filename, locals, destFileName, callback);
generate.fileToStream.should.have.been.calledWithExactly(filename, locals, sinon.match.func);
generate.render.should.have.been.calledWithExactly(filename, locals, sinon.match.func);
});
it('should callback with error from fileToStream', () => {
it('should callback with render error', () => {
let err = new Error();
generate.fileToStream.yields(err);
generate.render.yields(err);
generate.fileToFile(filename, locals, destFileName, callback);

@@ -302,19 +253,6 @@ callback.should.have.been.calledWithExactly(err);

it('should create a file stream with the dest filename', () => {
it('should render a PDF to a stream', () => {
generate.fileToFile(filename, locals, destFileName, callback);
fs.createWriteStream.should.have.been.calledWithExactly(destFileName);
xmlToPdf.toFile.should.have.been.calledWithExactly(stubs.rendered, 'path/to', destFileName, callback);
});
it('should pipe the document to contact to file stream', () => {
generate.fileToFile(filename, locals, destFileName, callback);
stubs.doc.pipe.should.have.been.calledWithExactly(stubs.stream);
callback.should.not.have.been.called;
});
it('should call the callback when the pipe is complete', () => {
stubs.stream.on.withArgs('finish').yields(null);
generate.fileToFile(filename, locals, destFileName, callback);
callback.should.have.been.calledWithExactly(null);
});
});

@@ -321,0 +259,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc