diff --git a/index.d.ts b/index.d.ts
index 98c2236..32a5f70 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -1,78 +1,70 @@
-/* eslint-disable no-redeclare */
-
-declare namespace srcset {
- interface SrcSetDefinition {
- url: string;
- width?: number;
- density?: number;
- }
-
- interface Options {
- /**
- When strict mode is enabled, errors will be thrown on invalid input.
-
- When disabled, a best effort will be made to handle invalid input and no errors will be thrown. The output may be invalid.
-
- @default false
- */
- strict?: boolean;
- }
+export interface SrcSetDefinition {
+ readonly url: string;
+ readonly width?: number;
+ readonly density?: number;
}
-declare const srcset: {
+export interface Options {
/**
- Parse the HTML `` [srcset](http://mobile.smashingmagazine.com/2013/08/21/webkit-implements-srcset-and-why-its-a-good-thing/) attribute.
-
- Accepts a “srcset” string and returns an array of objects with the possible properties: `url` (always), `width`, `density`, and `height`.
+ When strict mode is enabled, errors will be thrown on invalid input.
- @param srcset - A “srcset” string.
+ When disabled, a best effort will be made to handle invalid input and no errors will be thrown. The output may be invalid.
- @example
- ```
- import srcset = require('srcset');
-
- console.log(srcset.parse('banner-HD.jpg 2x, banner-phone.jpg 100w'));
- // [
- // {
- // url: 'banner-HD.jpg',
- // density: 2
- // },
- // {
- // url: 'banner-phone.jpg',
- // width: 100
- // }
- // ]
- ```
+ @default false
*/
- parse: (srcset: string, options?: srcset.Options) => srcset.SrcSetDefinition[];
-
- /**
- Stringify `SrcSetDefinition`s.
-
- @param SrcSetDefinitions - Each object should have a `url` field and may have either `width` or `density`. When the `strict` option is `true`, only `width` or `density` is accepted.
-
- @returns A “srcset” string.
-
- @example
- ```
- import srcset = require('srcset');
-
- const stringified = srcset.stringify([
- {
- url: 'banner-HD.jpg',
- density: 2
- },
- {
- url: 'banner-phone.jpg',
- width: 100
- }
- ]);
+ readonly strict?: boolean;
+}
- console.log(stringified);
- // banner-HD.jpg 2x, banner-phone.jpg 100w
- ```
- */
- stringify: (srcSetDefinitions: readonly srcset.SrcSetDefinition[], options?: srcset.Options) => string;
-};
+/**
+Parse the HTML `` [srcset](http://mobile.smashingmagazine.com/2013/08/21/webkit-implements-srcset-and-why-its-a-good-thing/) attribute.
+
+Accepts a “srcset” string and returns an array of objects with the possible properties: `url` (always), `width`, `density`, and `height`.
+
+@param srcset - A “srcset” string.
+
+@example
+```
+import {parseSrcset} from 'srcset';
+
+console.log(parseSrcset('banner-HD.jpg 2x, banner-phone.jpg 100w'));
+// [
+// {
+// url: 'banner-HD.jpg',
+// density: 2
+// },
+// {
+// url: 'banner-phone.jpg',
+// width: 100
+// }
+// ]
+```
+*/
+export function parseSrcset(srcset: string, options?: Options): SrcSetDefinition[];
+
+/**
+Stringify `SrcSetDefinition`s.
+
+@param SrcSetDefinitions - Each object should have a `url` field and may have either `width` or `density`. When the `strict` option is `true`, only `width` or `density` is accepted.
+
+@returns A “srcset” string.
+
+@example
+```
+import {stringifySrcset} from 'srcset';
+
+const stringified = stringifySrcset([
+ {
+ url: 'banner-HD.jpg',
+ density: 2
+ },
+ {
+ url: 'banner-phone.jpg',
+ width: 100
+ }
+]);
-export = srcset;
+console.log(stringified);
+// banner-HD.jpg 2x, banner-phone.jpg 100w
+```
+*/
+export function stringifySrcset(srcSetDefinitions: readonly SrcSetDefinition[], options?: Options): string;
diff --git a/index.js b/index.js
index 2b0a40e..cb6bd69 100644
--- a/index.js
+++ b/index.js
@@ -1,5 +1,3 @@
-'use strict';
-
/**
This regex represents a loose rule of an “image candidate string”.
@@ -80,8 +78,9 @@ const validDescriptorCheck = (value, postfix, descriptor) => {
}
};
-exports.parse = (string, {strict = false} = {}) => {
+export function parseSrcset(string, {strict = false} = {}) {
const allDescriptors = strict ? {} : undefined;
+
return string.split(imageCandidateRegex)
.filter((part, index) => index % 2 === 1)
.map(part => {
@@ -124,12 +123,13 @@ exports.parse = (string, {strict = false} = {}) => {
return result;
});
-};
+}
const knownDescriptors = new Set(['width', 'height', 'density']);
-exports.stringify = (array, {strict = false} = {}) => {
- const allDescriptors = strict ? {} : null;
+export function stringifySrcset(array, {strict = false} = {}) {
+ const allDescriptors = strict ? {} : undefined;
+
return array.map(element => {
if (!element.url) {
if (strict) {
@@ -183,4 +183,4 @@ exports.stringify = (array, {strict = false} = {}) => {
return result.join(' ');
}).join(', ');
-};
+}
diff --git a/index.test-d.ts b/index.test-d.ts
index c105ee4..ff1f29e 100644
--- a/index.test-d.ts
+++ b/index.test-d.ts
@@ -1,10 +1,10 @@
import {expectType, expectError} from 'tsd';
-import srcset = require('./index.js');
+import {parseSrcset, stringifySrcset, SrcSetDefinition} from './index.js';
-const parsed = srcset.parse('banner-HD.jpg 2x, banner-phone.jpg 100w');
-expectType(parsed);
+const parsed = parseSrcset('banner-HD.jpg 2x, banner-phone.jpg 100w');
+expectType(parsed);
parsed.push({url: 'banner-phone-HD.jpg'}, {url: 'banner-phone-HD.jpg', width: 100}, {url: 'banner-phone-HD.jpg', density: 2});
expectError(parsed.push({}));
-expectType(srcset.stringify(parsed));
+expectType(stringifySrcset(parsed));
diff --git a/package.json b/package.json
index a52a327..151eb1d 100644
--- a/package.json
+++ b/package.json
@@ -10,8 +10,10 @@
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
+ "type": "module",
+ "exports": "./index.js",
"engines": {
- "node": ">=12"
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"test": "xo && ava && tsd"
@@ -34,8 +36,8 @@
"element"
],
"devDependencies": {
- "ava": "^2.4.0",
- "tsd": "^0.13.1",
- "xo": "^0.39.0"
+ "ava": "^3.15.0",
+ "tsd": "^0.19.0",
+ "xo": "^0.46.4"
}
}
diff --git a/readme.md b/readme.md
index a419105..c86a06a 100644
--- a/readme.md
+++ b/readme.md
@@ -6,8 +6,8 @@ Can be useful if you're creating a build-tool.
## Install
-```
-$ npm install srcset
+```sh
+npm install srcset
```
## Usage
@@ -25,9 +25,9 @@ How an image with `srcset` might look like:
Then have some fun with it:
```js
-const srcset = require('srcset');
+import {parseSrcset, stringifySrcset} from 'srcset';
-const parsed = srcset.parse('banner-HD.jpg 2x, banner-phone.jpg 100w');
+const parsed = parseSrcset('banner-HD.jpg 2x, banner-phone.jpg 100w');
console.log(parsed);
/*
[
@@ -47,7 +47,7 @@ parsed.push({
density: 3
});
-const stringified = srcset.stringify(parsed);
+const stringified = stringifySrcset(parsed);
console.log(stringified);
/*
banner-HD.jpg 2x, banner-phone.jpg 100w, banner-super-HD.jpg 3x
@@ -56,7 +56,7 @@ banner-HD.jpg 2x, banner-phone.jpg 100w, banner-super-HD.jpg 3x
## API
-### .parse(string, options?)
+### parseSrcset(string, options?)
Parse the HTML `` [srcset](http://mobile.smashingmagazine.com/2013/08/21/webkit-implements-srcset-and-why-its-a-good-thing/) attribute.
@@ -79,7 +79,7 @@ Default: `false`
When enabled, an invalid “srcset” string will cause an error to be thrown. When disabled, a best effort will be made to parse the string, potentially resulting in invalid or nonsensical output.
-### .stringify(SrcSetDefinitions, options?)
+### stringifySrcset(SrcSetDefinitions, options?)
Stringify `SrcSetDefinition`s. Accepts an array of `SrcSetDefinition` objects and returns a “srcset” string.
@@ -95,11 +95,10 @@ Type: `object`
##### strict
-Type: `boolean`
-
+Type: `boolean`\
Default: `false`
-Enable or disable validation of the SrcSetDefinitions. When true, invalid input will cause an error to be thrown. When false, a best effort will be made to stringify invalid input, likely resulting in invalid srcset value.
+Enable or disable validation of the `SrcSetDefinition`'s. When true, invalid input will cause an error to be thrown. When false, a best effort will be made to stringify invalid input, likely resulting in invalid srcset value.
---
diff --git a/test.js b/test.js
index 3fa0fb5..3cd1852 100644
--- a/test.js
+++ b/test.js
@@ -1,55 +1,55 @@
import test from 'ava';
-import srcset from './index.js';
+import {parseSrcset, stringifySrcset} from './index.js';
-test('.parse() should parse srcset', t => {
+test('parseSrcset() should parse srcset', t => {
const fixture = ' banner-HD.jpeg 2x, banner-phone.jpeg 100w, http://site.com/image.jpg?foo=bar,lorem 3x ,banner.jpeg ';
- t.deepEqual(srcset.parse(fixture), [
+ t.deepEqual(parseSrcset(fixture), [
{url: 'banner-HD.jpeg', density: 2},
{url: 'banner-phone.jpeg', width: 100},
{url: 'http://site.com/image.jpg?foo=bar,lorem', density: 3},
- {url: 'banner.jpeg'}
+ {url: 'banner.jpeg'},
]);
});
-test('.parse() should parse URLs with commas', t => {
+test('parseSrcset() should parse URLs with commas', t => {
const fixture = 'https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_180,q_80,w_320/rbx48jwtuvpwum29aarr.jpg 320w, https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_264,q_80,w_470/rbx48jwtuvpwum29aarr.jpg 470w, https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_80,q_80,w_80/rbx48jwtuvpwum29aarr.jpg 80w';
- t.deepEqual(srcset.parse(fixture), [
+ t.deepEqual(parseSrcset(fixture), [
{
url: 'https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_180,q_80,w_320/rbx48jwtuvpwum29aarr.jpg',
- width: 320
+ width: 320,
},
{
url: 'https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_264,q_80,w_470/rbx48jwtuvpwum29aarr.jpg',
- width: 470
+ width: 470,
},
{
url: 'https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_80,q_80,w_80/rbx48jwtuvpwum29aarr.jpg',
- width: 80
- }
+ width: 80,
+ },
]);
});
-test('.parse() should parse srcset separated without whitespaces', t => {
+test('parseSrcset() should parse srcset separated without whitespaces', t => {
const fixture = 'banner-HD.jpeg 2x,banner-phone.jpeg 100w,http://site.com/image.jpg?foo=100w,lorem 1x';
- t.deepEqual(srcset.parse(fixture), [
+ t.deepEqual(parseSrcset(fixture), [
{url: 'banner-HD.jpeg', density: 2},
{url: 'banner-phone.jpeg', width: 100},
- {url: 'http://site.com/image.jpg?foo=100w,lorem', density: 1}
+ {url: 'http://site.com/image.jpg?foo=100w,lorem', density: 1},
]);
});
-test('.stringify() should stringify srcset', t => {
+test('stringifySrcset() should stringify srcset', t => {
const fixture = [
{url: 'banner-HD.jpeg', density: 2},
- {url: 'banner-phone.jpeg', width: 100}
+ {url: 'banner-phone.jpeg', width: 100},
];
t.is(
- srcset.stringify(fixture),
- 'banner-HD.jpeg 2x, banner-phone.jpeg 100w'
+ stringifySrcset(fixture),
+ 'banner-HD.jpeg 2x, banner-phone.jpeg 100w',
);
});
@@ -64,20 +64,20 @@ const invalidStrings = [
'banner.jpeg 3q', // Invalid descriptor
'banner.jpeg xxx', // Nonsense descriptor
'banner.jpg 1x, fallback.jpg', // Duplicate descriptor because the fallback is equivalent to 1x
- 'banner.jpg 2x, other.jpg 2.0x' // Duplicate descriptors after normalizing
+ 'banner.jpg 2x, other.jpg 2.0x', // Duplicate descriptors after normalizing
];
for (const invalidSrcset of invalidStrings) {
- test(`.parse() should throw on invalid input when strict mode is enabled: "${invalidSrcset}"`, t => {
+ test(`parseSrcset() should throw on invalid input when strict mode is enabled: "${invalidSrcset}"`, t => {
t.throws(() => {
- srcset.parse(invalidSrcset, {strict: true});
+ parseSrcset(invalidSrcset, {strict: true});
});
});
}
for (const invalidSrcset of invalidStrings) {
- test(`.parse() should not throw on invalid input when strict mode is disabled: "${invalidSrcset}"`, t => {
- srcset.parse(invalidSrcset, {strict: false});
+ test(`parseSrcset() should not throw on invalid input when strict mode is disabled: "${invalidSrcset}"`, t => {
+ parseSrcset(invalidSrcset, {strict: false});
t.pass();
});
}
@@ -93,21 +93,21 @@ const invalidArrays = [
[{url: 'banner.jpeg', width: Number.NaN}], // Invalid descriptor
[{url: 'banner.jpeg', width: 'xxx'}], // Nonsense descriptor
[{url: 'banner.jpg', density: 1}, {url: 'fallback.jpg'}], // Duplicate descriptor because the fallback is equivalent to 1x
- [{url: 'banner-hd.jpg', density: 2}, {url: 'other-hd.jpg', density: 2}] // Duplicate descriptors after normalizing
+ [{url: 'banner-hd.jpg', density: 2}, {url: 'other-hd.jpg', density: 2}], // Duplicate descriptors after normalizing
];
for (const invalidSrcset of invalidArrays) {
- test(`.stringify() should throw on invalid input when strict mode is enabled: ${JSON.stringify(invalidSrcset)}`, t => {
+ test(`stringifySrcset() should throw on invalid input when strict mode is enabled: ${JSON.stringify(invalidSrcset)}`, t => {
t.throws(() => {
- srcset.stringify(invalidSrcset, {strict: true});
+ stringifySrcset(invalidSrcset, {strict: true});
});
});
}
for (const invalidSrcset of invalidArrays) {
- test(`.stringify() should not throw on invalid input when strict mode is disabled: ${JSON.stringify(invalidSrcset)}`, t => {
+ test(`stringifySrcset() should not throw on invalid input when strict mode is disabled: ${JSON.stringify(invalidSrcset)}`, t => {
t.notThrows(() => {
- srcset.stringify(invalidSrcset, {strict: false});
+ stringifySrcset(invalidSrcset, {strict: false});
});
});
}