UNPKG

@cantoo/pdf-lib

Version:

Create and modify PDF files with JavaScript

229 lines 9.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const pako_1 = tslib_1.__importDefault(require("pako")); const PDFHeader_1 = tslib_1.__importDefault(require("./document/PDFHeader")); const errors_1 = require("./errors"); const PDFArray_1 = tslib_1.__importDefault(require("./objects/PDFArray")); const PDFBool_1 = tslib_1.__importDefault(require("./objects/PDFBool")); const PDFDict_1 = tslib_1.__importDefault(require("./objects/PDFDict")); const PDFHexString_1 = tslib_1.__importDefault(require("./objects/PDFHexString")); const PDFName_1 = tslib_1.__importDefault(require("./objects/PDFName")); const PDFNull_1 = tslib_1.__importDefault(require("./objects/PDFNull")); const PDFNumber_1 = tslib_1.__importDefault(require("./objects/PDFNumber")); const PDFObject_1 = tslib_1.__importDefault(require("./objects/PDFObject")); const PDFRawStream_1 = tslib_1.__importDefault(require("./objects/PDFRawStream")); const PDFRef_1 = tslib_1.__importDefault(require("./objects/PDFRef")); const PDFStream_1 = tslib_1.__importDefault(require("./objects/PDFStream")); const PDFString_1 = tslib_1.__importDefault(require("./objects/PDFString")); const PDFOperator_1 = tslib_1.__importDefault(require("./operators/PDFOperator")); const PDFOperatorNames_1 = tslib_1.__importDefault(require("./operators/PDFOperatorNames")); const PDFContentStream_1 = tslib_1.__importDefault(require("./structures/PDFContentStream")); const utils_1 = require("../utils"); const rng_1 = require("../utils/rng"); const byAscendingObjectNumber = ([a], [b]) => a.objectNumber - b.objectNumber; class PDFContext { constructor() { this.isDecrypted = true; this.largestObjectNumber = 0; this.header = PDFHeader_1.default.forVersion(1, 7); this.trailerInfo = {}; this.indirectObjects = new Map(); this.rng = rng_1.SimpleRNG.withSeed(1); } assign(ref, object) { this.indirectObjects.set(ref, object); if (ref.objectNumber > this.largestObjectNumber) { this.largestObjectNumber = ref.objectNumber; } } nextRef() { this.largestObjectNumber += 1; return PDFRef_1.default.of(this.largestObjectNumber); } register(object) { const ref = this.nextRef(); this.assign(ref, object); return ref; } delete(ref) { return this.indirectObjects.delete(ref); } lookupMaybe(ref, ...types) { // TODO: `preservePDFNull` is for backwards compatibility. Should be // removed in next breaking API change. const preservePDFNull = types.includes(PDFNull_1.default); const result = ref instanceof PDFRef_1.default ? this.indirectObjects.get(ref) : ref; if (!result || (result === PDFNull_1.default && !preservePDFNull)) return undefined; for (let idx = 0, len = types.length; idx < len; idx++) { const type = types[idx]; if (type === PDFNull_1.default) { if (result === PDFNull_1.default) return result; } else { if (result instanceof type) return result; } } throw new errors_1.UnexpectedObjectTypeError(types, result); } lookup(ref, ...types) { const result = ref instanceof PDFRef_1.default ? this.indirectObjects.get(ref) : ref; if (types.length === 0) return result; for (let idx = 0, len = types.length; idx < len; idx++) { const type = types[idx]; if (type === PDFNull_1.default) { if (result === PDFNull_1.default) return result; } else { if (result instanceof type) return result; } } throw new errors_1.UnexpectedObjectTypeError(types, result); } getObjectRef(pdfObject) { const entries = Array.from(this.indirectObjects.entries()); for (let idx = 0, len = entries.length; idx < len; idx++) { const [ref, object] = entries[idx]; if (object === pdfObject) { return ref; } } return undefined; } enumerateIndirectObjects() { return Array.from(this.indirectObjects.entries()).sort(byAscendingObjectNumber); } obj(literal) { if (literal instanceof PDFObject_1.default) { return literal; } else if (literal === null || literal === undefined) { return PDFNull_1.default; } else if (typeof literal === 'string') { return PDFName_1.default.of(literal); } else if (typeof literal === 'number') { return PDFNumber_1.default.of(literal); } else if (typeof literal === 'boolean') { return literal ? PDFBool_1.default.True : PDFBool_1.default.False; } else if (literal instanceof Uint8Array) { return PDFHexString_1.default.fromBytes(literal); } else if (Array.isArray(literal)) { const array = PDFArray_1.default.withContext(this); for (let idx = 0, len = literal.length; idx < len; idx++) { array.push(this.obj(literal[idx])); } return array; } else { const dict = PDFDict_1.default.withContext(this); const keys = Object.keys(literal); for (let idx = 0, len = keys.length; idx < len; idx++) { const key = keys[idx]; const value = literal[key]; if (value !== undefined) dict.set(PDFName_1.default.of(key), this.obj(value)); } return dict; } } getLiteral(obj, { deep = true, literalRef = false, literalStreamDict = false, literalString = false, } = {}) { const cfg = { deep, literalRef, literalStreamDict, literalString }; if (obj instanceof PDFArray_1.default) { const lit = obj.asArray(); return deep ? lit.map((value) => this.getLiteral(value, cfg)) : lit; } else if (obj instanceof PDFBool_1.default) { return obj.asBoolean(); } else if (obj instanceof PDFDict_1.default) { const lit = {}; const entries = obj.entries(); for (let idx = 0, len = entries.length; idx < len; idx++) { const [name, value] = entries[idx]; lit[this.getLiteral(name)] = deep ? this.getLiteral(value, cfg) : value; } return lit; } else if (obj instanceof PDFName_1.default) { return obj.decodeText(); } else if (obj === PDFNull_1.default) { return null; } else if (obj instanceof PDFNumber_1.default) { return obj.asNumber(); } else if (obj instanceof PDFRef_1.default && literalRef) { return obj.objectNumber; } else if (obj instanceof PDFStream_1.default && literalStreamDict) { return this.getLiteral(obj.dict, cfg); } else if ((obj instanceof PDFString_1.default || obj instanceof PDFHexString_1.default) && literalString) { return obj.asString(); } return obj; } stream(contents, dict = {}) { return PDFRawStream_1.default.of(this.obj(dict), (0, utils_1.typedArrayFor)(contents)); } flateStream(contents, dict = {}) { return this.stream(pako_1.default.deflate((0, utils_1.typedArrayFor)(contents)), Object.assign(Object.assign({}, dict), { Filter: 'FlateDecode' })); } contentStream(operators, dict = {}) { return PDFContentStream_1.default.of(this.obj(dict), operators); } formXObject(operators, dict = {}) { return this.contentStream(operators, Object.assign(Object.assign({ BBox: this.obj([0, 0, 0, 0]), Matrix: this.obj([1, 0, 0, 1, 0, 0]) }, dict), { Type: 'XObject', Subtype: 'Form' })); } /* * Reference to PDFContentStream that contains a single PDFOperator: `q`. * Used by [[PDFPageLeaf]] instances to ensure that when content streams are * added to a modified PDF, they start in the default, unchanged graphics * state. */ getPushGraphicsStateContentStream() { if (this.pushGraphicsStateContentStreamRef) { return this.pushGraphicsStateContentStreamRef; } const dict = this.obj({}); const op = PDFOperator_1.default.of(PDFOperatorNames_1.default.PushGraphicsState); const stream = PDFContentStream_1.default.of(dict, [op]); this.pushGraphicsStateContentStreamRef = this.register(stream); return this.pushGraphicsStateContentStreamRef; } /* * Reference to PDFContentStream that contains a single PDFOperator: `Q`. * Used by [[PDFPageLeaf]] instances to ensure that when content streams are * added to a modified PDF, they start in the default, unchanged graphics * state. */ getPopGraphicsStateContentStream() { if (this.popGraphicsStateContentStreamRef) { return this.popGraphicsStateContentStreamRef; } const dict = this.obj({}); const op = PDFOperator_1.default.of(PDFOperatorNames_1.default.PopGraphicsState); const stream = PDFContentStream_1.default.of(dict, [op]); this.popGraphicsStateContentStreamRef = this.register(stream); return this.popGraphicsStateContentStreamRef; } addRandomSuffix(prefix, suffixLength = 4) { return `${prefix}-${Math.floor(this.rng.nextInt() * Math.pow(10, suffixLength))}`; } } PDFContext.create = () => new PDFContext(); exports.default = PDFContext; //# sourceMappingURL=PDFContext.js.map