Skip to content

Commit

Permalink
add enableXfa option to PdfToPngOptions interface
Browse files Browse the repository at this point in the history
  • Loading branch information
dichovsky committed Apr 9, 2023
1 parent 30b4879 commit 514e966
Show file tree
Hide file tree
Showing 12 changed files with 79 additions and 23 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -30,6 +30,7 @@ test(`Convert PDF To PNG`, async () => {
{
disableFontFace: false, // When `false`, fonts will be rendered using a built-in font renderer that constructs the glyphs with primitive path commands. Default value is true.
useSystemFonts: false, // When `true`, fonts that aren't embedded in the PDF document will fallback to a system font. Default value is false.
enableXfa: false, // Render Xfa forms if any. Default value is false.
viewportScale: 2.0, // The desired scale of PNG viewport. Default value is 1.0.
outputFolder: 'output/folder', // Folder to write output PNG files. If not specified, PNG output will be available only as a Buffer content, without saving to a file.
outputFileMask: 'buffer', // Output filename mask. Default value is 'buffer'.
Expand Down
10 changes: 4 additions & 6 deletions __tests__/buffer.pdf.to.buffer.ts
@@ -1,7 +1,7 @@
import { existsSync, readFileSync } from 'node:fs';
import { parse, resolve } from 'node:path';
import comparePng from 'png-visual-compare';
import { pdfToPng, PngPageOutput } from '../src';
import { PngPageOutput, pdfToPng } from '../src';
import { comparePNG } from '../src/compare.png';
import { PDF_TO_PNG_OPTIONS_DEFAULTS } from '../src/const';

const pdfFilePath: string = resolve('test-data/large_pdf.pdf');
Expand All @@ -15,8 +15,7 @@ test(`should convert PDF To PNG without saving to file, output file mask is defi

pngPages.forEach((pngPage: PngPageOutput) => {
const expectedFilePath: string = resolve('test-data/pdf.to.buffer/expected', pngPage.name);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const compareResult: number = comparePng(pngPage.content, expectedFileContent);
const compareResult: number = comparePNG(pngPage.content, expectedFilePath);

expect(existsSync(pngPage.path)).toBe(false);
expect(compareResult).toBe(0);
Expand All @@ -33,8 +32,7 @@ test(`should convert PDF To PNG without saving to file, output file mask is not
'test-data/pdf.to.buffer/expected',
pngPage.name.replace(PDF_TO_PNG_OPTIONS_DEFAULTS.outputFileMask as string, parse(pdfFilePath).name),
);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const compareResult: number = comparePng(pngPage.content, expectedFileContent);
const compareResult: number = comparePNG(pngPage.content, expectedFilePath);

expect(pngPage.name).toBe(`${PDF_TO_PNG_OPTIONS_DEFAULTS.outputFileMask as string}_page_${index + 1}.png`);
expect(existsSync(pngPage.path)).toBe(false);
Expand Down
5 changes: 2 additions & 3 deletions __tests__/pdf.pages.to.file.ts
@@ -1,7 +1,7 @@
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import comparePng from 'png-visual-compare';
import { pdfToPng, PngPageOutput } from '../src';
import { comparePNG } from '../src/compare.png';

test(`should convert specific PDF pages To PNG files`, async () => {
const pdfFilePath: string = resolve('test-data/large_pdf.pdf');
Expand All @@ -15,9 +15,8 @@ test(`should convert specific PDF pages To PNG files`, async () => {

pngPages.forEach((pngPage: PngPageOutput) => {
const expectedFilePath: string = resolve('test-data/pdf.to.file/expected', pngPage.name);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const actualFileContent: Buffer = readFileSync(pngPage.path);
const compareResult: number = comparePng(actualFileContent, expectedFileContent);
const compareResult: number = comparePNG(actualFileContent, expectedFilePath);

expect(compareResult).toBe(0);
});
Expand Down
9 changes: 4 additions & 5 deletions __tests__/pdf.to.buffer.ts
@@ -1,7 +1,7 @@
import { existsSync, readFileSync } from 'node:fs';
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
import comparePng from 'png-visual-compare';
import { pdfToPng, PngPageOutput } from '../src';
import { PngPageOutput, pdfToPng } from '../src';
import { comparePNG } from '../src/compare.png';

test(`should convert PDF To PNG buffer (without saving to file)`, async () => {
const pdfFilePath: string = resolve('test-data/large_pdf.pdf');
Expand All @@ -11,8 +11,7 @@ test(`should convert PDF To PNG buffer (without saving to file)`, async () => {

pngPages.forEach((pngPage: PngPageOutput) => {
const expectedFilePath: string = resolve('test-data/pdf.to.buffer/expected', pngPage.name);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const compareResult: number = comparePng(pngPage.content, expectedFileContent);
const compareResult: number = comparePNG(pngPage.content, expectedFilePath);

expect(existsSync(pngPage.path)).toBe(false);
expect(compareResult).toBe(0);
Expand Down
5 changes: 2 additions & 3 deletions __tests__/pdf.to.file.ts
@@ -1,7 +1,7 @@
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import comparePng from 'png-visual-compare';
import { pdfToPng, PngPageOutput } from '../src';
import { comparePNG } from '../src/compare.png';

test(`should convert PDF To PNG files`, async () => {
const pdfFilePath: string = resolve('test-data/large_pdf.pdf');
Expand All @@ -11,9 +11,8 @@ test(`should convert PDF To PNG files`, async () => {

pngPages.forEach((pngPage: PngPageOutput) => {
const expectedFilePath: string = resolve('test-data/pdf.to.file/expected', pngPage.name);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const actualFileContent: Buffer = readFileSync(pngPage.path);
const compareResult: number = comparePng(actualFileContent, expectedFileContent);
const compareResult: number = comparePNG(actualFileContent, expectedFilePath);

expect(compareResult).toBe(0);
});
Expand Down
35 changes: 34 additions & 1 deletion __tests__/props.to.pdf.doc.init.params.ts
Expand Up @@ -8,9 +8,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
password: undefined,
},
},
Expand All @@ -20,9 +22,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
password: undefined,
},
},
Expand All @@ -34,9 +38,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
password: undefined,
},
},
Expand All @@ -48,9 +54,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: false,
useSystemFonts: false,
enableXfa: false,
password: undefined,
},
},
Expand All @@ -62,9 +70,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: true,
enableXfa: false,
password: undefined,
},
},
Expand All @@ -76,9 +86,11 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
password: '12345',
},
},
Expand All @@ -90,9 +102,27 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 1,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
password: undefined,
},
},
{
id: 'only enableXfa is specified',
props: {
enableXfa: true,
},
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 0,
disableFontFace: true,
useSystemFonts: false,
enableXfa: true,
password: undefined,
},
},
Expand All @@ -102,6 +132,7 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
viewportScale: 3.0,
disableFontFace: false,
useSystemFonts: true,
enableXfa: true,
pdfFilePassword: 'pdfFilePassword',
outputFolder: 'outputFolder',
outputFileMask: 'outputFileMask',
Expand All @@ -112,17 +143,19 @@ const testDataArray: { id: string; props?: PdfToPngOptions; expectedPdfDocInitPa
expectedPdfDocInitParams: {
cMapUrl: '../node_modules/pdfjs-dist/cmaps/',
cMapPacked: true,
standardFontDataUrl: '../node_modules/pdfjs-dist/standard_fonts/',
verbosity: 2,
disableFontFace: false,
useSystemFonts: true,
enableXfa: true,
password: 'pdfFilePassword',
},
},
];

for (const testData of testDataArray) {
test(`should convert props to PdfDocInitParams when ${testData.id}`, async () => {
const actualPdfDocInitParams = propsToPdfDocInitParams(testData.props);
const actualPdfDocInitParams: DocumentInitParameters = propsToPdfDocInitParams(testData.props);

expect(actualPdfDocInitParams).toStrictEqual(testData.expectedPdfDocInitParams);
});
Expand Down
6 changes: 2 additions & 4 deletions __tests__/protected.pdf.ts
@@ -1,7 +1,6 @@
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import comparePng from 'png-visual-compare';
import { pdfToPng, PngPageOutput } from '../src';
import { comparePNG } from '../src/compare.png';

test(`should convert protected PDF To PNG`, async () => {
const pdfFilePath: string = resolve('test-data/large_pdf-protected.pdf');
Expand All @@ -12,8 +11,7 @@ test(`should convert protected PDF To PNG`, async () => {

pngPages.forEach((pngPage: PngPageOutput) => {
const expectedFilePath: string = resolve('test-data/protected.pdf/expected', pngPage.name);
const expectedFileContent: Buffer = readFileSync(expectedFilePath);
const compareResult: number = comparePng(pngPage.content, expectedFileContent);
const compareResult: number = comparePNG(pngPage.content, expectedFilePath);

expect(compareResult).toBe(0);
});
Expand Down
22 changes: 22 additions & 0 deletions src/compare.png.ts
@@ -0,0 +1,22 @@
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import comparePng, { ComparePngOptions } from 'png-visual-compare';
import {parse} from 'path';
import { mkdirSync } from 'node:fs';
export function comparePNG(
actualFilePathOrBuffer: string | Buffer,
expectedFilePath: string,
opts?: ComparePngOptions,
) {
if (!existsSync(expectedFilePath)) {
const expectedFileDir = parse(expectedFilePath).dir
if(!existsSync(expectedFileDir)) {
mkdirSync(expectedFileDir, {recursive: true});
}
const actualBuffer: Buffer = typeof actualFilePathOrBuffer === 'string'
? readFileSync(actualFilePathOrBuffer)
: actualFilePathOrBuffer;
writeFileSync(expectedFilePath, actualBuffer);

}
return comparePng(actualFilePathOrBuffer, expectedFilePath, opts);
}
1 change: 1 addition & 0 deletions src/const.ts
Expand Up @@ -4,6 +4,7 @@ export const PDF_TO_PNG_OPTIONS_DEFAULTS: PdfToPngOptions = {
viewportScale: 1,
disableFontFace: true,
useSystemFonts: false,
enableXfa: false,
outputFileMask: 'buffer',
strictPagesToProcess: false,
pdfFilePassword: undefined,
Expand Down
2 changes: 1 addition & 1 deletion src/pdf.to.png.ts
Expand Up @@ -91,7 +91,7 @@ export async function pdfToPng(
};

canvasFactory.destroy(canvasAndContext);

page.cleanup();
if (props?.outputFolder) {
pngPageOutput.path = resolve(props.outputFolder, pngPageOutput.name);
writeFileSync(pngPageOutput.path, pngPageOutput.content);
Expand Down
5 changes: 5 additions & 0 deletions src/props.to.pdf.doc.init.params.ts
Expand Up @@ -6,9 +6,11 @@ import { VerbosityLevel } from './types/verbosity.level';
export function propsToPdfDocInitParams(props?: PdfToPngOptions): pdfApiTypes.DocumentInitParameters {
const cMapUrl = '../node_modules/pdfjs-dist/cmaps/';
const cMapPacked = true;
const standardFontDataUrl = '../node_modules/pdfjs-dist/standard_fonts/';
const pdfDocInitParams: pdfApiTypes.DocumentInitParameters = {
cMapUrl,
cMapPacked,
standardFontDataUrl,
};

pdfDocInitParams.verbosity = props?.verbosityLevel !== undefined ? props?.verbosityLevel : VerbosityLevel.ERRORS;
Expand All @@ -19,6 +21,9 @@ export function propsToPdfDocInitParams(props?: PdfToPngOptions): pdfApiTypes.Do
pdfDocInitParams.useSystemFonts =
props?.useSystemFonts !== undefined ? props.useSystemFonts : PDF_TO_PNG_OPTIONS_DEFAULTS.useSystemFonts;

pdfDocInitParams.enableXfa =
props?.enableXfa !== undefined ? props.enableXfa : PDF_TO_PNG_OPTIONS_DEFAULTS.enableXfa;

pdfDocInitParams.password =
props?.pdfFilePassword !== undefined ? props?.pdfFilePassword : PDF_TO_PNG_OPTIONS_DEFAULTS.pdfFilePassword;

Expand Down
1 change: 1 addition & 0 deletions src/types/pdf.to.png.options.ts
Expand Up @@ -2,6 +2,7 @@ export type PdfToPngOptions = {
viewportScale?: number;
disableFontFace?: boolean;
useSystemFonts?: boolean;
enableXfa?: boolean;
pdfFilePassword?: string;
outputFolder?: string;
outputFileMask?: string;
Expand Down

0 comments on commit 514e966

Please sign in to comment.