diff --git a/index.js b/index.js index 56b6ea8..8051d73 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ 'use strict'; -const integerRegex = /^-?\d+$/; +const srcsetRegex = /\s*([^,]\S*[^,](?:\s+[^,]+)?)\s*(?:,|$)/; function deepUnique(array) { return array.sort().filter((element, index) => { @@ -10,37 +10,37 @@ function deepUnique(array) { exports.parse = string => { return deepUnique( - string.split(/,\s+/).map(part => { - const result = {}; - - part - .trim() - .split(/\s+/) - .forEach((element, index) => { - if (index === 0) { - result.url = element; - return; - } + string.split(srcsetRegex) + .filter((part, index) => index % 2 === 1) + .map(part => { + const [url, ...descriptors] = part.trim().split(/\s+/); + + const result = {url}; - const value = element.slice(0, -1); - const postfix = element[element.length - 1]; - const integerValue = Number.parseInt(value, 10); - const floatValue = Number.parseFloat(value); + (descriptors.length > 0 ? descriptors : ['1x']).forEach(descriptor => { + const postfix = descriptor[descriptor.length - 1]; + const value = Number.parseFloat(descriptor.slice(0, -1)); - if (postfix === 'w' && integerRegex.test(value)) { - if (integerValue <= 0) { + if (Number.isNaN(value)) { + throw new TypeError(`${descriptor.slice(0, -1)} is not a valid number`); + } + + if (postfix === 'w') { + if (value <= 0) { throw new Error('Width descriptor must be greater than zero'); + } else if (!Number.isInteger(value)) { + throw new TypeError('Width descriptor must be an integer'); } - result.width = integerValue; - } else if (postfix === 'x' && !Number.isNaN(floatValue)) { - if (floatValue <= 0) { + result.width = value; + } else if (postfix === 'x') { + if (value <= 0) { throw new Error('Pixel density descriptor must be greater than zero'); } - result.density = floatValue; + result.density = value; } else { - throw new Error(`Invalid srcset descriptor: ${element}`); + throw new Error(`Invalid srcset descriptor: ${descriptor}`); } if (result.width && result.density) { @@ -48,8 +48,8 @@ exports.parse = string => { } }); - return result; - }) + return result; + }) ); }; diff --git a/test.js b/test.js index d868114..6be09fc 100644 --- a/test.js +++ b/test.js @@ -2,12 +2,13 @@ import test from 'ava'; import srcset from '.'; test('.parse() should parse srcset', t => { - const fixture = ' banner-HD.jpeg 2x, banner-HD.jpeg 2x, banner-HD.jpeg 2x, banner-phone.jpeg 100w, http://site.com/image.jpg?foo=bar,lorem 1x '; + const fixture = ' banner-HD.jpeg 2x, banner-HD.jpeg 2x, banner-HD.jpeg 2x, banner-phone.jpeg 100w, http://site.com/image.jpg?foo=bar,lorem 3x ,banner.jpeg '; t.deepEqual(srcset.parse(fixture), [ {url: 'banner-HD.jpeg', density: 2}, {url: 'banner-phone.jpeg', width: 100}, - {url: 'http://site.com/image.jpg?foo=bar,lorem', density: 1} + {url: 'http://site.com/image.jpg?foo=bar,lorem', density: 3}, + {url: 'banner.jpeg', density: 1} ]); }); @@ -42,6 +43,24 @@ test('.parse() should not parse invalid srcset', t => { t.throws(() => { srcset.parse('banner-phone-HD.jpeg -2x'); }); + + t.throws(() => { + srcset.parse('banner-phone-HD.jpeg 100.5w'); + }); + + t.throws(() => { + srcset.parse('banner-phone-HD.jpeg xxx'); + }); +}); + +test('.parse() should parse srcset separated without white spaces', t => { + const fixture = 'banner-HD.jpeg 2x,banner-HD.jpeg 2x,banner-HD.jpeg 2x,banner-phone.jpeg 100w,http://site.com/image.jpg?foo=100w,lorem 1x'; + + t.deepEqual(srcset.parse(fixture), [ + {url: 'banner-HD.jpeg', density: 2}, + {url: 'banner-phone.jpeg', width: 100}, + {url: 'http://site.com/image.jpg?foo=100w,lorem', density: 1} + ]); }); test('.stringify() should stringify srcset', t => {