pdf-lib
Version:
Create and modify PDF files with JavaScript
788 lines • 35.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var errors_1 = require("./errors");
var PDFFont_1 = tslib_1.__importDefault(require("./PDFFont"));
var PDFImage_1 = tslib_1.__importDefault(require("./PDFImage"));
var PDFPage_1 = tslib_1.__importDefault(require("./PDFPage"));
var sizes_1 = require("./sizes");
var core_1 = require("../core");
var utils_1 = require("../utils");
var ParseSpeeds;
(function (ParseSpeeds) {
ParseSpeeds[ParseSpeeds["Fastest"] = Infinity] = "Fastest";
ParseSpeeds[ParseSpeeds["Fast"] = 1500] = "Fast";
ParseSpeeds[ParseSpeeds["Medium"] = 500] = "Medium";
ParseSpeeds[ParseSpeeds["Slow"] = 100] = "Slow";
})(ParseSpeeds = exports.ParseSpeeds || (exports.ParseSpeeds = {}));
/**
* Represents a PDF document.
*/
var PDFDocument = /** @class */ (function () {
function PDFDocument(context, ignoreEncryption) {
var _this = this;
/** The default word breaks used in PDFPage.drawText */
this.defaultWordBreaks = [' '];
this.computePages = function () {
var pages = [];
_this.catalog.Pages().traverse(function (node, ref) {
if (node instanceof core_1.PDFPageLeaf) {
var page = _this.pageMap.get(node);
if (!page) {
page = PDFPage_1.default.of(node, ref, _this);
_this.pageMap.set(node, page);
}
pages.push(page);
}
});
return pages;
};
utils_1.assertIs(context, 'context', [[core_1.PDFContext, 'PDFContext']]);
utils_1.assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
this.context = context;
this.catalog = context.lookup(context.trailerInfo.Root);
this.isEncrypted = !!context.lookup(context.trailerInfo.Encrypt);
this.pageCache = utils_1.Cache.populatedBy(this.computePages);
this.pageMap = new Map();
this.fonts = [];
this.images = [];
if (!ignoreEncryption && this.isEncrypted)
throw new errors_1.EncryptedPDFError();
this.updateInfoDict();
}
/**
* Load an existing [[PDFDocument]]. The input data can be provided in
* multiple formats:
*
* | Type | Contents |
* | ------------- | ------------------------------------------------------ |
* | `string` | A base64 encoded string (or data URI) containing a PDF |
* | `Uint8Array` | The raw bytes of a PDF |
* | `ArrayBuffer` | The raw bytes of a PDF |
*
* For example:
* ```js
* import { PDFDocument } from 'pdf-lib'
*
* // pdf=string
* const base64 =
* 'JVBERi0xLjcKJYGBgYEKCjUgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbm' +
* 'd0aCAxMDQKPj4Kc3RyZWFtCniccwrhMlAAwaJ0Ln2P1Jyy1JLM5ERdc0MjCwUjE4WQNC4Q' +
* '6cNlCFZkqGCqYGSqEJLLZWNuYGZiZmbkYuZsZmlmZGRgZmluDCQNzc3NTM2NzdzMXMxMjQ' +
* 'ztFEKyuEK0uFxDuAAOERdVCmVuZHN0cmVhbQplbmRvYmoKCjYgMCBvYmoKPDwKL0ZpbHRl' +
* 'ciAvRmxhdGVEZWNvZGUKL1R5cGUgL09ialN0bQovTiA0Ci9GaXJzdCAyMAovTGVuZ3RoID' +
* 'IxNQo+PgpzdHJlYW0KeJxVj9GqwjAMhu/zFHkBzTo3nCCCiiKIHPEICuJF3cKoSCu2E8/b' +
* '20wPIr1p8v9/8kVhgilmGfawX2CGaVrgcAi0/bsy0lrX7IGWpvJ4iJYEN3gEmrrGBlQwGs' +
* 'HHO9VBX1wNrxAqMX87RBD5xpJuddqwd82tjAHxzV1U5LPgy52DKXWnr1Lheg+j/c/pzGVr' +
* 'iqV0VlwZPXGPCJjElw/ybkwUmeoWgxesDXGhHJC/D/iikp1Av80ptKU0FdBEe25pPihAM1' +
* 'u6ytgaaWfs2Hrz35CJT1+EWmAKZW5kc3RyZWFtCmVuZG9iagoKNyAwIG9iago8PAovU2l6' +
* 'ZSA4Ci9Sb290IDIgMCBSCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCi9UeXBlIC9YUmVmCi9MZW' +
* '5ndGggMzgKL1cgWyAxIDIgMiBdCi9JbmRleCBbIDAgOCBdCj4+CnN0cmVhbQp4nBXEwREA' +
* 'EBAEsCwz3vrvRmOOyyOoGhZdutHN2MT55fIAVocD+AplbmRzdHJlYW0KZW5kb2JqCgpzdG' +
* 'FydHhyZWYKNTEwCiUlRU9G'
*
* const dataUri = 'data:application/pdf;base64,' + base64
*
* const pdfDoc1 = await PDFDocument.load(base64)
* const pdfDoc2 = await PDFDocument.load(dataUri)
*
* // pdf=Uint8Array
* import fs from 'fs'
* const uint8Array = fs.readFileSync('with_update_sections.pdf')
* const pdfDoc3 = await PDFDocument.load(uint8Array)
*
* // pdf=ArrayBuffer
* const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
* const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
* const pdfDoc4 = await PDFDocument.load(arrayBuffer)
*
* ```
*
* @param pdf The input data containing a PDF document.
* @param options The options to be used when loading the document.
* @returns Resolves with a document loaded from the input.
*/
PDFDocument.load = function (pdf, options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, ignoreEncryption, _b, parseSpeed, bytes, context;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = options.ignoreEncryption, ignoreEncryption = _a === void 0 ? false : _a, _b = options.parseSpeed, parseSpeed = _b === void 0 ? ParseSpeeds.Slow : _b;
utils_1.assertIs(pdf, 'pdf', ['string', Uint8Array, ArrayBuffer]);
utils_1.assertIs(ignoreEncryption, 'ignoreEncryption', ['boolean']);
utils_1.assertIs(parseSpeed, 'parseSpeed', ['number']);
bytes = utils_1.toUint8Array(pdf);
return [4 /*yield*/, core_1.PDFParser.forBytesWithOptions(bytes, parseSpeed).parseDocument()];
case 1:
context = _c.sent();
return [2 /*return*/, new PDFDocument(context, ignoreEncryption)];
}
});
});
};
/**
* Create a new [[PDFDocument]].
* @returns Resolves with the newly created document.
*/
PDFDocument.create = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var context, pageTree, pageTreeRef, catalog;
return tslib_1.__generator(this, function (_a) {
context = core_1.PDFContext.create();
pageTree = core_1.PDFPageTree.withContext(context);
pageTreeRef = context.register(pageTree);
catalog = core_1.PDFCatalog.withContextAndPages(context, pageTreeRef);
context.trailerInfo.Root = context.register(catalog);
return [2 /*return*/, new PDFDocument(context, false)];
});
});
};
/**
* Register a fontkit instance. This must be done before custom fonts can
* be embedded. See [here](https://github.com/Hopding/pdf-lib/tree/Rewrite#fontkit-installation)
* for instructions on how to install and register a fontkit instance.
*
* > You do **not** need to call this method to embed standard fonts.
*
* @param fontkit The fontkit instance to be registered.
*/
PDFDocument.prototype.registerFontkit = function (fontkit) {
this.fontkit = fontkit;
};
/**
* Set this document's title metadata. The title will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setTitle('🥚 The Life of an Egg 🍳')
* ```
* @param title The title of this document.
*/
PDFDocument.prototype.setTitle = function (title) {
utils_1.assertIs(title, 'title', ['string']);
var key = core_1.PDFName.of('Title');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(title));
};
/**
* Set this document's author metadata. The author will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setAuthor('Humpty Dumpty')
* ```
* @param author The author of this document.
*/
PDFDocument.prototype.setAuthor = function (author) {
utils_1.assertIs(author, 'author', ['string']);
var key = core_1.PDFName.of('Author');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(author));
};
/**
* Set this document's subject metadata. The subject will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setSubject('📘 An Epic Tale of Woe 📖')
* ```
* @param subject The subject of this document.
*/
PDFDocument.prototype.setSubject = function (subject) {
utils_1.assertIs(subject, 'author', ['string']);
var key = core_1.PDFName.of('Subject');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(subject));
};
/**
* Set this document's keyword metadata. These keywords will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setKeywords(['eggs', 'wall', 'fall', 'king', 'horses', 'men'])
* ```
* @param keywords An array of keywords associated with this document.
*/
PDFDocument.prototype.setKeywords = function (keywords) {
utils_1.assertIs(keywords, 'keywords', [Array]);
var key = core_1.PDFName.of('Keywords');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(keywords.join(' ')));
};
/**
* Set this document's creator metadata. The creator will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setCreator('PDF App 9000 🤖')
* ```
* @param creator The creator of this document.
*/
PDFDocument.prototype.setCreator = function (creator) {
utils_1.assertIs(creator, 'creator', ['string']);
var key = core_1.PDFName.of('Creator');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(creator));
};
/**
* Set this document's producer metadata. The producer will appear in the
* "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setProducer('PDF App 9000 🤖')
* ```
* @param producer The producer of this document.
*/
PDFDocument.prototype.setProducer = function (producer) {
utils_1.assertIs(producer, 'creator', ['string']);
var key = core_1.PDFName.of('Producer');
this.getInfoDict().set(key, core_1.PDFHexString.fromText(producer));
};
/**
* Set this document's creation date metadata. The creation date will appear
* in the "Document Properties" section of most PDF readers. For example:
* ```js
* pdfDoc.setCreationDate(new Date())
* ```
* @param creationDate The date this document was created.
*/
PDFDocument.prototype.setCreationDate = function (creationDate) {
utils_1.assertIs(creationDate, 'creationDate', [[Date, 'Date']]);
var key = core_1.PDFName.of('CreationDate');
this.getInfoDict().set(key, core_1.PDFString.fromDate(creationDate));
};
/**
* Set this document's modification date metadata. The modification date will
* appear in the "Document Properties" section of most PDF readers. For
* example:
* ```js
* pdfDoc.setModificationDate(new Date())
* ```
* @param modificationDate The date this document was last modified.
*/
PDFDocument.prototype.setModificationDate = function (modificationDate) {
utils_1.assertIs(modificationDate, 'modificationDate', [[Date, 'Date']]);
var key = core_1.PDFName.of('ModDate');
this.getInfoDict().set(key, core_1.PDFString.fromDate(modificationDate));
};
/**
* Get the number of pages contained in this document. For example:
* ```js
* const totalPages = pdfDoc.getPageCount()
* ```
* @returns The number of pages in this document.
*/
PDFDocument.prototype.getPageCount = function () {
if (this.pageCount === undefined)
this.pageCount = this.getPages().length;
return this.pageCount;
};
/**
* Get an array of all the pages contained in this document. The pages are
* stored in the array in the same order that they are rendered in the
* document. For example:
* ```js
* const pages = pdfDoc.getPages()
* pages[0] // The first page of the document
* pages[2] // The third page of the document
* pages[197] // The 198th page of the document
* ```
* @returns An array of all the pages contained in this document.
*/
PDFDocument.prototype.getPages = function () {
return this.pageCache.access();
};
/**
* Get an array of indices for all the pages contained in this document. The
* array will contain a range of integers from
* `0..pdfDoc.getPageCount() - 1`. For example:
* ```js
* const pdfDoc = await PDFDocument.create()
* pdfDoc.addPage()
* pdfDoc.addPage()
* pdfDoc.addPage()
*
* const indices = pdfDoc.getPageIndices()
* indices // => [0, 1, 2]
* ```
* @returns An array of indices for all pages contained in this document.
*/
PDFDocument.prototype.getPageIndices = function () {
return utils_1.range(0, this.getPageCount());
};
/**
* Remove the page at a given index from this document. For example:
* ```js
* pdfDoc.removePage(0) // Remove the first page of the document
* pdfDoc.removePage(2) // Remove the third page of the document
* pdfDoc.removePage(197) // Remove the 198th page of the document
* ```
* Once a page has been removed, it will no longer be rendered at that index
* in the document.
* @param index The index of the page to be removed.
*/
PDFDocument.prototype.removePage = function (index) {
var pageCount = this.getPageCount();
if (this.pageCount === 0)
throw new errors_1.RemovePageFromEmptyDocumentError();
utils_1.assertRange(index, 'index', 0, pageCount - 1);
this.catalog.removeLeafNode(index);
this.pageCount = pageCount - 1;
};
/**
* Add a page to the end of this document. This method accepts three
* different value types for the `page` parameter:
*
* | Type | Behavior |
* | ------------------ | ----------------------------------------------------------------------------------- |
* | `undefined` | Create a new page and add it to the end of this document |
* | `[number, number]` | Create a new page with the given dimensions and add it to the end of this document |
* | `PDFPage` | Add the existing page to the end of this document |
*
* For example:
* ```js
* // page=undefined
* const newPage = pdfDoc.addPage()
*
* // page=[number, number]
* import { PageSizes } from 'pdf-lib'
* const newPage1 = pdfDoc.addPage(PageSizes.A7)
* const newPage2 = pdfDoc.addPage(PageSizes.Letter)
* const newPage3 = pdfDoc.addPage([500, 750])
*
* // page=PDFPage
* const pdfDoc1 = await PDFDocument.create()
* const pdfDoc2 = await PDFDocument.load(...)
* const [existingPage] = await pdfDoc1.copyPages(pdfDoc2, [0])
* pdfDoc1.addPage(existingPage)
* ```
*
* @param page Optionally, the desired dimensions or existing page.
* @returns The newly created (or existing) page.
*/
PDFDocument.prototype.addPage = function (page) {
utils_1.assertIs(page, 'page', ['undefined', [PDFPage_1.default, 'PDFPage'], Array]);
return this.insertPage(this.getPageCount(), page);
};
/**
* Insert a page at a given index within this document. This method accepts
* three different value types for the `page` parameter:
*
* | Type | Behavior |
* | ------------------ | ------------------------------------------------------------------------------ |
* | `undefined` | Create a new page and insert it into this document |
* | `[number, number]` | Create a new page with the given dimensions and insert it into this document |
* | `PDFPage` | Insert the existing page into this document |
*
* For example:
* ```js
* // page=undefined
* const newPage = pdfDoc.insertPage(2)
*
* // page=[number, number]
* import { PageSizes } from 'pdf-lib'
* const newPage1 = pdfDoc.insertPage(2, PageSizes.A7)
* const newPage2 = pdfDoc.insertPage(0, PageSizes.Letter)
* const newPage3 = pdfDoc.insertPage(198, [500, 750])
*
* // page=PDFPage
* const pdfDoc1 = await PDFDocument.create()
* const pdfDoc2 = await PDFDocument.load(...)
* const [existingPage] = await pdfDoc1.copyPages(pdfDoc2, [0])
* pdfDoc1.insertPage(0, existingPage)
* ```
*
* @param index The index at which the page should be inserted (zero-based).
* @param page Optionally, the desired dimensions or existing page.
* @returns The newly created (or existing) page.
*/
PDFDocument.prototype.insertPage = function (index, page) {
var pageCount = this.getPageCount();
utils_1.assertRange(index, 'index', 0, pageCount);
utils_1.assertIs(page, 'page', ['undefined', [PDFPage_1.default, 'PDFPage'], Array]);
if (!page || Array.isArray(page)) {
var dims = Array.isArray(page) ? page : sizes_1.PageSizes.A4;
page = PDFPage_1.default.create(this);
page.setSize.apply(page, dims);
}
else if (page.doc !== this) {
throw new errors_1.ForeignPageError();
}
var parentRef = this.catalog.insertLeafNode(page.ref, index);
page.node.setParent(parentRef);
this.pageMap.set(page.node, page);
this.pageCache.invalidate();
this.pageCount = pageCount + 1;
return page;
};
/**
* Copy pages from a source document into this document. Allows pages to be
* copied between different [[PDFDocument]] instances. For example:
* ```js
* const pdfDoc = await PDFDocument.create()
* const srcDoc = await PDFDocument.load(...)
*
* const copiedPages = await pdfDoc.copyPages(srcDoc, [0, 3, 89])
* const [firstPage, fourthPage, ninetiethPage] = copiedPages;
*
* pdfDoc.addPage(fourthPage)
* pdfDoc.insertPage(0, ninetiethPage)
* pdfDoc.addPage(firstPage)
* ```
* @param srcDoc The document from which pages should be copied.
* @param indices The indices of the pages that should be copied.
* @returns Resolves with an array of pages copied into this document.
*/
PDFDocument.prototype.copyPages = function (srcDoc, indices) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var copier, srcPages, copiedPages, idx, len, srcPage, copiedPage, ref;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
utils_1.assertIs(srcDoc, 'srcDoc', [[PDFDocument, 'PDFDocument']]);
utils_1.assertIs(indices, 'indices', [Array]);
return [4 /*yield*/, srcDoc.flush()];
case 1:
_a.sent();
copier = core_1.PDFObjectCopier.for(srcDoc.context, this.context);
srcPages = srcDoc.getPages();
copiedPages = new Array(indices.length);
for (idx = 0, len = indices.length; idx < len; idx++) {
srcPage = srcPages[indices[idx]];
copiedPage = copier.copy(srcPage.node);
ref = this.context.register(copiedPage);
copiedPages[idx] = PDFPage_1.default.of(copiedPage, ref, this);
}
return [2 /*return*/, copiedPages];
}
});
});
};
/**
* Embed a font into this document. The input data can be provided in multiple
* formats:
*
* | Type | Contents |
* | --------------- | ------------------------------------------------------- |
* | `StandardFonts` | One of the standard 14 fonts |
* | `string` | A base64 encoded string (or data URI) containing a font |
* | `Uint8Array` | The raw bytes of a font |
* | `ArrayBuffer` | The raw bytes of a font |
*
* For example:
* ```js
* // font=StandardFonts
* import { StandardFonts } from 'pdf-lib'
* const font1 = await pdfDoc.embedFont(StandardFonts.Helvetica)
*
* // font=string
* const font2 = await pdfDoc.embedFont('AAEAAAAVAQAABABQRFNJRx/upe...')
* const font3 = await pdfDoc.embedFont('data:font/opentype;base64,AAEAAA...')
*
* // font=Uint8Array
* import fs from 'fs'
* const font4 = await pdfDoc.embedFont(fs.readFileSync('Ubuntu-R.ttf'))
*
* // font=ArrayBuffer
* const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
* const ubuntuBytes = await fetch(url).then(res => res.arrayBuffer())
* const font5 = await pdfDoc.embedFont(ubuntuBytes)
* ```
* See also: [[registerFontkit]]
* @param font The input data for a font.
* @param options The options to be used when embedding the font.
* @returns Resolves with the embedded font.
*/
PDFDocument.prototype.embedFont = function (font, options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, subset, embedder, bytes, fontkit, _b, ref, pdfFont;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = options.subset, subset = _a === void 0 ? false : _a;
utils_1.assertIs(font, 'font', ['string', Uint8Array, ArrayBuffer]);
utils_1.assertIs(subset, 'subset', ['boolean']);
if (!utils_1.isStandardFont(font)) return [3 /*break*/, 1];
embedder = core_1.StandardFontEmbedder.for(font);
return [3 /*break*/, 7];
case 1:
if (!utils_1.canBeConvertedToUint8Array(font)) return [3 /*break*/, 6];
bytes = utils_1.toUint8Array(font);
fontkit = this.assertFontkit();
if (!subset) return [3 /*break*/, 3];
return [4 /*yield*/, core_1.CustomFontSubsetEmbedder.for(fontkit, bytes)];
case 2:
_b = _c.sent();
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, core_1.CustomFontEmbedder.for(fontkit, bytes)];
case 4:
_b = _c.sent();
_c.label = 5;
case 5:
embedder = _b;
return [3 /*break*/, 7];
case 6: throw new TypeError('`font` must be one of `StandardFonts | string | Uint8Array | ArrayBuffer`');
case 7:
ref = this.context.nextRef();
pdfFont = PDFFont_1.default.of(ref, this, embedder);
this.fonts.push(pdfFont);
return [2 /*return*/, pdfFont];
}
});
});
};
/**
* Embed a standard font into this document.
* For example:
* ```js
* import { StandardFonts } from 'pdf-lib'
* const helveticaFont = pdfDoc.embedFont(StandardFonts.Helvetica)
* ```
* @param font The standard font to be embedded.
* @returns The embedded font.
*/
PDFDocument.prototype.embedStandardFont = function (font) {
utils_1.assertIs(font, 'font', ['string']);
if (!utils_1.isStandardFont(font)) {
throw new TypeError('`font` must be one of type `StandardFontsr`');
}
var embedder = core_1.StandardFontEmbedder.for(font);
var ref = this.context.nextRef();
var pdfFont = PDFFont_1.default.of(ref, this, embedder);
this.fonts.push(pdfFont);
return pdfFont;
};
/**
* Embed a JPEG image into this document. The input data can be provided in
* multiple formats:
*
* | Type | Contents |
* | ------------- | ------------------------------------------------------------- |
* | `string` | A base64 encoded string (or data URI) containing a JPEG image |
* | `Uint8Array` | The raw bytes of a JPEG image |
* | `ArrayBuffer` | The raw bytes of a JPEG image |
*
* For example:
* ```js
* // jpg=string
* const image1 = await pdfDoc.embedJpg('/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD...')
* const image2 = await pdfDoc.embedJpg('data:image/jpeg;base64,/9j/4AAQ...')
*
* // jpg=Uint8Array
* import fs from 'fs'
* const uint8Array = fs.readFileSync('cat_riding_unicorn.jpg')
* const image3 = await pdfDoc.embedJpg(uint8Array)
*
* // jpg=ArrayBuffer
* const url = 'https://pdf-lib.js.org/assets/cat_riding_unicorn.jpg'
* const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
* const image4 = await pdfDoc.embedJpg(arrayBuffer)
* ```
*
* @param jpg The input data for a JPEG image.
* @returns Resolves with the embedded image.
*/
PDFDocument.prototype.embedJpg = function (jpg) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var bytes, embedder, ref, pdfImage;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
utils_1.assertIs(jpg, 'jpg', ['string', Uint8Array, ArrayBuffer]);
bytes = utils_1.toUint8Array(jpg);
return [4 /*yield*/, core_1.JpegEmbedder.for(bytes)];
case 1:
embedder = _a.sent();
ref = this.context.nextRef();
pdfImage = PDFImage_1.default.of(ref, this, embedder);
this.images.push(pdfImage);
return [2 /*return*/, pdfImage];
}
});
});
};
/**
* Embed a PNG image into this document. The input data can be provided in
* multiple formats:
*
* | Type | Contents |
* | ------------- | ------------------------------------------------------------ |
* | `string` | A base64 encoded string (or data URI) containing a PNG image |
* | `Uint8Array` | The raw bytes of a PNG image |
* | `ArrayBuffer` | The raw bytes of a PNG image |
*
* For example:
* ```js
* // png=string
* const image1 = await pdfDoc.embedPng('iVBORw0KGgoAAAANSUhEUgAAAlgAAAF3...')
* const image2 = await pdfDoc.embedPng('data:image/png;base64,iVBORw0KGg...')
*
* // png=Uint8Array
* import fs from 'fs'
* const uint8Array = fs.readFileSync('small_mario.png')
* const image3 = await pdfDoc.embedPng(uint8Array)
*
* // png=ArrayBuffer
* const url = 'https://pdf-lib.js.org/assets/small_mario.png'
* const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
* const image4 = await pdfDoc.embedPng(arrayBuffer)
* ```
*
* @param png The input data for a PNG image.
* @returns Resolves with the embedded image.
*/
PDFDocument.prototype.embedPng = function (png) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var bytes, embedder, ref, pdfImage;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
utils_1.assertIs(png, 'png', ['string', Uint8Array, ArrayBuffer]);
bytes = utils_1.toUint8Array(png);
return [4 /*yield*/, core_1.PngEmbedder.for(bytes)];
case 1:
embedder = _a.sent();
ref = this.context.nextRef();
pdfImage = PDFImage_1.default.of(ref, this, embedder);
this.images.push(pdfImage);
return [2 /*return*/, pdfImage];
}
});
});
};
/**
* > **NOTE:** You shouldn't need to call this method directly. The [[save]]
* > and [[saveAsBase64]] methods will automatically ensure that all embedded
* > assets are flushed before serializing the document.
*
* Flush all embedded fonts and images to this document's [[context]].
*
* @returns Resolves when the flush is complete.
*/
PDFDocument.prototype.flush = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var idx, len, font, idx, len, image;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
idx = 0, len = this.fonts.length;
_a.label = 1;
case 1:
if (!(idx < len)) return [3 /*break*/, 4];
font = this.fonts[idx];
return [4 /*yield*/, font.embed()];
case 2:
_a.sent();
_a.label = 3;
case 3:
idx++;
return [3 /*break*/, 1];
case 4:
idx = 0, len = this.images.length;
_a.label = 5;
case 5:
if (!(idx < len)) return [3 /*break*/, 8];
image = this.images[idx];
return [4 /*yield*/, image.embed()];
case 6:
_a.sent();
_a.label = 7;
case 7:
idx++;
return [3 /*break*/, 5];
case 8: return [2 /*return*/];
}
});
});
};
/**
* Serialize this document to an array of bytes making up a PDF file.
* For example:
* ```js
* const pdfBytes = await pdfDoc.save()
* ```
*
* There are a number of things you can do with the serialized document,
* depending on the JavaScript environment you're running in:
* * Write it to a file in Node or React Native
* * Download it as a Blob in the browser
* * Render it in an `iframe`
*
* @param options The options to be used when saving the document.
* @returns Resolves with the bytes of the serialized document.
*/
PDFDocument.prototype.save = function (options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, useObjectStreams, _b, addDefaultPage, _c, objectsPerTick, Writer;
return tslib_1.__generator(this, function (_d) {
switch (_d.label) {
case 0:
_a = options.useObjectStreams, useObjectStreams = _a === void 0 ? true : _a, _b = options.addDefaultPage, addDefaultPage = _b === void 0 ? true : _b, _c = options.objectsPerTick, objectsPerTick = _c === void 0 ? 50 : _c;
utils_1.assertIs(useObjectStreams, 'useObjectStreams', ['boolean']);
utils_1.assertIs(addDefaultPage, 'addDefaultPage', ['boolean']);
utils_1.assertIs(objectsPerTick, 'objectsPerTick', ['number']);
if (addDefaultPage && this.pageCount === 0)
this.addPage();
return [4 /*yield*/, this.flush()];
case 1:
_d.sent();
Writer = useObjectStreams ? core_1.PDFStreamWriter : core_1.PDFWriter;
return [2 /*return*/, Writer.forContext(this.context, objectsPerTick).serializeToBuffer()];
}
});
});
};
/**
* Serialize this document to a base64 encoded string or data URI making up a
* PDF file. For example:
* ```js
* const base64String = await pdfDoc.saveAsBase64()
* base64String // => 'JVBERi0xLjcKJYGBgYEKC...'
*
* const base64DataUri = await pdfDoc.saveAsBase64({ dataUri: true })
* base64DataUri // => 'data:application/pdf;base64,JVBERi0xLjcKJYGBgYEKC...'
* ```
*
* @param options The options to be used when saving the document.
* @returns Resolves with a base64 encoded string or data URI of the
* serialized document.
*/
PDFDocument.prototype.saveAsBase64 = function (options) {
if (options === void 0) { options = {}; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, dataUri, otherOptions, bytes, base64;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = options.dataUri, dataUri = _a === void 0 ? false : _a, otherOptions = tslib_1.__rest(options, ["dataUri"]);
utils_1.assertIs(dataUri, 'dataUri', ['boolean']);
return [4 /*yield*/, this.save(otherOptions)];
case 1:
bytes = _b.sent();
base64 = utils_1.encodeToBase64(bytes);
return [2 /*return*/, dataUri ? "data:application/pdf;base64," + base64 : base64];
}
});
});
};
PDFDocument.prototype.updateInfoDict = function () {
var pdfLib = "pdf-lib (https://github.com/Hopding/pdf-lib)";
var now = new Date();
var info = this.getInfoDict();
this.setProducer(pdfLib);
this.setModificationDate(now);
if (!info.get(core_1.PDFName.of('Creator')))
this.setCreator(pdfLib);
if (!info.get(core_1.PDFName.of('CreationDate')))
this.setCreationDate(now);
};
PDFDocument.prototype.getInfoDict = function () {
var existingInfo = this.context.lookup(this.context.trailerInfo.Info);
if (existingInfo instanceof core_1.PDFDict)
return existingInfo;
var newInfo = this.context.obj({});
this.context.trailerInfo.Info = this.context.register(newInfo);
return newInfo;
};
PDFDocument.prototype.assertFontkit = function () {
if (!this.fontkit)
throw new errors_1.FontkitNotRegisteredError();
return this.fontkit;
};
return PDFDocument;
}());
exports.default = PDFDocument;
//# sourceMappingURL=PDFDocument.js.map