feat: separate AGPL libraries and add dynamic WASM loading
- Add WASM settings page for configuring external AGPL modules - Implement dynamic loading for PyMuPDF, Ghostscript, and CoherentPDF - Add Cloudflare Worker proxy for serving WASM files with CORS - Update all affected tool pages to check WASM availability - Add showWasmRequiredDialog for missing module configuration Documentation: - Update README, licensing.html, and docs to clarify AGPL components are not bundled and must be configured separately - Add WASM-PROXY.md deployment guide with recommended source URLs - Rename "CPDF" to "CoherentPDF" for consistency
This commit is contained in:
5
public/workers/add-attachments.worker.d.ts
vendored
5
public/workers/add-attachments.worker.d.ts
vendored
@@ -5,6 +5,7 @@ interface AddAttachmentsMessage {
|
||||
pdfBuffer: ArrayBuffer;
|
||||
attachmentBuffers: ArrayBuffer[];
|
||||
attachmentNames: string[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface AddAttachmentsSuccessResponse {
|
||||
@@ -17,4 +18,6 @@ interface AddAttachmentsErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
type AddAttachmentsResponse = AddAttachmentsSuccessResponse | AddAttachmentsErrorResponse;
|
||||
type AddAttachmentsResponse =
|
||||
| AddAttachmentsSuccessResponse
|
||||
| AddAttachmentsErrorResponse;
|
||||
|
||||
@@ -1,13 +1,32 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parsePageRange(rangeString, totalPages) {
|
||||
const pages = new Set();
|
||||
const parts = rangeString.split(',').map(s => s.trim());
|
||||
const parts = rangeString.split(',').map((s) => s.trim());
|
||||
|
||||
for (const part of parts) {
|
||||
if (part.includes('-')) {
|
||||
const [start, end] = part.split('-').map(s => parseInt(s.trim(), 10));
|
||||
const [start, end] = part.split('-').map((s) => parseInt(s.trim(), 10));
|
||||
if (isNaN(start) || isNaN(end)) continue;
|
||||
for (let i = Math.max(1, start); i <= Math.min(totalPages, end); i++) {
|
||||
pages.add(i);
|
||||
@@ -23,7 +42,13 @@ function parsePageRange(rangeString, totalPages) {
|
||||
return Array.from(pages).sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNames, attachmentLevel, pageRange) {
|
||||
function addAttachmentsToPDFInWorker(
|
||||
pdfBuffer,
|
||||
attachmentBuffers,
|
||||
attachmentNames,
|
||||
attachmentLevel,
|
||||
pageRange
|
||||
) {
|
||||
try {
|
||||
const uint8Array = new Uint8Array(pdfBuffer);
|
||||
|
||||
@@ -33,18 +58,21 @@ function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNam
|
||||
} catch (error) {
|
||||
const errorMsg = error.message || error.toString();
|
||||
|
||||
if (errorMsg.includes('Failed to read PDF') ||
|
||||
if (
|
||||
errorMsg.includes('Failed to read PDF') ||
|
||||
errorMsg.includes('Could not read object') ||
|
||||
errorMsg.includes('No /Root entry') ||
|
||||
errorMsg.includes('PDFError')) {
|
||||
errorMsg.includes('PDFError')
|
||||
) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: 'The PDF file has structural issues and cannot be processed. The file may be corrupted, incomplete, or created with non-standard tools. Please try:\n\n• Opening and re-saving the PDF in another PDF viewer\n• Using a different PDF file\n• Repairing the PDF with a PDF repair tool'
|
||||
message:
|
||||
'The PDF file has structural issues and cannot be processed. The file may be corrupted, incomplete, or created with non-standard tools. Please try:\n\n• Opening and re-saving the PDF in another PDF viewer\n• Using a different PDF file\n• Repairing the PDF with a PDF repair tool',
|
||||
});
|
||||
} else {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: `Failed to load PDF: ${errorMsg}`
|
||||
message: `Failed to load PDF: ${errorMsg}`,
|
||||
});
|
||||
}
|
||||
return;
|
||||
@@ -57,7 +85,7 @@ function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNam
|
||||
if (!pageRange) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: 'Page range is required for page-level attachments.'
|
||||
message: 'Page range is required for page-level attachments.',
|
||||
});
|
||||
coherentpdf.deletePdf(pdf);
|
||||
return;
|
||||
@@ -66,7 +94,7 @@ function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNam
|
||||
if (targetPages.length === 0) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: 'Invalid page range specified.'
|
||||
message: 'Invalid page range specified.',
|
||||
});
|
||||
coherentpdf.deletePdf(pdf);
|
||||
return;
|
||||
@@ -82,21 +110,25 @@ function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNam
|
||||
coherentpdf.attachFileFromMemory(attachmentData, attachmentName, pdf);
|
||||
} else {
|
||||
for (const pageNum of targetPages) {
|
||||
coherentpdf.attachFileToPageFromMemory(attachmentData, attachmentName, pdf, pageNum);
|
||||
coherentpdf.attachFileToPageFromMemory(
|
||||
attachmentData,
|
||||
attachmentName,
|
||||
pdf,
|
||||
pageNum
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to attach file ${attachmentNames[i]}:`, error);
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: `Failed to attach file ${attachmentNames[i]}: ${error.message || error}`
|
||||
message: `Failed to attach file ${attachmentNames[i]}: ${error.message || error}`,
|
||||
});
|
||||
coherentpdf.deletePdf(pdf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the modified PDF
|
||||
const modifiedBytes = coherentpdf.toMemory(pdf, false, false);
|
||||
coherentpdf.deletePdf(pdf);
|
||||
|
||||
@@ -105,22 +137,46 @@ function addAttachmentsToPDFInWorker(pdfBuffer, attachmentBuffers, attachmentNam
|
||||
modifiedBytes.byteOffset + modifiedBytes.byteLength
|
||||
);
|
||||
|
||||
self.postMessage({
|
||||
status: 'success',
|
||||
modifiedPDF: buffer
|
||||
}, [buffer]);
|
||||
|
||||
self.postMessage(
|
||||
{
|
||||
status: 'success',
|
||||
modifiedPDF: buffer,
|
||||
},
|
||||
[buffer]
|
||||
);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred while adding attachments.'
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred while adding attachments.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'add-attachments') {
|
||||
addAttachmentsToPDFInWorker(
|
||||
e.data.pdfBuffer,
|
||||
|
||||
17
public/workers/alternate-merge.worker.d.ts
vendored
17
public/workers/alternate-merge.worker.d.ts
vendored
@@ -1,23 +1,24 @@
|
||||
declare const coherentpdf: typeof import('../../src/types/coherentpdf.global').coherentpdf;
|
||||
|
||||
interface InterleaveFile {
|
||||
name: string;
|
||||
data: ArrayBuffer;
|
||||
name: string;
|
||||
data: ArrayBuffer;
|
||||
}
|
||||
|
||||
interface InterleaveMessage {
|
||||
command: 'interleave';
|
||||
files: InterleaveFile[];
|
||||
command: 'interleave';
|
||||
files: InterleaveFile[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface InterleaveSuccessResponse {
|
||||
status: 'success';
|
||||
pdfBytes: ArrayBuffer;
|
||||
status: 'success';
|
||||
pdfBytes: ArrayBuffer;
|
||||
}
|
||||
|
||||
interface InterleaveErrorResponse {
|
||||
status: 'error';
|
||||
message: string;
|
||||
status: 'error';
|
||||
message: string;
|
||||
}
|
||||
|
||||
type InterleaveResponse = InterleaveSuccessResponse | InterleaveErrorResponse;
|
||||
|
||||
@@ -1,64 +1,109 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
self.onmessage = function (e) {
|
||||
const { command, files } = e.data;
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
if (command === 'interleave') {
|
||||
interleavePDFs(files);
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = async function (e) {
|
||||
const { command, files, cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'interleave') {
|
||||
interleavePDFs(files);
|
||||
}
|
||||
};
|
||||
|
||||
function interleavePDFs(files) {
|
||||
try {
|
||||
const loadedPdfs = [];
|
||||
const pageCounts = [];
|
||||
try {
|
||||
const loadedPdfs = [];
|
||||
const pageCounts = [];
|
||||
|
||||
for (const file of files) {
|
||||
const uint8Array = new Uint8Array(file.data);
|
||||
const pdfDoc = coherentpdf.fromMemory(uint8Array, "");
|
||||
loadedPdfs.push(pdfDoc);
|
||||
pageCounts.push(coherentpdf.pages(pdfDoc));
|
||||
}
|
||||
|
||||
if (loadedPdfs.length < 2) {
|
||||
throw new Error('At least two PDF files are required for interleaving.');
|
||||
}
|
||||
|
||||
const maxPages = Math.max(...pageCounts);
|
||||
|
||||
const pdfsToMerge = [];
|
||||
const rangesToMerge = [];
|
||||
|
||||
for (let i = 1; i <= maxPages; i++) {
|
||||
for (let j = 0; j < loadedPdfs.length; j++) {
|
||||
if (i <= pageCounts[j]) {
|
||||
pdfsToMerge.push(loadedPdfs[j]);
|
||||
rangesToMerge.push(coherentpdf.range(i, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdfsToMerge.length === 0) {
|
||||
throw new Error('No valid pages to merge.');
|
||||
}
|
||||
|
||||
const mergedPdf = coherentpdf.mergeSame(pdfsToMerge, true, true, rangesToMerge);
|
||||
|
||||
const mergedPdfBytes = coherentpdf.toMemory(mergedPdf, false, true);
|
||||
const buffer = mergedPdfBytes.buffer;
|
||||
coherentpdf.deletePdf(mergedPdf);
|
||||
loadedPdfs.forEach(pdf => coherentpdf.deletePdf(pdf));
|
||||
|
||||
self.postMessage({
|
||||
status: 'success',
|
||||
pdfBytes: buffer
|
||||
}, [buffer]);
|
||||
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message || 'Unknown error during interleave merge'
|
||||
});
|
||||
for (const file of files) {
|
||||
const uint8Array = new Uint8Array(file.data);
|
||||
const pdfDoc = coherentpdf.fromMemory(uint8Array, '');
|
||||
loadedPdfs.push(pdfDoc);
|
||||
pageCounts.push(coherentpdf.pages(pdfDoc));
|
||||
}
|
||||
|
||||
if (loadedPdfs.length < 2) {
|
||||
throw new Error('At least two PDF files are required for interleaving.');
|
||||
}
|
||||
|
||||
const maxPages = Math.max(...pageCounts);
|
||||
|
||||
const pdfsToMerge = [];
|
||||
const rangesToMerge = [];
|
||||
|
||||
for (let i = 1; i <= maxPages; i++) {
|
||||
for (let j = 0; j < loadedPdfs.length; j++) {
|
||||
if (i <= pageCounts[j]) {
|
||||
pdfsToMerge.push(loadedPdfs[j]);
|
||||
rangesToMerge.push(coherentpdf.range(i, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdfsToMerge.length === 0) {
|
||||
throw new Error('No valid pages to merge.');
|
||||
}
|
||||
|
||||
const mergedPdf = coherentpdf.mergeSame(
|
||||
pdfsToMerge,
|
||||
true,
|
||||
true,
|
||||
rangesToMerge
|
||||
);
|
||||
|
||||
const mergedPdfBytes = coherentpdf.toMemory(mergedPdf, false, true);
|
||||
const buffer = mergedPdfBytes.buffer;
|
||||
coherentpdf.deletePdf(mergedPdf);
|
||||
loadedPdfs.forEach((pdf) => coherentpdf.deletePdf(pdf));
|
||||
|
||||
self.postMessage(
|
||||
{
|
||||
status: 'success',
|
||||
pdfBytes: buffer,
|
||||
},
|
||||
[buffer]
|
||||
);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message || 'Unknown error during interleave merge',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
25
public/workers/edit-attachments.worker.d.ts
vendored
25
public/workers/edit-attachments.worker.d.ts
vendored
@@ -4,6 +4,7 @@ interface GetAttachmentsMessage {
|
||||
command: 'get-attachments';
|
||||
fileBuffer: ArrayBuffer;
|
||||
fileName: string;
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface EditAttachmentsMessage {
|
||||
@@ -11,13 +12,21 @@ interface EditAttachmentsMessage {
|
||||
fileBuffer: ArrayBuffer;
|
||||
fileName: string;
|
||||
attachmentsToRemove: number[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
type EditAttachmentsWorkerMessage = GetAttachmentsMessage | EditAttachmentsMessage;
|
||||
type EditAttachmentsWorkerMessage =
|
||||
| GetAttachmentsMessage
|
||||
| EditAttachmentsMessage;
|
||||
|
||||
interface GetAttachmentsSuccessResponse {
|
||||
status: 'success';
|
||||
attachments: Array<{ index: number; name: string; page: number; data: ArrayBuffer }>;
|
||||
attachments: Array<{
|
||||
index: number;
|
||||
name: string;
|
||||
page: number;
|
||||
data: ArrayBuffer;
|
||||
}>;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
@@ -37,6 +46,12 @@ interface EditAttachmentsErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
type GetAttachmentsResponse = GetAttachmentsSuccessResponse | GetAttachmentsErrorResponse;
|
||||
type EditAttachmentsResponse = EditAttachmentsSuccessResponse | EditAttachmentsErrorResponse;
|
||||
type EditAttachmentsWorkerResponse = GetAttachmentsResponse | EditAttachmentsResponse;
|
||||
type GetAttachmentsResponse =
|
||||
| GetAttachmentsSuccessResponse
|
||||
| GetAttachmentsErrorResponse;
|
||||
type EditAttachmentsResponse =
|
||||
| EditAttachmentsSuccessResponse
|
||||
| EditAttachmentsErrorResponse;
|
||||
type EditAttachmentsWorkerResponse =
|
||||
| GetAttachmentsResponse
|
||||
| EditAttachmentsResponse;
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAttachmentsFromPDFInWorker(fileBuffer, fileName) {
|
||||
try {
|
||||
@@ -11,7 +30,7 @@ function getAttachmentsFromPDFInWorker(fileBuffer, fileName) {
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: `Failed to load PDF: ${fileName}. Error: ${error.message || error}`
|
||||
message: `Failed to load PDF: ${fileName}. Error: ${error.message || error}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -23,7 +42,7 @@ function getAttachmentsFromPDFInWorker(fileBuffer, fileName) {
|
||||
self.postMessage({
|
||||
status: 'success',
|
||||
attachments: [],
|
||||
fileName: fileName
|
||||
fileName: fileName,
|
||||
});
|
||||
coherentpdf.deletePdf(pdf);
|
||||
return;
|
||||
@@ -37,13 +56,16 @@ function getAttachmentsFromPDFInWorker(fileBuffer, fileName) {
|
||||
const attachmentData = coherentpdf.getAttachmentData(i);
|
||||
|
||||
const dataArray = new Uint8Array(attachmentData);
|
||||
const buffer = dataArray.buffer.slice(dataArray.byteOffset, dataArray.byteOffset + dataArray.byteLength);
|
||||
const buffer = dataArray.buffer.slice(
|
||||
dataArray.byteOffset,
|
||||
dataArray.byteOffset + dataArray.byteLength
|
||||
);
|
||||
|
||||
attachments.push({
|
||||
index: i,
|
||||
name: String(name),
|
||||
page: Number(page),
|
||||
data: buffer
|
||||
data: buffer,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn(`Failed to get attachment ${i} from ${fileName}:`, error);
|
||||
@@ -56,22 +78,27 @@ function getAttachmentsFromPDFInWorker(fileBuffer, fileName) {
|
||||
const response = {
|
||||
status: 'success',
|
||||
attachments: attachments,
|
||||
fileName: fileName
|
||||
fileName: fileName,
|
||||
};
|
||||
|
||||
const transferBuffers = attachments.map(att => att.data);
|
||||
const transferBuffers = attachments.map((att) => att.data);
|
||||
self.postMessage(response, transferBuffers);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment listing.'
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment listing.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function editAttachmentsInPDFInWorker(fileBuffer, fileName, attachmentsToRemove) {
|
||||
function editAttachmentsInPDFInWorker(
|
||||
fileBuffer,
|
||||
fileName,
|
||||
attachmentsToRemove
|
||||
) {
|
||||
try {
|
||||
const uint8Array = new Uint8Array(fileBuffer);
|
||||
|
||||
@@ -81,7 +108,7 @@ function editAttachmentsInPDFInWorker(fileBuffer, fileName, attachmentsToRemove)
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: `Failed to load PDF: ${fileName}. Error: ${error.message || error}`
|
||||
message: `Failed to load PDF: ${fileName}. Error: ${error.message || error}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -103,7 +130,7 @@ function editAttachmentsInPDFInWorker(fileBuffer, fileName, attachmentsToRemove)
|
||||
attachmentsToKeep.push({
|
||||
name: String(name),
|
||||
page: Number(page),
|
||||
data: dataCopy
|
||||
data: dataCopy,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -114,9 +141,18 @@ function editAttachmentsInPDFInWorker(fileBuffer, fileName, attachmentsToRemove)
|
||||
|
||||
for (const attachment of attachmentsToKeep) {
|
||||
if (attachment.page === 0) {
|
||||
coherentpdf.attachFileFromMemory(attachment.data, attachment.name, pdf);
|
||||
coherentpdf.attachFileFromMemory(
|
||||
attachment.data,
|
||||
attachment.name,
|
||||
pdf
|
||||
);
|
||||
} else {
|
||||
coherentpdf.attachFileToPageFromMemory(attachment.data, attachment.name, pdf, attachment.page);
|
||||
coherentpdf.attachFileToPageFromMemory(
|
||||
attachment.data,
|
||||
attachment.name,
|
||||
pdf,
|
||||
attachment.page
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,29 +160,58 @@ function editAttachmentsInPDFInWorker(fileBuffer, fileName, attachmentsToRemove)
|
||||
const modifiedBytes = coherentpdf.toMemory(pdf, false, true);
|
||||
coherentpdf.deletePdf(pdf);
|
||||
|
||||
const buffer = modifiedBytes.buffer.slice(modifiedBytes.byteOffset, modifiedBytes.byteOffset + modifiedBytes.byteLength);
|
||||
const buffer = modifiedBytes.buffer.slice(
|
||||
modifiedBytes.byteOffset,
|
||||
modifiedBytes.byteOffset + modifiedBytes.byteLength
|
||||
);
|
||||
|
||||
const response = {
|
||||
status: 'success',
|
||||
modifiedPDF: buffer,
|
||||
fileName: fileName
|
||||
fileName: fileName,
|
||||
};
|
||||
|
||||
self.postMessage(response, [response.modifiedPDF]);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment editing.'
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment editing.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'get-attachments') {
|
||||
getAttachmentsFromPDFInWorker(e.data.fileBuffer, e.data.fileName);
|
||||
} else if (e.data.command === 'edit-attachments') {
|
||||
editAttachmentsInPDFInWorker(e.data.fileBuffer, e.data.fileName, e.data.attachmentsToRemove);
|
||||
editAttachmentsInPDFInWorker(
|
||||
e.data.fileBuffer,
|
||||
e.data.fileName,
|
||||
e.data.attachmentsToRemove
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ interface ExtractAttachmentsMessage {
|
||||
command: 'extract-attachments';
|
||||
fileBuffers: ArrayBuffer[];
|
||||
fileNames: string[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface ExtractAttachmentSuccessResponse {
|
||||
@@ -16,4 +17,6 @@ interface ExtractAttachmentErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
type ExtractAttachmentResponse = ExtractAttachmentSuccessResponse | ExtractAttachmentErrorResponse;
|
||||
type ExtractAttachmentResponse =
|
||||
| ExtractAttachmentSuccessResponse
|
||||
| ExtractAttachmentErrorResponse;
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function extractAttachmentsFromPDFsInWorker(fileBuffers, fileNames) {
|
||||
try {
|
||||
@@ -37,7 +56,7 @@ function extractAttachmentsFromPDFsInWorker(fileBuffers, fileNames) {
|
||||
|
||||
let uniqueName = attachmentName;
|
||||
let counter = 1;
|
||||
while (allAttachments.some(att => att.name === uniqueName)) {
|
||||
while (allAttachments.some((att) => att.name === uniqueName)) {
|
||||
const nameParts = attachmentName.split('.');
|
||||
if (nameParts.length > 1) {
|
||||
const extension = nameParts.pop();
|
||||
@@ -56,10 +75,13 @@ function extractAttachmentsFromPDFsInWorker(fileBuffers, fileNames) {
|
||||
|
||||
allAttachments.push({
|
||||
name: uniqueName,
|
||||
data: attachmentData.buffer.slice(0)
|
||||
data: attachmentData.buffer.slice(0),
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn(`Failed to extract attachment ${j} from ${fileName}:`, error);
|
||||
console.warn(
|
||||
`Failed to extract attachment ${j} from ${fileName}:`,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,21 +92,21 @@ function extractAttachmentsFromPDFsInWorker(fileBuffers, fileNames) {
|
||||
if (allAttachments.length === 0) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: 'No attachments were found in the selected PDF(s).'
|
||||
message: 'No attachments were found in the selected PDF(s).',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const response = {
|
||||
status: 'success',
|
||||
attachments: []
|
||||
attachments: [],
|
||||
};
|
||||
|
||||
const transferBuffers = [];
|
||||
for (const attachment of allAttachments) {
|
||||
response.attachments.push({
|
||||
name: attachment.name,
|
||||
data: attachment.data
|
||||
data: attachment.data,
|
||||
});
|
||||
transferBuffers.push(attachment.data);
|
||||
}
|
||||
@@ -93,15 +115,37 @@ function extractAttachmentsFromPDFsInWorker(fileBuffers, fileNames) {
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment extraction.'
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Unknown error occurred during attachment extraction.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'extract-attachments') {
|
||||
extractAttachmentsFromPDFsInWorker(e.data.fileBuffers, e.data.fileNames);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
2
public/workers/json-to-pdf.worker.d.ts
vendored
2
public/workers/json-to-pdf.worker.d.ts
vendored
@@ -4,6 +4,7 @@ interface ConvertJSONToPDFMessage {
|
||||
command: 'convert';
|
||||
fileBuffers: ArrayBuffer[];
|
||||
fileNames: string[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface JSONToPDFSuccessResponse {
|
||||
@@ -17,4 +18,3 @@ interface JSONToPDFErrorResponse {
|
||||
}
|
||||
|
||||
type JSONToPDFResponse = JSONToPDFSuccessResponse | JSONToPDFErrorResponse;
|
||||
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function convertJSONsToPDFInWorker(fileBuffers, fileNames) {
|
||||
try {
|
||||
@@ -15,13 +34,12 @@ function convertJSONsToPDFInWorker(fileBuffers, fileNames) {
|
||||
try {
|
||||
pdf = coherentpdf.fromJSONMemory(uint8Array);
|
||||
} catch (error) {
|
||||
const errorMsg = error && error.message
|
||||
? error.message
|
||||
: 'Unknown error';
|
||||
const errorMsg =
|
||||
error && error.message ? error.message : 'Unknown error';
|
||||
throw new Error(
|
||||
`Failed to convert "${fileName}" to PDF. ` +
|
||||
`The JSON file must be in the format produced by cpdf's outputJSONMemory. ` +
|
||||
`Error: ${errorMsg}`
|
||||
`The JSON file must be in the format produced by cpdf's outputJSONMemory. ` +
|
||||
`Error: ${errorMsg}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,9 +74,29 @@ function convertJSONsToPDFInWorker(fileBuffers, fileNames) {
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'convert') {
|
||||
convertJSONsToPDFInWorker(e.data.fileBuffers, e.data.fileNames);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
31
public/workers/merge.worker.d.ts
vendored
31
public/workers/merge.worker.d.ts
vendored
@@ -1,33 +1,34 @@
|
||||
declare const coherentpdf: typeof import('../../src/types/coherentpdf.global').coherentpdf;
|
||||
|
||||
interface MergeJob {
|
||||
fileName: string;
|
||||
rangeType: 'all' | 'specific' | 'single' | 'range';
|
||||
rangeString?: string;
|
||||
pageIndex?: number;
|
||||
startPage?: number;
|
||||
endPage?: number;
|
||||
fileName: string;
|
||||
rangeType: 'all' | 'specific' | 'single' | 'range';
|
||||
rangeString?: string;
|
||||
pageIndex?: number;
|
||||
startPage?: number;
|
||||
endPage?: number;
|
||||
}
|
||||
|
||||
interface MergeFile {
|
||||
name: string;
|
||||
data: ArrayBuffer;
|
||||
name: string;
|
||||
data: ArrayBuffer;
|
||||
}
|
||||
|
||||
interface MergeMessage {
|
||||
command: 'merge';
|
||||
files: MergeFile[];
|
||||
jobs: MergeJob[];
|
||||
command: 'merge';
|
||||
files: MergeFile[];
|
||||
jobs: MergeJob[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface MergeSuccessResponse {
|
||||
status: 'success';
|
||||
pdfBytes: ArrayBuffer;
|
||||
status: 'success';
|
||||
pdfBytes: ArrayBuffer;
|
||||
}
|
||||
|
||||
interface MergeErrorResponse {
|
||||
status: 'error';
|
||||
message: string;
|
||||
status: 'error';
|
||||
message: string;
|
||||
}
|
||||
|
||||
type MergeResponse = MergeSuccessResponse | MergeErrorResponse;
|
||||
|
||||
@@ -1,71 +1,116 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
self.onmessage = function (e) {
|
||||
const { command, files, jobs } = e.data;
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
if (command === 'merge') {
|
||||
mergePDFs(files, jobs);
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = async function (e) {
|
||||
const { command, files, jobs, cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (command === 'merge') {
|
||||
mergePDFs(files, jobs);
|
||||
}
|
||||
};
|
||||
|
||||
function mergePDFs(files, jobs) {
|
||||
try {
|
||||
const loadedPdfs = {};
|
||||
const pdfsToMerge = [];
|
||||
const rangesToMerge = [];
|
||||
try {
|
||||
const loadedPdfs = {};
|
||||
const pdfsToMerge = [];
|
||||
const rangesToMerge = [];
|
||||
|
||||
for (const file of files) {
|
||||
const uint8Array = new Uint8Array(file.data);
|
||||
const pdfDoc = coherentpdf.fromMemory(uint8Array, "");
|
||||
loadedPdfs[file.name] = pdfDoc;
|
||||
}
|
||||
|
||||
for (const job of jobs) {
|
||||
const sourcePdf = loadedPdfs[job.fileName];
|
||||
if (!sourcePdf) continue;
|
||||
|
||||
let range;
|
||||
if (job.rangeType === 'all') {
|
||||
range = coherentpdf.all(sourcePdf);
|
||||
} else if (job.rangeType === 'specific') {
|
||||
if (coherentpdf.validatePagespec(job.rangeString)) {
|
||||
range = coherentpdf.parsePagespec(sourcePdf, job.rangeString);
|
||||
} else {
|
||||
range = coherentpdf.all(sourcePdf);
|
||||
}
|
||||
} else if (job.rangeType === 'single') {
|
||||
const pageNum = job.pageIndex + 1;
|
||||
range = coherentpdf.range(pageNum, pageNum);
|
||||
} else if (job.rangeType === 'range') {
|
||||
range = coherentpdf.range(job.startPage, job.endPage);
|
||||
}
|
||||
|
||||
pdfsToMerge.push(sourcePdf);
|
||||
rangesToMerge.push(range);
|
||||
}
|
||||
|
||||
if (pdfsToMerge.length === 0) {
|
||||
throw new Error('No valid files or pages to merge.');
|
||||
}
|
||||
|
||||
const mergedPdf = coherentpdf.mergeSame(pdfsToMerge, true, true, rangesToMerge);
|
||||
|
||||
const mergedPdfBytes = coherentpdf.toMemory(mergedPdf, false, true);
|
||||
const buffer = mergedPdfBytes.buffer;
|
||||
|
||||
coherentpdf.deletePdf(mergedPdf);
|
||||
Object.values(loadedPdfs).forEach(pdf => coherentpdf.deletePdf(pdf));
|
||||
|
||||
self.postMessage({
|
||||
status: 'success',
|
||||
pdfBytes: buffer
|
||||
}, [buffer]);
|
||||
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message || 'Unknown error during merge'
|
||||
});
|
||||
for (const file of files) {
|
||||
const uint8Array = new Uint8Array(file.data);
|
||||
const pdfDoc = coherentpdf.fromMemory(uint8Array, '');
|
||||
loadedPdfs[file.name] = pdfDoc;
|
||||
}
|
||||
|
||||
for (const job of jobs) {
|
||||
const sourcePdf = loadedPdfs[job.fileName];
|
||||
if (!sourcePdf) continue;
|
||||
|
||||
let range;
|
||||
if (job.rangeType === 'all') {
|
||||
range = coherentpdf.all(sourcePdf);
|
||||
} else if (job.rangeType === 'specific') {
|
||||
if (coherentpdf.validatePagespec(job.rangeString)) {
|
||||
range = coherentpdf.parsePagespec(sourcePdf, job.rangeString);
|
||||
} else {
|
||||
range = coherentpdf.all(sourcePdf);
|
||||
}
|
||||
} else if (job.rangeType === 'single') {
|
||||
const pageNum = job.pageIndex + 1;
|
||||
range = coherentpdf.range(pageNum, pageNum);
|
||||
} else if (job.rangeType === 'range') {
|
||||
range = coherentpdf.range(job.startPage, job.endPage);
|
||||
}
|
||||
|
||||
pdfsToMerge.push(sourcePdf);
|
||||
rangesToMerge.push(range);
|
||||
}
|
||||
|
||||
if (pdfsToMerge.length === 0) {
|
||||
throw new Error('No valid files or pages to merge.');
|
||||
}
|
||||
|
||||
const mergedPdf = coherentpdf.mergeSame(
|
||||
pdfsToMerge,
|
||||
true,
|
||||
true,
|
||||
rangesToMerge
|
||||
);
|
||||
|
||||
const mergedPdfBytes = coherentpdf.toMemory(mergedPdf, false, true);
|
||||
const buffer = mergedPdfBytes.buffer;
|
||||
|
||||
coherentpdf.deletePdf(mergedPdf);
|
||||
Object.values(loadedPdfs).forEach((pdf) => coherentpdf.deletePdf(pdf));
|
||||
|
||||
self.postMessage(
|
||||
{
|
||||
status: 'success',
|
||||
pdfBytes: buffer,
|
||||
},
|
||||
[buffer]
|
||||
);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message || 'Unknown error during merge',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
2
public/workers/pdf-to-json.worker.d.ts
vendored
2
public/workers/pdf-to-json.worker.d.ts
vendored
@@ -4,6 +4,7 @@ interface ConvertPDFToJSONMessage {
|
||||
command: 'convert';
|
||||
fileBuffers: ArrayBuffer[];
|
||||
fileNames: string[];
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface PDFToJSONSuccessResponse {
|
||||
@@ -17,4 +18,3 @@ interface PDFToJSONErrorResponse {
|
||||
}
|
||||
|
||||
type PDFToJSONResponse = PDFToJSONSuccessResponse | PDFToJSONErrorResponse;
|
||||
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function convertPDFsToJSONInWorker(fileBuffers, fileNames) {
|
||||
try {
|
||||
@@ -12,8 +31,6 @@ function convertPDFsToJSONInWorker(fileBuffers, fileNames) {
|
||||
const uint8Array = new Uint8Array(buffer);
|
||||
const pdf = coherentpdf.fromMemory(uint8Array, '');
|
||||
|
||||
//TODO:@ALAM -> add options for users to select these settings
|
||||
// parse_content: true, no_stream_data: false, decompress_streams: false
|
||||
const jsonData = coherentpdf.outputJSONMemory(true, false, false, pdf);
|
||||
|
||||
const jsonBuffer = jsonData.buffer.slice(0);
|
||||
@@ -44,9 +61,29 @@ function convertPDFsToJSONInWorker(fileBuffers, fileNames) {
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'convert') {
|
||||
convertPDFsToJSONInWorker(e.data.fileBuffers, e.data.fileNames);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
1
public/workers/table-of-contents.worker.d.ts
vendored
1
public/workers/table-of-contents.worker.d.ts
vendored
@@ -7,6 +7,7 @@ interface GenerateTOCMessage {
|
||||
fontSize: number;
|
||||
fontFamily: number;
|
||||
addBookmark: boolean;
|
||||
cpdfUrl?: string;
|
||||
}
|
||||
|
||||
interface TOCSuccessResponse {
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
const baseUrl = self.location.href.substring(0, self.location.href.lastIndexOf('/workers/') + 1);
|
||||
self.importScripts(baseUrl + 'coherentpdf.browser.min.js');
|
||||
let cpdfLoaded = false;
|
||||
|
||||
function loadCpdf(cpdfUrl) {
|
||||
if (cpdfLoaded) return Promise.resolve();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (typeof coherentpdf !== 'undefined') {
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self.importScripts(cpdfUrl);
|
||||
cpdfLoaded = true;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to load CoherentPDF: ' + error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateTableOfContentsInWorker(
|
||||
pdfData,
|
||||
@@ -49,7 +68,28 @@ function generateTableOfContentsInWorker(
|
||||
}
|
||||
}
|
||||
|
||||
self.onmessage = (e) => {
|
||||
self.onmessage = async function (e) {
|
||||
const { cpdfUrl } = e.data;
|
||||
|
||||
if (!cpdfUrl) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message:
|
||||
'CoherentPDF URL not provided. Please configure it in WASM Settings.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await loadCpdf(cpdfUrl);
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
status: 'error',
|
||||
message: error.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.command === 'generate-toc') {
|
||||
generateTableOfContentsInWorker(
|
||||
e.data.pdfData,
|
||||
|
||||
Reference in New Issue
Block a user