@pdfme/pdf-lib
Version:
Create and modify PDF files with JavaScript
292 lines • 14.7 kB
JavaScript
import { PDFArray, PDFBool, PDFContentStream, PDFContext, PDFDict, PDFHexString, PDFName, PDFNull, PDFNumber, PDFObjectCopier, PDFPageLeaf, PDFPageTree, PDFRawStream, PDFRef, PDFString, } from '../../src/index';
describe(`PDFObjectCopier`, () => {
it(`copies PDFDicts, including their indirect references`, () => {
// Arrange
const src = PDFContext.create();
const origDict = src.obj({
Foo: PDFString.of('stuff and things'),
Bar: PDFRef.of(13),
});
src.register(origDict);
src.assign(PDFRef.of(13), src.obj([1, PDFRef.of(17)]));
src.assign(PDFRef.of(17), src.obj({ Baz: 'wallykazam' }));
const dest = PDFContext.create();
// Act
const copiedDict = PDFObjectCopier.for(src, dest).copy(origDict);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(2);
expect(copiedDict).not.toBe(origDict);
expect(copiedDict).toBeInstanceOf(PDFDict);
const Foo = PDFName.of('Foo');
expect(copiedDict.get(Foo)).not.toBe(origDict.get(Foo));
expect(copiedDict.get(Foo)).toBeInstanceOf(PDFString);
const Bar = PDFName.of('Bar');
expect(copiedDict.get(Bar)).not.toBe(origDict.get(Bar));
expect(copiedDict.get(Bar)).toBeInstanceOf(PDFRef);
const srcBar = src.lookup(origDict.get(Bar), PDFArray);
const destBar = dest.lookup(copiedDict.get(Bar), PDFArray);
expect(destBar).not.toBe(srcBar);
expect(destBar).toBeInstanceOf(PDFArray);
expect(destBar.get(0)).not.toBe(srcBar.get(0));
expect(destBar.get(0)).toBeInstanceOf(PDFNumber);
expect(destBar.get(1)).not.toBe(srcBar.get(1));
expect(destBar.get(1)).toBeInstanceOf(PDFRef);
const srcBar1 = src.lookup(srcBar.get(1), PDFDict);
const destBar1 = dest.lookup(destBar.get(1), PDFDict);
expect(destBar1).not.toBe(srcBar1);
expect(destBar1).toBeInstanceOf(PDFDict);
const Baz = PDFName.of('Baz');
expect(destBar1.get(Baz)).toBe(srcBar1.get(Baz));
expect(destBar1.get(Baz)).toBeInstanceOf(PDFName);
});
it(`copies PDFArrays, including their indirect references`, () => {
// Arrange
const src = PDFContext.create();
const origArray = src.obj([
PDFString.of('stuff and things'),
PDFRef.of(13),
]);
src.register(origArray);
src.assign(PDFRef.of(13), src.obj({ Foo: 1, Bar: PDFRef.of(17) }));
src.assign(PDFRef.of(17), src.obj(['wallykazam']));
const dest = PDFContext.create();
// Act
const copiedArray = PDFObjectCopier.for(src, dest).copy(origArray);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(2);
expect(copiedArray).not.toBe(origArray);
expect(copiedArray).toBeInstanceOf(PDFArray);
expect(copiedArray.get(0)).not.toBe(origArray.get(0));
expect(copiedArray.get(0)).toBeInstanceOf(PDFString);
expect(copiedArray.get(1)).not.toBe(origArray.get(1));
expect(copiedArray.get(1)).toBeInstanceOf(PDFRef);
const src1 = src.lookup(origArray.get(1), PDFDict);
const dest1 = dest.lookup(copiedArray.get(1), PDFDict);
expect(dest1).not.toBe(src1);
expect(dest1).toBeInstanceOf(PDFDict);
const Foo = PDFName.of('Foo');
expect(dest1.get(Foo)).not.toBe(src1.get(Foo));
expect(dest1.get(Foo)).toBeInstanceOf(PDFNumber);
const Bar = PDFName.of('Bar');
expect(dest1.get(Bar)).not.toBe(src1.get(Bar));
expect(dest1.get(Bar)).toBeInstanceOf(PDFRef);
const src1Bar = src.lookup(src1.get(Bar), PDFArray);
const dest1Bar = dest.lookup(dest1.get(Bar), PDFArray);
expect(dest1Bar).not.toBe(src1Bar);
expect(dest1Bar).toBeInstanceOf(PDFArray);
expect(dest1Bar.get(0)).toBe(src1Bar.get(0));
expect(dest1Bar.get(0)).toBeInstanceOf(PDFName);
});
it(`copies PDFStreams, including their indirect references`, () => {
// Arrange
const src = PDFContext.create();
const origStream = src.stream(new Uint8Array([1, 2, 3, 4, 5]), {
Foo: PDFString.of('stuff and things'),
Bar: PDFRef.of(13),
});
src.register(origStream);
src.assign(PDFRef.of(13), src.obj([1, PDFRef.of(17)]));
src.assign(PDFRef.of(17), src.obj({ Baz: 'wallykazam' }));
const dest = PDFContext.create();
// Act
const copiedStream = PDFObjectCopier.for(src, dest).copy(origStream);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(2);
expect(copiedStream).not.toBe(origStream);
expect(copiedStream).toBeInstanceOf(PDFRawStream);
expect(copiedStream.contents).not.toBe(origStream.contents);
expect(copiedStream.contents).toEqual(origStream.contents);
const Foo = PDFName.of('Foo');
expect(copiedStream.dict.get(Foo)).not.toBe(origStream.dict.get(Foo));
expect(copiedStream.dict.get(Foo)).toBeInstanceOf(PDFString);
const Bar = PDFName.of('Bar');
expect(copiedStream.dict.get(Bar)).not.toBe(origStream.dict.get(Bar));
expect(copiedStream.dict.get(Bar)).toBeInstanceOf(PDFRef);
const srcBar = src.lookup(origStream.dict.get(Bar), PDFArray);
const destBar = dest.lookup(copiedStream.dict.get(Bar), PDFArray);
expect(destBar).not.toBe(srcBar);
expect(destBar).toBeInstanceOf(PDFArray);
expect(destBar.get(0)).not.toBe(srcBar.get(0));
expect(destBar.get(0)).toBeInstanceOf(PDFNumber);
expect(destBar.get(1)).not.toBe(srcBar.get(1));
expect(destBar.get(1)).toBeInstanceOf(PDFRef);
const srcBar1 = src.lookup(srcBar.get(1), PDFDict);
const destBar1 = dest.lookup(destBar.get(1), PDFDict);
expect(destBar1).not.toBe(srcBar1);
expect(destBar1).toBeInstanceOf(PDFDict);
const Baz = PDFName.of('Baz');
expect(destBar1.get(Baz)).toBe(srcBar1.get(Baz));
expect(destBar1.get(Baz)).toBeInstanceOf(PDFName);
});
it(`copies PDFRefs, including their indirect references`, () => {
// Arrange
const src = PDFContext.create();
const origRef = PDFRef.of(21);
src.assign(origRef, src.obj({ Foo: PDFString.of('stuff and things'), Bar: PDFRef.of(13) }));
src.assign(PDFRef.of(13), src.obj([1, PDFRef.of(17)]));
src.assign(PDFRef.of(17), src.obj({ Baz: 'wallykazam' }));
const dest = PDFContext.create();
// Act
const copiedRef = PDFObjectCopier.for(src, dest).copy(origRef);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(3);
expect(copiedRef).not.toBe(origRef);
expect(copiedRef).toBeInstanceOf(PDFRef);
const origDeref = src.lookup(origRef, PDFDict);
const copiedDeref = dest.lookup(copiedRef, PDFDict);
const Foo = PDFName.of('Foo');
expect(copiedDeref.get(Foo)).not.toBe(origDeref.get(Foo));
expect(copiedDeref.get(Foo)).toBeInstanceOf(PDFString);
const Bar = PDFName.of('Bar');
expect(copiedDeref.get(Bar)).not.toBe(origDeref.get(Bar));
expect(copiedDeref.get(Bar)).toBeInstanceOf(PDFRef);
const srcBar = src.lookup(origDeref.get(Bar), PDFArray);
const destBar = dest.lookup(copiedDeref.get(Bar), PDFArray);
expect(destBar).not.toBe(srcBar);
expect(destBar).toBeInstanceOf(PDFArray);
expect(destBar.get(0)).not.toBe(srcBar.get(0));
expect(destBar.get(0)).toBeInstanceOf(PDFNumber);
expect(destBar.get(1)).not.toBe(srcBar.get(1));
expect(destBar.get(1)).toBeInstanceOf(PDFRef);
const srcBar1 = src.lookup(srcBar.get(1), PDFDict);
const destBar1 = dest.lookup(destBar.get(1), PDFDict);
expect(destBar1).not.toBe(srcBar1);
expect(destBar1).toBeInstanceOf(PDFDict);
const Baz = PDFName.of('Baz');
expect(destBar1.get(Baz)).toBe(srcBar1.get(Baz));
expect(destBar1.get(Baz)).toBeInstanceOf(PDFName);
});
it(`copies individual PDFPageLeaf objects, without bringing along the whole page tree`, () => {
// Arrange
const src = PDFContext.create();
const contentStreamRef = PDFRef.of(21);
const origPageRef = src.nextRef();
const middlePageTreeRef = src.nextRef();
const rootPageTreeRef = src.nextRef();
const contentStream = PDFContentStream.of(src.obj({}), []);
const origPage = PDFPageLeaf.withContextAndParent(src, middlePageTreeRef);
origPage.set(PDFName.of('Contents'), src.obj([contentStreamRef]));
const middlePageTree = PDFPageTree.withContext(src, rootPageTreeRef);
const rectangle = src.obj([1, 2, 3, 4]);
const rootPageTree = PDFPageTree.withContext(src);
rootPageTree.set(PDFName.of('Resources'), src.obj({}));
rootPageTree.set(PDFName.of('MediaBox'), rectangle);
rootPageTree.set(PDFName.of('CropBox'), rectangle);
rootPageTree.set(PDFName.of('Rotate'), PDFNumber.of(180));
rootPageTree.pushTreeNode(middlePageTreeRef);
middlePageTree.pushLeafNode(origPageRef);
src.assign(contentStreamRef, contentStream);
src.assign(origPageRef, origPage);
src.assign(middlePageTreeRef, middlePageTree);
src.assign(rootPageTreeRef, rootPageTree);
const dest = PDFContext.create();
// Act
const copiedPage = PDFObjectCopier.for(src, dest).copy(origPage);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(1);
expect(copiedPage).not.toBe(origPage);
expect(copiedPage).toBeInstanceOf(PDFPageLeaf);
const Contents = copiedPage.Contents();
expect(Contents).not.toBe(origPage.Contents());
expect(Contents).toBeInstanceOf(PDFArray);
expect(Contents.size()).toBe(1);
expect(Contents.get(0)).not.toBe(origPage.Contents().get(0));
expect(Contents.get(0)).toBeInstanceOf(PDFRef);
const Resources = copiedPage.Resources();
expect(Resources).not.toBe(rootPageTree.get(PDFName.of('Resources')));
expect(Resources).toBeInstanceOf(PDFDict);
const MediaBox = copiedPage.MediaBox();
expect(MediaBox).not.toBe(rootPageTree.get(PDFName.of('MediaBox')));
expect(MediaBox).toBeInstanceOf(PDFArray);
const CropBox = copiedPage.CropBox();
expect(CropBox).not.toBe(rootPageTree.get(PDFName.of('CropBox')));
expect(CropBox).toBeInstanceOf(PDFArray);
const Rotate = copiedPage.Rotate();
expect(Rotate).not.toBe(rootPageTree.get(PDFName.of('Rotate')));
expect(Rotate).toBeInstanceOf(PDFNumber);
});
it(`copies objects with cyclic references`, () => {
// Arrange
const src = PDFContext.create();
const dictRef = src.nextRef();
const arrayRef = src.nextRef();
const dict = src.obj({ Foo: arrayRef, Bar: dictRef });
const array = src.obj([dictRef, arrayRef]);
src.assign(dictRef, dict);
src.assign(arrayRef, array);
const dest = PDFContext.create();
// Act
PDFObjectCopier.for(src, dest).copy(dict);
// Assert
expect(dest.enumerateIndirectObjects().length).toBe(src.enumerateIndirectObjects().length);
});
it(`copies all types of PDFObjects`, () => {
// Arrange
const src = PDFContext.create();
const dest = PDFContext.create();
const copier = PDFObjectCopier.for(src, dest);
const origArray = src.obj([]);
const origBool = src.obj(true);
const origDict = src.obj({});
const origHexString = PDFHexString.of('ABC123');
const origIndirectRef = src.register(origBool);
const origName = src.obj('QuxBaz');
const origNull = src.obj(null);
const origNumber = src.obj(21);
const origRawStream = src.stream(new Uint8Array([1, 2]));
const origString = PDFString.of('Stuff and thingz');
// Act
const copiedArray = copier.copy(origArray);
const copiedBool = copier.copy(origBool);
const copiedDict = copier.copy(origDict);
const copiedHexString = copier.copy(origHexString);
const copiedIndirectRef = copier.copy(origIndirectRef);
const copiedName = copier.copy(origName);
const copiedNull = copier.copy(origNull);
const copiedNumber = copier.copy(origNumber);
const copiedRawStream = copier.copy(origRawStream);
const copiedString = copier.copy(origString);
// Assert
expect(copiedArray).not.toBe(origArray);
expect(copiedArray).toBeInstanceOf(PDFArray);
expect(copiedBool).toBe(origBool);
expect(copiedBool).toBeInstanceOf(PDFBool);
expect(copiedDict).not.toBe(origDict);
expect(copiedDict).toBeInstanceOf(PDFDict);
expect(copiedHexString).not.toBe(origHexString);
expect(copiedHexString).toBeInstanceOf(PDFHexString);
expect(copiedIndirectRef).toBe(origIndirectRef);
expect(copiedIndirectRef).toBeInstanceOf(PDFRef);
expect(copiedName).toBe(origName);
expect(copiedName).toBeInstanceOf(PDFName);
expect(copiedNull).toBe(origNull);
expect(copiedNull).toBe(PDFNull);
expect(copiedNumber).not.toBe(origNumber);
expect(copiedNumber).toBeInstanceOf(PDFNumber);
expect(copiedRawStream).not.toBe(origRawStream);
expect(copiedRawStream).toBeInstanceOf(PDFRawStream);
expect(copiedString).not.toBe(origString);
expect(copiedString).toBeInstanceOf(PDFString);
});
it(`copies objects with undefined references`, () => {
// Arrange
const src = PDFContext.create();
const dest = PDFContext.create();
const copier = PDFObjectCopier.for(src, dest);
const origArray = src.obj([PDFRef.of(21)]);
const origDict = src.obj({ Foo: PDFRef.of(21) });
// Act
const copiedArray = copier.copy(origArray);
const copiedDict = copier.copy(origDict);
// Assert
expect(copiedArray).not.toBe(origArray);
expect(copiedArray).toBeInstanceOf(PDFArray);
expect(copiedArray.size()).toBe(1);
expect(copiedArray.get(0)).toBe(PDFRef.of(1));
expect(copiedDict).not.toBe(origDict);
expect(copiedDict).toBeInstanceOf(PDFDict);
expect(copiedDict.entries().length).toBe(1);
expect(copiedDict.get(PDFName.of('Foo'))).toBe(PDFRef.of(1));
});
});
//# sourceMappingURL=PDFObjectCopier.spec.js.map