pdf-visual-compare 1.4.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -20
- package/out/comparePdf.d.ts +3 -0
- package/out/comparePdf.d.ts.map +1 -0
- package/out/comparePdf.js +68 -0
- package/out/comparePdf.js.map +1 -0
- package/out/const.js +2 -5
- package/out/const.js.map +1 -1
- package/out/index.d.ts +5 -2
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -22
- package/out/index.js.map +1 -1
- package/out/types/ComparePdfOptions.d.ts +9 -0
- package/out/types/ComparePdfOptions.d.ts.map +1 -0
- package/out/types/ComparePdfOptions.js +2 -0
- package/out/types/ComparePdfOptions.js.map +1 -0
- package/out/types/{excluded.page.area.d.ts → ExcludedPageArea.d.ts} +2 -2
- package/out/types/ExcludedPageArea.d.ts.map +1 -0
- package/out/types/ExcludedPageArea.js +2 -0
- package/out/types/ExcludedPageArea.js.map +1 -0
- package/package.json +33 -25
- package/out/compare.pdf.d.ts +0 -3
- package/out/compare.pdf.d.ts.map +0 -1
- package/out/compare.pdf.js +0 -79
- package/out/compare.pdf.js.map +0 -1
- package/out/types/compare.options.d.ts +0 -8
- package/out/types/compare.options.d.ts.map +0 -1
- package/out/types/compare.options.js +0 -3
- package/out/types/compare.options.js.map +0 -1
- package/out/types/excluded.page.area.d.ts.map +0 -1
- package/out/types/excluded.page.area.js +0 -3
- package/out/types/excluded.page.area.js.map +0 -1
- package/out/types/index.d.ts +0 -5
- package/out/types/index.d.ts.map +0 -1
- package/out/types/index.js +0 -3
- package/out/types/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
# pdf-visual-compare
|
|
2
2
|
|
|
3
|
-
Visual regression testing library for PDFs in
|
|
3
|
+
Visual regression testing library for PDFs in JavaScript/TypeScript without binary and OS dependencies.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/dichovsky/pdf-visual-compare/actions/workflows/test.yml)
|
|
6
6
|
|
|
7
|
-
## Getting
|
|
7
|
+
## Getting Started
|
|
8
8
|
|
|
9
|
-
Installation
|
|
9
|
+
### Installation
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
npm install -D pdf-visual-compare
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Example
|
|
16
16
|
|
|
17
17
|
```javascript
|
|
18
|
-
|
|
18
|
+
const result = await comparePdf('./pdf1.pdf', './pdf2.pdf');
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// If you want to configure the comparing process, use the following options
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
diffsOutputFolder
|
|
24
|
-
pdfToPngConvertOptions
|
|
25
|
-
viewportScale: 2.0, // The desired scale of PNG viewport. Default value is
|
|
26
|
-
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.
|
|
22
|
+
const result = await comparePdf('./pdf1.pdf', './pdf2.pdf', {
|
|
23
|
+
diffsOutputFolder: 'diffs', // Folder to write output PNG files with differences
|
|
24
|
+
pdfToPngConvertOptions: {
|
|
25
|
+
viewportScale: 2.0, // The desired scale of PNG viewport. Default value is 2.0.
|
|
26
|
+
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.
|
|
27
27
|
useSystemFonts: false, // When `true`, fonts that aren't embedded in the PDF document will fallback to a system font. Default value is false.
|
|
28
28
|
pdfFilePassword: 'pa$$word', // Password for encrypted PDF.
|
|
29
29
|
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.
|
|
30
30
|
outputFileMask: 'buffer', // Output filename mask. Default value is 'buffer'.
|
|
31
|
-
pagesToProcess: [1, 3, 11],
|
|
32
|
-
strictPagesToProcess: false // When `true`, will throw an error if specified page number in pagesToProcess is invalid, otherwise will skip invalid page. Default value is false.
|
|
31
|
+
pagesToProcess: [1, 3, 11], // Subset of pages to convert (first page = 1), other pages will be skipped if specified.
|
|
32
|
+
strictPagesToProcess: false, // When `true`, will throw an error if specified page number in pagesToProcess is invalid, otherwise will skip invalid page. Default value is false.
|
|
33
33
|
verbosityLevel: 0 // Verbosity level. ERRORS: 0, WARNINGS: 1, INFOS: 5. Default value is 0.
|
|
34
|
-
}
|
|
35
|
-
excludedAreas
|
|
36
|
-
compareThreshold
|
|
34
|
+
},
|
|
35
|
+
excludedAreas: [], // Areas list to exclude from comparing for each PDF page. Empty array by default.
|
|
36
|
+
compareThreshold: 0.1 // Comparing threshold, ranges from 0 to 1. Smaller values make the comparison more sensitive. 0.1 by default.
|
|
37
37
|
});
|
|
38
|
-
|
|
39
38
|
```
|
|
40
39
|
|
|
41
|
-
##
|
|
40
|
+
## Support
|
|
41
|
+
|
|
42
|
+
If you want to support my work, you can buy me a coffee.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
[](https://buymeacoffee.com/dichovsky)
|
|
44
45
|
|
|
45
|
-
[](https://buymeacoffee.com/dichovsky)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparePdf.d.ts","sourceRoot":"","sources":["../src/comparePdf.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAYjE,wBAAsB,UAAU,CAC5B,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,IAAI,GAAE,iBAAsB,GAC7B,OAAO,CAAC,OAAO,CAAC,CA0DlB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import { pdfToPng } from 'pdf-to-png-converter';
|
|
13
|
+
import comparePng from 'png-visual-compare';
|
|
14
|
+
import { DEFAULT_DIFFS_FOLDER } from './const.js';
|
|
15
|
+
export function comparePdf(actualPdf_1, expectedPdf_1) {
|
|
16
|
+
return __awaiter(this, arguments, void 0, function* (actualPdf, expectedPdf, opts = {}) {
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
validateInputFileType(actualPdf);
|
|
19
|
+
validateInputFileType(expectedPdf);
|
|
20
|
+
const pdfToPngConvertOpts = Object.assign({}, opts.pdfToPngConvertOptions);
|
|
21
|
+
if (!pdfToPngConvertOpts.viewportScale) {
|
|
22
|
+
pdfToPngConvertOpts.viewportScale = 2.0;
|
|
23
|
+
}
|
|
24
|
+
if (!pdfToPngConvertOpts.outputFileMaskFunc) {
|
|
25
|
+
pdfToPngConvertOpts.outputFileMaskFunc = (pageNumber) => `comparePdf_${pageNumber}.png`;
|
|
26
|
+
}
|
|
27
|
+
const diffsOutputFolder = (_a = opts === null || opts === void 0 ? void 0 : opts.diffsOutputFolder) !== null && _a !== void 0 ? _a : DEFAULT_DIFFS_FOLDER;
|
|
28
|
+
const compareThreshold = (_b = opts === null || opts === void 0 ? void 0 : opts.compareThreshold) !== null && _b !== void 0 ? _b : 0;
|
|
29
|
+
const excludedAreas = (_c = opts === null || opts === void 0 ? void 0 : opts.excludedAreas) !== null && _c !== void 0 ? _c : [];
|
|
30
|
+
if (compareThreshold < 0) {
|
|
31
|
+
throw Error('Compare Threshold cannot be less than 0.');
|
|
32
|
+
}
|
|
33
|
+
let [actualPdfPngPages, expectedPdfPngPages] = yield Promise.all([
|
|
34
|
+
pdfToPng(actualPdf, pdfToPngConvertOpts),
|
|
35
|
+
pdfToPng(expectedPdf, pdfToPngConvertOpts),
|
|
36
|
+
]);
|
|
37
|
+
if (actualPdfPngPages.length < expectedPdfPngPages.length) {
|
|
38
|
+
[actualPdfPngPages, expectedPdfPngPages] = [expectedPdfPngPages, actualPdfPngPages];
|
|
39
|
+
}
|
|
40
|
+
let documentCompareResult = true;
|
|
41
|
+
actualPdfPngPages.forEach((pngPage, index) => {
|
|
42
|
+
var _a;
|
|
43
|
+
const comparePngOpts = Object.assign(Object.assign(Object.assign({}, opts === null || opts === void 0 ? void 0 : opts.pdfToPngConvertOptions), excludedAreas[index]), { throwErrorOnInvalidInputData: false });
|
|
44
|
+
comparePngOpts.diffFilePath = resolve(diffsOutputFolder, `diff_${pngPage.name}`);
|
|
45
|
+
const pngPageOutputToCompareWith = expectedPdfPngPages.find((p) => p.name === pngPage.name);
|
|
46
|
+
const pageCompareResult = comparePng(pngPage.content, (_a = pngPageOutputToCompareWith === null || pngPageOutputToCompareWith === void 0 ? void 0 : pngPageOutputToCompareWith.content) !== null && _a !== void 0 ? _a : '', comparePngOpts);
|
|
47
|
+
if (pageCompareResult > compareThreshold) {
|
|
48
|
+
documentCompareResult = false;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return documentCompareResult;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function validateInputFileType(inputFile) {
|
|
55
|
+
if (Buffer.isBuffer(inputFile)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (typeof inputFile === 'string') {
|
|
59
|
+
if (existsSync(inputFile)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw Error(`PDF file not found: ${inputFile}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw Error(`Unknown input file type.`);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=comparePdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparePdf.js","sourceRoot":"","sources":["../src/comparePdf.ts"],"names":[],"mappings":"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"}
|
package/out/const.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.DEFAULT_DIFFS_FOLDER = void 0;
|
|
4
|
-
const path_1 = require("path");
|
|
5
|
-
exports.DEFAULT_DIFFS_FOLDER = (0, path_1.resolve)(`./comparePdfOutput`);
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
export const DEFAULT_DIFFS_FOLDER = resolve(`./comparePdfOutput`);
|
|
6
3
|
//# sourceMappingURL=const.js.map
|
package/out/const.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const.js","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"const.js","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC"}
|
package/out/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import comparePdf from './
|
|
1
|
+
import { comparePdf } from './comparePdf.js';
|
|
2
2
|
export default comparePdf;
|
|
3
|
-
export
|
|
3
|
+
export { PdfToPngOptions } from 'pdf-to-png-converter';
|
|
4
|
+
export { Area, Color } from 'png-visual-compare';
|
|
5
|
+
export { ComparePdfOptions } from './types/ComparePdfOptions.js';
|
|
6
|
+
export { ExcludedPageArea } from './types/ExcludedPageArea.js';
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,eAAe,UAAU,CAAC;AAG1B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/out/index.js
CHANGED
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
-
};
|
|
19
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
const compare_pdf_1 = __importDefault(require("./compare.pdf"));
|
|
21
|
-
exports.default = compare_pdf_1.default;
|
|
22
|
-
__exportStar(require("./types"), exports);
|
|
1
|
+
import { comparePdf } from './comparePdf.js';
|
|
2
|
+
export default comparePdf;
|
|
23
3
|
//# sourceMappingURL=index.js.map
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PdfToPngOptions } from 'pdf-to-png-converter';
|
|
2
|
+
import { ExcludedPageArea } from './ExcludedPageArea.js';
|
|
3
|
+
export type ComparePdfOptions = {
|
|
4
|
+
diffsOutputFolder?: string;
|
|
5
|
+
pdfToPngConvertOptions?: PdfToPngOptions;
|
|
6
|
+
excludedAreas?: readonly ExcludedPageArea[];
|
|
7
|
+
compareThreshold?: number;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=ComparePdfOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComparePdfOptions.d.ts","sourceRoot":"","sources":["../../src/types/ComparePdfOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,eAAe,CAAC;IACzC,aAAa,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComparePdfOptions.js","sourceRoot":"","sources":["../../src/types/ComparePdfOptions.ts"],"names":[],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Area, Color } from '
|
|
1
|
+
import { Area, Color } from 'png-visual-compare';
|
|
2
2
|
export type ExcludedPageArea = {
|
|
3
3
|
pageNumber: number;
|
|
4
4
|
excludedAreas?: Area[];
|
|
@@ -6,4 +6,4 @@ export type ExcludedPageArea = {
|
|
|
6
6
|
diffFilePath?: string;
|
|
7
7
|
matchingThreshold?: number;
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=
|
|
9
|
+
//# sourceMappingURL=ExcludedPageArea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExcludedPageArea.d.ts","sourceRoot":"","sources":["../../src/types/ExcludedPageArea.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,KAAK,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExcludedPageArea.js","sourceRoot":"","sources":["../../src/types/ExcludedPageArea.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-visual-compare",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Visual regression testing library for PDFs in Js/Ts without binary and OS dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pdf",
|
|
@@ -18,42 +18,50 @@
|
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"author": "Igor Magdich <magdich.igor@gmail.com>",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"default": "./out/index.js",
|
|
25
|
+
"types": "./out/index.d.ts"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"main": "./out/index.js",
|
|
29
|
+
"types": "./out/index.d.ts",
|
|
23
30
|
"files": [
|
|
24
|
-
"
|
|
31
|
+
"./out"
|
|
25
32
|
],
|
|
26
33
|
"scripts": {
|
|
27
|
-
"
|
|
34
|
+
"prebuild": "npm run clean",
|
|
35
|
+
"build": "tsc --pretty",
|
|
28
36
|
"clean": "rimraf ./out ./coverage ./test-results ./comparePdfOutput",
|
|
29
37
|
"docker:build": "docker build --compress -t test-pdf-visual-compare .",
|
|
30
38
|
"predocker:run": "npm run clean",
|
|
31
|
-
"docker:run": "docker run --rm -it -v test-results:/usr/pkg/test-results test-pdf-visual-compare",
|
|
32
|
-
"docker:test": "
|
|
39
|
+
"docker:run": "docker run --rm -it -v $PWD/test-results:/usr/pkg/test-results test-pdf-visual-compare",
|
|
40
|
+
"docker:test": "vitest run",
|
|
33
41
|
"license-checker": "npx license-checker --production --onlyAllow 'MIT; MIT OR X11; BSD; ISC; Apache-2.0; Unlicense'",
|
|
34
42
|
"lint": "eslint .",
|
|
35
43
|
"lint:fix": "npm run lint -- --fix",
|
|
36
|
-
"pretest": "npm run
|
|
37
|
-
"test": "
|
|
38
|
-
"test:
|
|
39
|
-
"test:docker": "npm run docker:build && npm run docker:run",
|
|
40
|
-
"tsc": "tsc --pretty"
|
|
44
|
+
"pretest": "npm run clean",
|
|
45
|
+
"test": "vitest run --coverage",
|
|
46
|
+
"test:docker": "npm run docker:build && npm run docker:run"
|
|
41
47
|
},
|
|
42
48
|
"dependencies": {
|
|
43
|
-
"pdf-to-png-converter": "^
|
|
44
|
-
"png-visual-compare": "^
|
|
45
|
-
"pngjs": "^6.0.0"
|
|
49
|
+
"pdf-to-png-converter": "^3.6.1",
|
|
50
|
+
"png-visual-compare": "^2.2.1"
|
|
46
51
|
},
|
|
47
52
|
"devDependencies": {
|
|
48
|
-
"@types/
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
53
|
+
"@types/node": "^22.10.1",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^8.17.0",
|
|
55
|
+
"@typescript-eslint/parser": "^8.17.0",
|
|
56
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
57
|
+
"eslint": "^9.16.0",
|
|
58
|
+
"rimraf": "^6.0.1",
|
|
59
|
+
"ts-node": "^10.9.2",
|
|
60
|
+
"typescript": "^5.7.2",
|
|
61
|
+
"vitest": "^2.1.8"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=20",
|
|
65
|
+
"yarn": "please-use-npm"
|
|
58
66
|
}
|
|
59
67
|
}
|
package/out/compare.pdf.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { ComparePdfOptions } from './types';
|
|
2
|
-
export default function comparePdf(actualPdfFilePathOrBuffer: string | ArrayBufferLike, expectedPdfFilePathOrBuffer: string | ArrayBufferLike, opts?: ComparePdfOptions): Promise<boolean>;
|
|
3
|
-
//# sourceMappingURL=compare.pdf.d.ts.map
|
package/out/compare.pdf.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare.pdf.d.ts","sourceRoot":"","sources":["../src/compare.pdf.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAqC,MAAM,SAAS,CAAC;AAE/E,wBAA8B,UAAU,CACtC,yBAAyB,EAAE,MAAM,GAAG,eAAe,EACnD,2BAA2B,EAAE,MAAM,GAAG,eAAe,EACrD,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,OAAO,CAAC,CAmElB"}
|
package/out/compare.pdf.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const fs_1 = require("fs");
|
|
7
|
-
const path_1 = require("path");
|
|
8
|
-
const pdf_to_png_converter_1 = require("pdf-to-png-converter");
|
|
9
|
-
const png_visual_compare_1 = __importDefault(require("png-visual-compare"));
|
|
10
|
-
const pngjs_1 = require("pngjs");
|
|
11
|
-
const const_1 = require("./const");
|
|
12
|
-
async function comparePdf(actualPdfFilePathOrBuffer, expectedPdfFilePathOrBuffer, opts) {
|
|
13
|
-
if (!Buffer.isBuffer(actualPdfFilePathOrBuffer) && !(0, fs_1.existsSync)(actualPdfFilePathOrBuffer)) {
|
|
14
|
-
throw Error('Actual PDF file not found.');
|
|
15
|
-
}
|
|
16
|
-
if (!Buffer.isBuffer(expectedPdfFilePathOrBuffer) && !(0, fs_1.existsSync)(expectedPdfFilePathOrBuffer)) {
|
|
17
|
-
throw Error('Expected PDF file not found.');
|
|
18
|
-
}
|
|
19
|
-
const pdfToPngConvertOpts = { ...opts?.pdfToPngConvertOptions };
|
|
20
|
-
if (!pdfToPngConvertOpts.viewportScale) {
|
|
21
|
-
pdfToPngConvertOpts.viewportScale = 2.0;
|
|
22
|
-
}
|
|
23
|
-
if (!pdfToPngConvertOpts.outputFileMask) {
|
|
24
|
-
pdfToPngConvertOpts.outputFileMask = 'comparePdf';
|
|
25
|
-
}
|
|
26
|
-
const diffsOutputFolder = opts?.diffsOutputFolder
|
|
27
|
-
? opts.diffsOutputFolder
|
|
28
|
-
: const_1.DEFAULT_DIFFS_FOLDER;
|
|
29
|
-
const compareThreshold = opts?.compareThreshold
|
|
30
|
-
? opts?.compareThreshold
|
|
31
|
-
: 0;
|
|
32
|
-
const excludedAreas = opts?.excludedAreas
|
|
33
|
-
? opts.excludedAreas
|
|
34
|
-
: [];
|
|
35
|
-
if (compareThreshold < 0) {
|
|
36
|
-
throw Error('Compare Threshold cannot be less than 0.');
|
|
37
|
-
}
|
|
38
|
-
let [actualPdfPngPages, expectedPdfPngPages] = await Promise.all([
|
|
39
|
-
(0, pdf_to_png_converter_1.pdfToPng)(actualPdfFilePathOrBuffer, pdfToPngConvertOpts),
|
|
40
|
-
(0, pdf_to_png_converter_1.pdfToPng)(expectedPdfFilePathOrBuffer, pdfToPngConvertOpts),
|
|
41
|
-
]);
|
|
42
|
-
if (actualPdfPngPages.length < expectedPdfPngPages.length) {
|
|
43
|
-
[actualPdfPngPages, expectedPdfPngPages] = [expectedPdfPngPages, actualPdfPngPages];
|
|
44
|
-
}
|
|
45
|
-
let documentCompareResult = true;
|
|
46
|
-
actualPdfPngPages.forEach((pngPage, index) => {
|
|
47
|
-
const comparePngOpts = { ...opts?.pdfToPngConvertOptions, ...excludedAreas[index] };
|
|
48
|
-
comparePngOpts.diffFilePath = (0, path_1.resolve)(diffsOutputFolder, `diff_${pngPage.name}`);
|
|
49
|
-
const pngPageOutputToCompareWith = expectedPdfPngPages.find((p) => p.name === pngPage.name);
|
|
50
|
-
let bufferToCompareWith;
|
|
51
|
-
if (pngPageOutputToCompareWith) {
|
|
52
|
-
bufferToCompareWith = pngPageOutputToCompareWith.content;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const originalPngMetaData = pngjs_1.PNG.sync.read(pngPage.content);
|
|
56
|
-
bufferToCompareWith = getEmptyPngBuffer(originalPngMetaData.width, originalPngMetaData.height);
|
|
57
|
-
}
|
|
58
|
-
const pageCompareResult = (0, png_visual_compare_1.default)(pngPage.content, bufferToCompareWith, comparePngOpts);
|
|
59
|
-
if (pageCompareResult > compareThreshold) {
|
|
60
|
-
documentCompareResult = false;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
return documentCompareResult;
|
|
64
|
-
}
|
|
65
|
-
exports.default = comparePdf;
|
|
66
|
-
function getEmptyPngBuffer(width, height) {
|
|
67
|
-
const image = new pngjs_1.PNG({ width, height });
|
|
68
|
-
for (let y = 0; y < image.height; y++) {
|
|
69
|
-
for (let x = 0; x < image.width; x++) {
|
|
70
|
-
const position = (image.width * y + x) << 2;
|
|
71
|
-
image.data[position + 0] = 255;
|
|
72
|
-
image.data[position + 1] = 255;
|
|
73
|
-
image.data[position + 2] = 255;
|
|
74
|
-
image.data[position + 3] = 255;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return pngjs_1.PNG.sync.write(image);
|
|
78
|
-
}
|
|
79
|
-
//# sourceMappingURL=compare.pdf.js.map
|
package/out/compare.pdf.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare.pdf.js","sourceRoot":"","sources":["../src/compare.pdf.ts"],"names":[],"mappings":";;;;;AAAA,2BAAgC;AAChC,+BAA+B;AAC/B,+DAA+D;AAC/D,4EAAmE;AACnE,iCAA6C;AAC7C,mCAA+C;AAGhC,KAAK,UAAU,UAAU,CACtC,yBAAmD,EACnD,2BAAqD,EACrD,IAAwB;IAExB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAA,eAAU,EAAC,yBAAmC,CAAC,EAAE;QACnG,MAAM,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC3C;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAA,eAAU,EAAC,2BAAqC,CAAC,EAAE;QACvG,MAAM,KAAK,CAAC,8BAA8B,CAAC,CAAC;KAC7C;IAED,MAAM,mBAAmB,GAAoB,EAAE,GAAG,IAAI,EAAE,sBAAsB,EAAE,CAAC;IACjF,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE;QACtC,mBAAmB,CAAC,aAAa,GAAG,GAAG,CAAC;KACzC;IACD,IAAI,CAAC,mBAAmB,CAAC,cAAc,EAAE;QACvC,mBAAmB,CAAC,cAAc,GAAG,YAAY,CAAC;KACnD;IAED,MAAM,iBAAiB,GAAW,IAAI,EAAE,iBAAiB;QACvD,CAAC,CAAC,IAAI,CAAC,iBAAiB;QACxB,CAAC,CAAC,4BAAoB,CAAC;IACzB,MAAM,gBAAgB,GAAW,IAAI,EAAE,gBAAgB;QACrD,CAAC,CAAC,IAAI,EAAE,gBAAgB;QACxB,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,aAAa,GAAuB,IAAI,EAAE,aAAa;QAC3D,CAAC,CAAC,IAAI,CAAC,aAAa;QACpB,CAAC,CAAC,EAAE,CAAC;IAEP,IAAI,gBAAgB,GAAG,CAAC,EAAE;QACxB,MAAM,KAAK,CAAC,0CAA0C,CAAC,CAAC;KACzD;IAED,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/D,IAAA,+BAAQ,EAAC,yBAAyB,EAAE,mBAAmB,CAAC;QACxD,IAAA,+BAAQ,EAAC,2BAA2B,EAAE,mBAAmB,CAAC;KAC3D,CAAC,CAAC;IAEH,IAAI,iBAAiB,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,EAAE;QACzD,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;KACrF;IAED,IAAI,qBAAqB,GAAG,IAAI,CAAC;IACjC,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC3C,MAAM,cAAc,GAAsB,EAAE,GAAG,IAAI,EAAE,sBAAsB,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACvG,cAAc,CAAC,YAAY,GAAG,IAAA,cAAO,EAAC,iBAAiB,EAAE,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAEjF,MAAM,0BAA0B,GAA8B,mBAAmB,CAAC,IAAI,CACpF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAC/B,CAAC;QAEF,IAAI,mBAA2B,CAAC;QAEhC,IAAI,0BAA0B,EAAE;YAC9B,mBAAmB,GAAG,0BAA0B,CAAC,OAAO,CAAC;SAC1D;aAAM;YAEL,MAAM,mBAAmB,GAAoB,WAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC5E,mBAAmB,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;SAChG;QAED,MAAM,iBAAiB,GAAW,IAAA,4BAAU,EAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;QAEnG,IAAI,iBAAiB,GAAG,gBAAgB,EAAE;YACxC,qBAAqB,GAAG,KAAK,CAAC;SAC/B;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAvED,6BAuEC;AAED,SAAS,iBAAiB,CAAC,KAAa,EAAE,MAAc;IACtD,MAAM,KAAK,GAAG,IAAI,WAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,QAAQ,GAAW,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YAEpD,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;SAChC;KACF;IACD,OAAO,WAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ExcludedPageArea, PdfToPngOptions } from '.';
|
|
2
|
-
export type ComparePdfOptions = {
|
|
3
|
-
diffsOutputFolder?: string;
|
|
4
|
-
pdfToPngConvertOptions?: PdfToPngOptions;
|
|
5
|
-
excludedAreas?: ExcludedPageArea[];
|
|
6
|
-
compareThreshold?: number;
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=compare.options.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare.options.d.ts","sourceRoot":"","sources":["../../src/types/compare.options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,eAAe,CAAC;IACzC,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compare.options.js","sourceRoot":"","sources":["../../src/types/compare.options.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"excluded.page.area.d.ts","sourceRoot":"","sources":["../../src/types/excluded.page.area.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC;AAEhC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,KAAK,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"excluded.page.area.js","sourceRoot":"","sources":["../../src/types/excluded.page.area.ts"],"names":[],"mappings":""}
|
package/out/types/index.d.ts
DELETED
package/out/types/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/out/types/index.js
DELETED
package/out/types/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|