Skip to content

Commit

Permalink
Add new getSrcset function
Browse files Browse the repository at this point in the history
  • Loading branch information
bookernath committed Jul 8, 2019
1 parent 308fcb9 commit 40956c0
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/test-unit/tools.image.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import tools from '../tools';

describe('tools.image', () => {
it('should return a src if a valid image and size is passed (inherent width string)', () => {
const expected = 'https://cdn.example.com/path/to/100w/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
'100w'
);

expect(actual).toEqual(expected);
});

it('should return a src if a valid image and size is passed (pixel size string)', () => {
const expected = 'https://cdn.example.com/path/to/100x100/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
'100x100'
);

expect(actual).toEqual(expected);
});

it('should return a src if a valid image and size is passed (pixel size object)', () => {
const expected = 'https://cdn.example.com/path/to/123x123/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
{ width: 123, height: 123 }
);

expect(actual).toEqual(expected);
});

it('should return a src 100px wide if width is missing (pixel size object)', () => {
const expected = 'https://cdn.example.com/path/to/100x123/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
{ height: 123 }
);

expect(actual).toEqual(expected);
});

it('should return a src 100px high if height is missing (pixel size object)', () => {
const expected = 'https://cdn.example.com/path/to/123x100/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
{ width: 123 }
);

expect(actual).toEqual(expected);
});

it('should return the original image if an invalid size is passed', () => {
const expected = 'https://cdn.example.com/path/to/original/image.png?c=2';
const actual = tools.image.getSrc(
'https://cdn.example.com/path/to/{:size}/image.png?c=2',
'100'
);

expect(actual).toEqual(expected);
});
});
80 changes: 80 additions & 0 deletions src/test-unit/tools.imageSrcset.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import tools from '../tools';

describe('tools.imageSrcset', () => {
it('should return a srcset if a valid image and srcset sizes are passed (inherent width)', () => {
const expected = 'https://cdn.example.com/path/to/100w/image.png?c=2 100w, ' +
'https://cdn.example.com/path/to/200w/image.png?c=2 200w, ' +
'https://cdn.example.com/path/to/300w/image.png?c=2 300w, ' +
'https://cdn.example.com/path/to/1000w/image.png?c=2 1000w';
const actual = tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2',
{
'100w': '100w',
'200w': '200w',
'300w': '300w',
'1000w': '1000w',
}
);

expect(actual).toEqual(expected);
});

it('should return a srcset if a valid image and srcset sizes are passed (pixel density)', () => {
const expected = 'https://cdn.example.com/path/to/100x100/image.png?c=2 1x, ' +
'https://cdn.example.com/path/to/150x150/image.png?c=2 1.5x, ' +
'https://cdn.example.com/path/to/200x200/image.png?c=2 2x';
const actual = tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2',
{
'1x': '100x100',
'1.5x': '150x150',
'2x': '200x200',
}
);

expect(actual).toEqual(expected);
});

it('should return a src if a valid image and srcset size is passed (inherent width)', () => {
const expected = 'https://cdn.example.com/path/to/100w/image.png?c=2';
const actual = tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2',
{
'1x': '100w',
}
);

expect(actual).toEqual(expected);
});

it('should return a src if a valid image and srcset size is passed (pixel density)', () => {
const expected = 'https://cdn.example.com/path/to/100x100/image.png?c=2';
const actual = tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2',
{
'1x': '100x100',
}
);

expect(actual).toEqual(expected);
});

it('should return a srcset made of default sizes if no sizes are provided', () => {
const expected = 'https://cdn.example.com/path/to/80w/image.png?c=2 80w, ' +
'https://cdn.example.com/path/to/160w/image.png?c=2 160w, ' +
'https://cdn.example.com/path/to/320w/image.png?c=2 320w, ' +
'https://cdn.example.com/path/to/640w/image.png?c=2 640w, ' +
'https://cdn.example.com/path/to/960w/image.png?c=2 960w, ' +
'https://cdn.example.com/path/to/1280w/image.png?c=2 1280w, ' +
'https://cdn.example.com/path/to/1920w/image.png?c=2 1920w, ' +
'https://cdn.example.com/path/to/2560w/image.png?c=2 2560w';
const actual = tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2');

expect(actual).toEqual(expected);
});

it('should throw an error if an invalid srcset string is provided', () => {
expect(() => {tools.imageSrcset.getSrcset('https://cdn.example.com/path/to/{:size}/image.png?c=2',
{
'100w': '100w',
'1000w': '1000',
}
)}).toThrow(new Error('Invalid srcset descriptor or size'));
});
});
2 changes: 2 additions & 0 deletions src/tools.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import ImageTool from './tools/image';
import ImageSrcsetTool from './tools/imageSrcset';
import StorageTools from './tools/storage';

export default {
image: new ImageTool(),
imageSrcset: new ImageSrcsetTool(),
storage: new StorageTools(),
};
2 changes: 1 addition & 1 deletion src/tools/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class {

size = `${width}x${height}`;
} else if (typeof(dimensions) === 'string' && sizeRegex.test(dimensions)) {
// If dimensions is a string and match the NNNxNNN format
// If dimensions is a string and match the NNNxNNN or NNNw format
size = dimensions;
} else {
// Use the original image size
Expand Down
48 changes: 48 additions & 0 deletions src/tools/imageSrcset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export default class {
getSrcset(url, sizes) {
// Regex to test size string is of the form 123x123 or 100w
const sizeRegex = /(^\d+w$)|(^(\d+?)x(\d+?)$)/;
// Regex to test to that srcset descriptor is of the form 1x 1.5x 2x OR 123w
const descriptorRegex = /(^\d+w$)|(^([0-9](\.[0-9]+)?)x)$/;

function isObject(obj) {
return obj === Object(obj);
}

function srcsetsAreValid(srcsets) {
return !Object.keys(srcsets).some(descriptor =>
!(descriptorRegex.test(descriptor) && sizeRegex.test(srcsets[descriptor]))
);
}

let srcsets = {};

if (!sizes) {
// Use default srcsets if none are provided
srcsets = {
'80w': '80w',
'160w': '160w',
'320w': '320w',
'640w': '640w',
'960w': '960w',
'1280w': '1280w',
'1920w': '1920w',
'2560w': '2560w',
};
} else if (isObject(sizes) && srcsetsAreValid(sizes)) {
// If object consists of valid srcsets, use it instead
srcsets = sizes;
// If there's only one argument, return a `src` only (also works for `srcset`)
if (Object.keys(srcsets).length === 1) {
return (url.replace('{:size}', srcsets[Object.keys(srcsets)[0]]));
}
} else {
throw new Error('Invalid srcset descriptor or size');
}

// eslint-disable-next-line new-cap
return Object.keys(srcsets).map(descriptor =>
[url.replace('{:size}', srcsets[descriptor]), descriptor].join(' ')
).join(', ');
}
}

0 comments on commit 40956c0

Please sign in to comment.