Skip to content

Commit

Permalink
feat: add support for resolving blob images (#2573)
Browse files Browse the repository at this point in the history
  • Loading branch information
davbrito committed Feb 5, 2024
1 parent 1fd9844 commit 9af07fe
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 3 deletions.
7 changes: 7 additions & 0 deletions .changeset/cuddly-poets-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@react-pdf/image": patch
"@react-pdf/layout": patch
"@react-pdf/types": patch
---

feat: add support for resolving blob images
29 changes: 27 additions & 2 deletions packages/image/src/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,30 @@ const resolveBufferImage = (buffer) => {
return Promise.resolve();
};

const getImageFormat = (body) => {
const resolveBlobImage = async blob => {
const { type } = blob;
if (!type || type === 'application/octet-stream') {
const arrayBuffer = await blob.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
return resolveBufferImage(buffer);
}

if (!type.startsWith('image/')) {
throw new Error(`Invalid blob type: ${type}`);
}

const format = type.replace('image/', '');

if (!isValidFormat(format)) {
throw new Error(`Invalid blob type: ${type}`);
}

const buffer = await blob.arrayBuffer();

return getImage(Buffer.from(buffer), format);
};

const getImageFormat = body => {
const isPng =
body[0] === 137 &&
body[1] === 80 &&
Expand Down Expand Up @@ -170,7 +193,9 @@ const resolveImage = (src, { cache = true } = {}) => {
let image;
const cacheKey = src.data ? src.data.toString() : src.uri;

if (Buffer.isBuffer(src)) {
if (typeof Blob !== 'undefined' && src instanceof Blob) {
image = resolveBlobImage(src);
} else if (Buffer.isBuffer(src)) {
image = resolveBufferImage(src);
} else if (cache && IMAGE_CACHE.get(cacheKey)) {
return IMAGE_CACHE.get(cacheKey);
Expand Down
29 changes: 29 additions & 0 deletions packages/image/tests/resolve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,33 @@ describe('image resolveImage', () => {

expect(image1).not.toBe(image2);
});

test('Should render a blob image', async () => {
const blob = new Blob([localJPGImage], { type: 'image/jpeg' });
const image = await resolveImage(blob);

expect(image.data).toBeTruthy();
expect(image.width).toBeGreaterThan(0);
expect(image.height).toBeGreaterThan(0);
});

test('Should render a blob without type', async () => {
const blob = new Blob([localJPGImage]);
const image = await resolveImage(blob);

expect(image.data).toBeTruthy();
expect(image.width).toBeGreaterThan(0);
expect(image.height).toBeGreaterThan(0);
});

test('Should render a blob image with type application/octet-stream', async () => {
const blob = new Blob([localJPGImage], {
type: 'application/octet-stream',
});
const image = await resolveImage(blob);

expect(image.data).toBeTruthy();
expect(image.width).toBeGreaterThan(0);
expect(image.height).toBeGreaterThan(0);
});
});
19 changes: 19 additions & 0 deletions packages/layout/tests/image/resolveSource.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const SOURCE_URL = 'gotcha';
const SOURCE_URL_OBJECT = { uri: 'gotcha', method: 'GET' };
const SOURCE_BUFFER = Buffer.from('gotcha');
const SOURCE_DATA_BUFFER = { data: Buffer.from('gotcha'), format: 'png' };
const SOURCE_BLOB = new Blob([SOURCE_BUFFER], { type: 'image/png' });

describe('image resolveSource', () => {
describe('source', () => {
Expand All @@ -26,6 +27,10 @@ describe('image resolveSource', () => {
SOURCE_DATA_BUFFER,
);
});

it('resolves blob', () => {
expect(resolveSource(SOURCE_BLOB)).resolves.toBe(SOURCE_BLOB);
});
});

describe('async', () => {
Expand All @@ -52,6 +57,12 @@ describe('image resolveSource', () => {
SOURCE_DATA_BUFFER,
);
});

it('resolves blob', () => {
expect(resolveSource(Promise.resolve(SOURCE_BLOB))).resolves.toBe(
SOURCE_BLOB,
);
});
});

describe('factory', () => {
Expand Down Expand Up @@ -80,6 +91,10 @@ describe('image resolveSource', () => {
it('resolves undefined', () => {
expect(resolveSource(() => undefined)).resolves.toBe(undefined);
});

it('resolves blob', () => {
expect(resolveSource(() => SOURCE_BLOB)).resolves.toBe(SOURCE_BLOB);
});
});

describe('async factory', () => {
Expand Down Expand Up @@ -110,5 +125,9 @@ describe('image resolveSource', () => {
it('resolves undefined', () => {
expect(resolveSource(async () => undefined)).resolves.toBe(undefined);
});

it('resolves blob', () => {
expect(resolveSource(async () => SOURCE_BLOB)).resolves.toBe(SOURCE_BLOB);
});
});
});
5 changes: 4 additions & 1 deletion packages/types/image.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ type SourceURL = string;

type SourceBuffer = Buffer;

type SourceDataBuffer = { data: Buffer; format: 'png' | 'jpg' };
type SourceBlob = Blob

type SourceDataBuffer = { data: Buffer; format: 'png' | 'jpg' }

type SourceURLObject = {
uri: string;
Expand All @@ -17,6 +19,7 @@ type SourceURLObject = {
type Source =
| SourceURL
| SourceBuffer
| SourceBlob
| SourceDataBuffer
| SourceURLObject
| undefined;
Expand Down

0 comments on commit 9af07fe

Please sign in to comment.