@signiphi/page-assembly 0.2.0-beta.10 → 0.2.0-beta.12
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/dist/index.d.mts +31 -8
- package/dist/index.d.ts +31 -8
- package/dist/index.js +70 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -23
- package/dist/index.mjs.map +1 -1
- package/dist/styles/index.css +6 -73
- package/package.json +5 -2
package/dist/index.d.mts
CHANGED
|
@@ -238,15 +238,34 @@ declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
|
|
|
238
238
|
*/
|
|
239
239
|
declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
interface PdfPasswordRequiredErrorConstructor {
|
|
242
|
+
new (): PdfPasswordRequiredError;
|
|
243
|
+
readonly prototype: PdfPasswordRequiredError;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Thrown when the PDF needs a non-empty user password, which this package
|
|
247
|
+
* cannot supply. Match it with {@link isPdfPasswordRequiredError} rather than
|
|
248
|
+
* `instanceof` — see the header note on copies.
|
|
249
|
+
*/
|
|
250
|
+
interface PdfPasswordRequiredError extends Error {
|
|
251
|
+
/** Always `'PDF_PASSWORD_REQUIRED'`. The check that survives package boundaries. */
|
|
242
252
|
code: string;
|
|
243
253
|
recoverable: boolean;
|
|
244
254
|
userMessage: string;
|
|
245
|
-
constructor();
|
|
246
255
|
}
|
|
247
|
-
declare
|
|
248
|
-
|
|
256
|
+
declare const PdfPasswordRequiredError: PdfPasswordRequiredErrorConstructor;
|
|
257
|
+
interface UnsupportedPdfEncryptionErrorConstructor {
|
|
258
|
+
new (detail: string): UnsupportedPdfEncryptionError;
|
|
259
|
+
readonly prototype: UnsupportedPdfEncryptionError;
|
|
260
|
+
}
|
|
261
|
+
/** Thrown for security handlers this decryptor does not implement. */
|
|
262
|
+
interface UnsupportedPdfEncryptionError extends Error {
|
|
263
|
+
/** Always `'UnsupportedPdfEncryptionError'`. */
|
|
264
|
+
name: string;
|
|
265
|
+
/** The scheme that is not supported, e.g. `'V5 /R6'`. */
|
|
266
|
+
readonly detail: string;
|
|
249
267
|
}
|
|
268
|
+
declare const UnsupportedPdfEncryptionError: UnsupportedPdfEncryptionErrorConstructor;
|
|
250
269
|
/**
|
|
251
270
|
* Decrypt an encrypted PDF that opens with an empty user password.
|
|
252
271
|
* Returns re-saved, fully decrypted bytes with `/Encrypt` removed.
|
|
@@ -254,11 +273,15 @@ declare class UnsupportedPdfEncryptionError extends Error {
|
|
|
254
273
|
* @throws {PdfPasswordRequiredError} when a non-empty password is required
|
|
255
274
|
* @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
|
|
256
275
|
*/
|
|
257
|
-
declare
|
|
276
|
+
declare const decryptPdf: (pdfBytes: Uint8Array) => Promise<Uint8Array>;
|
|
258
277
|
/**
|
|
259
|
-
* Ingestion gate
|
|
260
|
-
*
|
|
261
|
-
*
|
|
278
|
+
* Ingestion gate — see `@signiphi/pdf-crypto`'s `normalizePdfEncryption`.
|
|
279
|
+
* Returns the bytes untouched (same reference) for ordinary PDFs; decrypts and
|
|
280
|
+
* re-saves encrypted ones so every downstream `PDFDocument.load` (page
|
|
281
|
+
* assembly, field extraction) sees a normal document.
|
|
282
|
+
*
|
|
283
|
+
* @throws {PdfPasswordRequiredError} when a non-empty password is required
|
|
284
|
+
* @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
|
|
262
285
|
*/
|
|
263
286
|
declare function normalizePdfEncryption(pdfBytes: Uint8Array): Promise<Uint8Array>;
|
|
264
287
|
|
package/dist/index.d.ts
CHANGED
|
@@ -238,15 +238,34 @@ declare function createPdfBlobUrl(pdfBytes: Uint8Array): string;
|
|
|
238
238
|
*/
|
|
239
239
|
declare function downloadPdf(pdfBytes: Uint8Array, filename: string): void;
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
interface PdfPasswordRequiredErrorConstructor {
|
|
242
|
+
new (): PdfPasswordRequiredError;
|
|
243
|
+
readonly prototype: PdfPasswordRequiredError;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Thrown when the PDF needs a non-empty user password, which this package
|
|
247
|
+
* cannot supply. Match it with {@link isPdfPasswordRequiredError} rather than
|
|
248
|
+
* `instanceof` — see the header note on copies.
|
|
249
|
+
*/
|
|
250
|
+
interface PdfPasswordRequiredError extends Error {
|
|
251
|
+
/** Always `'PDF_PASSWORD_REQUIRED'`. The check that survives package boundaries. */
|
|
242
252
|
code: string;
|
|
243
253
|
recoverable: boolean;
|
|
244
254
|
userMessage: string;
|
|
245
|
-
constructor();
|
|
246
255
|
}
|
|
247
|
-
declare
|
|
248
|
-
|
|
256
|
+
declare const PdfPasswordRequiredError: PdfPasswordRequiredErrorConstructor;
|
|
257
|
+
interface UnsupportedPdfEncryptionErrorConstructor {
|
|
258
|
+
new (detail: string): UnsupportedPdfEncryptionError;
|
|
259
|
+
readonly prototype: UnsupportedPdfEncryptionError;
|
|
260
|
+
}
|
|
261
|
+
/** Thrown for security handlers this decryptor does not implement. */
|
|
262
|
+
interface UnsupportedPdfEncryptionError extends Error {
|
|
263
|
+
/** Always `'UnsupportedPdfEncryptionError'`. */
|
|
264
|
+
name: string;
|
|
265
|
+
/** The scheme that is not supported, e.g. `'V5 /R6'`. */
|
|
266
|
+
readonly detail: string;
|
|
249
267
|
}
|
|
268
|
+
declare const UnsupportedPdfEncryptionError: UnsupportedPdfEncryptionErrorConstructor;
|
|
250
269
|
/**
|
|
251
270
|
* Decrypt an encrypted PDF that opens with an empty user password.
|
|
252
271
|
* Returns re-saved, fully decrypted bytes with `/Encrypt` removed.
|
|
@@ -254,11 +273,15 @@ declare class UnsupportedPdfEncryptionError extends Error {
|
|
|
254
273
|
* @throws {PdfPasswordRequiredError} when a non-empty password is required
|
|
255
274
|
* @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
|
|
256
275
|
*/
|
|
257
|
-
declare
|
|
276
|
+
declare const decryptPdf: (pdfBytes: Uint8Array) => Promise<Uint8Array>;
|
|
258
277
|
/**
|
|
259
|
-
* Ingestion gate
|
|
260
|
-
*
|
|
261
|
-
*
|
|
278
|
+
* Ingestion gate — see `@signiphi/pdf-crypto`'s `normalizePdfEncryption`.
|
|
279
|
+
* Returns the bytes untouched (same reference) for ordinary PDFs; decrypts and
|
|
280
|
+
* re-saves encrypted ones so every downstream `PDFDocument.load` (page
|
|
281
|
+
* assembly, field extraction) sees a normal document.
|
|
282
|
+
*
|
|
283
|
+
* @throws {PdfPasswordRequiredError} when a non-empty password is required
|
|
284
|
+
* @throws {UnsupportedPdfEncryptionError} for non-standard security handlers
|
|
262
285
|
*/
|
|
263
286
|
declare function normalizePdfEncryption(pdfBytes: Uint8Array): Promise<Uint8Array>;
|
|
264
287
|
|
package/dist/index.js
CHANGED
|
@@ -43,9 +43,7 @@ var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMe
|
|
|
43
43
|
var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
|
|
44
44
|
var pdfjsLib__namespace = /*#__PURE__*/_interopNamespace(pdfjsLib);
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
48
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
46
|
+
// src/components/PageAssembler.tsx
|
|
49
47
|
function cn(...inputs) {
|
|
50
48
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
51
49
|
}
|
|
@@ -580,9 +578,8 @@ var PdfPasswordRequiredError = class extends Error {
|
|
|
580
578
|
constructor() {
|
|
581
579
|
const message = "This PDF is password-protected. Please remove the password and upload it again.";
|
|
582
580
|
super(message);
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
__publicField(this, "userMessage");
|
|
581
|
+
this.code = "PDF_PASSWORD_REQUIRED";
|
|
582
|
+
this.recoverable = true;
|
|
586
583
|
this.name = "PdfPasswordRequiredError";
|
|
587
584
|
this.userMessage = message;
|
|
588
585
|
}
|
|
@@ -591,6 +588,7 @@ var UnsupportedPdfEncryptionError = class extends Error {
|
|
|
591
588
|
constructor(detail) {
|
|
592
589
|
super(`This PDF uses an unsupported encryption scheme (${detail}).`);
|
|
593
590
|
this.name = "UnsupportedPdfEncryptionError";
|
|
591
|
+
this.detail = detail;
|
|
594
592
|
}
|
|
595
593
|
};
|
|
596
594
|
function concatBytes(...parts) {
|
|
@@ -1128,30 +1126,70 @@ async function decryptPdf(pdfBytes) {
|
|
|
1128
1126
|
if (!doc.isEncrypted) return pdfBytes;
|
|
1129
1127
|
return decryptLoadedDocument(doc);
|
|
1130
1128
|
}
|
|
1131
|
-
var
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1129
|
+
var SLASH = 47;
|
|
1130
|
+
var HASH = 35;
|
|
1131
|
+
var ENCRYPT_NAME = "Encrypt";
|
|
1132
|
+
function hexDigit(byte) {
|
|
1133
|
+
if (byte === void 0) return -1;
|
|
1134
|
+
if (byte >= 48 && byte <= 57) return byte - 48;
|
|
1135
|
+
if (byte >= 65 && byte <= 70) return byte - 65 + 10;
|
|
1136
|
+
if (byte >= 97 && byte <= 102) return byte - 97 + 10;
|
|
1137
|
+
return -1;
|
|
1138
|
+
}
|
|
1139
|
+
function matchesEncryptNameAt(bytes, start) {
|
|
1140
|
+
let at = start;
|
|
1141
|
+
for (let k = 0; k < ENCRYPT_NAME.length; k++) {
|
|
1142
|
+
const want = ENCRYPT_NAME.charCodeAt(k);
|
|
1143
|
+
const byte = bytes[at];
|
|
1144
|
+
if (byte === want) {
|
|
1145
|
+
at += 1;
|
|
1146
|
+
continue;
|
|
1137
1147
|
}
|
|
1138
|
-
|
|
1148
|
+
if (byte === HASH) {
|
|
1149
|
+
const high = hexDigit(bytes[at + 1]);
|
|
1150
|
+
const low = hexDigit(bytes[at + 2]);
|
|
1151
|
+
if (high >= 0 && low >= 0 && (high << 4 | low) === want) {
|
|
1152
|
+
at += 3;
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return false;
|
|
1157
|
+
}
|
|
1158
|
+
return true;
|
|
1159
|
+
}
|
|
1160
|
+
function containsEncryptMarker(bytes) {
|
|
1161
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1162
|
+
if (bytes[i] !== SLASH) continue;
|
|
1163
|
+
if (matchesEncryptNameAt(bytes, i + 1)) return true;
|
|
1139
1164
|
}
|
|
1140
1165
|
return false;
|
|
1141
1166
|
}
|
|
1142
|
-
async function normalizePdfEncryption(pdfBytes) {
|
|
1167
|
+
async function normalizePdfEncryption(pdfBytes, options) {
|
|
1143
1168
|
if (!containsEncryptMarker(pdfBytes)) return pdfBytes;
|
|
1144
1169
|
const doc = await pdfLib.PDFDocument.load(pdfBytes.slice(), {
|
|
1145
1170
|
ignoreEncryption: true,
|
|
1146
1171
|
updateMetadata: false
|
|
1147
1172
|
});
|
|
1148
1173
|
if (!doc.isEncrypted) return pdfBytes;
|
|
1149
|
-
|
|
1150
|
-
console.info("[PageAssembler] Encrypted PDF detected during ingestion; decrypting");
|
|
1151
|
-
}
|
|
1174
|
+
options?.logger?.info("[PDF_DECRYPT] Encrypted PDF detected during ingestion; decrypting");
|
|
1152
1175
|
return decryptLoadedDocument(doc);
|
|
1153
1176
|
}
|
|
1154
1177
|
|
|
1178
|
+
// src/utils/pdf-decrypt.ts
|
|
1179
|
+
var PdfPasswordRequiredError2 = PdfPasswordRequiredError;
|
|
1180
|
+
var UnsupportedPdfEncryptionError2 = UnsupportedPdfEncryptionError;
|
|
1181
|
+
var decryptPdf2 = decryptPdf;
|
|
1182
|
+
var consoleLogger = {
|
|
1183
|
+
info(message, ...args) {
|
|
1184
|
+
if (typeof process === "undefined" || process.env?.NODE_ENV !== "production") {
|
|
1185
|
+
console.info(`[PageAssembler] ${message}`, ...args);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
function normalizePdfEncryption2(pdfBytes) {
|
|
1190
|
+
return normalizePdfEncryption(pdfBytes, { logger: consoleLogger });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1155
1193
|
// src/utils/pdf-helpers.ts
|
|
1156
1194
|
if (typeof window !== "undefined") {
|
|
1157
1195
|
pdfjsLib__namespace.GlobalWorkerOptions.workerSrc = "/pdfjs/build/pdf.worker.mjs";
|
|
@@ -1243,7 +1281,7 @@ async function rasterizePdfToPdf(pdfBytes) {
|
|
|
1243
1281
|
sourceDoc = await pdfjsLib__namespace.getDocument({ data: pdfBytes.slice(0), verbosity: 0 }).promise;
|
|
1244
1282
|
} catch (error) {
|
|
1245
1283
|
if (error?.name === "PasswordException") {
|
|
1246
|
-
throw new
|
|
1284
|
+
throw new PdfPasswordRequiredError2();
|
|
1247
1285
|
}
|
|
1248
1286
|
throw error;
|
|
1249
1287
|
}
|
|
@@ -1275,10 +1313,10 @@ async function rasterizePdfToPdf(pdfBytes) {
|
|
|
1275
1313
|
}
|
|
1276
1314
|
async function normalizeUploadedPdfBytes(pdfBytes) {
|
|
1277
1315
|
try {
|
|
1278
|
-
const normalized = await
|
|
1316
|
+
const normalized = await normalizePdfEncryption2(pdfBytes);
|
|
1279
1317
|
return normalized === pdfBytes ? pdfBytes : new Uint8Array(normalized);
|
|
1280
1318
|
} catch (error) {
|
|
1281
|
-
if (error instanceof
|
|
1319
|
+
if (error instanceof PdfPasswordRequiredError2) throw error;
|
|
1282
1320
|
console.warn(
|
|
1283
1321
|
"[PageAssembler] Structural decryption failed; rebuilding document from rendered pages:",
|
|
1284
1322
|
error
|
|
@@ -1403,11 +1441,17 @@ function getBaseFieldName(encodedName) {
|
|
|
1403
1441
|
}
|
|
1404
1442
|
return baseName;
|
|
1405
1443
|
}
|
|
1444
|
+
function stripFieldTypeSuffix(value) {
|
|
1445
|
+
const stripped = value.replace(/_(signature|initials|date)$/i, "");
|
|
1446
|
+
return stripped || value;
|
|
1447
|
+
}
|
|
1406
1448
|
function getSignerFromFieldName(encodedName) {
|
|
1407
1449
|
if (encodedName.includes("__SIGNER__")) {
|
|
1408
1450
|
const parts = encodedName.split("__SIGNER__");
|
|
1409
1451
|
if (parts[1]) {
|
|
1410
|
-
|
|
1452
|
+
const segment = parts[1].split("__")[0] || parts[1];
|
|
1453
|
+
const isTerminal = segment === parts[1];
|
|
1454
|
+
return isTerminal ? stripFieldTypeSuffix(segment) : segment;
|
|
1411
1455
|
}
|
|
1412
1456
|
}
|
|
1413
1457
|
return void 0;
|
|
@@ -2751,7 +2795,7 @@ var PageAssembler = React7.forwardRef(
|
|
|
2751
2795
|
dispatch({ type: "ADD_FILE", payload: fileInfo });
|
|
2752
2796
|
} catch (error) {
|
|
2753
2797
|
console.error(`Error processing file ${file.name}:`, error);
|
|
2754
|
-
if (error instanceof
|
|
2798
|
+
if (error instanceof PdfPasswordRequiredError2) {
|
|
2755
2799
|
setUploadError(`${file.name}: ${error.userMessage}`);
|
|
2756
2800
|
} else {
|
|
2757
2801
|
setUploadError(`Failed to process "${file.name}". The file may be corrupted or unsupported.`);
|
|
@@ -3336,17 +3380,17 @@ function debounce(func, wait) {
|
|
|
3336
3380
|
exports.Button = Button;
|
|
3337
3381
|
exports.FormFieldType = FormFieldType;
|
|
3338
3382
|
exports.PageAssembler = PageAssembler;
|
|
3339
|
-
exports.PdfPasswordRequiredError =
|
|
3340
|
-
exports.UnsupportedPdfEncryptionError =
|
|
3383
|
+
exports.PdfPasswordRequiredError = PdfPasswordRequiredError2;
|
|
3384
|
+
exports.UnsupportedPdfEncryptionError = UnsupportedPdfEncryptionError2;
|
|
3341
3385
|
exports.addFormFieldsToPdf = addFormFieldsToPdf;
|
|
3342
3386
|
exports.createPdfBlobUrl = createPdfBlobUrl;
|
|
3343
|
-
exports.decryptPdf =
|
|
3387
|
+
exports.decryptPdf = decryptPdf2;
|
|
3344
3388
|
exports.downloadPdf = downloadPdf;
|
|
3345
3389
|
exports.extractFieldsFromPdf = extractFieldsFromPdf;
|
|
3346
3390
|
exports.getSigniphiMetadata = getSigniphiMetadata;
|
|
3347
3391
|
exports.imageToPdf = imageToPdf;
|
|
3348
3392
|
exports.mapFieldPositionsAfterAssembly = mapFieldPositionsAfterAssembly;
|
|
3349
|
-
exports.normalizePdfEncryption =
|
|
3393
|
+
exports.normalizePdfEncryption = normalizePdfEncryption2;
|
|
3350
3394
|
exports.normalizeUploadedPdfBytes = normalizeUploadedPdfBytes;
|
|
3351
3395
|
exports.pdfToImages = pdfToImages;
|
|
3352
3396
|
exports.rasterizePdfToPdf = rasterizePdfToPdf;
|