New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

idea-html2pdf

Package Overview
Dependencies
Maintainers
2
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

idea-html2pdf - npm Package Compare versions

Comparing version 1.3.2 to 2.0.0

77

dist/src/html2pdf.d.ts
/// <reference types="node" />
import { S3, Lambda } from 'aws-sdk';
import * as Handlebars from 'handlebars';

@@ -9,20 +8,5 @@ import { Languages, SignedURL } from 'idea-toolbox';

export declare class HTML2PDF {
private options;
constructor(options?: HTML2PDFInitParameters);
/**
* The instance of Lambda.
*/
protected lambda: Lambda;
/**
* The instance of S3.
*/
protected s3: S3;
/**
* The name of the default Lambda function to invoke.
*/
protected LAMBDA_NAME: string;
/**
* The name of the default Lambda function to invoke (alternate version via S3 Bucket).
*/
protected LAMBDA_NAME_VIA_S3_BUCKET: string;
constructor();
/**
* Compile an Handlebars template.

@@ -40,8 +24,15 @@ */

/**
* Register some commonly-used handlebars helpers.
*/
private handlebarsRegisterDefaultHelpers;
/**
* Register handlebars helpers for the `PDFTemplateSection` IDEA standard.
*/
handlebarsRegisterHelpersForPDFTemplate(htmlInnerTemplate: string): any;
/**
* Create a new PDF created by an HTML source.
* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the PDF data (buffer)
*/
create(params: HTML2PDFParameters, alternativeLambda?: string): Promise<Buffer>;
create(params: HTML2PDFCreateParameters): Promise<Buffer>;
/**

@@ -52,21 +43,39 @@ * Create a new PDF created by an HTML source.

* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the PDF data (buffer)
*/
createViaS3Bucket(params: HTML2PDFParameters, alternativeLambda?: string): Promise<Buffer>;
createViaS3Bucket(params: HTML2PDFCreateViaS3BucketParameters): Promise<Buffer>;
/**
* Create the signedURL to a new PDF created by an HTML source.
* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the URL to download the PDF
*/
createLink(params: HTML2PDFParameters, alternativeLambda?: string): Promise<SignedURL>;
createLink(params: HTML2PDFCreateViaS3BucketParameters): Promise<SignedURL>;
}
export interface HTML2PDFInitParameters {
/**
* Helper function to prepare Handlebar's helper for the `PDFTemplateSection` standard.
* The language configuration to use to enable translations helpers.
*/
getHandlebarHelpersForPDFTemplate(language: string, languages: Languages, htmlInnerTemplate: string, additionalTranslations?: {
languages?: Languages;
/**
* The preferred language for translations helpers.
*/
language?: string;
/**
* Additional dictionary to use in translations helpers.
*/
additionalTranslations?: {
[term: string]: string;
}): any;
};
/**
* The name of the default Lambda function to invoke.
* Default: `idea_html2pdf`.
*/
lambdaFnName?: string;
/**
* The name of the default Lambda function to invoke (alternate version via S3 Bucket).
* Default: `idea_html2pdf_viaS3Bucket`.
*/
lambdaFnViaS3BucketName?: string;
}
export interface HTML2PDFParameters {
export interface HTML2PDFCreateParameters {
/**

@@ -89,2 +98,12 @@ * The html main body.

}
export declare const PDF_TEMPLATE = "\n <!DOCTYPE html>\n <html>\n\n <head>\n <meta charset=\"utf8\" />\n <title>\n PDF template\n </title>\n <link href=\"https://fonts.googleapis.com/css?family=Lato\" rel=\"stylesheet\">\n <style>\n html,\n body {\n margin: 0;\n padding: 0;\n font-size: 10pt;\n font-family: 'Lato', Arial, Helvetica, sans-serif;\n }\n\n table {\n width: 100%;\n table-layout: fixed;\n font-size: 1rem;\n }\n\n table,\n tr,\n td {\n margin: 0;\n padding: 0;\n border-spacing: 0;\n border-collapse: collapse;\n vertical-align: middle;\n }\n\n .dontBreak {\n page-break-inside: avoid !important;\n }\n .pageBreak {\n page-break-after: always;\n }\n\n table.border td {\n border: 1px solid #eee;\n }\n\n td > p {\n margin: 0;\n padding: 0;\n }\n\n .normalRow td {\n padding: 6px 8px;\n letter-spacing: -0.2px;\n }\n\n td .label {\n display: block;\n font-size: 0.8rem;\n font-weight: bold;\n color: #555;\n }\n\n .headerTable {\n margin-top: 20px;\n page-break-inside: avoid;\n }\n .headerTable::after {\n /* trick to avoid a page break right after the header */\n content: \"-\";\n color: white;\n display: block;\n height: 150px;\n margin-bottom: -150px;\n }\n .headerTitle {\n padding: 4px 8px;\n background-color: #444;\n border: 1px solid transparent;\n border-radius: 5px;\n font-size: 0.9rem;\n font-weight: 500;\n color: white;\n }\n\n .numericField {\n text-align: right;\n }\n .checkbox {\n width: 12px;\n padding-top: 2px;\n }\n </style>\n </head>\n\n <body>\n\n <!-- PDF TEMPLATE BEGIN -->\n\n <div class=\"pdfTemplate\">\n {{#each _template as |section|}}\n {{! page break }}\n {{#ifEqual section.type 0}}\n <div class=\"pageBreak\"></div>\n {{/ifEqual}}\n {{! empty row }}\n {{#ifEqual section.type 1}}\n <br />\n {{/ifEqual}}\n {{! row }}\n {{#ifEqual section.type 2}}\n <table class=\"normalRow dontBreak {{#if row.border}}border{{/if}}\">\n <tr>\n {{#each section.columns as |content|}}\n {{#if content}}\n {{#if (doesColumnContainAField section @index)}}{{! field (that may be repeated for more cols) }}\n {{#with content as |field|}}\n {{! simple field }}\n {{#if field.code}}\n <td\n colspan=\"{{getColumnFieldSize section @index}}\"\n class=\"{{#if (isFieldANumber _data field.code)}}numericField{{/if}}\"\n >\n <span class=\"label\">\n {{translate (label field.label)}}&nbsp;\n </span>\n {{#if (isFieldABoolean _data field.code)}}\n {{#if (get _data field.code)}}\n <img\n class=\"checkbox\"\n src=\"https://s3.eu-west-2.amazonaws.com/scarlett-app/assets/icons/check-true.png\"\n />\n {{else}}\n <img\n class=\"checkbox\"\n src=\"https://s3.eu-west-2.amazonaws.com/scarlett-app/assets/icons/check-false.png\"\n />\n {{/if}}\n {{else}}\n {{mdToHTML (translate (getOrDash _data field.code))}}\n {{/if}}\n </td>\n {{! complext field }}\n {{else}}\n <td colspan=\"{{getColumnFieldSize section @index}}\">\n {{#ifEqual 12 (getColumnFieldSize section @index)}}\n {{! no extra spacing }}\n {{else}}\n <span class=\"label\">&nbsp;</span>\n {{/ifEqual}}\n {{mdToHTML (substituteVars _data (translate (label field.content)))}}\n </td>\n {{/if}}\n {{/with}}\n {{/if}}\n {{else}}\n {{! empty col }}\n <td colspan=\"1\"></td>\n {{/if}}\n {{/each}}\n </tr>\n </table>\n {{/ifEqual}}\n {{! header }}\n {{#ifEqual section.type 3}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{mdToHTML (substituteVars _data (translate (label section.title)))}}\n </td>\n </tr>\n </table>\n {{/ifEqual}}\n {{! inner section }}\n {{#ifEqual section.type 4}}\n {{#if (get _data section.context)}}\n {{#if (label section.title)}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{translate (label section.title)}}\n </td>\n </tr>\n </table>\n {{/if}}\n {{inception section.innerTemplate (get _data section.context)}}\n {{/if}}\n {{/ifEqual}}\n {{! repeated inner section }}\n {{#ifEqual section.type 5}}\n {{#with (get _data section.context) as |innerSections|}}\n {{#if innerSections.length}}\n {{#if (label section.title)}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{translate (label section.title)}}\n </td>\n </tr>\n </table>\n {{/if}}\n {{/if}}\n {{#each innerSections as |innerSection|}}\n {{inception section.innerTemplate innerSection}}\n {{/each}}\n {{/with}}\n {{/ifEqual}}\n {{/each}}\n </div>\n\n </body>\n\n </html>\n";
export interface HTML2PDFCreateViaS3BucketParameters extends HTML2PDFCreateParameters {
/**
* The S3 bucket where to put the generated PDF file.
*/
s3Bucket: string;
/**
* The prefix for the generated PDF file in the S3 bucket.
*/
s3Prefix: string;
}
export declare const PDF_DEFAULT_TEMPLATE = "\n <!DOCTYPE html>\n <html>\n\n <head>\n <meta charset=\"utf8\" />\n <title>\n PDF template\n </title>\n <link href=\"https://fonts.googleapis.com/css?family=Lato\" rel=\"stylesheet\">\n <style>\n html,\n body {\n margin: 0;\n padding: 0;\n font-size: 10pt;\n font-family: 'Lato', Arial, Helvetica, sans-serif;\n }\n\n table {\n width: 100%;\n table-layout: fixed;\n font-size: 1rem;\n }\n\n table,\n tr,\n td {\n margin: 0;\n padding: 0;\n border-spacing: 0;\n border-collapse: collapse;\n vertical-align: middle;\n }\n\n .dontBreak {\n page-break-inside: avoid !important;\n }\n .pageBreak {\n page-break-after: always;\n }\n\n table.border td {\n border: 1px solid #eee;\n }\n\n td > p {\n margin: 0;\n padding: 0;\n }\n\n .normalRow td {\n padding: 6px 8px;\n letter-spacing: -0.2px;\n }\n\n td .label {\n display: block;\n font-size: 0.8rem;\n font-weight: bold;\n color: #555;\n }\n\n .headerTable {\n margin-top: 20px;\n page-break-inside: avoid;\n }\n .headerTable::after {\n /* trick to avoid a page break right after the header */\n content: \"-\";\n color: white;\n display: block;\n height: 150px;\n margin-bottom: -150px;\n }\n .headerTitle {\n padding: 4px 8px;\n background-color: #444;\n border: 1px solid transparent;\n border-radius: 5px;\n font-size: 0.9rem;\n font-weight: 500;\n color: white;\n }\n\n .numericField {\n text-align: right;\n }\n .checkbox {\n width: 12px;\n padding-top: 2px;\n }\n </style>\n </head>\n\n <body>\n\n <!-- PDF TEMPLATE BEGIN -->\n\n <div class=\"pdfTemplate\">\n {{#each _template as |section|}}\n {{! page break }}\n {{#ifEqual section.type 0}}\n <div class=\"pageBreak\"></div>\n {{/ifEqual}}\n {{! empty row }}\n {{#ifEqual section.type 1}}\n <br />\n {{/ifEqual}}\n {{! row }}\n {{#ifEqual section.type 2}}\n <table class=\"normalRow dontBreak {{#if row.border}}border{{/if}}\">\n <tr>\n {{#each section.columns as |content|}}\n {{#if content}}\n {{#if (doesColumnContainAField section @index)}}{{! field (that may be repeated for more cols) }}\n {{#with content as |field|}}\n {{! simple field }}\n {{#if field.code}}\n <td\n colspan=\"{{getColumnFieldSize section @index}}\"\n class=\"{{#if (isFieldANumber _data field.code)}}numericField{{/if}}\"\n >\n <span class=\"label\">\n {{translate (label field.label)}}&nbsp;\n </span>\n {{#if (isFieldABoolean _data field.code)}}\n {{#if (get _data field.code)}}\n <img\n class=\"checkbox\"\n src=\"https://s3.eu-west-2.amazonaws.com/scarlett-app/assets/icons/check-true.png\"\n />\n {{else}}\n <img\n class=\"checkbox\"\n src=\"https://s3.eu-west-2.amazonaws.com/scarlett-app/assets/icons/check-false.png\"\n />\n {{/if}}\n {{else}}\n {{mdToHTML (translate (getOrDash _data field.code))}}\n {{/if}}\n </td>\n {{! complext field }}\n {{else}}\n <td colspan=\"{{getColumnFieldSize section @index}}\">\n {{#ifEqual 12 (getColumnFieldSize section @index)}}\n {{! no extra spacing }}\n {{else}}\n <span class=\"label\">&nbsp;</span>\n {{/ifEqual}}\n {{mdToHTML (substituteVars _data (translate (label field.content)))}}\n </td>\n {{/if}}\n {{/with}}\n {{/if}}\n {{else}}\n {{! empty col }}\n <td colspan=\"1\"></td>\n {{/if}}\n {{/each}}\n </tr>\n </table>\n {{/ifEqual}}\n {{! header }}\n {{#ifEqual section.type 3}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{mdToHTML (substituteVars _data (translate (label section.title)))}}\n </td>\n </tr>\n </table>\n {{/ifEqual}}\n {{! inner section }}\n {{#ifEqual section.type 4}}\n {{#if (get _data section.context)}}\n {{#if (label section.title)}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{translate (label section.title)}}\n </td>\n </tr>\n </table>\n {{/if}}\n {{inception section.innerTemplate (get _data section.context)}}\n {{/if}}\n {{/ifEqual}}\n {{! repeated inner section }}\n {{#ifEqual section.type 5}}\n {{#with (get _data section.context) as |innerSections|}}\n {{#if innerSections.length}}\n {{#if (label section.title)}}\n <table class=\"headerTable\">\n <tr>\n <td class=\"headerTitle\">\n {{translate (label section.title)}}\n </td>\n </tr>\n </table>\n {{/if}}\n {{/if}}\n {{#each innerSections as |innerSection|}}\n {{inception section.innerTemplate innerSection}}\n {{/each}}\n {{/with}}\n {{/ifEqual}}\n {{/each}}\n </div>\n\n </body>\n\n </html>\n";

@@ -22,9 +22,8 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.PDF_TEMPLATE = exports.HTML2PDF = void 0;
exports.PDF_DEFAULT_TEMPLATE = exports.HTML2PDF = void 0;
const aws_sdk_1 = require("aws-sdk");
const Handlebars = __importStar(require("handlebars"));
const idea_toolbox_1 = require("idea-toolbox");
// declare libs as global vars to be reused in warm starts by the Lambda function
let ideaWarmStart_s3 = null;
let ideaWarmStart_lambda = null;
const s3 = new aws_sdk_1.S3({ apiVersion: '2006-03-01', signatureVersion: 'v4' });
const lambda = new aws_sdk_1.Lambda();
/**

@@ -34,17 +33,8 @@ * A custom class that takes advantage of the `idea_html2pdf` Lambda function to easily manage the creation of PDFs.

class HTML2PDF {
constructor() {
/**
* The name of the default Lambda function to invoke.
*/
this.LAMBDA_NAME = 'idea_html2pdf:prod';
/**
* The name of the default Lambda function to invoke (alternate version via S3 Bucket).
*/
this.LAMBDA_NAME_VIA_S3_BUCKET = 'idea_html2pdf_viaS3Bucket:prod';
if (!ideaWarmStart_s3)
ideaWarmStart_s3 = new aws_sdk_1.S3({ apiVersion: '2006-03-01', signatureVersion: 'v4' });
this.s3 = ideaWarmStart_s3;
if (!ideaWarmStart_lambda)
ideaWarmStart_lambda = new aws_sdk_1.Lambda();
this.lambda = ideaWarmStart_lambda;
constructor(options = {
lambdaFnName: 'idea_html2pdf',
lambdaFnViaS3BucketName: 'idea_html2pdf_viaS3Bucket'
}) {
this.options = options;
this.handlebarsRegisterDefaultHelpers();
}

@@ -70,12 +60,61 @@ /**

/**
* Register some commonly-used handlebars helpers.
*/
handlebarsRegisterDefaultHelpers() {
const defaultHelpers = {
get: (context, x) => context[x],
getOrDash: (context, x) => (context[x] !== null && context[x] !== undefined ? context[x] : '-'),
substituteVars: (data, str) => {
if (!str || !data)
return str || '';
str = String(str);
const matches = str.match(/@\w*/gm);
if (matches)
matches.forEach(attr => {
if (data[attr] !== undefined)
str = str.replace(attr, data[attr] === null ? '' : data[attr]);
});
return str;
},
isFieldABoolean: (data, value) => typeof data[value] === 'boolean',
isFieldANumber: (data, value) => typeof data[value] === 'number',
ifEqual: (a, b, opt) => (a === b ? opt.fn(this) : opt.inverse(this)),
mdToHTML: (s) => typeof s === 'string' ? new Handlebars.SafeString((0, idea_toolbox_1.mdToHtml)(s)) : s
};
if (this.options.languages) {
const lang = this.options.language || this.options.languages.default;
defaultHelpers.label = (label) => label ? label[lang] || label[this.options.languages.default] : null;
}
if (this.options.additionalTranslations)
defaultHelpers.translate = (s) => s && this.options.additionalTranslations[s] ? this.options.additionalTranslations[s] : s;
for (const h in defaultHelpers)
if (defaultHelpers[h])
this.handlebarsRegisterHelper(h, defaultHelpers[h]);
}
/**
* Register handlebars helpers for the `PDFTemplateSection` IDEA standard.
*/
handlebarsRegisterHelpersForPDFTemplate(htmlInnerTemplate) {
const helpers = {
doesColumnContainAField: (section, colIndex) => section.doesColumnContainAField(colIndex),
getColumnFieldSize: (section, colIndex) => section.getColumnFieldSize(colIndex),
inception: (_template, _data) => {
const variables = { _template, _data };
return new Handlebars.SafeString(Handlebars.compile(htmlInnerTemplate, { compat: true })(variables));
}
};
for (const h in helpers)
if (helpers[h])
this.handlebarsRegisterHelper(h, helpers[h]);
}
/**
* Create a new PDF created by an HTML source.
* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the PDF data (buffer)
*/
async create(params, alternativeLambda) {
async create(params) {
try {
const result = await this.lambda
const result = await lambda
.invoke({
FunctionName: alternativeLambda || this.LAMBDA_NAME,
FunctionName: this.options.lambdaFnName,
InvocationType: 'RequestResponse',

@@ -88,3 +127,3 @@ Payload: JSON.stringify(params)

catch (err) {
(0, idea_toolbox_1.logger)('PDF creation failed', err, alternativeLambda || this.LAMBDA_NAME);
console.error('PDF creation failed', err, this.options.lambdaFnName);
throw err;

@@ -98,10 +137,9 @@ }

* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the PDF data (buffer)
*/
async createViaS3Bucket(params, alternativeLambda) {
async createViaS3Bucket(params) {
try {
const result = await this.lambda
const result = await lambda
.invoke({
FunctionName: alternativeLambda || this.LAMBDA_NAME_VIA_S3_BUCKET,
FunctionName: this.options.lambdaFnViaS3BucketName,
InvocationType: 'RequestResponse',

@@ -112,7 +150,7 @@ Payload: JSON.stringify(params)

const s3params = JSON.parse(result.Payload);
const s3Obj = await this.s3.getObject(s3params).promise();
const s3Obj = await s3.getObject(s3params).promise();
return s3Obj.Body;
}
catch (err) {
(0, idea_toolbox_1.logger)('PDF creation failed', err, alternativeLambda || this.LAMBDA_NAME_VIA_S3_BUCKET);
console.error('PDF creation failed', err, this.options.lambdaFnViaS3BucketName);
throw err;

@@ -124,49 +162,15 @@ }

* @param params the parameters to create the PDF
* @param alternativeLambda an alternative lambda function to use to generate the PDF
* @return the URL to download the PDF
*/
async createLink(params, alternativeLambda) {
const pdfData = await this.create(params, alternativeLambda);
const Key = 'html2pdf'.concat(new Date().getTime().toString().concat(Math.random().toString(36).slice(2)), '.pdf');
const Bucket = 'idea-downloads';
const Expires = 60;
await this.s3.upload({ Bucket, Key, Body: pdfData }).promise();
return new idea_toolbox_1.SignedURL({ url: this.s3.getSignedUrl('getObject', { Bucket, Key, Expires }) });
async createLink(params) {
const pdfData = await this.create(params);
const Key = params.s3Prefix.concat(new Date().getTime().toString().concat(Math.random().toString(36).slice(2)), '.pdf');
const Bucket = params.s3Bucket;
const Expires = 120;
await s3.upload({ Bucket, Key, Body: pdfData }).promise();
return new idea_toolbox_1.SignedURL({ url: s3.getSignedUrl('getObject', { Bucket, Key, Expires }) });
}
/**
* Helper function to prepare Handlebar's helper for the `PDFTemplateSection` standard.
*/
getHandlebarHelpersForPDFTemplate(language, languages, htmlInnerTemplate, additionalTranslations) {
return {
get: (context, x) => context[x],
getOrDash: (context, x) => (context[x] !== null && context[x] !== undefined ? context[x] : '-'),
doesColumnContainAField: (section, colIndex) => section.doesColumnContainAField(colIndex),
getColumnFieldSize: (section, colIndex) => section.getColumnFieldSize(colIndex),
substituteVars: (data, str) => {
if (!str || !data)
return str || '';
str = String(str);
const matches = str.match(/@\w*/gm);
if (matches)
matches.forEach(attr => {
if (data[attr] !== undefined)
str = str.replace(attr, data[attr] === null ? '' : data[attr]);
});
return str;
},
inception: (_template, _data) => {
const variables = { _template, _data };
return new Handlebars.SafeString(Handlebars.compile(htmlInnerTemplate, { compat: true })(variables));
},
isFieldABoolean: (data, value) => typeof data[value] === 'boolean',
isFieldANumber: (data, value) => typeof data[value] === 'number',
ifEqual: (a, b, opt) => (a === b ? opt.fn(this) : opt.inverse(this)),
label: (label) => (label ? label[language] || label[languages.default] : null),
mdToHTML: (s) => (typeof s === 'string' ? new Handlebars.SafeString((0, idea_toolbox_1.mdToHtml)(s)) : s),
translate: (s) => s && additionalTranslations && additionalTranslations[s] ? additionalTranslations[s] : s
};
}
}
exports.HTML2PDF = HTML2PDF;
exports.PDF_TEMPLATE = `
exports.PDF_DEFAULT_TEMPLATE = `
<!DOCTYPE html>

@@ -173,0 +177,0 @@ <html>

{
"name": "idea-html2pdf",
"version": "1.3.2",
"version": "2.0.0",
"description": "IDEA helper for generating a PDF from HTML contents",

@@ -35,3 +35,3 @@ "engines": {

"handlebars": "^4.7.7",
"idea-toolbox": "^6.5.11"
"idea-toolbox": "^6.5.15"
},

@@ -38,0 +38,0 @@ "devDependencies": {

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