pdfdataextract
Version:
Extract data from a pdf with pure javascript
275 lines • 12 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.PdfDataExtractor = void 0;
const pdf_mjs_1 = require("pdfjs-dist/legacy/build/pdf.mjs");
const pdfpagedata_1 = require("./pdfpagedata");
const types_1 = require("./types");
async function getPageNumber(pdf_document, pageRef, cache) {
const ref = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
let number = cache[ref];
if (number == null) {
number = await pdf_document.getPageIndex(pageRef);
cache[ref] = number;
}
return number;
}
function parseRemoteUrlDest(remoteUrlDest) {
try {
const remoteDest = JSON.parse(remoteUrlDest);
if (Array.isArray(remoteDest) && Number.isInteger(remoteDest[0])) {
return remoteDest[0];
}
}
catch (_a) { }
return undefined;
}
async function parseOutline(pdf_document, outlineData, cache) {
const outline = [];
for (const o of outlineData) {
const dest = typeof (o.dest) === 'string' ? await pdf_document.getDestination(o.dest) : o.dest;
if (dest == null) {
if (o.unsafeUrl != null) {
if (o.url == null) {
const remoteUrl = o.unsafeUrl.split('#', 2);
const remoteBaseUrl = remoteUrl[0];
if (remoteBaseUrl.toLowerCase().endsWith('.pdf')) {
if (remoteUrl.length == 2) {
outline.push(new types_1.PdfReferenceOutline(o.title, remoteBaseUrl, parseRemoteUrlDest(remoteUrl[1]), o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
else {
outline.push(new types_1.PdfReferenceOutline(o.title, remoteBaseUrl, undefined, o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
}
else {
outline.push(new types_1.UrlOutline(o.title, o.unsafeUrl, false, o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
}
else {
outline.push(new types_1.UrlOutline(o.title, o.url, true, o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
}
else {
// TODO: ?
}
}
else if (Array.isArray(dest)) {
if (typeof dest[0] === 'object') {
outline.push(new types_1.PageNumberOutline(o.title, await getPageNumber(pdf_document, dest[0], cache), o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
else if (Number.isInteger(dest[0])) {
outline.push(new types_1.PageNumberOutline(o.title, dest[0], o.items ? await parseOutline(pdf_document, o.items, cache) : undefined));
}
else {
// TODO: ?
}
}
}
return outline;
}
async function getInstalledCanvasApi() {
try {
require.resolve('canvas');
return (await Promise.resolve().then(() => __importStar(require('./nodecanvas')))).NodeCanvas;
}
catch (_e) { }
try {
require.resolve('@napi-rs/canvas');
return (await Promise.resolve().then(() => __importStar(require('./nodeskiacanvas')))).NodeSkiaCanvas;
}
catch (_e) { }
try {
require.resolve('pureimage');
return (await Promise.resolve().then(() => __importStar(require('./pureimagecanvas')))).PureimageCanvas;
}
catch (_e) { }
return null;
}
async function getInstalledOcrApi() {
try {
require.resolve('tesseract.js');
return (await Promise.resolve().then(() => __importStar(require('./tesseractjsocr')))).TesseractJsOcr;
}
catch (_e) { }
return null;
}
/**
* the extractor for the data of the pdf
*/
class PdfDataExtractor {
constructor(pdf_document, canvasApi, ocrApi) {
this.pdf_document = pdf_document;
this.canvasApi = canvasApi;
this.ocrApi = ocrApi;
}
/**
* get the extractor for the data
*
* @param {Uint8Array} data - the binary data file
* @param {PdfDataExtractorOptions} [options={}] - the options on how to open the data in the extractor
* @returns {Promise<PdfDataExtractor>} a promise that is resolved with a {PdfDataExtractor} object to pull the extracted data from
*/
static async get(data, options = {}) {
var _a, _b, _c;
if (data instanceof Buffer) {
data = new Uint8Array(data);
}
const pdf_document = await (0, pdf_mjs_1.getDocument)({
data: data,
password: options.password,
verbosity: (_a = options.verbosity) !== null && _a !== void 0 ? _a : types_1.VerbosityLevel.ERRORS,
isEvalSupported: false,
}).promise;
return new PdfDataExtractor(pdf_document, (_b = options.canvasApi) !== null && _b !== void 0 ? _b : await getInstalledCanvasApi(), (_c = options.ocrApi) !== null && _c !== void 0 ? _c : await getInstalledOcrApi());
}
/**
* get the fingerprint
*
* @returns {string | null} the fingerprint
*/
get fingerprint() {
return this.pdf_document.fingerprints[0];
}
/**
* get the number of pages
*
* @returns {string} the number of pages
*/
get pages() {
return this.pdf_document.numPages;
}
/**
* get the permission flags
*
* @returns {Promise<Permissions | null>} a promise that is resolved with a {Permissions | null} object that contains the permission flags for the PDF
*/
async getPermissions() {
const permission_flag_array = await this.pdf_document.getPermissions();
return permission_flag_array == null ? null : {
assemble: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.ASSEMBLE),
copy: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.COPY),
copyForAccessibility: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.COPY_FOR_ACCESSIBILITY),
fillInteractiveForms: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.FILL_INTERACTIVE_FORMS),
modifyAnnotations: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.MODIFY_ANNOTATIONS),
print: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.PRINT),
printHQ: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.PRINT_HIGH_QUALITY),
modifyContents: permission_flag_array.includes(pdf_mjs_1.PermissionFlag.MODIFY_CONTENTS),
};
}
/**
* get the text
*
* @param {number|number[]|((pageNumber: number) => boolean)} [pages] - can either be the number of pages to be read,
* a number array with the specific pages (sorted by page number)
* or a filter function (return true to parse the page)
* @param {boolean|Sort} [sort=false] - sort the text by text coordinates
* @returns {Promise<string[]>} a promise that is resolved with a {string[]} array with the extracted text per page
*/
async getText(pages, sort = false) {
return Promise.all((await this.getPageData(pages)).map(async (page) => page == null ? '' : page.toText(sort)));
}
/**
* get the text
*
* @param {number|number[]|((pageNumber: number) => boolean)} [pages] - can either be the number of pages to be read,
* a number array with the specific pages (sorted by page number)
* or a filter function (return true to parse the page)
* @returns {Promise<string[]>} a promise that is resolved with a {string[]} array with the extracted text per page
*/
async getPageData(pages) {
const page_array = [];
const numPages = this.pdf_document.numPages;
if (pages === undefined) {
for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
const page = await this.pdf_document.getPage(pageNumber).catch(() => null);
page_array.push(page == null ? null : new pdfpagedata_1.PdfPageData(page, this.canvasApi, this.ocrApi));
}
}
else if (typeof (pages) === 'number') {
const counter = pages > numPages ? numPages : pages;
for (let pageNumber = 1; pageNumber <= counter; pageNumber++) {
const page = await this.pdf_document.getPage(pageNumber).catch(() => null);
page_array.push(page == null ? null : new pdfpagedata_1.PdfPageData(page, this.canvasApi, this.ocrApi));
}
}
else if (typeof (pages) === 'function') {
for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
if (pages(pageNumber)) {
const page = await this.pdf_document.getPage(pageNumber).catch(() => null);
page_array.push(page == null ? null : new pdfpagedata_1.PdfPageData(page, this.canvasApi, this.ocrApi));
}
}
}
else {
pages = pages.filter((value, index, self) => self.indexOf(value) === index).sort((a, b) => a - b);
for (const pageNumber of pages) {
if (pageNumber <= numPages) {
const page = await this.pdf_document.getPage(pageNumber).catch(() => null);
page_array.push(page == null ? null : new pdfpagedata_1.PdfPageData(page, this.canvasApi, this.ocrApi));
}
}
}
return page_array;
}
/**
* get the outline/bookmarks
*
* @returns {Promise<Outline[]>} a promise that is resolved with a {Outline[]} array with information from the tree outline
*/
async getOutline() {
const outlineData = await this.pdf_document.getOutline();
if (outlineData == null)
return null;
return parseOutline(this.pdf_document, outlineData, {});
}
/**
* get the metadata
*
* @returns {Promise<MetadataInfo | null>} a promise that is resolved with a {MetadataInfo | null} object with information from the metadata section
*/
async getMetadata() {
return await this.pdf_document.getMetadata().catch(() => null);
}
/**
* close the extractor
*
* @returns {Promise<void>} a promise that is resolved when destruction is completed
*/
async close() {
return this.pdf_document.destroy();
}
}
exports.PdfDataExtractor = PdfDataExtractor;
//# sourceMappingURL=pdfdataextractor.js.map