Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
@param options - The options for renaming.
@returns - The new filename for the downloaded file.
@description - This function is used to determine the filename for each downloaded file.
*/
export type RenameFunction = (options: {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options is the wrong term here. They are not options.

url: string;
index: number;
urls: string[];
}) => string;

/*
Options for the multiDownload function.
*/
export type Options = {
/**
@default undefined - (use original filenames)
@description - A function that returns the new filename for each downloaded file.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing example like in the readme.

*/
rename?: RenameFunction;
/**
The delay time between each file download in milliseconds.
@default 1000
*/
downloadInterval?: number;
};

/**
@param urls - The URLs to download.
@param options - The options for downloading.
@returns - A promise that resolves when all files have been downloaded.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the correct TSDoc syntax. Applies to the everything else too.

Suggested change
@returns - A promise that resolves when all files have been downloaded.
@returns A promise that resolves when all files have been downloaded.

@description - Download multiple files from an array of URLs.
@example
```
import { multiDownload } from "multi-download";
async function downloadFiles() {
const urls = [
"https://example.com/file1.txt",
"https://example.com/file2.txt",
"https://example.com/file3.txt",
];
try {
await multiDownload(urls, {
rename: ({ url, index }) => `file${index + 1}.txt`,
downloadInterval: 1000,
});
console.log("Files downloaded successfully");
} catch (error) {
console.error("Error downloading files:", error);
}
}
await downloadFiles();
```
*/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is messy code style wise. You are mixing spaces with tabs and the formatting is completely off.

Use the formatting shown in https://github.com/sindresorhus/typescript-definition-style-guide#documentation

Use single-quotes.

export default function multiDownload(
urls: string[],
options?: Options
): Promise<void>;
34 changes: 26 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const delay = milliseconds => new Promise(resolve => {
setTimeout(resolve, milliseconds);
});
const delay = milliseconds =>
new Promise(resolve => {
setTimeout(resolve, milliseconds);
});

const download = async (url, name) => {
const a = document.createElement('a');
Expand All @@ -15,15 +16,32 @@ const download = async (url, name) => {
a.remove();
};

export default async function multiDownload(urls, {rename} = {}) {
if (!urls) {
const getName = ({url}) => {
const match = url.match(/\/([^/]+)$/);
return match ? match[1] : 'file';
};

export default async function multiDownload(urls = [], options = {}) {
const {downloadInterval = 1000, rename = getName} = options;
if (!urls?.length) {
throw new Error('`urls` required');
}

for (const [index, url] of urls.entries()) {
const name = typeof rename === 'function' ? rename({url, index, urls}) : '';
if (urls.some(url => typeof url !== 'string')) {
throw new Error('`urls` must be an array of strings');
}

await delay(index * 1000); // eslint-disable-line no-await-in-loop
if (typeof downloadInterval !== 'number') {
throw new TypeError('The `downloadInterval` option must be a number');
}

if (typeof rename !== 'function') {
throw new TypeError('The `rename` option must be a function');
}

for (const [index, url] of urls.entries()) {
const name = rename({url, index, urls});
await delay(index * downloadInterval); // eslint-disable-line no-await-in-loop
download(url, name);
}
}
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"exports": {
"types": "./index.d.ts",
"default": "./index.js"
},
"scripts": {
"test": "xo"
},
"files": [
"index.js"
"index.js",
"index.d.ts"
],
"keywords": [
"browser",
Expand Down
20 changes: 19 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ Type: `Function`

A function that accepts an object containing `url`, `index`, and `urls` properties and is expected to return the new filename.

##### downloadInterval

Type: `number`

The delay time between each file download in milliseconds.
Comment on lines +77 to +81
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong location. Please look at the readme and you'll see that the below code example is for the rename option.


```html
<button id="download-button" data-files="unicorn.jpg rainbow.jpg">Download</button>
```
Expand All @@ -84,7 +90,19 @@ import multiDownload from 'multi-download';
document.querySelector('#download-button').addEventListener('click', event => {
const files = event.target.dataset.files.split(' ');
multiDownload(files, {
rename: ({url, index, urls}) => 'New name.pdf'
rename: ({url, index, urls}) => 'New name.pdf',
});
});
```

```js
import multiDownload from 'multi-download';

document.querySelector('#download-button').addEventListener('click', event => {
const files = event.target.dataset.files.split(' ');
multiDownload(files, {
rename: ({url, index, urls}) => 'New name.pdf',
downloadInterval: 500
});
});
```
Expand Down