pdf-diff-viewer 1.2.0 → 1.3.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/package.json +1 -1
- package/src/PDFDiffViewer.js +36 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-diff-viewer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Browser-based PDF comparison tool with visual diff highlighting. Zero system dependencies, pure JavaScript, client-side processing.",
|
|
5
5
|
"main": "src/PDFDiffViewer.js",
|
|
6
6
|
"type": "module",
|
package/src/PDFDiffViewer.js
CHANGED
|
@@ -20,19 +20,21 @@ class PDFDiffViewer {
|
|
|
20
20
|
scale: options.scale || 3.0,
|
|
21
21
|
maxShift: options.maxShift || 3,
|
|
22
22
|
dilationRadius: options.dilationRadius || 0,
|
|
23
|
-
colorTolerance: options.colorTolerance ||
|
|
23
|
+
colorTolerance: options.colorTolerance || 120,
|
|
24
24
|
minHighlightArea: options.minHighlightArea || 60,
|
|
25
25
|
minWordSize: options.minWordSize || 8,
|
|
26
26
|
highlightAlpha: options.highlightAlpha || 0.32,
|
|
27
|
+
highlightColorA: options.highlightColorA || '#FF1744', // Red for Doc A changes
|
|
28
|
+
highlightColorB: options.highlightColorB || '#2196F3', // Blue for Doc B changes
|
|
29
|
+
backgroundFillColor: options.backgroundFillColor || 'white', // Canvas background
|
|
27
30
|
labelA: options.labelA || 'Document A',
|
|
28
31
|
labelB: options.labelB || 'Document B',
|
|
29
32
|
workerSrc: options.workerSrc || 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js',
|
|
30
33
|
showPageNumbers: options.showPageNumbers !== false,
|
|
31
34
|
cropRegions: options.cropRegions || [],
|
|
32
35
|
maskRegions: options.maskRegions || [],
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
similarityThreshold: options.similarityThreshold || 0.3 // Minimum similarity score (0-1)
|
|
36
|
+
alignmentTolerance: options.alignmentTolerance || 2,
|
|
37
|
+
similarityThreshold: options.similarityThreshold || 0.3
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
// Check if PDF.js is loaded
|
|
@@ -72,13 +74,9 @@ class PDFDiffViewer {
|
|
|
72
74
|
summaryDiv.className = 'pdf-diff-summary';
|
|
73
75
|
this.container.appendChild(summaryDiv);
|
|
74
76
|
|
|
75
|
-
//
|
|
76
|
-
if (
|
|
77
|
-
summaryDiv.innerHTML = '<p>Analyzing document structure for smart alignment...</p>';
|
|
77
|
+
// Automatically handle different page counts with smart alignment
|
|
78
|
+
if (docA.numPages !== docB.numPages) {
|
|
78
79
|
pageMapping = await this._findPageMappings(docA, docB);
|
|
79
|
-
summaryDiv.innerHTML = `<h3>Smart Alignment Active: Comparing ${pageMapping.length} matched page(s)</h3>`;
|
|
80
|
-
} else if (docA.numPages !== docB.numPages) {
|
|
81
|
-
throw new Error(`Page count mismatch: ${docA.numPages} vs ${docB.numPages}. Enable 'smartAlignment' option to handle different page counts.`);
|
|
82
80
|
} else {
|
|
83
81
|
// Direct 1-to-1 mapping
|
|
84
82
|
for (let i = 1; i <= docA.numPages; i++) {
|
|
@@ -105,11 +103,7 @@ class PDFDiffViewer {
|
|
|
105
103
|
|
|
106
104
|
// Update summary
|
|
107
105
|
if (this.options.showPageNumbers) {
|
|
108
|
-
|
|
109
|
-
summaryDiv.innerHTML = `<h3>Comparison Results: ${docA.numPages} page(s)</h3>`;
|
|
110
|
-
} else {
|
|
111
|
-
summaryDiv.innerHTML += `<p>Doc A: ${docA.numPages} pages | Doc B: ${docB.numPages} pages</p>`;
|
|
112
|
-
}
|
|
106
|
+
summaryDiv.innerHTML = `<h3>Comparison Results: ${pageMapping.length} page(s)</h3>`;
|
|
113
107
|
}
|
|
114
108
|
|
|
115
109
|
return this.results;
|
|
@@ -358,7 +352,7 @@ class PDFDiffViewer {
|
|
|
358
352
|
padded.height = targetHeight;
|
|
359
353
|
|
|
360
354
|
const ctx = padded.getContext('2d');
|
|
361
|
-
ctx.fillStyle =
|
|
355
|
+
ctx.fillStyle = this.options.backgroundFillColor;
|
|
362
356
|
ctx.fillRect(0, 0, targetWidth, targetHeight);
|
|
363
357
|
ctx.drawImage(srcCanvas, 0, 0);
|
|
364
358
|
return padded;
|
|
@@ -369,7 +363,7 @@ class PDFDiffViewer {
|
|
|
369
363
|
temp.width = width;
|
|
370
364
|
temp.height = height;
|
|
371
365
|
const ctx = temp.getContext('2d');
|
|
372
|
-
ctx.fillStyle =
|
|
366
|
+
ctx.fillStyle = this.options.backgroundFillColor;
|
|
373
367
|
ctx.fillRect(0, 0, width, height);
|
|
374
368
|
ctx.drawImage(srcCanvas, dx, dy);
|
|
375
369
|
return ctx.getImageData(0, 0, width, height);
|
|
@@ -529,11 +523,14 @@ class PDFDiffViewer {
|
|
|
529
523
|
_drawHighlightBoxes(ctx, boxes, color = 'red') {
|
|
530
524
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
531
525
|
const alpha = this.options.highlightAlpha;
|
|
526
|
+
|
|
527
|
+
// Use configured colors or fallback to color parameter
|
|
532
528
|
if (color === 'red') {
|
|
533
|
-
ctx.fillStyle =
|
|
529
|
+
ctx.fillStyle = this._hexToRgba(this.options.highlightColorA, alpha);
|
|
534
530
|
} else if (color === 'green') {
|
|
535
|
-
ctx.fillStyle =
|
|
531
|
+
ctx.fillStyle = this._hexToRgba(this.options.highlightColorB, alpha);
|
|
536
532
|
}
|
|
533
|
+
|
|
537
534
|
boxes.forEach(({ x, y, width, height }) => {
|
|
538
535
|
ctx.fillRect(x, y, width, height);
|
|
539
536
|
});
|
|
@@ -784,6 +781,26 @@ class PDFDiffViewer {
|
|
|
784
781
|
.split(/\s+/)
|
|
785
782
|
.filter(word => word.length > 2 && !stopwords.has(word));
|
|
786
783
|
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Convert hex color to rgba with alpha
|
|
787
|
+
*/
|
|
788
|
+
_hexToRgba(hex, alpha) {
|
|
789
|
+
// Handle both #RGB and #RRGGBB formats
|
|
790
|
+
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
791
|
+
hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
|
|
792
|
+
|
|
793
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
794
|
+
if (result) {
|
|
795
|
+
const r = parseInt(result[1], 16);
|
|
796
|
+
const g = parseInt(result[2], 16);
|
|
797
|
+
const b = parseInt(result[3], 16);
|
|
798
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Fallback to red if invalid hex
|
|
802
|
+
return `rgba(255, 0, 0, ${alpha})`;
|
|
803
|
+
}
|
|
787
804
|
}
|
|
788
805
|
|
|
789
806
|
// Export for different module systems
|